UNPKG

@module-federation/enhanced

Version:

This package provides enhanced features for module federation.

163 lines (161 loc) • 7.58 kB
Object.defineProperties(exports, { __esModule: { value: true }, [Symbol.toStringTag]: { value: 'Module' } }); const require_runtime = require('../../../_virtual/_rolldown/runtime.js'); const require_lib_sharing_tree_shaking_SharedUsedExportsOptimizerRuntimeModule = require('./SharedUsedExportsOptimizerRuntimeModule.js'); let _module_federation_sdk = require("@module-federation/sdk"); //#region src/lib/sharing/tree-shaking/SharedUsedExportsOptimizerPlugin.ts function isHarmonyImportSpecifierDependency(dependency) { return dependency.type === "harmony import specifier"; } function isImportDependency(dependency) { return dependency.type === "import()"; } var SharedUsedExportsOptimizerPlugin = class { constructor(sharedOptions, injectTreeShakingUsedExports, ignoredRuntime, manifestOptions) { this.name = "SharedUsedExportsOptimizerPlugin"; this.sharedOptions = sharedOptions; this.injectTreeShakingUsedExports = injectTreeShakingUsedExports ?? true; this.manifestOptions = manifestOptions ?? {}; this.sharedReferencedExports = /* @__PURE__ */ new Map(); this.sharedOptions.forEach(([key, config]) => { if (!config.treeShaking) return; this.sharedReferencedExports.set(key, /* @__PURE__ */ new Set()); }); this.ignoredRuntime = ignoredRuntime || []; } applyCustomReferencedExports() { const { sharedReferencedExports, sharedOptions } = this; const addCustomExports = (shareKey, exports) => { if (!sharedReferencedExports.get(shareKey)) sharedReferencedExports.set(shareKey, /* @__PURE__ */ new Set()); const sharedExports = sharedReferencedExports.get(shareKey); exports.forEach((item) => { sharedExports.add(item); }); }; sharedOptions.forEach(([shareKey, config]) => { if (config.treeShaking?.usedExports) addCustomExports(shareKey, config.treeShaking.usedExports); }); } apply(compiler) { const { sharedReferencedExports, sharedOptions, injectTreeShakingUsedExports, manifestOptions } = this; if (!sharedOptions.length) return; compiler.hooks.compilation.tap("SharedUsedExportsOptimizerPlugin", (compilation) => { compilation.hooks.dependencyReferencedExports.tap("SharedUsedExportsOptimizerPlugin", (referencedExports, dependency, runtime) => { if (!("request" in dependency)) return referencedExports; const shareKey = dependency.request; if (typeof shareKey !== "string" || sharedOptions.every(([key]) => key !== shareKey)) return referencedExports; let currentReferencedExports = referencedExports; if (isImportDependency(dependency) && referencedExports === compilation.compiler.webpack.Dependency.EXPORTS_OBJECT_REFERENCED) { sharedReferencedExports.delete(shareKey); return currentReferencedExports; } if (isHarmonyImportSpecifierDependency(dependency) && dependency.ids && dependency.ids[0] === "default") { const { ids, referencedPropertiesInDestructuring } = dependency; const getOriginalReferencedExports = () => { if (referencedPropertiesInDestructuring) { /** @type {string[][]} */ const refs = []; for (const key of referencedPropertiesInDestructuring) refs.push({ name: ids ? ids.concat([key]) : [key], canMangle: false }); return refs; } return ids ? [ids] : [[]]; }; currentReferencedExports = getOriginalReferencedExports(); } if (!currentReferencedExports.length) return referencedExports; currentReferencedExports.forEach((item) => { if (typeof runtime !== "string") return; const exportNames = []; if (Array.isArray(item)) exportNames.push(...item); else if (Array.isArray(item.name)) exportNames.push(...item.name); exportNames.forEach((i) => { const moduleExports = sharedReferencedExports.get(shareKey); if (!moduleExports) return; moduleExports.add(i); }); }); return referencedExports; }); compilation.hooks.optimizeDependencies.tap({ name: "SharedUsedExportsOptimizerPlugin", stage: 1 }, (modules) => { this.applyCustomReferencedExports(); const sharedModules = [...modules].filter((m) => [ "consume-shared-module", "provide-module", "shared-entry-module" ].includes(m.type)); const moduleGraph = compilation.moduleGraph; sharedModules.forEach((module) => { const shareKey = module.options?.shareKey || module._name || module._name; if (!shareKey) return; if (!sharedOptions.find(([key]) => key === shareKey)?.[1].treeShaking) return; const referenceExports = sharedReferencedExports.get(shareKey); if (!referenceExports || !referenceExports.size) return; const realSharedModule = [...modules].find((m) => "rawRequest" in m && m.rawRequest === shareKey); if (realSharedModule?.factoryMeta?.sideEffectFree !== true) { referenceExports.clear(); return; } const handleDependency = (dep) => { const usedExport = [...referenceExports]; const referencedModule = moduleGraph.getModule(dep); if (!referencedModule) return; const exportsInfo = moduleGraph.getExportsInfo(referencedModule); for (let i = 0; i < usedExport.length; i++) exportsInfo.getExportInfo(usedExport[i]).setUsed(compiler.webpack.UsageState.Used, void 0); }; module.blocks.forEach((block) => { block.dependencies.forEach((dep) => { handleDependency(dep); }); }); module.dependencies.forEach((dep) => { handleDependency(dep); }); module.factoryMeta ||= {}; module.factoryMeta.sideEffectFree = true; if (!realSharedModule) return; const exportsInfo = compilation.moduleGraph.getExportsInfo(realSharedModule); let canUpdateModuleUsedStage = true; for (const subExport of exportsInfo.exports) { const used = subExport.getUsed(void 0); if (used !== 3 && used !== 0) { if (referenceExports.has(subExport.name)) continue; canUpdateModuleUsedStage = false; break; } } if (canUpdateModuleUsedStage) for (const exportInfo of exportsInfo.exports) exportInfo.setUsedConditionally((used) => used === 3, 0, void 0); }); }); if (manifestOptions) compilation.hooks.processAssets.tapPromise({ name: "injectReferenceExports", stage: compilation.constructor.PROCESS_ASSETS_STAGE_OPTIMIZE_TRANSFER }, async () => { const { statsFileName } = (0, _module_federation_sdk.getManifestFileName)(manifestOptions); const stats = compilation.getAsset(statsFileName); if (!stats) return; const statsContent = JSON.parse(stats.source.source().toString()); for (const key of sharedReferencedExports.keys()) { const sharedModule = statsContent.shared.find((s) => s.name === key); if (!sharedModule) continue; const sharedReferenceExports = sharedReferencedExports.get(key); if (!sharedReferenceExports) continue; sharedModule.usedExports = [...sharedReferenceExports]; } compilation.updateAsset(statsFileName, new compiler.webpack.sources.RawSource(JSON.stringify(statsContent, null, 2))); }); if (!injectTreeShakingUsedExports) return; compilation.hooks.additionalTreeRuntimeRequirements.tap("SharedUsedExportsOptimizerPlugin", (chunk, set) => { set.add(compiler.webpack.RuntimeGlobals.runtimeId); compilation.addRuntimeModule(chunk, new require_lib_sharing_tree_shaking_SharedUsedExportsOptimizerRuntimeModule.default(this.sharedReferencedExports)); }); }); } }; //#endregion exports.default = SharedUsedExportsOptimizerPlugin; //# sourceMappingURL=SharedUsedExportsOptimizerPlugin.js.map