add overridables to ContainerPlugin

This commit is contained in:
Tobias Koppers 2020-02-26 22:32:48 +01:00
parent 95347e17d5
commit 25cd520012
8 changed files with 69 additions and 20 deletions

View File

@ -27,10 +27,6 @@ const ContainerExposedDependency = require("./ContainerExposedDependency");
/** @typedef {import("./ContainerEntryDependency")} ContainerEntryDependency */ /** @typedef {import("./ContainerEntryDependency")} ContainerEntryDependency */
const SOURCE_TYPES = new Set(["javascript"]); const SOURCE_TYPES = new Set(["javascript"]);
const RUNTIME_REQUIREMENTS = new Set([
RuntimeGlobals.definePropertyGetters,
RuntimeGlobals.exports
]);
module.exports = class ContainerEntryModule extends Module { module.exports = class ContainerEntryModule extends Module {
/** /**
@ -117,7 +113,10 @@ module.exports = class ContainerEntryModule extends Module {
*/ */
codeGeneration({ moduleGraph, chunkGraph, runtimeTemplate }) { codeGeneration({ moduleGraph, chunkGraph, runtimeTemplate }) {
const sources = new Map(); const sources = new Map();
const runtimeRequirements = RUNTIME_REQUIREMENTS; const runtimeRequirements = new Set([
RuntimeGlobals.definePropertyGetters,
RuntimeGlobals.exports
]);
const getters = []; const getters = [];
for (const block of this.blocks) { for (const block of this.blocks) {
@ -172,10 +171,15 @@ module.exports = class ContainerEntryModule extends Module {
["module"], ["module"],
`return typeof __MODULE_MAP__[module] ==='function' ? __MODULE_MAP__[module].apply(null) : Promise.reject(new Error('Module ' + module + ' does not exist.'))` `return typeof __MODULE_MAP__[module] ==='function' ? __MODULE_MAP__[module].apply(null) : Promise.reject(new Error('Module ' + module + ' does not exist.'))`
)};`, )};`,
`var __OVERRIDE__ = ${runtimeTemplate.basicFunction(
"override",
`Object.assign(${RuntimeGlobals.overrides}, override);`
)}`,
"", "",
`${RuntimeGlobals.definePropertyGetters}(exports, {`, `${RuntimeGlobals.definePropertyGetters}(exports, {`,
Template.indent([ Template.indent([
`get: ${runtimeTemplate.returningFunction("__GET_MODULE__")}` `get: ${runtimeTemplate.returningFunction("__GET_MODULE__")},`,
`override: ${runtimeTemplate.returningFunction("__OVERRIDE__")}`
]), ]),
"});" "});"
]) ])

View File

@ -10,6 +10,7 @@ const schema = require("../../schemas/plugins/ContainerPlugin.json");
const ContainerEntryDependency = require("./ContainerEntryDependency"); const ContainerEntryDependency = require("./ContainerEntryDependency");
const ContainerEntryModuleFactory = require("./ContainerEntryModuleFactory"); const ContainerEntryModuleFactory = require("./ContainerEntryModuleFactory");
const ContainerExposedDependency = require("./ContainerExposedDependency"); const ContainerExposedDependency = require("./ContainerExposedDependency");
const OverridablesPlugin = require("./OverridablesPlugin");
const parseOptions = require("./parseOptions"); const parseOptions = require("./parseOptions");
/** @typedef {import("../../declarations/plugins/ContainerPlugin").ContainerPluginOptions} ContainerPluginOptions */ /** @typedef {import("../../declarations/plugins/ContainerPlugin").ContainerPluginOptions} ContainerPluginOptions */
@ -25,7 +26,7 @@ module.exports = class ContainerPlugin {
validateOptions(schema, options, { name: PLUGIN_NAME }); validateOptions(schema, options, { name: PLUGIN_NAME });
this.options = { this.options = {
overridables: parseOptions(options.overridables), overridables: options.overridables,
name: options.name, name: options.name,
library: options.library || { library: options.library || {
type: "var", type: "var",
@ -41,10 +42,12 @@ module.exports = class ContainerPlugin {
* @returns {void} * @returns {void}
*/ */
apply(compiler) { apply(compiler) {
const { name, exposes, filename, library } = this.options; const { name, exposes, filename, library, overridables } = this.options;
compiler.options.output.enabledLibraryTypes.push(library.type); compiler.options.output.enabledLibraryTypes.push(library.type);
new OverridablesPlugin(overridables).apply(compiler);
compiler.hooks.make.tapAsync(PLUGIN_NAME, (compilation, callback) => { compiler.hooks.make.tapAsync(PLUGIN_NAME, (compilation, callback) => {
const dep = new ContainerEntryDependency(exposes); const dep = new ContainerEntryDependency(exposes);
dep.loc = { name }; dep.loc = { name };

View File

@ -75,16 +75,14 @@ module.exports = class ContainerReferencePlugin {
} }
); );
compilation.hooks.additionalTreeRuntimeRequirements.tap( compilation.hooks.runtimeRequirementInTree
"OverridablesPlugin", .for(RuntimeGlobals.ensureChunkHandlers)
(chunk, set) => { .tap("OverridablesPlugin", (chunk, set) => {
set.add(RuntimeGlobals.module); set.add(RuntimeGlobals.module);
set.add(RuntimeGlobals.moduleFactories); set.add(RuntimeGlobals.moduleFactories);
set.add(RuntimeGlobals.hasOwnProperty); set.add(RuntimeGlobals.hasOwnProperty);
set.add(RuntimeGlobals.ensureChunkHandlers);
compilation.addRuntimeModule(chunk, new RemoteRuntimeModule()); compilation.addRuntimeModule(chunk, new RemoteRuntimeModule());
} });
);
} }
); );
} }

View File

@ -72,19 +72,17 @@ class OverridablesPlugin {
if (key !== undefined) return new OverridableModule(module, key); if (key !== undefined) return new OverridableModule(module, key);
} }
); );
compilation.hooks.additionalTreeRuntimeRequirements.tap( compilation.hooks.runtimeRequirementInTree
"OverridablesPlugin", .for(RuntimeGlobals.ensureChunkHandlers)
(chunk, set) => { .tap("OverridablesPlugin", (chunk, set) => {
set.add(RuntimeGlobals.module); set.add(RuntimeGlobals.module);
set.add(RuntimeGlobals.moduleFactories); set.add(RuntimeGlobals.moduleFactories);
set.add(RuntimeGlobals.hasOwnProperty); set.add(RuntimeGlobals.hasOwnProperty);
set.add(RuntimeGlobals.ensureChunkHandlers);
compilation.addRuntimeModule( compilation.addRuntimeModule(
chunk, chunk,
new OverridablesRuntimeModule() new OverridablesRuntimeModule()
); );
} });
);
} }
); );
} }

View File

@ -0,0 +1,23 @@
it("should expose modules from the container", async () => {
const container = __non_webpack_require__("./container-file.js");
expect(container).toBeTypeOf("object");
expect(container.override).toBeTypeOf("function");
container.override({
value: () =>
new Promise(resolve => {
setTimeout(() => {
resolve(() => ({
__esModule: true,
default: "overriden-value"
}));
}, 100);
})
});
const testFactory = await container.get("test");
expect(testFactory).toBeTypeOf("function");
expect(testFactory()).toEqual(
nsObj({
default: "test overriden-value"
})
);
});

View File

@ -0,0 +1,3 @@
import value from "./value";
export default `test ${value}`;

View File

@ -0,0 +1 @@
export default "value";

View File

@ -0,0 +1,19 @@
const ContainerPlugin = require("../../../../lib/container/ContainerPlugin");
module.exports = {
plugins: [
new ContainerPlugin({
name: "container",
filename: "container-file.js",
library: {
type: "commonjs-module"
},
exposes: {
test: "./test"
},
overridables: {
value: "./value"
}
})
]
};