UNPKG

@module-federation/enhanced

Version:

This package provides enhanced features for module federation.

136 lines (133 loc) • 7.31 kB
'use strict'; Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' }); const require_runtime = require('../../_virtual/_rolldown/runtime.js'); let _module_federation_sdk_normalize_webpack_path = require("@module-federation/sdk/normalize-webpack-path"); //#region src/lib/startup/StartupHelpers.ts const { RuntimeGlobals, Template } = require((0, _module_federation_sdk_normalize_webpack_path.normalizeWebpackPath)("webpack")); const { isSubset } = require((0, _module_federation_sdk_normalize_webpack_path.normalizeWebpackPath)("webpack/lib/util/SetHelpers")); const { getAllChunks } = require((0, _module_federation_sdk_normalize_webpack_path.normalizeWebpackPath)("webpack/lib/javascript/ChunkHelpers")); const HotUpdateChunk = require((0, _module_federation_sdk_normalize_webpack_path.normalizeWebpackPath)("webpack/lib/HotUpdateChunk")); const { getUndoPath } = require((0, _module_federation_sdk_normalize_webpack_path.normalizeWebpackPath)("webpack/lib/util/identifier")); const EXPORT_PREFIX = `var ${RuntimeGlobals.exports} = `; const federationStartup = "federation-entry-startup"; const generateEntryStartup = (compilation, chunkGraph, runtimeTemplate, entries, chunk, passive) => { /** @type {string[]} */ const runtime = [ `var __webpack_exec__ = ${runtimeTemplate.returningFunction(`${RuntimeGlobals.require}(${RuntimeGlobals.entryModuleId} = moduleId)`, "moduleId")}`, "", "\n", "var promises = [];", "if (typeof __webpack_require__.x === \"function\") {", " __webpack_require__.x();", "} else {", " console.warn(\"[Module Federation] __webpack_require__.x is not a function, skipping startup extension\");", "}" ]; const treeRuntimeRequirements = chunkGraph.getTreeRuntimeRequirements(chunk); const federation = chunkGraph.getChunkRuntimeRequirements(chunk).has(federationStartup) || treeRuntimeRequirements.has(federationStartup); const runModule = (id) => { return `__webpack_exec__(${JSON.stringify(id)})`; }; const outputCombination = (chunks, moduleIds, final) => { if (chunks.size === 0 && !federation) runtime.push(`${final ? EXPORT_PREFIX : ""}(${moduleIds.map(runModule).join(", ")});`); else { const fn = runtimeTemplate.returningFunction(moduleIds.map(runModule).join(", ")); if (federation) { const chunkIds = Array.from(chunks, (c) => c.id); const wrappedInit = (body) => Template.asString([ "Promise.all([", Template.indent([`${RuntimeGlobals.ensureChunkHandlers}.consumes || function(chunkId, promises) {},`, `${RuntimeGlobals.ensureChunkHandlers}.remotes || function(chunkId, promises) {},`]), `].reduce(${runtimeTemplate.returningFunction(`handler('${chunk.id}', p), p`, "p, handler")}, promises)`, `).then(${runtimeTemplate.returningFunction(body)});` ]); const wrap = wrappedInit(`${passive ? RuntimeGlobals.onChunksLoaded : RuntimeGlobals.startupEntrypoint}(0, ${JSON.stringify(chunkIds)}, ${fn})`); runtime.push(`${final && !passive ? EXPORT_PREFIX : ""}${wrap}`); } else { const chunkIds = Array.from(chunks, (c) => c.id); runtime.push(`${final && !passive ? EXPORT_PREFIX : ""}${passive ? RuntimeGlobals.onChunksLoaded : RuntimeGlobals.startupEntrypoint}(0, ${JSON.stringify(chunkIds)}, ${fn});`); if (final && passive) runtime.push(`${EXPORT_PREFIX}${RuntimeGlobals.onChunksLoaded}();`); } } }; let currentChunks = void 0; let currentModuleIds = void 0; for (const [module, entrypoint] of entries) { if (!entrypoint) continue; const runtimeChunk = entrypoint.getRuntimeChunk(); const moduleId = chunkGraph.getModuleId(module); const chunks = getAllChunks(entrypoint, chunk, runtimeChunk); if (currentChunks && currentChunks.size === chunks.size && isSubset(currentChunks, chunks)) currentModuleIds.push(moduleId); else { if (currentChunks) outputCombination(currentChunks, currentModuleIds); currentChunks = chunks; currentModuleIds = [moduleId]; } } if (currentChunks) outputCombination(currentChunks, currentModuleIds, true); runtime.push(""); return Template.asString(runtime); }; const generateESMEntryStartup = (compilation, chunkGraph, runtimeTemplate, entries, chunk, passive) => { const { chunkHasJs, getChunkFilenameTemplate } = compilation.compiler.webpack?.javascript?.JavascriptModulesPlugin || compilation.compiler.webpack.JavascriptModulesPlugin; const { ConcatSource } = compilation.compiler.webpack.sources; if (chunk instanceof HotUpdateChunk ? chunk : null) throw new Error("HMR is not implemented for module chunk format yet"); else { const treeRuntimeRequirements = chunkGraph.getTreeRuntimeRequirements(chunk); const federation = chunkGraph.getChunkRuntimeRequirements(chunk).has(federationStartup) || treeRuntimeRequirements.has(federationStartup); if (entries.length > 0) { const runtimeChunk = entries[0]?.[1]?.getRuntimeChunk?.(); if (!runtimeChunk) throw new Error("Runtime chunk is undefined"); const currentOutputName = compilation.getPath(getChunkFilenameTemplate(chunk, compilation.outputOptions), { chunk, contentHashType: "javascript" }).replace(/^\/+/g, "").split("/"); /** * @param {Chunk} chunk the chunk * @returns {string} the relative path */ const getRelativePath = (chunk) => { const baseOutputName = currentOutputName.slice(); const chunkOutputName = compilation.getPath(getChunkFilenameTemplate(chunk, compilation.outputOptions), { chunk, contentHashType: "javascript" }).replace(/^\/+/g, "").split("/"); while (baseOutputName.length > 1 && chunkOutputName.length > 1 && baseOutputName[0] === chunkOutputName[0]) { baseOutputName.shift(); chunkOutputName.shift(); } const last = chunkOutputName.join("/"); return getUndoPath(baseOutputName.join("/"), last, true) + last; }; const startupSource = new ConcatSource(); startupSource.add(`var __webpack_exec__ = ${runtimeTemplate.returningFunction(`${RuntimeGlobals.require}(${RuntimeGlobals.entryModuleId} = moduleId)`, "moduleId")}\n`); const loadedChunks = /* @__PURE__ */ new Set(); let index = 0; for (let i = 0; i < entries.length; i++) { const [module, entrypoint] = entries[i]; if (!entrypoint) continue; const final = i + 1 === entries.length; const moduleId = chunkGraph.getModuleId(module); const chunks = getAllChunks(entrypoint, runtimeChunk, void 0); for (const chunk of chunks) { if (loadedChunks.has(chunk) || !chunkHasJs(chunk, chunkGraph)) continue; loadedChunks.add(chunk); startupSource.add(`import * as __webpack_chunk_${index}__ from ${JSON.stringify(getRelativePath(chunk))};\n`); startupSource.add(`${RuntimeGlobals.externalInstallChunk}(__webpack_chunk_${index}__);\n`); index++; } if (!federation) startupSource.add(`${final ? EXPORT_PREFIX : ""}__webpack_exec__(${JSON.stringify(moduleId)});\n`); } if (federation) { startupSource.add("\n"); startupSource.add(generateEntryStartup(compilation, chunkGraph, runtimeTemplate, entries, chunk, passive)); } return startupSource.source(); } } return ""; }; //#endregion exports.federationStartup = federationStartup; exports.generateESMEntryStartup = generateESMEntryStartup; exports.generateEntryStartup = generateEntryStartup; //# sourceMappingURL=StartupHelpers.js.map