Merge pull request #10646 from ScriptedAlchemy/patch-1

fix: module federation plugin library should be optional
This commit is contained in:
Tobias Koppers 2020-04-14 18:49:40 +02:00 committed by GitHub
commit 46db02ca2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 162 additions and 17 deletions

View File

@ -43,7 +43,7 @@ module.exports = class ContainerReferencePlugin {
remoteExternals[`container-reference/${key}`] = value;
}
new ExternalsPlugin(remoteType, remoteExternals).apply(compiler);
new ExternalsPlugin(remoteType || "var", remoteExternals).apply(compiler);
compiler.hooks.compilation.tap(
"ContainerReferencePlugin",

View File

@ -22,18 +22,31 @@ class ModuleFederationPlugin {
*/
apply(compiler) {
const { options } = this;
new ContainerPlugin({
name: options.name,
library: options.library,
filename: options.filename,
exposes: options.exposes,
overridables: options.shared
}).apply(compiler);
new ContainerReferencePlugin({
remoteType: options.remoteType || options.library.type,
remotes: options.remotes,
overrides: options.shared
}).apply(compiler);
if (
options.library &&
!compiler.options.output.enabledLibraryTypes.includes(
options.library.type
)
) {
compiler.options.output.enabledLibraryTypes.push(options.library.type);
}
compiler.hooks.afterPlugins.tap("ModuleFederationPlugin", () => {
new ContainerPlugin({
name: options.name,
library: options.library || compiler.options.output.library,
filename: options.filename,
exposes: options.exposes,
overridables: options.shared
}).apply(compiler);
new ContainerReferencePlugin({
remoteType:
options.remoteType ||
(options.library && options.library.type) ||
compiler.options.externalsType,
remotes: options.remotes,
overrides: options.shared
}).apply(compiler);
});
}
}

View File

@ -0,0 +1 @@
module.exports = "dep";

View File

@ -0,0 +1,3 @@
it("should import the correct modules", () => {
return import("./module").then(({ test }) => test());
});

View File

@ -0,0 +1,19 @@
import abc from "abc/system-hello-world";
import def, { module } from "def/system-hello-world";
import def2, { module as module2 } from "def/system-hello/other/world";
import other from "other/other";
import otherSelf from "other/self";
import self from "self/self";
import selfOther from "self/other";
export function test() {
expect(abc).toBe("abc system-hello-world");
expect(def).toBe("def");
expect(def2).toBe("def");
expect(module).toBe("system-hello-world");
expect(module2).toBe("system-hello/other/world");
expect(other).toBe("other and dep");
expect(otherSelf).toBe("self and dep");
expect(self).toBe("self and dep");
expect(selfOther).toBe("other and dep");
}

View File

@ -0,0 +1,3 @@
import andBack from "other/dep";
export default `other and ${andBack}`;

View File

@ -0,0 +1,3 @@
import andBack from "self/dep";
export default `self and ${andBack}`;

View File

@ -0,0 +1,36 @@
const System = require("../../../helpers/fakeSystem");
module.exports = {
beforeExecute: () => {
System.init();
},
moduleScope(scope) {
System.setRequire(scope.require);
scope.System = System;
System.set("ABC", {
get(module) {
return new Promise(resolve => {
setTimeout(() => {
resolve(() => "abc " + module);
}, 100);
});
}
});
System.set("DEF", {
get(module) {
return new Promise(resolve => {
setTimeout(() => {
resolve(() => ({
__esModule: true,
module,
default: "def"
}));
}, 100);
});
}
});
},
afterExecute: () => {
System.execute("(anonym)");
}
};

View File

@ -0,0 +1,35 @@
const ModuleFederationPlugin = require("../../../../lib/container/ModuleFederationPlugin");
function createConfig() {
return {
output: {
libraryTarget: "system"
},
plugins: [
new ModuleFederationPlugin({
name: "container",
filename: "container.js",
exposes: ["./other", "./self", "./dep"],
remotes: {
abc: "ABC",
def: "DEF",
self: "./container.js",
other: "./container2.js"
}
}),
new ModuleFederationPlugin({
name: "container2",
filename: "container2.js",
exposes: ["./other", "./self", "./dep"],
remotes: {
abc: "ABC",
def: "DEF",
self: "./container2.js",
other: "./container.js"
}
})
]
};
}
module.exports = createConfig();

View File

@ -6,7 +6,7 @@ const System = {
if (typeof name !== "string") {
fn = deps;
deps = name;
name = "(anonym)";
name = System._nextName;
}
if (!Array.isArray(deps)) {
fn = deps;
@ -17,6 +17,16 @@ const System = {
throw new Error(`Module ${name} calls dynamicExport too late`);
}
entry.exports = result;
for (const mod of Object.keys(System.registry)) {
const m = System.registry[mod];
if (!m.deps) continue;
for (let i = 0; i < m.deps.length; i++) {
const dep = m.deps[i];
if (dep !== name) continue;
const setters = m.mod.setters[i];
setters(result);
}
}
};
const systemContext = {
meta: {
@ -52,7 +62,19 @@ const System = {
};
System.registry[name] = entry;
},
set: (name, exports) => {
System.registry[name] = {
name,
executed: true,
exports
};
},
registry: undefined,
_require: undefined,
_nextName: "(anonym)",
setRequire: req => {
System._require = req;
},
init: modules => {
System.registry = {};
if (modules) {
@ -71,15 +93,25 @@ const System = {
return System.ensureExecuted(name);
},
ensureExecuted: name => {
const m = System.registry[name];
if (!m) throw new Error(`Module ${name} not registered`);
let m = System.registry[name];
if (!m && System._require) {
const oldName = System._nextName;
System._nextName = name;
System._require(name);
System._nextName = oldName;
m = System.registry[name];
}
if (!m) {
throw new Error(`Module ${name} not registered`);
}
if (!m.executed) {
m.executed = true;
for (let i = 0; i < m.deps.length; i++) {
const dep = m.deps[i];
const setters = m.mod.setters[i];
System.ensureExecuted(dep);
setters(System.registry[dep].exports);
const { exports } = System.registry[dep];
if (exports !== undefined) setters(exports);
}
m.mod.execute();
}