UNPKG

@module-federation/enhanced

Version:

This package provides enhanced features for module federation.

265 lines (263 loc) • 14 kB
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