@module-federation/enhanced
Version:
This package provides enhanced features for module federation.
136 lines (133 loc) • 7.31 kB
JavaScript
;
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