You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
143 lines
4.2 KiB
143 lines
4.2 KiB
4 weeks ago
|
/*
|
||
|
MIT License http://www.opensource.org/licenses/mit-license.php
|
||
|
Author Tobias Koppers @sokra and Zackary Jackson @ScriptedAlchemy
|
||
|
*/
|
||
|
|
||
|
"use strict";
|
||
|
|
||
|
const ExternalsPlugin = require("../ExternalsPlugin");
|
||
|
const RuntimeGlobals = require("../RuntimeGlobals");
|
||
|
const createSchemaValidation = require("../util/create-schema-validation");
|
||
|
const FallbackDependency = require("./FallbackDependency");
|
||
|
const FallbackItemDependency = require("./FallbackItemDependency");
|
||
|
const FallbackModuleFactory = require("./FallbackModuleFactory");
|
||
|
const RemoteModule = require("./RemoteModule");
|
||
|
const RemoteRuntimeModule = require("./RemoteRuntimeModule");
|
||
|
const RemoteToExternalDependency = require("./RemoteToExternalDependency");
|
||
|
const { parseOptions } = require("./options");
|
||
|
|
||
|
/** @typedef {import("../../declarations/plugins/container/ContainerReferencePlugin").ContainerReferencePluginOptions} ContainerReferencePluginOptions */
|
||
|
/** @typedef {import("../../declarations/plugins/container/ContainerReferencePlugin").RemotesConfig} RemotesConfig */
|
||
|
/** @typedef {import("../Compiler")} Compiler */
|
||
|
|
||
|
const validate = createSchemaValidation(
|
||
|
require("../../schemas/plugins/container/ContainerReferencePlugin.check.js"),
|
||
|
() =>
|
||
|
require("../../schemas/plugins/container/ContainerReferencePlugin.json"),
|
||
|
{
|
||
|
name: "Container Reference Plugin",
|
||
|
baseDataPath: "options"
|
||
|
}
|
||
|
);
|
||
|
|
||
|
const slashCode = "/".charCodeAt(0);
|
||
|
|
||
|
class ContainerReferencePlugin {
|
||
|
/**
|
||
|
* @param {ContainerReferencePluginOptions} options options
|
||
|
*/
|
||
|
constructor(options) {
|
||
|
validate(options);
|
||
|
|
||
|
this._remoteType = options.remoteType;
|
||
|
this._remotes = parseOptions(
|
||
|
options.remotes,
|
||
|
item => ({
|
||
|
external: Array.isArray(item) ? item : [item],
|
||
|
shareScope: options.shareScope || "default"
|
||
|
}),
|
||
|
item => ({
|
||
|
external: Array.isArray(item.external)
|
||
|
? item.external
|
||
|
: [item.external],
|
||
|
shareScope: item.shareScope || options.shareScope || "default"
|
||
|
})
|
||
|
);
|
||
|
}
|
||
|
|
||
|
/**
|
||
|
* Apply the plugin
|
||
|
* @param {Compiler} compiler the compiler instance
|
||
|
* @returns {void}
|
||
|
*/
|
||
|
apply(compiler) {
|
||
|
const { _remotes: remotes, _remoteType: remoteType } = this;
|
||
|
|
||
|
/** @type {Record<string, string>} */
|
||
|
const remoteExternals = {};
|
||
|
for (const [key, config] of remotes) {
|
||
|
let i = 0;
|
||
|
for (const external of config.external) {
|
||
|
if (external.startsWith("internal ")) continue;
|
||
|
remoteExternals[
|
||
|
`webpack/container/reference/${key}${i ? `/fallback-${i}` : ""}`
|
||
|
] = external;
|
||
|
i++;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
new ExternalsPlugin(remoteType, remoteExternals).apply(compiler);
|
||
|
|
||
|
compiler.hooks.compilation.tap(
|
||
|
"ContainerReferencePlugin",
|
||
|
(compilation, { normalModuleFactory }) => {
|
||
|
compilation.dependencyFactories.set(
|
||
|
RemoteToExternalDependency,
|
||
|
normalModuleFactory
|
||
|
);
|
||
|
|
||
|
compilation.dependencyFactories.set(
|
||
|
FallbackItemDependency,
|
||
|
normalModuleFactory
|
||
|
);
|
||
|
|
||
|
compilation.dependencyFactories.set(
|
||
|
FallbackDependency,
|
||
|
new FallbackModuleFactory()
|
||
|
);
|
||
|
|
||
|
normalModuleFactory.hooks.factorize.tap(
|
||
|
"ContainerReferencePlugin",
|
||
|
data => {
|
||
|
if (!data.request.includes("!")) {
|
||
|
for (const [key, config] of remotes) {
|
||
|
if (
|
||
|
data.request.startsWith(`${key}`) &&
|
||
|
(data.request.length === key.length ||
|
||
|
data.request.charCodeAt(key.length) === slashCode)
|
||
|
) {
|
||
|
return new RemoteModule(
|
||
|
data.request,
|
||
|
config.external.map((external, i) =>
|
||
|
external.startsWith("internal ")
|
||
|
? external.slice(9)
|
||
|
: `webpack/container/reference/${key}${
|
||
|
i ? `/fallback-${i}` : ""
|
||
|
}`
|
||
|
),
|
||
|
`.${data.request.slice(key.length)}`,
|
||
|
config.shareScope
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
}
|
||
|
);
|
||
|
|
||
|
compilation.hooks.runtimeRequirementInTree
|
||
|
.for(RuntimeGlobals.ensureChunkHandlers)
|
||
|
.tap("ContainerReferencePlugin", (chunk, set) => {
|
||
|
set.add(RuntimeGlobals.module);
|
||
|
set.add(RuntimeGlobals.moduleFactoriesAddOnly);
|
||
|
set.add(RuntimeGlobals.hasOwnProperty);
|
||
|
set.add(RuntimeGlobals.initializeSharing);
|
||
|
set.add(RuntimeGlobals.shareScopeMap);
|
||
|
compilation.addRuntimeModule(chunk, new RemoteRuntimeModule());
|
||
|
});
|
||
|
}
|
||
|
);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
module.exports = ContainerReferencePlugin;
|