webpack/lib/container/ContainerReferencePlugin.js

140 lines
4.0 KiB
JavaScript
Raw Normal View History

2020-02-25 04:18:14 +08:00
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra and Zackary Jackson @ScriptedAlchemy
*/
"use strict";
2020-02-27 04:14:49 +08:00
const validateOptions = require("schema-utils");
const schema = require("../../schemas/plugins/container/ContainerReferencePlugin.json");
2020-02-25 04:18:14 +08:00
const ExternalsPlugin = require("../ExternalsPlugin");
const RuntimeGlobals = require("../RuntimeGlobals");
const RemoteModule = require("./RemoteModule");
2020-02-27 06:27:56 +08:00
const RemoteOverrideDependency = require("./RemoteOverrideDependency");
const RemoteOverridesDependency = require("./RemoteOverridesDependency");
const RemoteOverridesModuleFactory = require("./RemoteOverridesModuleFactory");
2020-02-25 04:18:14 +08:00
const RemoteRuntimeModule = require("./RemoteRuntimeModule");
const RemoteToExternalDependency = require("./RemoteToExternalDependency");
const { parseOptions } = require("./options");
2020-02-25 04:18:14 +08:00
/** @typedef {import("../../declarations/plugins/container/ContainerReferencePlugin").ContainerReferencePluginOptions} ContainerReferencePluginOptions */
/** @typedef {import("../../declarations/plugins/container/ContainerReferencePlugin").RemotesConfig} RemotesConfig */
2020-02-25 04:18:14 +08:00
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("./RemoteOverridesModule").OverrideOptions} OverrideOptions */
2020-02-25 04:18:14 +08:00
class ContainerReferencePlugin {
/**
* @param {ContainerReferencePluginOptions} options options
*/
2020-02-25 04:18:14 +08:00
constructor(options) {
validateOptions(schema, options, { name: "Container Reference Plugin" });
2020-02-25 04:18:14 +08:00
this._remoteType = options.remoteType;
this._remotes = parseOptions(
options.remotes,
item => ({
external: Array.isArray(item) ? item : [item]
}),
item => ({
external: Array.isArray(item.external) ? item.external : [item.external]
})
);
/** @type {[string, OverrideOptions][]} */
this._overrides = parseOptions(
options.overrides,
item => {
if (Array.isArray(item))
throw new Error("Unexpected array of overrides");
return {
import: item
};
},
item => ({
import: item.import
})
);
this._overrides.sort(([a], [b]) => {
if (a < b) return -1;
if (b < a) return 1;
return 0;
});
2020-02-25 04:18:14 +08:00
}
/**
* Apply the plugin
* @param {Compiler} compiler the compiler instance
2020-02-25 04:18:14 +08:00
* @returns {void}
*/
apply(compiler) {
const { _remotes: remotes, _remoteType: remoteType } = this;
2020-02-25 04:18:14 +08:00
/** @type {Record<string, string>} */
2020-02-25 04:18:14 +08:00
const remoteExternals = {};
for (const [key, config] of remotes) {
let i = 0;
for (const external of config.external) {
remoteExternals[
`webpack/container/reference/${key}${i ? `/fallback-${i}` : ""}`
] = external;
i++;
}
2020-02-25 04:18:14 +08:00
}
new ExternalsPlugin(remoteType, remoteExternals).apply(compiler);
2020-02-25 04:18:14 +08:00
compiler.hooks.compilation.tap(
"ContainerReferencePlugin",
(compilation, { normalModuleFactory }) => {
compilation.dependencyFactories.set(
RemoteToExternalDependency,
normalModuleFactory
);
2020-02-27 06:27:56 +08:00
compilation.dependencyFactories.set(
RemoteOverrideDependency,
normalModuleFactory
);
compilation.dependencyFactories.set(
RemoteOverridesDependency,
new RemoteOverridesModuleFactory()
);
2020-02-25 04:18:14 +08:00
normalModuleFactory.hooks.factorize.tap(
"ContainerReferencePlugin",
data => {
if (!data.request.includes("!")) {
for (const [key, config] of remotes) {
2020-02-25 04:18:14 +08:00
if (data.request.startsWith(`${key}/`)) {
return new RemoteModule(
data.request,
this._overrides,
config.external.map(
(_, i) =>
`webpack/container/reference/${key}${
i ? `/fallback-${i}` : ""
}`
),
2020-02-25 04:18:14 +08:00
data.request.slice(key.length + 1)
);
}
}
}
}
);
2020-02-27 05:32:48 +08:00
compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.ensureChunkHandlers)
.tap("OverridablesPlugin", (chunk, set) => {
2020-02-25 04:18:14 +08:00
set.add(RuntimeGlobals.module);
set.add(RuntimeGlobals.moduleFactories);
set.add(RuntimeGlobals.hasOwnProperty);
compilation.addRuntimeModule(chunk, new RemoteRuntimeModule());
2020-02-27 05:32:48 +08:00
});
2020-02-25 04:18:14 +08:00
}
);
}
}
module.exports = ContainerReferencePlugin;