Skip to content
This repository was archived by the owner on Dec 18, 2024. It is now read-only.

Commit 36bc7e3

Browse files
committed
0.3.1
1 parent a39325f commit 36bc7e3

File tree

4 files changed

+134
-99
lines changed

4 files changed

+134
-99
lines changed
Lines changed: 70 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,12 @@
11
# universal-module-federation-plugin
22

3+
[![npm](https://img.shields.io/npm/v/universal-module-federation-plugin.svg)](https://www.npmjs.com/package/universal-module-federation-plugin)
4+
35
Keep the original API of module-federation, support the integration of various module specifications
46

57
Allows you to control all the processes of each dependency by yourself
68

7-
Can do almost anything you want
8-
9-
## umd
9+
## umd examles
1010

1111
Allow module-federation to use umd module, umd dependencies can be obtained from shareScopes or remotes
1212

@@ -21,8 +21,8 @@ module.exports = {
2121
filename: 'remoteEntry.js',
2222
remotes: {
2323
app2: "app2@http://localhost:9002/remoteEntry.js",
24-
app4reactRouter: "app4reactRouter@https://unpkg.com/react-router@6.4.3/dist/umd/react-router.production.min.js",
25-
app5remixRouter: "app5remixRouter@https://unpkg.com/@remix-run/router@1.0.3/dist/router.umd.min.js"
24+
"react-router": "app4reactRouter@https://unpkg.com/react-router@6.4.3/dist/umd/react-router.production.min.js",
25+
"@remix-run/router": "app5remixRouter@https://unpkg.com/@remix-run/router@1.0.3/dist/router.umd.min.js"
2626
},
2727
exposes: {
2828
'./App': './src/App',
@@ -31,30 +31,9 @@ module.exports = {
3131
}),
3232
new UmdPlugin({
3333
// The matched remotes are loaded in umd mode
34-
includeRemotes: ["app4reactRouter", /app5remixRouter/],
35-
// $umdValue: Module object exposed by umd
36-
// $moduleName: "./App" <=== import "umdRemote/App"
37-
runtimeUmdExposes({ $umdValue, $moduleName }) {
38-
$moduleName = $moduleName.replace(/^\.\/?/, "")
39-
if ($moduleName) {
40-
return $umdValue[$moduleName]
41-
}
42-
return $umdValue
43-
},
34+
includeRemotes: [/react-router/, "@remix-run/router"],
4435
dependencies: {
45-
// Automatically match dependencies with the same name in remotes and shared
46-
// !!! "automatic" is under development
4736
automatic: ["shareScopes", "remotes"],
48-
referenceShares: {
49-
// "react" This dependency is fetched from shareScopes
50-
react: {
51-
singleton: true
52-
},
53-
},
54-
referenceRemotes: {
55-
// "@remix-run/router" This dependency is obtained from remotes
56-
"@remix-run/router": "app5remixRouter"
57-
}
5837
}
5938
}),
6039
new UmdPlugin({
@@ -65,60 +44,76 @@ module.exports = {
6544
}
6645
```
6746

47+
## umd api
48+
49+
| options | desc | default | examles |
50+
|-------------------------------|---------------------------------------------------------------------------|-----------------------------------|:--------------------------------------------------|
51+
| includeRemotes | match umd remotes | [] | [/umd-app/, "app3"] |
52+
| excludeRemotes | exclude umd remotes | [] | ["app2"] |
53+
| dependencies.automatic | Automatically match dependencies with the same name in remotes and shared | ["shareScopes", "remotes"] | |
54+
| dependencies.referenceShares | umd dependencies use by shares | {} | {react: {singleton: true, requiredVersion: "17"}} |
55+
| dependencies.referenceRemotes | umd dependencies use by remotes | {} | {react: "app5"} |
56+
| runtimeUmdExposes | | ({$umdValue}) => return $umdValue | |
57+
58+
#### runtimeUmdExposes
59+
``` js
60+
// $umdValue: Module object exposed by umd
61+
// $moduleName: "./App" <=== import "umdRemote/App"
62+
runtimeUmdExposes({ $umdValue, $moduleName }) {
63+
$moduleName = $moduleName.replace(/^\.\/?/, "")
64+
if ($moduleName) {
65+
return $umdValue[$moduleName]
66+
}
67+
return $umdValue
68+
}
69+
```
70+
6871
## custom module specification
6972

7073
If you have modified systemjs, or you have your own module specification, you can use UniversalModuleFederationPlugin to integrate it. The following is the source code of UmdPlugin, and the explanation of each API will be updated after the documentation.
7174

72-
```
75+
``` js
7376
// webpack.config.js
74-
const {UniversalModuleFederationPlugin} = require("universal-
75-
module.exports = {
76-
plugins: [
77-
new UniversalModuleFederationPlugin({
78-
includeRemotes: this.options.includeRemotes,
79-
excludeRemotes: this.options.excludeRemotes,
80-
runtimeInjectVars: {
81-
referenceShares: this.options.dependencies.referenceShares,
82-
referenceRemotes: this.options.dependencies.referenceRemotes,
83-
umdExposes: this.options.runtimeUmdExposes
84-
},
85-
runtimeInject: ({$semverhook, $getShare, $getRemote, $injectVars}) => {
86-
const {
87-
referenceRemotes,
88-
referenceShares,
89-
umdExposes
90-
} = $injectVars
91-
const {interceptSystemDep} = require("umfjs")
92-
const interceptDeps = Object.keys(referenceShares)
93-
.concat(Object.keys(referenceRemotes))
94-
95-
$semverhook.on("resolve", (url) => {})
96-
$semverhook.on("import", (url) => {
97-
return {
98-
init(){},
99-
async get(moduleName = "") {
100-
const res = await window.System.import(url)
101-
return function() {
102-
return umdExposes({
103-
$umdValue: res,
104-
$moduleName: moduleName
105-
})
106-
}
107-
}
108-
}
109-
})
110-
111-
interceptSystemDep(interceptDeps, async (dep) => {
112-
let depValue = null
113-
if (referenceShares[dep]) {
114-
depValue = await $getShare(referenceShares[dep].import || dep, referenceShares[dep])
115-
} else if (referenceRemotes[dep]) {
116-
depValue = await $getRemote(referenceRemotes[dep])
77+
78+
const PLUGIN_NAME = 'UmdPlugin';
79+
const UniversalModuleFederationPlugin = require("./UniversalModuleFederationPlugin")
80+
81+
class UmdPlugin {
82+
83+
apply(compiler) {
84+
new UniversalModuleFederationPlugin({
85+
runtimeInject: ({$semverhook, $getShare, $getRemote, $containerRemoteKeyMap, $injectVars}) => {
86+
const {interceptSystemAllDep} = require("umfjs")
87+
const {System, eventBus} = interceptSystemAllDep()
88+
89+
$semverhook.on("import", (url) => {
90+
return {
91+
init(){},
92+
async get(moduleName = "") {
93+
const res = await System.import(url)
94+
return function() {
95+
return umdExposes({
96+
$umdValue: res,
97+
$moduleName: moduleName
98+
})
11799
}
118-
return depValue
119-
})
100+
}
120101
}
121-
}).apply(compiler)
122-
]
102+
})
103+
104+
eventBus.on("importDep", (dep) => {
105+
if (referenceRemotes[dep]) {
106+
return $getRemote(referenceRemotes[dep] || dep)
107+
}
108+
})
109+
eventBus.on("importDep", (dep) => {
110+
if (referenceShares[dep]) {
111+
return $getShare(referenceShares[dep].import || dep, referenceShares[dep])
112+
}
113+
})
114+
}
115+
}).apply(compiler)
116+
}
117+
123118
}
124119
```

packages/universal-module-federation-plugin/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "universal-module-federation-plugin",
3-
"version": "0.2.0",
3+
"version": "0.3.0",
44
"description": "Module federation supports the integration of various specifications, such as umd",
55
"main": "src/index.js",
66
"keywords": [
@@ -14,7 +14,7 @@
1414
"semverhook": "^1.0.7",
1515
"inject-webpack": "^0.1.5",
1616
"webpack-virtual-modules": "^0.4.6",
17-
"umfjs": "^0.1.0"
17+
"umfjs": "^0.3.0"
1818
},
1919
"scripts": {
2020
"test": "echo \"Error: no test specified\" && exit 1"

packages/universal-module-federation-plugin/src/UniversalModuleFederationPlugin.js

Lines changed: 29 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,29 +19,38 @@ class UniversalModuleFederationPlugin {
1919
this.appName = ""
2020
this.hookIndex = ++hookIndex
2121
this.mfOptions = null
22+
this.containerRemoteKeyMap = null
2223
}
2324
apply(compiler) {
2425
this.mfOptions = this.getMfOptions(compiler.options.plugins)
26+
this.containerRemoteKeyMap = this.getContainerRemoteKeyMap(this.mfOptions.remotes)
2527
this.appName = this.mfOptions.name
2628
let injectCode = `
2729
let __umf__ = {
2830
$semverhook: null,
2931
$getRemote: null,
3032
$getShare: null,
33+
$containerRemoteKeyMap: null,
3134
$injectVars: null
3235
}
3336
if (!window.__umfplugin__semverhook_${this.appName}_${this.hookIndex}) {
3437
;(function () {
3538
window.__umfplugin__semverhook_${this.appName}_${this.hookIndex} = require("semverhook")()
3639
const {findShare} = require("umfjs")
3740
38-
async function $getShare(pkg, config) {
39-
return (await findShare(pkg, config, __webpack_share_scopes__)[1].get())()
41+
function $getShare(pkg, config) {
42+
var share = findShare(pkg, config, __webpack_share_scopes__)
43+
if (share) {
44+
return share[1].get().then(res => res())
45+
}
46+
return null
4047
}
4148
async function $getRemote(request = "") {
42-
const requestArray = request.split("/")
43-
const containerName = requestArray[0]
44-
const moduleName = "./" + requestArray.slice(1).join("/")
49+
const containerName = Object.keys(__umf__.$containerRemoteKeyMap).filter(function(containerName) {
50+
const remoteKey = __umf__.$containerRemoteKeyMap[containerName]
51+
return request.indexOf(remoteKey) === 0
52+
})[0]
53+
const moduleName = request.replace(__umf__.$containerRemoteKeyMap[containerName], "./")
4554
if (!window[containerName]) {
4655
throw new Error("container " + containerName + " not found")
4756
}
@@ -51,6 +60,7 @@ class UniversalModuleFederationPlugin {
5160
$semverhook: window.__umfplugin__semverhook_${this.appName}_${this.hookIndex},
5261
$getRemote,
5362
$getShare,
63+
$containerRemoteKeyMap: ${JSON.stringify(this.containerRemoteKeyMap)},
5464
$injectVars: ${stringifyHasFn(this.options.runtimeInjectVars)}
5565
}
5666
})();
@@ -88,8 +98,7 @@ class UniversalModuleFederationPlugin {
8898
const request = (module.request || "")
8999
const url = request.split("@").slice(1).join("@")
90100
const name = request.split("@")[0]
91-
92-
if (!this.matchRemotes(name)) {
101+
if (!this.matchRemotes(this.containerRemoteKeyMap[name])) {
93102
return
94103
}
95104
const sourceMap = compilation.codeGenerationResults.get(module).sources;
@@ -121,6 +130,19 @@ class UniversalModuleFederationPlugin {
121130
return inheritedPluginOptions
122131
}
123132

133+
getContainerRemoteKeyMap(remotes = {}) {
134+
const map = {}
135+
Object.keys(remotes).forEach(key => {
136+
const remoteStr = typeof remotes[key] === "string" ? remotes[key] : remotes[key].external
137+
if (remoteStr.indexOf("@") === -1) {
138+
return
139+
}
140+
const containerName = remoteStr.split("@")[0]
141+
map[containerName] = key
142+
})
143+
return map
144+
}
145+
124146
matchRemotes(name = "") {
125147
function match(patternOrStr, val) {
126148
if (typeof patternOrStr === "string") {

packages/universal-module-federation-plugin/src/index.js

Lines changed: 33 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ class UmdPlugin {
1515
// },
1616
// referenceRemotes: {
1717
// "Button": "app5/Button"
18-
// }
18+
// },
19+
// automatic: ["remotes", "shareScopes"]
1920
},
2021
runtimeUmdExposes({$umdValue, $moduleName}) {
2122
return $umdValue
@@ -28,6 +29,9 @@ class UmdPlugin {
2829
if (!options.dependencies.referenceRemotes) {
2930
options.dependencies.referenceRemotes = {}
3031
}
32+
if (!options.dependencies.automatic) {
33+
options.dependencies.automatic = ["remotes", "shareScopes"]
34+
}
3135
}
3236

3337
apply(compiler) {
@@ -37,24 +41,26 @@ class UmdPlugin {
3741
runtimeInjectVars: {
3842
referenceShares: this.options.dependencies.referenceShares,
3943
referenceRemotes: this.options.dependencies.referenceRemotes,
40-
umdExposes: this.options.runtimeUmdExposes
44+
umdExposes: this.options.runtimeUmdExposes,
45+
automatic: this.options.dependencies.automatic,
4146
},
42-
runtimeInject: ({$semverhook, $getShare, $getRemote, $injectVars}) => {
47+
runtimeInject: ({$semverhook, $getShare, $getRemote, $containerRemoteKeyMap, $injectVars}) => {
4348
const {
4449
referenceRemotes,
4550
referenceShares,
46-
umdExposes
51+
umdExposes,
52+
automatic
4753
} = $injectVars
48-
const {interceptSystemDep} = require("umfjs")
49-
const interceptDeps = Object.keys(referenceShares)
50-
.concat(Object.keys(referenceRemotes))
54+
const {interceptSystemAllDep} = require("umfjs")
55+
const {System, eventBus} = interceptSystemAllDep()
56+
const isInterceptDepFromAllRemotes = automatic.indexOf("remotes") > -1
57+
const isInterceptDepFromAllShares = automatic.indexOf("shareScopes") > -1
5158

52-
$semverhook.on("resolve", (url) => {})
5359
$semverhook.on("import", (url) => {
5460
return {
5561
init(){},
5662
async get(moduleName = "") {
57-
const res = await window.System.import(url)
63+
const res = await System.import(url)
5864
return function() {
5965
return umdExposes({
6066
$umdValue: res,
@@ -65,14 +71,26 @@ class UmdPlugin {
6571
}
6672
})
6773

68-
interceptSystemDep(interceptDeps, async (dep) => {
69-
let depValue = null
74+
eventBus.on("importDep", (dep) => {
75+
if (referenceRemotes[dep]) {
76+
return $getRemote(referenceRemotes[dep] || dep)
77+
}
78+
if (isInterceptDepFromAllRemotes) {
79+
const containerName = Object.keys($containerRemoteKeyMap).filter(function (containerName) {
80+
const remoteKey = $containerRemoteKeyMap[containerName]
81+
return remoteKey === dep
82+
})[0]
83+
return containerName && $getRemote(dep)
84+
}
85+
})
86+
eventBus.on("importDep", (dep) => {
87+
if (/^https?:/.test(dep)) return
7088
if (referenceShares[dep]) {
71-
depValue = await $getShare(referenceShares[dep].import || dep, referenceShares[dep])
72-
} else if (referenceRemotes[dep]) {
73-
depValue = await $getRemote(referenceRemotes[dep])
89+
return $getShare(referenceShares[dep].import || dep, referenceShares[dep])
90+
}
91+
if (isInterceptDepFromAllShares) {
92+
return $getShare(dep, {singleton: true})
7493
}
75-
return depValue
7694
})
7795
}
7896
}).apply(compiler)

0 commit comments

Comments
 (0)