first commit

This commit is contained in:
monjack
2025-06-20 18:01:48 +08:00
commit 6daa6d65c1
24611 changed files with 2512443 additions and 0 deletions

View File

@ -0,0 +1,48 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra, Zackary Jackson @ScriptedAlchemy, Marais Rossouw @maraisr
*/
"use strict";
const Dependency = require("../Dependency");
const makeSerializable = require("../util/makeSerializable");
/** @typedef {import("./ContainerEntryModule").ExposeOptions} ExposeOptions */
/** @typedef {import("./ContainerEntryModule").ExposesList} ExposesList */
class ContainerEntryDependency extends Dependency {
/**
* @param {string} name entry name
* @param {ExposesList} exposes list of exposed modules
* @param {string} shareScope name of the share scope
*/
constructor(name, exposes, shareScope) {
super();
this.name = name;
this.exposes = exposes;
this.shareScope = shareScope;
}
/**
* @returns {string | null} an identifier to merge equal requests
*/
getResourceIdentifier() {
return `container-entry-${this.name}`;
}
get type() {
return "container entry";
}
get category() {
return "esm";
}
}
makeSerializable(
ContainerEntryDependency,
"webpack/lib/container/ContainerEntryDependency"
);
module.exports = ContainerEntryDependency;

View File

@ -0,0 +1,297 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra, Zackary Jackson @ScriptedAlchemy, Marais Rossouw @maraisr
*/
"use strict";
const { OriginalSource, RawSource } = require("webpack-sources");
const AsyncDependenciesBlock = require("../AsyncDependenciesBlock");
const Module = require("../Module");
const { JS_TYPES } = require("../ModuleSourceTypesConstants");
const { JAVASCRIPT_MODULE_TYPE_DYNAMIC } = require("../ModuleTypeConstants");
const RuntimeGlobals = require("../RuntimeGlobals");
const Template = require("../Template");
const StaticExportsDependency = require("../dependencies/StaticExportsDependency");
const makeSerializable = require("../util/makeSerializable");
const ContainerExposedDependency = require("./ContainerExposedDependency");
/** @typedef {import("../../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */
/** @typedef {import("../ChunkGraph")} ChunkGraph */
/** @typedef {import("../ChunkGroup")} ChunkGroup */
/** @typedef {import("../Compilation")} Compilation */
/** @typedef {import("../Module").BuildCallback} BuildCallback */
/** @typedef {import("../Module").CodeGenerationContext} CodeGenerationContext */
/** @typedef {import("../Module").CodeGenerationResult} CodeGenerationResult */
/** @typedef {import("../Module").LibIdentOptions} LibIdentOptions */
/** @typedef {import("../Module").NeedBuildCallback} NeedBuildCallback */
/** @typedef {import("../Module").NeedBuildContext} NeedBuildContext */
/** @typedef {import("../Module").SourceTypes} SourceTypes */
/** @typedef {import("../RequestShortener")} RequestShortener */
/** @typedef {import("../ResolverFactory").ResolverWithOptions} ResolverWithOptions */
/** @typedef {import("../WebpackError")} WebpackError */
/** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
/** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */
/** @typedef {import("../util/Hash")} Hash */
/** @typedef {import("../util/fs").InputFileSystem} InputFileSystem */
/** @typedef {import("./ContainerEntryDependency")} ContainerEntryDependency */
/**
* @typedef {object} ExposeOptions
* @property {string[]} import requests to exposed modules (last one is exported)
* @property {string} name custom chunk name for the exposed module
*/
/** @typedef {[string, ExposeOptions][]} ExposesList */
class ContainerEntryModule extends Module {
/**
* @param {string} name container entry name
* @param {ExposesList} exposes list of exposed modules
* @param {string} shareScope name of the share scope
*/
constructor(name, exposes, shareScope) {
super(JAVASCRIPT_MODULE_TYPE_DYNAMIC, null);
this._name = name;
this._exposes = exposes;
this._shareScope = shareScope;
}
/**
* @returns {SourceTypes} types available (do not mutate)
*/
getSourceTypes() {
return JS_TYPES;
}
/**
* @returns {string} a unique identifier of the module
*/
identifier() {
return `container entry (${this._shareScope}) ${JSON.stringify(
this._exposes
)}`;
}
/**
* @param {RequestShortener} requestShortener the request shortener
* @returns {string} a user readable identifier of the module
*/
readableIdentifier(requestShortener) {
return "container entry";
}
/**
* @param {LibIdentOptions} options options
* @returns {string | null} an identifier for library inclusion
*/
libIdent(options) {
return `${this.layer ? `(${this.layer})/` : ""}webpack/container/entry/${
this._name
}`;
}
/**
* @param {NeedBuildContext} context context info
* @param {NeedBuildCallback} callback callback function, returns true, if the module needs a rebuild
* @returns {void}
*/
needBuild(context, callback) {
return callback(null, !this.buildMeta);
}
/**
* @param {WebpackOptions} options webpack options
* @param {Compilation} compilation the compilation
* @param {ResolverWithOptions} resolver the resolver
* @param {InputFileSystem} fs the file system
* @param {BuildCallback} callback callback function
* @returns {void}
*/
build(options, compilation, resolver, fs, callback) {
this.buildMeta = {};
this.buildInfo = {
strict: true,
topLevelDeclarations: new Set(["moduleMap", "get", "init"])
};
this.buildMeta.exportsType = "namespace";
this.clearDependenciesAndBlocks();
for (const [name, options] of this._exposes) {
const block = new AsyncDependenciesBlock(
{
name: options.name
},
{ name },
options.import[options.import.length - 1]
);
let idx = 0;
for (const request of options.import) {
const dep = new ContainerExposedDependency(name, request);
dep.loc = {
name,
index: idx++
};
block.addDependency(dep);
}
this.addBlock(block);
}
this.addDependency(new StaticExportsDependency(["get", "init"], false));
callback();
}
/**
* @param {CodeGenerationContext} context context for code generation
* @returns {CodeGenerationResult} result
*/
codeGeneration({ moduleGraph, chunkGraph, runtimeTemplate }) {
const sources = new Map();
const runtimeRequirements = new Set([
RuntimeGlobals.definePropertyGetters,
RuntimeGlobals.hasOwnProperty,
RuntimeGlobals.exports
]);
const getters = [];
for (const block of this.blocks) {
const { dependencies } = block;
const modules = dependencies.map(dependency => {
const dep = /** @type {ContainerExposedDependency} */ (dependency);
return {
name: dep.exposedName,
module: moduleGraph.getModule(dep),
request: dep.userRequest
};
});
let str;
if (modules.some(m => !m.module)) {
str = runtimeTemplate.throwMissingModuleErrorBlock({
request: modules.map(m => m.request).join(", ")
});
} else {
str = `return ${runtimeTemplate.blockPromise({
block,
message: "",
chunkGraph,
runtimeRequirements
})}.then(${runtimeTemplate.returningFunction(
runtimeTemplate.returningFunction(
`(${modules
.map(({ module, request }) =>
runtimeTemplate.moduleRaw({
module,
chunkGraph,
request,
weak: false,
runtimeRequirements
})
)
.join(", ")})`
)
)});`;
}
getters.push(
`${JSON.stringify(modules[0].name)}: ${runtimeTemplate.basicFunction(
"",
str
)}`
);
}
const source = Template.asString([
"var moduleMap = {",
Template.indent(getters.join(",\n")),
"};",
`var get = ${runtimeTemplate.basicFunction("module, getScope", [
`${RuntimeGlobals.currentRemoteGetScope} = getScope;`,
// reusing the getScope variable to avoid creating a new var (and module is also used later)
"getScope = (",
Template.indent([
`${RuntimeGlobals.hasOwnProperty}(moduleMap, module)`,
Template.indent([
"? moduleMap[module]()",
`: Promise.resolve().then(${runtimeTemplate.basicFunction(
"",
"throw new Error('Module \"' + module + '\" does not exist in container.');"
)})`
])
]),
");",
`${RuntimeGlobals.currentRemoteGetScope} = undefined;`,
"return getScope;"
])};`,
`var init = ${runtimeTemplate.basicFunction("shareScope, initScope", [
`if (!${RuntimeGlobals.shareScopeMap}) return;`,
`var name = ${JSON.stringify(this._shareScope)}`,
`var oldScope = ${RuntimeGlobals.shareScopeMap}[name];`,
'if(oldScope && oldScope !== shareScope) throw new Error("Container initialization failed as it has already been initialized with a different share scope");',
`${RuntimeGlobals.shareScopeMap}[name] = shareScope;`,
`return ${RuntimeGlobals.initializeSharing}(name, initScope);`
])};`,
"",
"// This exports getters to disallow modifications",
`${RuntimeGlobals.definePropertyGetters}(exports, {`,
Template.indent([
`get: ${runtimeTemplate.returningFunction("get")},`,
`init: ${runtimeTemplate.returningFunction("init")}`
]),
"});"
]);
sources.set(
"javascript",
this.useSourceMap || this.useSimpleSourceMap
? new OriginalSource(source, "webpack/container-entry")
: new RawSource(source)
);
return {
sources,
runtimeRequirements
};
}
/**
* @param {string=} type the source type for which the size should be estimated
* @returns {number} the estimated size of the module (must be non-zero)
*/
size(type) {
return 42;
}
/**
* @param {ObjectSerializerContext} context context
*/
serialize(context) {
const { write } = context;
write(this._name);
write(this._exposes);
write(this._shareScope);
super.serialize(context);
}
/**
* @param {ObjectDeserializerContext} context context
* @returns {ContainerEntryModule} deserialized container entry module
*/
static deserialize(context) {
const { read } = context;
const obj = new ContainerEntryModule(read(), read(), read());
obj.deserialize(context);
return obj;
}
}
makeSerializable(
ContainerEntryModule,
"webpack/lib/container/ContainerEntryModule"
);
module.exports = ContainerEntryModule;

View File

@ -0,0 +1,27 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra, Zackary Jackson @ScriptedAlchemy, Marais Rossouw @maraisr
*/
"use strict";
const ModuleFactory = require("../ModuleFactory");
const ContainerEntryModule = require("./ContainerEntryModule");
/** @typedef {import("../ModuleFactory").ModuleFactoryCallback} ModuleFactoryCallback */
/** @typedef {import("../ModuleFactory").ModuleFactoryCreateData} ModuleFactoryCreateData */
/** @typedef {import("./ContainerEntryDependency")} ContainerEntryDependency */
module.exports = class ContainerEntryModuleFactory extends ModuleFactory {
/**
* @param {ModuleFactoryCreateData} data data object
* @param {ModuleFactoryCallback} callback callback
* @returns {void}
*/
create({ dependencies: [dependency] }, callback) {
const dep = /** @type {ContainerEntryDependency} */ (dependency);
callback(null, {
module: new ContainerEntryModule(dep.name, dep.exposes, dep.shareScope)
});
}
};

View File

@ -0,0 +1,61 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra, Zackary Jackson @ScriptedAlchemy, Marais Rossouw @maraisr
*/
"use strict";
const ModuleDependency = require("../dependencies/ModuleDependency");
const makeSerializable = require("../util/makeSerializable");
/** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
/** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */
class ContainerExposedDependency extends ModuleDependency {
/**
* @param {string} exposedName public name
* @param {string} request request to module
*/
constructor(exposedName, request) {
super(request);
this.exposedName = exposedName;
}
get type() {
return "container exposed";
}
get category() {
return "esm";
}
/**
* @returns {string | null} an identifier to merge equal requests
*/
getResourceIdentifier() {
return `exposed dependency ${this.exposedName}=${this.request}`;
}
/**
* @param {ObjectSerializerContext} context context
*/
serialize(context) {
context.write(this.exposedName);
super.serialize(context);
}
/**
* @param {ObjectDeserializerContext} context context
*/
deserialize(context) {
this.exposedName = context.read();
super.deserialize(context);
}
}
makeSerializable(
ContainerExposedDependency,
"webpack/lib/container/ContainerExposedDependency"
);
module.exports = ContainerExposedDependency;

View File

@ -0,0 +1,119 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra, Zackary Jackson @ScriptedAlchemy, Marais Rossouw @maraisr
*/
"use strict";
const createSchemaValidation = require("../util/create-schema-validation");
const memoize = require("../util/memoize");
const ContainerEntryDependency = require("./ContainerEntryDependency");
const ContainerEntryModuleFactory = require("./ContainerEntryModuleFactory");
const ContainerExposedDependency = require("./ContainerExposedDependency");
const { parseOptions } = require("./options");
/** @typedef {import("../../declarations/plugins/container/ContainerPlugin").ContainerPluginOptions} ContainerPluginOptions */
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("./ContainerEntryModule").ExposeOptions} ExposeOptions */
/** @typedef {import("./ContainerEntryModule").ExposesList} ExposesList */
const getModuleFederationPlugin = memoize(() =>
require("./ModuleFederationPlugin")
);
const validate = createSchemaValidation(
require("../../schemas/plugins/container/ContainerPlugin.check.js"),
() => require("../../schemas/plugins/container/ContainerPlugin.json"),
{
name: "Container Plugin",
baseDataPath: "options"
}
);
const PLUGIN_NAME = "ContainerPlugin";
class ContainerPlugin {
/**
* @param {ContainerPluginOptions} options options
*/
constructor(options) {
validate(options);
this._options = {
name: options.name,
shareScope: options.shareScope || "default",
library: options.library || {
type: "var",
name: options.name
},
runtime: options.runtime,
filename: options.filename || undefined,
exposes: /** @type {ExposesList} */ (
parseOptions(
options.exposes,
item => ({
import: Array.isArray(item) ? item : [item],
name: undefined
}),
item => ({
import: Array.isArray(item.import) ? item.import : [item.import],
name: item.name || undefined
})
)
)
};
}
/**
* Apply the plugin
* @param {Compiler} compiler the compiler instance
* @returns {void}
*/
apply(compiler) {
const { name, exposes, shareScope, filename, library, runtime } =
this._options;
if (!compiler.options.output.enabledLibraryTypes.includes(library.type)) {
compiler.options.output.enabledLibraryTypes.push(library.type);
}
compiler.hooks.make.tapAsync(PLUGIN_NAME, (compilation, callback) => {
const hooks =
getModuleFederationPlugin().getCompilationHooks(compilation);
const dep = new ContainerEntryDependency(name, exposes, shareScope);
dep.loc = { name };
compilation.addEntry(
/** @type {string} */ (compilation.options.context),
dep,
{
name,
filename,
runtime,
library
},
error => {
if (error) return callback(error);
hooks.addContainerEntryDependency.call(dep);
callback();
}
);
});
compiler.hooks.thisCompilation.tap(
PLUGIN_NAME,
(compilation, { normalModuleFactory }) => {
compilation.dependencyFactories.set(
ContainerEntryDependency,
new ContainerEntryModuleFactory()
);
compilation.dependencyFactories.set(
ContainerExposedDependency,
normalModuleFactory
);
}
);
}
}
module.exports = ContainerPlugin;

View File

@ -0,0 +1,140 @@
/*
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);
const PLUGIN_NAME = "ContainerReferencePlugin";
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(
PLUGIN_NAME,
(compilation, { normalModuleFactory }) => {
compilation.dependencyFactories.set(
RemoteToExternalDependency,
normalModuleFactory
);
compilation.dependencyFactories.set(
FallbackItemDependency,
normalModuleFactory
);
compilation.dependencyFactories.set(
FallbackDependency,
new FallbackModuleFactory()
);
normalModuleFactory.hooks.factorize.tap(PLUGIN_NAME, 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(PLUGIN_NAME, (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;

View File

@ -0,0 +1,64 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const Dependency = require("../Dependency");
const makeSerializable = require("../util/makeSerializable");
/** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
/** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */
class FallbackDependency extends Dependency {
/**
* @param {string[]} requests requests
*/
constructor(requests) {
super();
this.requests = requests;
}
/**
* @returns {string | null} an identifier to merge equal requests
*/
getResourceIdentifier() {
return `fallback ${this.requests.join(" ")}`;
}
get type() {
return "fallback";
}
get category() {
return "esm";
}
/**
* @param {ObjectSerializerContext} context context
*/
serialize(context) {
const { write } = context;
write(this.requests);
super.serialize(context);
}
/**
* @param {ObjectDeserializerContext} context context
* @returns {FallbackDependency} deserialize fallback dependency
*/
static deserialize(context) {
const { read } = context;
const obj = new FallbackDependency(read());
obj.deserialize(context);
return obj;
}
}
makeSerializable(
FallbackDependency,
"webpack/lib/container/FallbackDependency"
);
module.exports = FallbackDependency;

View File

@ -0,0 +1,33 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const ModuleDependency = require("../dependencies/ModuleDependency");
const makeSerializable = require("../util/makeSerializable");
class FallbackItemDependency extends ModuleDependency {
/**
* @param {string} request request
*/
constructor(request) {
super(request);
}
get type() {
return "fallback item";
}
get category() {
return "esm";
}
}
makeSerializable(
FallbackItemDependency,
"webpack/lib/container/FallbackItemDependency"
);
module.exports = FallbackItemDependency;

View File

@ -0,0 +1,186 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra and Zackary Jackson @ScriptedAlchemy
*/
"use strict";
const { RawSource } = require("webpack-sources");
const Module = require("../Module");
const { JS_TYPES } = require("../ModuleSourceTypesConstants");
const { WEBPACK_MODULE_TYPE_FALLBACK } = require("../ModuleTypeConstants");
const RuntimeGlobals = require("../RuntimeGlobals");
const Template = require("../Template");
const makeSerializable = require("../util/makeSerializable");
const FallbackItemDependency = require("./FallbackItemDependency");
/** @typedef {import("../../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */
/** @typedef {import("../Chunk")} Chunk */
/** @typedef {import("../ChunkGraph")} ChunkGraph */
/** @typedef {import("../ChunkGroup")} ChunkGroup */
/** @typedef {import("../Compilation")} Compilation */
/** @typedef {import("../Module").BuildCallback} BuildCallback */
/** @typedef {import("../Module").CodeGenerationContext} CodeGenerationContext */
/** @typedef {import("../Module").CodeGenerationResult} CodeGenerationResult */
/** @typedef {import("../Module").LibIdentOptions} LibIdentOptions */
/** @typedef {import("../Module").NeedBuildCallback} NeedBuildCallback */
/** @typedef {import("../Module").NeedBuildContext} NeedBuildContext */
/** @typedef {import("../Module").SourceTypes} SourceTypes */
/** @typedef {import("../RequestShortener")} RequestShortener */
/** @typedef {import("../ResolverFactory").ResolverWithOptions} ResolverWithOptions */
/** @typedef {import("../WebpackError")} WebpackError */
/** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
/** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */
/** @typedef {import("../util/Hash")} Hash */
/** @typedef {import("../util/fs").InputFileSystem} InputFileSystem */
const RUNTIME_REQUIREMENTS = new Set([RuntimeGlobals.module]);
class FallbackModule extends Module {
/**
* @param {string[]} requests list of requests to choose one
*/
constructor(requests) {
super(WEBPACK_MODULE_TYPE_FALLBACK);
this.requests = requests;
this._identifier = `fallback ${this.requests.join(" ")}`;
}
/**
* @returns {string} a unique identifier of the module
*/
identifier() {
return this._identifier;
}
/**
* @param {RequestShortener} requestShortener the request shortener
* @returns {string} a user readable identifier of the module
*/
readableIdentifier(requestShortener) {
return this._identifier;
}
/**
* @param {LibIdentOptions} options options
* @returns {string | null} an identifier for library inclusion
*/
libIdent(options) {
return `${this.layer ? `(${this.layer})/` : ""}webpack/container/fallback/${
this.requests[0]
}/and ${this.requests.length - 1} more`;
}
/**
* @param {Chunk} chunk the chunk which condition should be checked
* @param {Compilation} compilation the compilation
* @returns {boolean} true, if the chunk is ok for the module
*/
chunkCondition(chunk, { chunkGraph }) {
return chunkGraph.getNumberOfEntryModules(chunk) > 0;
}
/**
* @param {NeedBuildContext} context context info
* @param {NeedBuildCallback} callback callback function, returns true, if the module needs a rebuild
* @returns {void}
*/
needBuild(context, callback) {
callback(null, !this.buildInfo);
}
/**
* @param {WebpackOptions} options webpack options
* @param {Compilation} compilation the compilation
* @param {ResolverWithOptions} resolver the resolver
* @param {InputFileSystem} fs the file system
* @param {BuildCallback} callback callback function
* @returns {void}
*/
build(options, compilation, resolver, fs, callback) {
this.buildMeta = {};
this.buildInfo = {
strict: true
};
this.clearDependenciesAndBlocks();
for (const request of this.requests)
this.addDependency(new FallbackItemDependency(request));
callback();
}
/**
* @param {string=} type the source type for which the size should be estimated
* @returns {number} the estimated size of the module (must be non-zero)
*/
size(type) {
return this.requests.length * 5 + 42;
}
/**
* @returns {SourceTypes} types available (do not mutate)
*/
getSourceTypes() {
return JS_TYPES;
}
/**
* @param {CodeGenerationContext} context context for code generation
* @returns {CodeGenerationResult} result
*/
codeGeneration({ runtimeTemplate, moduleGraph, chunkGraph }) {
const ids = this.dependencies.map(dep =>
chunkGraph.getModuleId(/** @type {Module} */ (moduleGraph.getModule(dep)))
);
const code = Template.asString([
`var ids = ${JSON.stringify(ids)};`,
"var error, result, i = 0;",
`var loop = ${runtimeTemplate.basicFunction("next", [
"while(i < ids.length) {",
Template.indent([
`try { next = ${RuntimeGlobals.require}(ids[i++]); } catch(e) { return handleError(e); }`,
"if(next) return next.then ? next.then(handleResult, handleError) : handleResult(next);"
]),
"}",
"if(error) throw error;"
])}`,
`var handleResult = ${runtimeTemplate.basicFunction("result", [
"if(result) return result;",
"return loop();"
])};`,
`var handleError = ${runtimeTemplate.basicFunction("e", [
"error = e;",
"return loop();"
])};`,
"module.exports = loop();"
]);
const sources = new Map();
sources.set("javascript", new RawSource(code));
return { sources, runtimeRequirements: RUNTIME_REQUIREMENTS };
}
/**
* @param {ObjectSerializerContext} context context
*/
serialize(context) {
const { write } = context;
write(this.requests);
super.serialize(context);
}
/**
* @param {ObjectDeserializerContext} context context
* @returns {FallbackModule} deserialized fallback module
*/
static deserialize(context) {
const { read } = context;
const obj = new FallbackModule(read());
obj.deserialize(context);
return obj;
}
}
makeSerializable(FallbackModule, "webpack/lib/container/FallbackModule");
module.exports = FallbackModule;

View File

@ -0,0 +1,27 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra, Zackary Jackson @ScriptedAlchemy, Marais Rossouw @maraisr
*/
"use strict";
const ModuleFactory = require("../ModuleFactory");
const FallbackModule = require("./FallbackModule");
/** @typedef {import("../ModuleFactory").ModuleFactoryCallback} ModuleFactoryCallback */
/** @typedef {import("../ModuleFactory").ModuleFactoryCreateData} ModuleFactoryCreateData */
/** @typedef {import("./FallbackDependency")} FallbackDependency */
module.exports = class FallbackModuleFactory extends ModuleFactory {
/**
* @param {ModuleFactoryCreateData} data data object
* @param {ModuleFactoryCallback} callback callback
* @returns {void}
*/
create({ dependencies: [dependency] }, callback) {
const dep = /** @type {FallbackDependency} */ (dependency);
callback(null, {
module: new FallbackModule(dep.requests)
});
}
};

View File

@ -0,0 +1,250 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Zackary Jackson @ScriptedAlchemy
*/
"use strict";
const AsyncDependenciesBlock = require("../AsyncDependenciesBlock");
const ExternalModule = require("../ExternalModule");
const { STAGE_ADVANCED } = require("../OptimizationStages");
const memoize = require("../util/memoize");
const { forEachRuntime } = require("../util/runtime");
/** @typedef {import("../Compilation")} Compilation */
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("../Dependency")} Dependency */
/** @typedef {import("../Module")} Module */
const getModuleFederationPlugin = memoize(() =>
require("./ModuleFederationPlugin")
);
const PLUGIN_NAME = "HoistContainerReferences";
/**
* This class is used to hoist container references in the code.
*/
class HoistContainerReferences {
/**
* Apply the plugin to the compiler.
* @param {Compiler} compiler The webpack compiler instance.
*/
apply(compiler) {
compiler.hooks.thisCompilation.tap(PLUGIN_NAME, compilation => {
const hooks =
getModuleFederationPlugin().getCompilationHooks(compilation);
const depsToTrace = new Set();
const entryExternalsToHoist = new Set();
hooks.addContainerEntryDependency.tap(PLUGIN_NAME, dep => {
depsToTrace.add(dep);
});
hooks.addFederationRuntimeDependency.tap(PLUGIN_NAME, dep => {
depsToTrace.add(dep);
});
compilation.hooks.addEntry.tap(PLUGIN_NAME, entryDep => {
if (entryDep.type === "entry") {
entryExternalsToHoist.add(entryDep);
}
});
// Hook into the optimizeChunks phase
compilation.hooks.optimizeChunks.tap(
{
name: PLUGIN_NAME,
// advanced stage is where SplitChunksPlugin runs.
stage: STAGE_ADVANCED + 1
},
chunks => {
this.hoistModulesInChunks(
compilation,
depsToTrace,
entryExternalsToHoist
);
}
);
});
}
/**
* Hoist modules in chunks.
* @param {Compilation} compilation The webpack compilation instance.
* @param {Set<Dependency>} depsToTrace Set of container entry dependencies.
* @param {Set<Dependency>} entryExternalsToHoist Set of container entry dependencies to hoist.
*/
hoistModulesInChunks(compilation, depsToTrace, entryExternalsToHoist) {
const { chunkGraph, moduleGraph } = compilation;
// loop over entry points
for (const dep of entryExternalsToHoist) {
const entryModule = moduleGraph.getModule(dep);
if (!entryModule) continue;
// get all the external module types and hoist them to the runtime chunk, this will get RemoteModule externals
const allReferencedModules = getAllReferencedModules(
compilation,
entryModule,
"external",
false
);
const containerRuntimes = chunkGraph.getModuleRuntimes(entryModule);
const runtimes = new Set();
for (const runtimeSpec of containerRuntimes) {
forEachRuntime(runtimeSpec, runtimeKey => {
if (runtimeKey) {
runtimes.add(runtimeKey);
}
});
}
for (const runtime of runtimes) {
const runtimeChunk = compilation.namedChunks.get(runtime);
if (!runtimeChunk) continue;
for (const module of allReferencedModules) {
if (!chunkGraph.isModuleInChunk(module, runtimeChunk)) {
chunkGraph.connectChunkAndModule(runtimeChunk, module);
}
}
}
this.cleanUpChunks(compilation, allReferencedModules);
}
// handle container entry specifically
for (const dep of depsToTrace) {
const containerEntryModule = moduleGraph.getModule(dep);
if (!containerEntryModule) continue;
const allReferencedModules = getAllReferencedModules(
compilation,
containerEntryModule,
"initial",
false
);
const allRemoteReferences = getAllReferencedModules(
compilation,
containerEntryModule,
"external",
false
);
for (const remote of allRemoteReferences) {
allReferencedModules.add(remote);
}
const containerRuntimes =
chunkGraph.getModuleRuntimes(containerEntryModule);
const runtimes = new Set();
for (const runtimeSpec of containerRuntimes) {
forEachRuntime(runtimeSpec, runtimeKey => {
if (runtimeKey) {
runtimes.add(runtimeKey);
}
});
}
for (const runtime of runtimes) {
const runtimeChunk = compilation.namedChunks.get(runtime);
if (!runtimeChunk) continue;
for (const module of allReferencedModules) {
if (!chunkGraph.isModuleInChunk(module, runtimeChunk)) {
chunkGraph.connectChunkAndModule(runtimeChunk, module);
}
}
}
this.cleanUpChunks(compilation, allReferencedModules);
}
}
/**
* Clean up chunks by disconnecting unused modules.
* @param {Compilation} compilation The webpack compilation instance.
* @param {Set<Module>} modules Set of modules to clean up.
*/
cleanUpChunks(compilation, modules) {
const { chunkGraph } = compilation;
for (const module of modules) {
for (const chunk of chunkGraph.getModuleChunks(module)) {
if (!chunk.hasRuntime()) {
chunkGraph.disconnectChunkAndModule(chunk, module);
if (
chunkGraph.getNumberOfChunkModules(chunk) === 0 &&
chunkGraph.getNumberOfEntryModules(chunk) === 0
) {
chunkGraph.disconnectChunk(chunk);
compilation.chunks.delete(chunk);
if (chunk.name) {
compilation.namedChunks.delete(chunk.name);
}
}
}
}
}
modules.clear();
}
}
/**
* Helper method to collect all referenced modules recursively.
* @param {Compilation} compilation The webpack compilation instance.
* @param {Module} module The module to start collecting from.
* @param {string} type The type of modules to collect ("initial", "external", or "all").
* @param {boolean} includeInitial Should include the referenced module passed
* @returns {Set<Module>} Set of collected modules.
*/
function getAllReferencedModules(compilation, module, type, includeInitial) {
const collectedModules = new Set(includeInitial ? [module] : []);
const visitedModules = new WeakSet([module]);
const stack = [module];
while (stack.length > 0) {
const currentModule = stack.pop();
if (!currentModule) continue;
const outgoingConnections =
compilation.moduleGraph.getOutgoingConnections(currentModule);
if (outgoingConnections) {
for (const connection of outgoingConnections) {
const connectedModule = connection.module;
// Skip if module has already been visited
if (!connectedModule || visitedModules.has(connectedModule)) {
continue;
}
// Handle 'initial' type (skipping async blocks)
if (type === "initial") {
const parentBlock = compilation.moduleGraph.getParentBlock(
/** @type {Dependency} */
(connection.dependency)
);
if (parentBlock instanceof AsyncDependenciesBlock) {
continue;
}
}
// Handle 'external' type (collecting only external modules)
if (type === "external") {
if (connection.module instanceof ExternalModule) {
collectedModules.add(connectedModule);
}
} else {
// Handle 'all' or unspecified types
collectedModules.add(connectedModule);
}
// Add connected module to the stack and mark it as visited
visitedModules.add(connectedModule);
stack.push(connectedModule);
}
}
}
return collectedModules;
}
module.exports = HoistContainerReferences;

View File

@ -0,0 +1,132 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra and Zackary Jackson @ScriptedAlchemy
*/
"use strict";
const { SyncHook } = require("tapable");
const isValidExternalsType = require("../../schemas/plugins/container/ExternalsType.check.js");
const Compilation = require("../Compilation");
const SharePlugin = require("../sharing/SharePlugin");
const createSchemaValidation = require("../util/create-schema-validation");
const ContainerPlugin = require("./ContainerPlugin");
const ContainerReferencePlugin = require("./ContainerReferencePlugin");
const HoistContainerReferences = require("./HoistContainerReferencesPlugin");
/** @typedef {import("../../declarations/plugins/container/ModuleFederationPlugin").ExternalsType} ExternalsType */
/** @typedef {import("../../declarations/plugins/container/ModuleFederationPlugin").ModuleFederationPluginOptions} ModuleFederationPluginOptions */
/** @typedef {import("../../declarations/plugins/container/ModuleFederationPlugin").Shared} Shared */
/** @typedef {import("../Compiler")} Compiler */
/** @typedef {import("../Dependency")} Dependency */
/**
* @typedef {object} CompilationHooks
* @property {SyncHook<Dependency>} addContainerEntryDependency
* @property {SyncHook<Dependency>} addFederationRuntimeDependency
*/
const validate = createSchemaValidation(
require("../../schemas/plugins/container/ModuleFederationPlugin.check.js"),
() => require("../../schemas/plugins/container/ModuleFederationPlugin.json"),
{
name: "Module Federation Plugin",
baseDataPath: "options"
}
);
/** @type {WeakMap<Compilation, CompilationHooks>} */
const compilationHooksMap = new WeakMap();
const PLUGIN_NAME = "ModuleFederationPlugin";
class ModuleFederationPlugin {
/**
* @param {ModuleFederationPluginOptions} options options
*/
constructor(options) {
validate(options);
this._options = options;
}
/**
* Get the compilation hooks associated with this plugin.
* @param {Compilation} compilation The compilation instance.
* @returns {CompilationHooks} The hooks for the compilation.
*/
static getCompilationHooks(compilation) {
if (!(compilation instanceof Compilation)) {
throw new TypeError(
"The 'compilation' argument must be an instance of Compilation"
);
}
let hooks = compilationHooksMap.get(compilation);
if (!hooks) {
hooks = {
addContainerEntryDependency: new SyncHook(["dependency"]),
addFederationRuntimeDependency: new SyncHook(["dependency"])
};
compilationHooksMap.set(compilation, hooks);
}
return hooks;
}
/**
* Apply the plugin
* @param {Compiler} compiler the compiler instance
* @returns {void}
*/
apply(compiler) {
const { _options: options } = this;
const library = options.library || { type: "var", name: options.name };
const remoteType =
options.remoteType ||
(options.library && isValidExternalsType(options.library.type)
? /** @type {ExternalsType} */ (options.library.type)
: "script");
if (
library &&
!compiler.options.output.enabledLibraryTypes.includes(library.type)
) {
compiler.options.output.enabledLibraryTypes.push(library.type);
}
compiler.hooks.afterPlugins.tap(PLUGIN_NAME, () => {
if (
options.exposes &&
(Array.isArray(options.exposes)
? options.exposes.length > 0
: Object.keys(options.exposes).length > 0)
) {
new ContainerPlugin({
name: /** @type {string} */ (options.name),
library,
filename: options.filename,
runtime: options.runtime,
shareScope: options.shareScope,
exposes: options.exposes
}).apply(compiler);
}
if (
options.remotes &&
(Array.isArray(options.remotes)
? options.remotes.length > 0
: Object.keys(options.remotes).length > 0)
) {
new ContainerReferencePlugin({
remoteType,
shareScope: options.shareScope,
remotes: options.remotes
}).apply(compiler);
}
if (options.shared) {
new SharePlugin({
shared: options.shared,
shareScope: options.shareScope
}).apply(compiler);
}
new HoistContainerReferences().apply(compiler);
});
}
}
module.exports = ModuleFederationPlugin;

View File

@ -0,0 +1,186 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra and Zackary Jackson @ScriptedAlchemy
*/
"use strict";
const { RawSource } = require("webpack-sources");
const Module = require("../Module");
const {
REMOTE_AND_SHARE_INIT_TYPES
} = require("../ModuleSourceTypesConstants");
const { WEBPACK_MODULE_TYPE_REMOTE } = require("../ModuleTypeConstants");
const RuntimeGlobals = require("../RuntimeGlobals");
const makeSerializable = require("../util/makeSerializable");
const FallbackDependency = require("./FallbackDependency");
const RemoteToExternalDependency = require("./RemoteToExternalDependency");
/** @typedef {import("../../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */
/** @typedef {import("../ChunkGraph")} ChunkGraph */
/** @typedef {import("../ChunkGroup")} ChunkGroup */
/** @typedef {import("../Compilation")} Compilation */
/** @typedef {import("../Module").BuildCallback} BuildCallback */
/** @typedef {import("../Module").CodeGenerationContext} CodeGenerationContext */
/** @typedef {import("../Module").CodeGenerationResult} CodeGenerationResult */
/** @typedef {import("../Module").LibIdentOptions} LibIdentOptions */
/** @typedef {import("../Module").NeedBuildCallback} NeedBuildCallback */
/** @typedef {import("../Module").NeedBuildContext} NeedBuildContext */
/** @typedef {import("../Module").SourceTypes} SourceTypes */
/** @typedef {import("../RequestShortener")} RequestShortener */
/** @typedef {import("../ResolverFactory").ResolverWithOptions} ResolverWithOptions */
/** @typedef {import("../WebpackError")} WebpackError */
/** @typedef {import("../serialization/ObjectMiddleware").ObjectDeserializerContext} ObjectDeserializerContext */
/** @typedef {import("../serialization/ObjectMiddleware").ObjectSerializerContext} ObjectSerializerContext */
/** @typedef {import("../util/Hash")} Hash */
/** @typedef {import("../util/fs").InputFileSystem} InputFileSystem */
const RUNTIME_REQUIREMENTS = new Set([RuntimeGlobals.module]);
class RemoteModule extends Module {
/**
* @param {string} request request string
* @param {string[]} externalRequests list of external requests to containers
* @param {string} internalRequest name of exposed module in container
* @param {string} shareScope the used share scope name
*/
constructor(request, externalRequests, internalRequest, shareScope) {
super(WEBPACK_MODULE_TYPE_REMOTE);
this.request = request;
this.externalRequests = externalRequests;
this.internalRequest = internalRequest;
this.shareScope = shareScope;
this._identifier = `remote (${shareScope}) ${this.externalRequests.join(
" "
)} ${this.internalRequest}`;
}
/**
* @returns {string} a unique identifier of the module
*/
identifier() {
return this._identifier;
}
/**
* @param {RequestShortener} requestShortener the request shortener
* @returns {string} a user readable identifier of the module
*/
readableIdentifier(requestShortener) {
return `remote ${this.request}`;
}
/**
* @param {LibIdentOptions} options options
* @returns {string | null} an identifier for library inclusion
*/
libIdent(options) {
return `${this.layer ? `(${this.layer})/` : ""}webpack/container/remote/${
this.request
}`;
}
/**
* @param {NeedBuildContext} context context info
* @param {NeedBuildCallback} callback callback function, returns true, if the module needs a rebuild
* @returns {void}
*/
needBuild(context, callback) {
callback(null, !this.buildInfo);
}
/**
* @param {WebpackOptions} options webpack options
* @param {Compilation} compilation the compilation
* @param {ResolverWithOptions} resolver the resolver
* @param {InputFileSystem} fs the file system
* @param {BuildCallback} callback callback function
* @returns {void}
*/
build(options, compilation, resolver, fs, callback) {
this.buildMeta = {};
this.buildInfo = {
strict: true
};
this.clearDependenciesAndBlocks();
if (this.externalRequests.length === 1) {
this.addDependency(
new RemoteToExternalDependency(this.externalRequests[0])
);
} else {
this.addDependency(new FallbackDependency(this.externalRequests));
}
callback();
}
/**
* @param {string=} type the source type for which the size should be estimated
* @returns {number} the estimated size of the module (must be non-zero)
*/
size(type) {
return 6;
}
/**
* @returns {SourceTypes} types available (do not mutate)
*/
getSourceTypes() {
return REMOTE_AND_SHARE_INIT_TYPES;
}
/**
* @returns {string | null} absolute path which should be used for condition matching (usually the resource path)
*/
nameForCondition() {
return this.request;
}
/**
* @param {CodeGenerationContext} context context for code generation
* @returns {CodeGenerationResult} result
*/
codeGeneration({ runtimeTemplate, moduleGraph, chunkGraph }) {
const module = moduleGraph.getModule(this.dependencies[0]);
const id = module && chunkGraph.getModuleId(module);
const sources = new Map();
sources.set("remote", new RawSource(""));
const data = new Map();
data.set("share-init", [
{
shareScope: this.shareScope,
initStage: 20,
init: id === undefined ? "" : `initExternal(${JSON.stringify(id)});`
}
]);
return { sources, data, runtimeRequirements: RUNTIME_REQUIREMENTS };
}
/**
* @param {ObjectSerializerContext} context context
*/
serialize(context) {
const { write } = context;
write(this.request);
write(this.externalRequests);
write(this.internalRequest);
write(this.shareScope);
super.serialize(context);
}
/**
* @param {ObjectDeserializerContext} context context
* @returns {RemoteModule} deserialized module
*/
static deserialize(context) {
const { read } = context;
const obj = new RemoteModule(read(), read(), read(), read());
obj.deserialize(context);
return obj;
}
}
makeSerializable(RemoteModule, "webpack/lib/container/RemoteModule");
module.exports = RemoteModule;

View File

@ -0,0 +1,144 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const RuntimeGlobals = require("../RuntimeGlobals");
const RuntimeModule = require("../RuntimeModule");
const Template = require("../Template");
/** @typedef {import("../Chunk")} Chunk */
/** @typedef {import("../Chunk").ChunkId} ChunkId */
/** @typedef {import("../ChunkGraph")} ChunkGraph */
/** @typedef {import("../ChunkGraph").ModuleId} ModuleId */
/** @typedef {import("../Compilation")} Compilation */
/** @typedef {import("./RemoteModule")} RemoteModule */
class RemoteRuntimeModule extends RuntimeModule {
constructor() {
super("remotes loading");
}
/**
* @returns {string | null} runtime code
*/
generate() {
const compilation = /** @type {Compilation} */ (this.compilation);
const chunkGraph = /** @type {ChunkGraph} */ (this.chunkGraph);
const { runtimeTemplate, moduleGraph } = compilation;
/** @type {Record<ChunkId, (string | number)[]>} */
const chunkToRemotesMapping = {};
/** @type {Record<ModuleId, [string, string, string | number | null]>} */
const idToExternalAndNameMapping = {};
for (const chunk of /** @type {Chunk} */ (
this.chunk
).getAllReferencedChunks()) {
const modules = chunkGraph.getChunkModulesIterableBySourceType(
chunk,
"remote"
);
if (!modules) continue;
/** @type {ModuleId[]} */
const remotes = (chunkToRemotesMapping[
/** @type {ChunkId} */
(chunk.id)
] = []);
for (const m of modules) {
const module = /** @type {RemoteModule} */ (m);
const name = module.internalRequest;
const id = /** @type {ModuleId} */ (chunkGraph.getModuleId(module));
const shareScope = module.shareScope;
const dep = module.dependencies[0];
const externalModule = moduleGraph.getModule(dep);
const externalModuleId =
/** @type {ModuleId} */
(externalModule && chunkGraph.getModuleId(externalModule));
remotes.push(id);
idToExternalAndNameMapping[id] = [shareScope, name, externalModuleId];
}
}
return Template.asString([
`var chunkMapping = ${JSON.stringify(
chunkToRemotesMapping,
null,
"\t"
)};`,
`var idToExternalAndNameMapping = ${JSON.stringify(
idToExternalAndNameMapping,
null,
"\t"
)};`,
`${
RuntimeGlobals.ensureChunkHandlers
}.remotes = ${runtimeTemplate.basicFunction("chunkId, promises", [
`if(${RuntimeGlobals.hasOwnProperty}(chunkMapping, chunkId)) {`,
Template.indent([
`chunkMapping[chunkId].forEach(${runtimeTemplate.basicFunction("id", [
`var getScope = ${RuntimeGlobals.currentRemoteGetScope};`,
"if(!getScope) getScope = [];",
"var data = idToExternalAndNameMapping[id];",
"if(getScope.indexOf(data) >= 0) return;",
"getScope.push(data);",
"if(data.p) return promises.push(data.p);",
`var onError = ${runtimeTemplate.basicFunction("error", [
'if(!error) error = new Error("Container missing");',
'if(typeof error.message === "string")',
Template.indent(
"error.message += '\\nwhile loading \"' + data[1] + '\" from ' + data[2];"
),
`${
RuntimeGlobals.moduleFactories
}[id] = ${runtimeTemplate.basicFunction("", ["throw error;"])}`,
"data.p = 0;"
])};`,
`var handleFunction = ${runtimeTemplate.basicFunction(
"fn, arg1, arg2, d, next, first",
[
"try {",
Template.indent([
"var promise = fn(arg1, arg2);",
"if(promise && promise.then) {",
Template.indent([
`var p = promise.then(${runtimeTemplate.returningFunction(
"next(result, d)",
"result"
)}, onError);`,
"if(first) promises.push(data.p = p); else return p;"
]),
"} else {",
Template.indent(["return next(promise, d, first);"]),
"}"
]),
"} catch(error) {",
Template.indent(["onError(error);"]),
"}"
]
)}`,
`var onExternal = ${runtimeTemplate.returningFunction(
`external ? handleFunction(${RuntimeGlobals.initializeSharing}, data[0], 0, external, onInitialized, first) : onError()`,
"external, _, first"
)};`,
`var onInitialized = ${runtimeTemplate.returningFunction(
"handleFunction(external.get, data[1], getScope, 0, onFactory, first)",
"_, external, first"
)};`,
`var onFactory = ${runtimeTemplate.basicFunction("factory", [
"data.p = 1;",
`${
RuntimeGlobals.moduleFactories
}[id] = ${runtimeTemplate.basicFunction("module", [
"module.exports = factory();"
])}`
])};`,
`handleFunction(${RuntimeGlobals.require}, data[2], 0, 0, onExternal, 1);`
])});`
]),
"}"
])}`
]);
}
}
module.exports = RemoteRuntimeModule;

View File

@ -0,0 +1,33 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
const ModuleDependency = require("../dependencies/ModuleDependency");
const makeSerializable = require("../util/makeSerializable");
class RemoteToExternalDependency extends ModuleDependency {
/**
* @param {string} request request
*/
constructor(request) {
super(request);
}
get type() {
return "remote to external";
}
get category() {
return "esm";
}
}
makeSerializable(
RemoteToExternalDependency,
"webpack/lib/container/RemoteToExternalDependency"
);
module.exports = RemoteToExternalDependency;

105
app_vue/node_modules/webpack/lib/container/options.js generated vendored Normal file
View File

@ -0,0 +1,105 @@
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
"use strict";
/**
* @template T
* @typedef {Record<string, string | string[] | T>} Item
*/
/**
* @template T
* @typedef {(string | Item<T>)[] | Item<T>} ContainerOptionsFormat
*/
/**
* @template T
* @template N
* @param {ContainerOptionsFormat<T>} options options passed by the user
* @param {(item: string | string[], itemOrKey: string) => N} normalizeSimple normalize a simple item
* @param {(value: T, key: string) => N} normalizeOptions normalize a complex item
* @param {(item: string, normalized: N) => void} fn processing function
* @returns {void}
*/
const process = (options, normalizeSimple, normalizeOptions, fn) => {
/**
* @param {(string | Item<T>)[]} items items
*/
const array = items => {
for (const item of items) {
if (typeof item === "string") {
fn(item, normalizeSimple(item, item));
} else if (item && typeof item === "object") {
object(item);
} else {
throw new Error("Unexpected options format");
}
}
};
/**
* @param {Item<T>} obj an object
*/
const object = obj => {
for (const [key, value] of Object.entries(obj)) {
if (typeof value === "string" || Array.isArray(value)) {
fn(key, normalizeSimple(value, key));
} else {
fn(key, normalizeOptions(value, key));
}
}
};
if (!options) {
// Do nothing
} else if (Array.isArray(options)) {
array(options);
} else if (typeof options === "object") {
object(options);
} else {
throw new Error("Unexpected options format");
}
};
/**
* @template T
* @template R
* @param {ContainerOptionsFormat<T>} options options passed by the user
* @param {(item: string | string[], itemOrKey: string) => R} normalizeSimple normalize a simple item
* @param {(value: T, key: string) => R} normalizeOptions normalize a complex item
* @returns {[string, R][]} parsed options
*/
const parseOptions = (options, normalizeSimple, normalizeOptions) => {
/** @type {[string, R][]} */
const items = [];
process(options, normalizeSimple, normalizeOptions, (key, value) => {
items.push([key, value]);
});
return items;
};
/**
* @template T
* @param {string} scope scope name
* @param {ContainerOptionsFormat<T>} options options passed by the user
* @returns {Record<string, string | string[] | T>} options to spread or pass
*/
const scope = (scope, options) => {
/** @type {Record<string, string | string[] | T>} */
const obj = {};
process(
options,
item => /** @type {string | string[] | T} */ (item),
item => /** @type {string | string[] | T} */ (item),
(key, value) => {
obj[
key.startsWith("./") ? `${scope}${key.slice(1)}` : `${scope}/${key}`
] = value;
}
);
return obj;
};
module.exports.parseOptions = parseOptions;
module.exports.scope = scope;