@module-federation/enhanced
Version:
This package provides enhanced features for module federation.
265 lines (263 loc) • 14 kB
JavaScript
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: 'Module' } });
const require_runtime = require('../../../_virtual/_rolldown/runtime.js');
const require_lib_container_runtime_utils = require('./utils.js');
const require_lib_container_runtime_FederationRuntimeModule = require('./FederationRuntimeModule.js');
const require_lib_container_constant = require('../constant.js');
const require_lib_container_runtime_FederationModulesPlugin = require('./FederationModulesPlugin.js');
const require_lib_container_runtime_EmbedFederationRuntimePlugin = require('./EmbedFederationRuntimePlugin.js');
const require_lib_container_HoistContainerReferencesPlugin = require('../HoistContainerReferencesPlugin.js');
const require_lib_container_runtime_FederationRuntimeDependency = require('./FederationRuntimeDependency.js');
let _module_federation_sdk_normalize_webpack_path = require("@module-federation/sdk/normalize-webpack-path");
let path = require("path");
path = require_runtime.__toESM(path);
let fs = require("fs");
fs = require_runtime.__toESM(fs);
//#region src/lib/container/runtime/FederationRuntimePlugin.ts
const ModuleDependency = require((0, _module_federation_sdk_normalize_webpack_path.normalizeWebpackPath)("webpack/lib/dependencies/ModuleDependency"));
const { RuntimeGlobals, Template } = require((0, _module_federation_sdk_normalize_webpack_path.normalizeWebpackPath)("webpack"));
const { mkdirpSync } = require((0, _module_federation_sdk_normalize_webpack_path.normalizeWebpackPath)("webpack/lib/util/fs"));
function resolveRuntimeEntry(spec, implementation, resolve = require.resolve) {
const candidates = [
spec.bundler,
spec.esm,
spec.cjs
];
const modulePaths = implementation ? [implementation] : void 0;
let lastError;
for (const candidate of candidates) try {
return modulePaths ? resolve(candidate, { paths: modulePaths }) : resolve(candidate);
} catch (error) {
lastError = error;
}
throw lastError;
}
function resolveRuntimeEntryWithFallback(spec, implementation, resolve = require.resolve) {
if (implementation) try {
return resolveRuntimeEntry(spec, implementation, resolve);
} catch {}
return resolveRuntimeEntry(spec, void 0, resolve);
}
function resolveRuntimePaths(implementation, resolve = require.resolve) {
const runtimeToolsPath = resolveRuntimeEntryWithFallback({
bundler: "@module-federation/runtime-tools/bundler",
esm: "@module-federation/runtime-tools/dist/index.js",
cjs: "@module-federation/runtime-tools/dist/index.cjs"
}, implementation, resolve);
const moduleBase = implementation || runtimeToolsPath;
return {
runtimeToolsPath,
bundlerRuntimePath: resolveRuntimeEntry({
bundler: "@module-federation/webpack-bundler-runtime/bundler",
esm: "@module-federation/webpack-bundler-runtime/dist/index.js",
cjs: "@module-federation/webpack-bundler-runtime/dist/index.cjs"
}, moduleBase, resolve),
runtimePath: resolveRuntimeEntry({
bundler: "@module-federation/runtime/bundler",
esm: "@module-federation/runtime/dist/index.js",
cjs: "@module-federation/runtime/dist/index.cjs"
}, moduleBase, resolve)
};
}
const { runtimeToolsPath: RuntimeToolsPath, bundlerRuntimePath: BundlerRuntimePath, runtimePath: RuntimePath } = resolveRuntimePaths();
const federationGlobal = require_lib_container_runtime_utils.getFederationGlobalScope(RuntimeGlobals);
const onceForCompiler = /* @__PURE__ */ new WeakSet();
const onceForCompilerEntryMap = /* @__PURE__ */ new WeakMap();
var FederationRuntimePlugin = class FederationRuntimePlugin {
constructor(options) {
this.options = options ? { ...options } : void 0;
this.entryFilePath = "";
this.bundlerRuntimePath = BundlerRuntimePath;
this.runtimePath = RuntimePath;
this.runtimeToolsPath = RuntimeToolsPath;
this.federationRuntimeDependency = void 0;
}
static getTemplate(compiler, options, bundlerRuntimePath) {
const runtimePlugins = options.runtimePlugins;
const normalizedBundlerRuntimePath = require_lib_container_runtime_utils.normalizeToPosixPath(bundlerRuntimePath || BundlerRuntimePath);
let runtimePluginTemplates = "";
const runtimePluginCalls = [];
if (Array.isArray(runtimePlugins)) runtimePlugins.forEach((runtimePlugin, index) => {
if (!runtimePlugin) return;
const runtimePluginName = `plugin_${index}`;
const runtimePluginEntry = Array.isArray(runtimePlugin) ? runtimePlugin[0] : runtimePlugin;
const runtimePluginPath = require_lib_container_runtime_utils.normalizeToPosixPath(path.default.isAbsolute(runtimePluginEntry) ? runtimePluginEntry : path.default.join(process.cwd(), runtimePluginEntry));
const paramsStr = Array.isArray(runtimePlugin) && runtimePlugin.length > 1 ? JSON.stringify(runtimePlugin[1]) : "undefined";
runtimePluginTemplates += `import ${runtimePluginName} from '${runtimePluginPath}';\n`;
runtimePluginCalls.push(`${runtimePluginName} ? (${runtimePluginName}.default || ${runtimePluginName})(${paramsStr}) : false`);
});
const embedRuntimeLines = Template.asString([
`if(!${federationGlobal}.runtime || !${federationGlobal}.bundlerRuntime){`,
Template.indent([
`var prevFederation = ${federationGlobal};`,
`${federationGlobal} = {}`,
`for(var key in federation){`,
Template.indent([`${federationGlobal}[key] = federation[key];`]),
"}",
`for(var key in prevFederation){`,
Template.indent([`${federationGlobal}[key] = prevFederation[key];`]),
"}"
]),
"}"
]);
return Template.asString([
`import federation from '${normalizedBundlerRuntimePath}';`,
runtimePluginTemplates,
embedRuntimeLines,
`if(!${federationGlobal}.instance){`,
Template.indent([
runtimePluginCalls.length ? Template.asString([
`var pluginsToAdd = [`,
Template.indent(Template.indent(runtimePluginCalls.map((call) => `${call},`))),
`].filter(Boolean);`,
`${federationGlobal}.initOptions.plugins = ${federationGlobal}.initOptions.plugins ? `,
`${federationGlobal}.initOptions.plugins.concat(pluginsToAdd) : pluginsToAdd;`
]) : "",
`${federationGlobal}.instance = ${federationGlobal}.bundlerRuntime.init({webpackRequire:${RuntimeGlobals.require}});`,
`if(${federationGlobal}.attachShareScopeMap){`,
Template.indent([`${federationGlobal}.attachShareScopeMap(${RuntimeGlobals.require})`]),
"}",
`if(${federationGlobal}.installInitialConsumes){`,
Template.indent([`${federationGlobal}.installInitialConsumes()`]),
"}"
]),
"}"
]);
}
getFilePath(compiler) {
if (!this.options) return "";
const existedFilePath = onceForCompilerEntryMap.get(compiler);
if (existedFilePath) return existedFilePath;
let entryFilePath = "";
if (!this.options?.virtualRuntimeEntry) {
const containerName = this.options.name;
const hash = require_lib_container_runtime_utils.createHash(`${containerName} ${FederationRuntimePlugin.getTemplate(compiler, this.options, this.bundlerRuntimePath)}`);
entryFilePath = path.default.join(require_lib_container_constant.TEMP_DIR, `entry.${hash}.js`);
} else entryFilePath = `data:text/javascript;charset=utf-8;base64,${Buffer.from(FederationRuntimePlugin.getTemplate(compiler, this.options, this.bundlerRuntimePath), "utf8").toString("base64")}`;
onceForCompilerEntryMap.set(compiler, entryFilePath);
return entryFilePath;
}
ensureFile(compiler) {
if (!this.options) return;
if (this.options?.virtualRuntimeEntry) return;
const filePath = this.entryFilePath;
const outputFs = compiler.outputFileSystem;
const fsLike = outputFs && typeof outputFs.readFileSync === "function" && typeof outputFs.writeFileSync === "function" ? outputFs : fs.default;
try {
fsLike.readFileSync(filePath);
} catch {
mkdirpSync(fsLike, require_lib_container_constant.TEMP_DIR);
fsLike.writeFileSync(filePath, FederationRuntimePlugin.getTemplate(compiler, this.options, this.bundlerRuntimePath));
}
}
getDependency(compiler) {
if (this.federationRuntimeDependency) return this.federationRuntimeDependency;
this.ensureFile(compiler);
this.federationRuntimeDependency = new require_lib_container_runtime_FederationRuntimeDependency.default(this.entryFilePath);
return this.federationRuntimeDependency;
}
prependEntry(compiler) {
if (!this.options?.virtualRuntimeEntry) this.ensureFile(compiler);
compiler.hooks.thisCompilation.tap(this.constructor.name, (compilation, { normalModuleFactory }) => {
compilation.dependencyFactories.set(require_lib_container_runtime_FederationRuntimeDependency.default, normalModuleFactory);
compilation.dependencyTemplates.set(require_lib_container_runtime_FederationRuntimeDependency.default, new ModuleDependency.Template());
});
compiler.hooks.make.tapAsync(this.constructor.name, (compilation, callback) => {
const federationRuntimeDependency = this.getDependency(compiler);
const hooks = require_lib_container_runtime_FederationModulesPlugin.default.getCompilationHooks(compilation);
compilation.addInclude(compiler.context, federationRuntimeDependency, { name: void 0 }, (err) => {
if (err) return callback(err);
hooks.addFederationRuntimeDependency.call(federationRuntimeDependency);
callback();
});
});
}
injectRuntime(compiler) {
if (!this.options || !this.options.name) return;
const name = this.options.name;
const initOptionsWithoutShared = require_lib_container_runtime_utils.normalizeRuntimeInitOptionsWithOutShared(this.options);
const federationGlobal = require_lib_container_runtime_utils.getFederationGlobalScope(RuntimeGlobals || {});
compiler.hooks.thisCompilation.tap(this.constructor.name, (compilation) => {
const handler = (chunk, runtimeRequirements) => {
if (runtimeRequirements.has(federationGlobal)) return;
runtimeRequirements.add(federationGlobal);
runtimeRequirements.add(RuntimeGlobals.interceptModuleExecution);
runtimeRequirements.add(RuntimeGlobals.moduleCache);
runtimeRequirements.add(RuntimeGlobals.compatGetDefaultExport);
compilation.addRuntimeModule(chunk, new require_lib_container_runtime_FederationRuntimeModule.default(runtimeRequirements, name, initOptionsWithoutShared));
};
compilation.hooks.additionalTreeRuntimeRequirements.tap(this.constructor.name, (chunk, runtimeRequirements) => {
if (!chunk.hasRuntime()) return;
if (runtimeRequirements.has(RuntimeGlobals.initializeSharing)) return;
if (runtimeRequirements.has(RuntimeGlobals.currentRemoteGetScope)) return;
if (runtimeRequirements.has(RuntimeGlobals.shareScopeMap)) return;
if (runtimeRequirements.has(federationGlobal)) return;
handler(chunk, runtimeRequirements);
});
compilation.hooks.runtimeRequirementInTree.for(RuntimeGlobals.initializeSharing).tap(this.constructor.name, handler);
compilation.hooks.runtimeRequirementInTree.for(RuntimeGlobals.currentRemoteGetScope).tap(this.constructor.name, handler);
compilation.hooks.runtimeRequirementInTree.for(RuntimeGlobals.shareScopeMap).tap(this.constructor.name, handler);
compilation.hooks.runtimeRequirementInTree.for(federationGlobal).tap(this.constructor.name, handler);
});
}
getRuntimeAlias(compiler) {
const { implementation } = this.options || {};
const alias = compiler.options.resolve.alias || {};
const resolvedPaths = resolveRuntimePaths(implementation);
this.runtimeToolsPath = resolvedPaths.runtimeToolsPath;
this.bundlerRuntimePath = resolvedPaths.bundlerRuntimePath;
if (alias["@module-federation/runtime$"]) {
this.runtimePath = alias["@module-federation/runtime$"];
return this.runtimePath;
}
this.runtimePath = resolvedPaths.runtimePath;
return this.runtimePath;
}
setRuntimeAlias(compiler) {
const { implementation } = this.options || {};
const alias = compiler.options.resolve.alias || {};
const runtimePath = this.getRuntimeAlias(compiler);
alias["@module-federation/runtime$"] = alias["@module-federation/runtime$"] || runtimePath;
alias["@module-federation/runtime-tools$"] = alias["@module-federation/runtime-tools$"] || implementation || this.runtimeToolsPath;
compiler.options.resolve.alias = alias;
}
apply(compiler) {
if (compiler.options.plugins.find((p) => {
if (typeof p !== "object" || !p) return false;
return p["name"] === "SharedContainerPlugin";
})) return;
const useModuleFederationPlugin = compiler.options.plugins.find((p) => {
if (typeof p !== "object" || !p) return false;
return p["name"] === "ModuleFederationPlugin";
});
if (useModuleFederationPlugin && !this.options) this.options = useModuleFederationPlugin._options;
const useContainerPlugin = compiler.options.plugins.find((p) => {
if (typeof p !== "object" || !p) return false;
return p["name"] === "ContainerPlugin";
});
if (useContainerPlugin && !this.options) this.options = useContainerPlugin._options;
if (!useContainerPlugin && !useModuleFederationPlugin) this.options = {
remotes: {},
...this.options
};
if (this.options && !this.options?.name)
//! the instance may get the same one if the name is the same https://github.com/module-federation/core/blob/main/packages/runtime/src/index.ts#L18
this.options.name = compiler.options.output.uniqueName || `container_${Date.now()}`;
const resolvedPaths = resolveRuntimePaths(this.options?.implementation);
this.bundlerRuntimePath = resolvedPaths.bundlerRuntimePath;
this.runtimePath = resolvedPaths.runtimePath;
this.runtimeToolsPath = resolvedPaths.runtimeToolsPath;
this.entryFilePath = this.getFilePath(compiler);
new require_lib_container_runtime_EmbedFederationRuntimePlugin.default().apply(compiler);
new require_lib_container_HoistContainerReferencesPlugin.default().apply(compiler);
if (!onceForCompiler.has(compiler)) {
this.prependEntry(compiler);
this.injectRuntime(compiler);
this.setRuntimeAlias(compiler);
onceForCompiler.add(compiler);
}
}
};
//#endregion
exports.default = FederationRuntimePlugin;
exports.resolveRuntimePaths = resolveRuntimePaths;
//# sourceMappingURL=FederationRuntimePlugin.js.map