@module-federation/vite 1.15.2 → 1.15.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.cjs +185 -131
- package/lib/index.mjs +189 -135
- package/package.json +2 -1
package/lib/index.cjs
CHANGED
|
@@ -544,7 +544,7 @@ function normalizeShareItem(key, shareItem) {
|
|
|
544
544
|
shareConfig: {
|
|
545
545
|
import: shareItem.import,
|
|
546
546
|
singleton: shareItem.singleton || false,
|
|
547
|
-
requiredVersion: shareItem.requiredVersion || (version ? `^${version}` : "*"),
|
|
547
|
+
requiredVersion: shareItem.requiredVersion || (isImportFalse ? "*" : version ? `^${version}` : "*"),
|
|
548
548
|
strictVersion: !!shareItem.strictVersion
|
|
549
549
|
}
|
|
550
550
|
};
|
|
@@ -661,35 +661,6 @@ function normalizeModuleFederationOptions(options) {
|
|
|
661
661
|
}
|
|
662
662
|
//#endregion
|
|
663
663
|
//#region src/utils/VirtualModule.ts
|
|
664
|
-
/**
|
|
665
|
-
* Initialize virtual module infrastructure BEFORE VirtualModule class is used.
|
|
666
|
-
* This must be called in the config hook to ensure the directory exists
|
|
667
|
-
* before Vite's optimization phase.
|
|
668
|
-
*/
|
|
669
|
-
function initVirtualModuleInfrastructure(root, virtualModuleDir = "__mf__virtual") {
|
|
670
|
-
const virtualPackagePath = (0, pathe.join)((0, pathe.join)(root, "node_modules"), virtualModuleDir);
|
|
671
|
-
(0, fs.mkdirSync)(virtualPackagePath, { recursive: true });
|
|
672
|
-
(0, fs.writeFileSync)((0, pathe.join)(virtualPackagePath, "empty.js"), "");
|
|
673
|
-
(0, fs.writeFileSync)((0, pathe.join)(virtualPackagePath, "package.json"), JSON.stringify({
|
|
674
|
-
name: virtualModuleDir,
|
|
675
|
-
main: "empty.js"
|
|
676
|
-
}));
|
|
677
|
-
}
|
|
678
|
-
let rootDir;
|
|
679
|
-
function findNodeModulesDir(root = process.cwd()) {
|
|
680
|
-
let currentDir = root;
|
|
681
|
-
while (currentDir !== (0, pathe.parse)(currentDir).root) {
|
|
682
|
-
const nodeModulesPath = (0, pathe.join)(currentDir, "node_modules");
|
|
683
|
-
if ((0, fs.existsSync)(nodeModulesPath)) return nodeModulesPath;
|
|
684
|
-
currentDir = (0, pathe.dirname)(currentDir);
|
|
685
|
-
}
|
|
686
|
-
return "";
|
|
687
|
-
}
|
|
688
|
-
let cachedNodeModulesDir;
|
|
689
|
-
function getNodeModulesDir() {
|
|
690
|
-
if (!cachedNodeModulesDir) cachedNodeModulesDir = findNodeModulesDir(rootDir);
|
|
691
|
-
return cachedNodeModulesDir;
|
|
692
|
-
}
|
|
693
664
|
function getSuffix(name) {
|
|
694
665
|
const base = (0, pathe.basename)(name);
|
|
695
666
|
const dotIndex = base.lastIndexOf(".");
|
|
@@ -698,9 +669,6 @@ function getSuffix(name) {
|
|
|
698
669
|
}
|
|
699
670
|
const patternMap = {};
|
|
700
671
|
const cacheMap = {};
|
|
701
|
-
/**
|
|
702
|
-
* Physically generate files as virtual modules under node_modules/__mf__virtual/*
|
|
703
|
-
*/
|
|
704
672
|
function assertModuleFound(tag, str = "") {
|
|
705
673
|
const module = VirtualModule.findModule(tag, str);
|
|
706
674
|
if (!module) throw createModuleFederationError(`Module Federation shared module '${str}' not found. Please ensure it's installed as a dependency in your package.json.`);
|
|
@@ -711,33 +679,16 @@ var VirtualModule = class {
|
|
|
711
679
|
tag;
|
|
712
680
|
suffix;
|
|
713
681
|
inited = false;
|
|
714
|
-
|
|
715
|
-
* Set the root path for finding node_modules
|
|
716
|
-
* @param root - Root path
|
|
717
|
-
*/
|
|
718
|
-
static setRoot(root) {
|
|
719
|
-
rootDir = root;
|
|
720
|
-
cachedNodeModulesDir = void 0;
|
|
721
|
-
}
|
|
722
|
-
/**
|
|
723
|
-
* Ensure virtual package directory exists
|
|
724
|
-
*/
|
|
725
|
-
static ensureVirtualPackageExists() {
|
|
726
|
-
const nodeModulesDir = getNodeModulesDir();
|
|
727
|
-
const { virtualModuleDir } = getNormalizeModuleFederationOptions();
|
|
728
|
-
const virtualPackagePath = (0, pathe.resolve)(nodeModulesDir, virtualModuleDir);
|
|
729
|
-
(0, fs.mkdirSync)(virtualPackagePath, { recursive: true });
|
|
730
|
-
(0, fs.writeFileSync)((0, pathe.resolve)(virtualPackagePath, "empty.js"), "");
|
|
731
|
-
(0, fs.writeFileSync)((0, pathe.resolve)(virtualPackagePath, "package.json"), JSON.stringify({
|
|
732
|
-
name: virtualModuleDir,
|
|
733
|
-
main: "empty.js"
|
|
734
|
-
}));
|
|
735
|
-
}
|
|
682
|
+
code;
|
|
736
683
|
static findModule(tag, str = "") {
|
|
737
684
|
if (!patternMap[tag]) patternMap[tag] = new RegExp(`(.*${packageNameEncode(tag)}(.+?)${packageNameEncode(tag)}.*)`);
|
|
738
685
|
const moduleName = (str.match(patternMap[tag]) || [])[2];
|
|
739
686
|
if (moduleName) return cacheMap[tag][packageNameDecode(moduleName)];
|
|
740
687
|
}
|
|
688
|
+
static findById(id) {
|
|
689
|
+
const normalized = id.replace(/^\0+/, "").replace(/^\/@id\//, "").replace(/^__x00__/, "").replace(/[?#].*$/, "");
|
|
690
|
+
for (const modules of Object.values(cacheMap)) for (const module of Object.values(modules)) if (module.getImportId() === normalized) return module;
|
|
691
|
+
}
|
|
741
692
|
constructor(name, tag = "__mf_v__", suffix = "") {
|
|
742
693
|
this.name = name;
|
|
743
694
|
this.tag = tag;
|
|
@@ -745,24 +696,20 @@ var VirtualModule = class {
|
|
|
745
696
|
if (!cacheMap[this.tag]) cacheMap[this.tag] = {};
|
|
746
697
|
cacheMap[this.tag][this.name] = this;
|
|
747
698
|
}
|
|
748
|
-
getPath() {
|
|
749
|
-
return (0, pathe.resolve)(getNodeModulesDir(), this.getImportId());
|
|
750
|
-
}
|
|
751
699
|
getImportId() {
|
|
752
|
-
const { internalName: mfName
|
|
753
|
-
return
|
|
700
|
+
const { internalName: mfName } = getNormalizeModuleFederationOptions();
|
|
701
|
+
return `virtual:mf:${packageNameEncode(`${mfName}${this.tag}${this.name}${this.tag}`)}${this.suffix}`;
|
|
702
|
+
}
|
|
703
|
+
getResolvedId() {
|
|
704
|
+
return `\0${this.getImportId()}`;
|
|
754
705
|
}
|
|
755
706
|
writeSync(code, force) {
|
|
756
707
|
if (!force && this.inited) return;
|
|
757
708
|
if (!this.inited) this.inited = true;
|
|
758
|
-
|
|
759
|
-
(0, fs.mkdirSync)((0, pathe.dirname)(path), { recursive: true });
|
|
760
|
-
(0, fs.writeFileSync)(path, code);
|
|
709
|
+
this.code = code;
|
|
761
710
|
}
|
|
762
711
|
write(code) {
|
|
763
|
-
|
|
764
|
-
(0, fs.mkdirSync)((0, pathe.dirname)(path), { recursive: true });
|
|
765
|
-
(0, fs.writeFile)(path, code, function() {});
|
|
712
|
+
this.writeSync(code, true);
|
|
766
713
|
}
|
|
767
714
|
};
|
|
768
715
|
//#endregion
|
|
@@ -964,6 +911,14 @@ globalThis[__mfCacheGlobalKey].remote ||= {};
|
|
|
964
911
|
const __mfModuleCache = globalThis[__mfCacheGlobalKey];
|
|
965
912
|
`;
|
|
966
913
|
}
|
|
914
|
+
function getRuntimeInitPromiseBootstrapCode() {
|
|
915
|
+
return getRuntimeInitStateBootstrapCode({
|
|
916
|
+
globalKeyVar: "__mfPromiseGlobalKey",
|
|
917
|
+
stateVar: "__mfPromiseState",
|
|
918
|
+
exposedConst: "initPromise",
|
|
919
|
+
exposedProperty: "initPromise"
|
|
920
|
+
});
|
|
921
|
+
}
|
|
967
922
|
function getRuntimeInitResolveBootstrapCode() {
|
|
968
923
|
return getRuntimeInitStateBootstrapCode({
|
|
969
924
|
globalKeyVar: "__mfResolveGlobalKey",
|
|
@@ -1208,6 +1163,16 @@ function writePreBuildLibPath(pkg, shareItem) {
|
|
|
1208
1163
|
export const jsx = __mfPrebuildExports.jsx;
|
|
1209
1164
|
export const jsxs = __mfPrebuildExports.jsxs;
|
|
1210
1165
|
export default __mfPrebuildExports;
|
|
1166
|
+
`, true);
|
|
1167
|
+
return;
|
|
1168
|
+
}
|
|
1169
|
+
const namedExports = getPackageNamedExports(pkg);
|
|
1170
|
+
if (namedExports.length > 0) {
|
|
1171
|
+
preBuildCacheMap[pkg].writeSync(`
|
|
1172
|
+
import * as __mfPrebuildNamespace from ${escapeGeneratedStringLiteral(importSource)};
|
|
1173
|
+
const __mfPrebuildExports = __mfPrebuildNamespace;
|
|
1174
|
+
${namedExports.map((name) => `export const ${name} = __mfPrebuildExports[${escapeGeneratedStringLiteral(name)}];`).join("\n ")}
|
|
1175
|
+
export default __mfPrebuildExports;
|
|
1211
1176
|
`, true);
|
|
1212
1177
|
return;
|
|
1213
1178
|
}
|
|
@@ -1235,25 +1200,62 @@ function getLoadShareImportId(pkg, _isRolldown) {
|
|
|
1235
1200
|
}
|
|
1236
1201
|
function getLoadShareModulePath(pkg, isRolldown) {
|
|
1237
1202
|
if (!loadShareCacheMap[pkg]) getLoadShareImportId(pkg, isRolldown);
|
|
1238
|
-
return loadShareCacheMap[pkg].
|
|
1203
|
+
return loadShareCacheMap[pkg].getImportId();
|
|
1239
1204
|
}
|
|
1205
|
+
function generateDeferredHostProvidedExports(namedExports, pkg) {
|
|
1206
|
+
const namedExportVars = namedExports.map((_name, i) => `__mf_${i}`);
|
|
1207
|
+
const declarations = ["let __mf_default;", ...namedExportVars.map((name) => `let ${name};`)].join("\n ");
|
|
1208
|
+
const assignments = [...namedExports.map((name, i) => `${namedExportVars[i]} = exportModule[${escapeGeneratedStringLiteral(name)}];`), "__mf_default = exportModule.default ?? exportModule;"].join("\n ");
|
|
1209
|
+
const namedExportLine = namedExports.length > 0 ? `\n export { ${namedExports.map((name, i) => `${namedExportVars[i]} as ${name}`).join(", ")} };` : "";
|
|
1210
|
+
return `${declarations}
|
|
1211
|
+
const __mfApplyHostProvidedExports = (exportModule) => {
|
|
1212
|
+
${assignments}
|
|
1213
|
+
};
|
|
1214
|
+
let exportModule = __mfModuleCache.share[${escapeGeneratedStringLiteral(pkg)}];
|
|
1215
|
+
if (exportModule === undefined) {
|
|
1216
|
+
initPromise.then(() => {
|
|
1217
|
+
exportModule = __mfModuleCache.share[${escapeGeneratedStringLiteral(pkg)}];
|
|
1218
|
+
if (exportModule === undefined) {
|
|
1219
|
+
throw new Error("[Module Federation] Shared module ${pkg} was imported before federation bootstrap finished.");
|
|
1220
|
+
}
|
|
1221
|
+
__mfApplyHostProvidedExports(exportModule);
|
|
1222
|
+
});
|
|
1223
|
+
} else {
|
|
1224
|
+
__mfApplyHostProvidedExports(exportModule);
|
|
1225
|
+
}
|
|
1226
|
+
export { __mf_default as default };${namedExportLine}`;
|
|
1227
|
+
}
|
|
1228
|
+
function generateShareModuleUnwrapCode({ source, preserveNamedExports, stopWithReturn }) {
|
|
1229
|
+
return `let current = ${source};
|
|
1230
|
+
for (let i = 0; i < 5; i++) {
|
|
1231
|
+
const defaultExport = current?.default;
|
|
1232
|
+
${stopWithReturn ? `if (!defaultExport || typeof defaultExport !== "object") return ${stopWithReturn};` : `if (!defaultExport || typeof defaultExport !== "object") break;`}${preserveNamedExports ? `
|
|
1233
|
+
const namedValues = Object.keys(current).filter((key) => key !== "default").map((key) => current[key]);
|
|
1234
|
+
if (namedValues.length > 0 && namedValues.some((value) => value !== undefined)) break;` : ""}
|
|
1235
|
+
current = defaultExport;
|
|
1236
|
+
}
|
|
1237
|
+
return current;`;
|
|
1238
|
+
}
|
|
1239
|
+
const normalizeLocalShareModuleCode = `const __mfNormalizeShareModule = (mod) => {
|
|
1240
|
+
${generateShareModuleUnwrapCode({
|
|
1241
|
+
source: "mod",
|
|
1242
|
+
preserveNamedExports: true
|
|
1243
|
+
})}
|
|
1244
|
+
};`;
|
|
1240
1245
|
function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
|
|
1241
1246
|
if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, ".mjs");
|
|
1242
1247
|
const importLine = getRuntimeModuleCacheBootstrapCode();
|
|
1243
1248
|
if (shareItem.shareConfig.import === false) {
|
|
1244
1249
|
const namedExports = getPackageNamedExports(pkg);
|
|
1245
1250
|
let exportLine;
|
|
1246
|
-
if (namedExports.length > 0) exportLine =
|
|
1251
|
+
if (namedExports.length > 0) exportLine = generateDeferredHostProvidedExports(namedExports, pkg);
|
|
1247
1252
|
else {
|
|
1248
1253
|
mfWarn(`Shared dependency "${pkg}" has import: false but is not installed locally.\n Named imports (e.g. import { ... } from '${pkg}') will not work in production builds.\n Install it as a devDependency to enable named export detection.`);
|
|
1249
|
-
exportLine =
|
|
1254
|
+
exportLine = generateDeferredHostProvidedExports([], pkg);
|
|
1250
1255
|
}
|
|
1251
1256
|
loadShareCacheMap[pkg].writeSync(`
|
|
1257
|
+
${getRuntimeInitPromiseBootstrapCode()}
|
|
1252
1258
|
${importLine}
|
|
1253
|
-
const exportModule = __mfModuleCache.share[${escapeGeneratedStringLiteral(pkg)}]
|
|
1254
|
-
if (exportModule === undefined) {
|
|
1255
|
-
throw new Error("[Module Federation] Shared module ${pkg} was imported before federation bootstrap finished.")
|
|
1256
|
-
}
|
|
1257
1259
|
${exportLine}
|
|
1258
1260
|
`, true);
|
|
1259
1261
|
return;
|
|
@@ -1268,8 +1270,20 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
|
|
|
1268
1270
|
const usesLazyLocalFallback = isWorkspacePackage && shareItem.shareConfig.singleton === true;
|
|
1269
1271
|
const namedExports = getPackageNamedExports(pkg);
|
|
1270
1272
|
let exportLine;
|
|
1271
|
-
if (namedExports.length > 0)
|
|
1272
|
-
|
|
1273
|
+
if (namedExports.length > 0) {
|
|
1274
|
+
const destructure = `const { ${namedExports.map((name, i) => `${name}: __mf_${i}`).join(", ")} } = exportModule;`;
|
|
1275
|
+
const namedExportLine = `export { ${namedExports.map((name, i) => `__mf_${i} as ${name}`).join(", ")} };`;
|
|
1276
|
+
exportLine = `const __mfDefaultExport = (() => {
|
|
1277
|
+
${generateShareModuleUnwrapCode({
|
|
1278
|
+
source: "exportModule",
|
|
1279
|
+
preserveNamedExports: false,
|
|
1280
|
+
stopWithReturn: "defaultExport ?? current"
|
|
1281
|
+
})}
|
|
1282
|
+
})();
|
|
1283
|
+
export default __mfDefaultExport;
|
|
1284
|
+
${destructure}
|
|
1285
|
+
${namedExportLine}`;
|
|
1286
|
+
} else if (usesLazyLocalFallback) exportLine = `export default exportModule.default ?? exportModule`;
|
|
1273
1287
|
else exportLine = `export default exportModule.default ?? exportModule\n export * from ${escapeGeneratedStringLiteral(sharedImportSource)}`;
|
|
1274
1288
|
const prebuildImportLine = usesLazyLocalFallback || isWorkspacePackage && command !== "build" ? "" : `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(skipServePrebuildWarmup ? devImportSource : sharedImportSource)};`;
|
|
1275
1289
|
const devDynamicImportLine = isWorkspacePackage ? "" : command !== "build" && !skipServePrebuildWarmup ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
|
|
@@ -1277,10 +1291,11 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
|
|
|
1277
1291
|
${prebuildImportLine}
|
|
1278
1292
|
${devDynamicImportLine}
|
|
1279
1293
|
${importLine}
|
|
1294
|
+
${normalizeLocalShareModuleCode}
|
|
1280
1295
|
let exportModule = __mfModuleCache.share[${escapeGeneratedStringLiteral(pkg)}]
|
|
1281
1296
|
if (exportModule === undefined) {
|
|
1282
|
-
${usesLazyLocalFallback ? `exportModule = await import(${escapeGeneratedStringLiteral(lazyLocalFallbackSource)});
|
|
1283
|
-
__mfModuleCache.share[${escapeGeneratedStringLiteral(pkg)}] = exportModule;` : `exportModule = __mfLocalShare;
|
|
1297
|
+
${usesLazyLocalFallback ? `exportModule = __mfNormalizeShareModule(await import(${escapeGeneratedStringLiteral(lazyLocalFallbackSource)}));
|
|
1298
|
+
__mfModuleCache.share[${escapeGeneratedStringLiteral(pkg)}] = exportModule;` : `exportModule = __mfNormalizeShareModule(__mfLocalShare);
|
|
1284
1299
|
__mfModuleCache.share[${escapeGeneratedStringLiteral(pkg)}] = exportModule;`}
|
|
1285
1300
|
}
|
|
1286
1301
|
${exportLine}
|
|
@@ -1438,9 +1453,9 @@ function getShareItemForPreload(pkg) {
|
|
|
1438
1453
|
function generateSharedCacheSeedItem(pkg, importPath) {
|
|
1439
1454
|
return `if (__mfModuleCache.share[${JSON.stringify(pkg)}] === undefined) {
|
|
1440
1455
|
const mod = await import(${JSON.stringify(importPath)});
|
|
1441
|
-
|
|
1442
|
-
|
|
1443
|
-
|
|
1456
|
+
${normalizeRuntimeShareCode}
|
|
1457
|
+
const normalizedModule = __mfNormalizeRuntimeShare(mod);
|
|
1458
|
+
const exportModule = normalizedModule === mod ? {...mod} : normalizedModule;
|
|
1444
1459
|
Object.defineProperty(exportModule, "__esModule", {
|
|
1445
1460
|
value: true,
|
|
1446
1461
|
enumerable: false
|
|
@@ -1448,6 +1463,17 @@ function generateSharedCacheSeedItem(pkg, importPath) {
|
|
|
1448
1463
|
__mfModuleCache.share[${JSON.stringify(pkg)}] = exportModule;
|
|
1449
1464
|
}`;
|
|
1450
1465
|
}
|
|
1466
|
+
const normalizeRuntimeShareCode = `const __mfNormalizeRuntimeShare = (mod) => {
|
|
1467
|
+
let current = mod;
|
|
1468
|
+
for (let i = 0; i < 5; i++) {
|
|
1469
|
+
const defaultExport = current?.default;
|
|
1470
|
+
if (!defaultExport || typeof defaultExport !== "object") break;
|
|
1471
|
+
const namedValues = Object.keys(current).filter((key) => key !== "default").map((key) => current[key]);
|
|
1472
|
+
if (namedValues.length > 0 && namedValues.some((value) => value !== undefined)) break;
|
|
1473
|
+
current = defaultExport;
|
|
1474
|
+
}
|
|
1475
|
+
return current;
|
|
1476
|
+
};`;
|
|
1451
1477
|
function generateDirectSharedCacheSeedCode(command = "build") {
|
|
1452
1478
|
return getOrderedUsedShares().map((pkg) => {
|
|
1453
1479
|
const shareItem = getShareItemForPreload(pkg);
|
|
@@ -1470,7 +1496,8 @@ function getHostAutoInitSharedSeedItems() {
|
|
|
1470
1496
|
return priority(a.pkg) - priority(b.pkg) || Number(aIsLocal) - Number(bIsLocal) || a.pkg.localeCompare(b.pkg);
|
|
1471
1497
|
});
|
|
1472
1498
|
}
|
|
1473
|
-
function generateHostAutoInitSharedCacheSeedCode() {
|
|
1499
|
+
function generateHostAutoInitSharedCacheSeedCode(command = "build") {
|
|
1500
|
+
if (command === "build") return "";
|
|
1474
1501
|
return getHostAutoInitSharedSeedItems().map(({ pkg, shareItem }) => {
|
|
1475
1502
|
if (!shareItem) return null;
|
|
1476
1503
|
return generateSharedCacheSeedItem(pkg, getBrowserImportPath(getDirectSharedCacheSeedImportPath(pkg, shareItem)));
|
|
@@ -1502,14 +1529,13 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
1502
1529
|
if (typeof __VUE_HMR_RUNTIME__ === 'undefined') {
|
|
1503
1530
|
globalThis.__VUE_HMR_RUNTIME__ = { createRecord() {}, rerender() {}, reload() {} };
|
|
1504
1531
|
}
|
|
1505
|
-
import {
|
|
1532
|
+
import {init as runtimeInit, loadRemote} from "@module-federation/runtime";
|
|
1506
1533
|
${pluginImportNames.map((item) => item[1]).join("\n")}
|
|
1507
1534
|
${command === "build" ? getRuntimeInitResolveBootstrapCode() : getRuntimeInitBootstrapCode() + "\n const { initResolve } = globalThis[globalKey];"}
|
|
1508
1535
|
${getRuntimeModuleCacheBootstrapCode()}
|
|
1509
1536
|
const initTokens = {}
|
|
1510
1537
|
const shareScopeName = ${JSON.stringify(options.shareScope)}
|
|
1511
1538
|
const mfName = ${JSON.stringify(options.internalName)}
|
|
1512
|
-
let runtimeInstance
|
|
1513
1539
|
let localSharedImportMapPromise
|
|
1514
1540
|
let exposesMapPromise
|
|
1515
1541
|
const shouldRetrySharedInitError = ${command !== "build"} && ((error) => {
|
|
@@ -1552,19 +1578,13 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
1552
1578
|
async function init(shared = {}, initScope = []) {
|
|
1553
1579
|
const {usedShared, usedRemotes} = await getLocalSharedImportMap()
|
|
1554
1580
|
${generateDirectSharedCacheSeedCode(command)}
|
|
1555
|
-
const
|
|
1581
|
+
const initRes = runtimeInit({
|
|
1556
1582
|
name: mfName,
|
|
1557
1583
|
remotes: usedRemotes,
|
|
1558
1584
|
shared: usedShared,
|
|
1559
1585
|
plugins: [${pluginImportNames.map((item) => `${item[0]}(${item[2]})`).join(", ")}],
|
|
1560
1586
|
${options.shareStrategy ? `shareStrategy: '${options.shareStrategy}'` : ""}
|
|
1561
|
-
};
|
|
1562
|
-
if (!runtimeInstance) {
|
|
1563
|
-
runtimeInstance = createInstance(runtimeOptions);
|
|
1564
|
-
} else {
|
|
1565
|
-
runtimeInstance.initOptions(runtimeOptions);
|
|
1566
|
-
}
|
|
1567
|
-
const initRes = runtimeInstance;
|
|
1587
|
+
});
|
|
1568
1588
|
// handling circular init calls
|
|
1569
1589
|
var initToken = initTokens[shareScopeName];
|
|
1570
1590
|
if (!initToken)
|
|
@@ -1584,6 +1604,17 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
1584
1604
|
} catch (e) {
|
|
1585
1605
|
console.error('[Module Federation]', e)
|
|
1586
1606
|
}
|
|
1607
|
+
for (const [pkg, share] of Object.entries(usedShared)) {
|
|
1608
|
+
if (share.shareConfig?.import !== false || __mfModuleCache.share[pkg] !== undefined) continue;
|
|
1609
|
+
${normalizeRuntimeShareCode}
|
|
1610
|
+
const versions = shared?.[pkg];
|
|
1611
|
+
const provider = versions && versions[Object.keys(versions)[0]];
|
|
1612
|
+
if (!provider) continue;
|
|
1613
|
+
const factory = provider.lib || (provider.loading ? await provider.loading : await provider.get?.());
|
|
1614
|
+
const mod = typeof factory === "function" ? factory() : factory;
|
|
1615
|
+
const resolved = await Promise.resolve(mod);
|
|
1616
|
+
__mfModuleCache.share[pkg] = __mfNormalizeRuntimeShare(resolved);
|
|
1617
|
+
}
|
|
1587
1618
|
return initRes
|
|
1588
1619
|
}
|
|
1589
1620
|
|
|
@@ -1608,10 +1639,11 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build") {
|
|
|
1608
1639
|
async function initHost() {
|
|
1609
1640
|
if (!hostInitPromise) {
|
|
1610
1641
|
hostInitPromise = (async () => {
|
|
1611
|
-
${generateHostAutoInitSharedCacheSeedCode()}
|
|
1642
|
+
${generateHostAutoInitSharedCacheSeedCode(_command)}
|
|
1612
1643
|
const remoteEntry = await import(${remoteEntryImport});
|
|
1613
1644
|
const runtime = await remoteEntry.init();
|
|
1614
1645
|
const usedShared = ${generateUsedSharedPreloadConfig()};
|
|
1646
|
+
${normalizeRuntimeShareCode}
|
|
1615
1647
|
for (const [pkg, share] of Object.entries(usedShared)) {
|
|
1616
1648
|
if (__mfModuleCache.share[pkg] !== undefined) {
|
|
1617
1649
|
continue;
|
|
@@ -1621,7 +1653,7 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build") {
|
|
|
1621
1653
|
}).then((factory) => {
|
|
1622
1654
|
const mod = typeof factory === "function" ? factory() : factory;
|
|
1623
1655
|
return Promise.resolve(mod).then((resolved) => {
|
|
1624
|
-
__mfModuleCache.share[pkg] = resolved;
|
|
1656
|
+
__mfModuleCache.share[pkg] = __mfNormalizeRuntimeShare(resolved);
|
|
1625
1657
|
});
|
|
1626
1658
|
});
|
|
1627
1659
|
}
|
|
@@ -1650,7 +1682,7 @@ function getHostAutoInitImportId() {
|
|
|
1650
1682
|
return hostAutoInitModule.getImportId();
|
|
1651
1683
|
}
|
|
1652
1684
|
function getHostAutoInitPath() {
|
|
1653
|
-
return hostAutoInitModule.
|
|
1685
|
+
return hostAutoInitModule.getImportId();
|
|
1654
1686
|
}
|
|
1655
1687
|
//#endregion
|
|
1656
1688
|
//#region src/virtualModules/virtualRemotes.ts
|
|
@@ -1673,7 +1705,9 @@ function getUsedRemotesMap() {
|
|
|
1673
1705
|
}
|
|
1674
1706
|
function generateRemotes(id, command) {
|
|
1675
1707
|
const useReactProxy = command === "serve" && hasPackageDependency("react");
|
|
1676
|
-
const reactImportLine = useReactProxy ? `import
|
|
1708
|
+
const reactImportLine = useReactProxy ? `import __mfReactDefault from "react";
|
|
1709
|
+
import * as __mfReactNamespace from "react";
|
|
1710
|
+
const __mfReact = __mfReactDefault ?? __mfReactNamespace.default ?? __mfReactNamespace;` : "";
|
|
1677
1711
|
const importLine = command === "build" ? `${getRuntimeModuleCacheBootstrapCode()}
|
|
1678
1712
|
import { hostInitPromise as __mfHostInitPromise } from ${JSON.stringify(getHostAutoInitPath())};` : `${getRuntimeInitBootstrapCode()}
|
|
1679
1713
|
const { initPromise, moduleCache: __mfModuleCache } = globalThis[globalKey];`;
|
|
@@ -1683,13 +1717,13 @@ function generateRemotes(id, command) {
|
|
|
1683
1717
|
}
|
|
1684
1718
|
export const __moduleExports = exportModule;
|
|
1685
1719
|
export const __mf_remote_pending = Promise.resolve(exportModule);
|
|
1686
|
-
export default exportModule?.__esModule ? exportModule.default : exportModule.default ?? exportModule` : command === "build" ? `if (__mfRemotePending) {
|
|
1720
|
+
export default exportModule?.__mf_is_remote_proxy ? exportModule : exportModule?.__esModule ? exportModule.default : exportModule.default ?? exportModule` : command === "build" ? `if (__mfRemotePending) {
|
|
1687
1721
|
const mod = await __mfRemotePending;
|
|
1688
1722
|
if (mod !== undefined) exportModule = mod;
|
|
1689
1723
|
}
|
|
1690
1724
|
export const __moduleExports = exportModule;
|
|
1691
1725
|
export const __mf_remote_pending = Promise.resolve(exportModule);
|
|
1692
|
-
export default exportModule?.__esModule ? exportModule.default : exportModule.default ?? exportModule` : "export default exportModule";
|
|
1726
|
+
export default exportModule?.__mf_is_remote_proxy ? exportModule : exportModule?.__esModule ? exportModule.default : exportModule.default ?? exportModule` : "export default exportModule";
|
|
1693
1727
|
return `
|
|
1694
1728
|
${reactImportLine}
|
|
1695
1729
|
${importLine}
|
|
@@ -1889,6 +1923,9 @@ ${importHelper}(async () => {
|
|
|
1889
1923
|
if (inject === "html" && hasPackageDependency("@sveltejs/kit")) return false;
|
|
1890
1924
|
return inject === "entry" || !htmlFilePath;
|
|
1891
1925
|
}
|
|
1926
|
+
function normalizeDevHtmlProxyId(id) {
|
|
1927
|
+
return id.replace(/^\0/, "").replace(/^\/@id\//, "").replace(/^__x00__/, "");
|
|
1928
|
+
}
|
|
1892
1929
|
return [{
|
|
1893
1930
|
name: "add-entry",
|
|
1894
1931
|
apply: "serve",
|
|
@@ -1907,7 +1944,20 @@ ${importHelper}(async () => {
|
|
|
1907
1944
|
}
|
|
1908
1945
|
},
|
|
1909
1946
|
configureServer(server) {
|
|
1910
|
-
server.middlewares.use((req,
|
|
1947
|
+
server.middlewares.use((req, res, next) => {
|
|
1948
|
+
const rawUrl = req.url?.split("#")[0] ?? "";
|
|
1949
|
+
if (normalizeDevHtmlProxyId(rawUrl.split("?")[0]) === DEV_HTML_PROXY_PREFIX.slice(0, -1)) {
|
|
1950
|
+
const query = rawUrl.slice(rawUrl.indexOf("?") + 1);
|
|
1951
|
+
const params = new URLSearchParams(query);
|
|
1952
|
+
const initSrc = params.get("init");
|
|
1953
|
+
const entrySrc = params.get("entry");
|
|
1954
|
+
if (initSrc && entrySrc) {
|
|
1955
|
+
res.statusCode = 200;
|
|
1956
|
+
res.setHeader("Content-Type", "application/javascript");
|
|
1957
|
+
res.end(getBootstrapSource(initSrc, entrySrc));
|
|
1958
|
+
return;
|
|
1959
|
+
}
|
|
1960
|
+
}
|
|
1911
1961
|
if (!fileName) {
|
|
1912
1962
|
next();
|
|
1913
1963
|
return;
|
|
@@ -1924,7 +1974,7 @@ ${importHelper}(async () => {
|
|
|
1924
1974
|
const base = viteConfig.base.replace(/\/$/, "");
|
|
1925
1975
|
const stripBase = (p) => base && p.startsWith(base + "/") ? p.slice(base.length) : p;
|
|
1926
1976
|
const html = rewriteEntryScripts(c, (originalSrc) => {
|
|
1927
|
-
return `/@id
|
|
1977
|
+
return `/@id/__x00__${DEV_HTML_PROXY_PREFIX}${new URLSearchParams({
|
|
1928
1978
|
init: sanitizeDevEntryPath(stripBase(devEntryPath)),
|
|
1929
1979
|
entry: sanitizeDevEntryPath(stripBase(originalSrc))
|
|
1930
1980
|
}).toString()}`;
|
|
@@ -1933,11 +1983,12 @@ ${importHelper}(async () => {
|
|
|
1933
1983
|
}
|
|
1934
1984
|
},
|
|
1935
1985
|
resolveId(id) {
|
|
1936
|
-
if (id.startsWith(DEV_HTML_PROXY_PREFIX)) return id;
|
|
1986
|
+
if (normalizeDevHtmlProxyId(id).startsWith(DEV_HTML_PROXY_PREFIX)) return id;
|
|
1937
1987
|
},
|
|
1938
1988
|
load(id) {
|
|
1939
|
-
|
|
1940
|
-
|
|
1989
|
+
const normalizedId = normalizeDevHtmlProxyId(id);
|
|
1990
|
+
if (!normalizedId.startsWith(DEV_HTML_PROXY_PREFIX)) return;
|
|
1991
|
+
const params = new URLSearchParams(normalizedId.slice(28));
|
|
1941
1992
|
const initSrc = params.get("init");
|
|
1942
1993
|
const entrySrc = params.get("entry");
|
|
1943
1994
|
if (!initSrc || !entrySrc) return;
|
|
@@ -2744,7 +2795,7 @@ function collectSystemProxyInfos(proxyChunks, loadShareTag) {
|
|
|
2744
2795
|
for (const m of proxyInfo.code.matchAll(/exports\(\s*["']([^"']+)["']\s*,([\s\S]*?)\);/g)) {
|
|
2745
2796
|
const exported = m[1];
|
|
2746
2797
|
const expression = m[2];
|
|
2747
|
-
for (const [local, exportName] of Object.entries(loadShareBindings)) if (new RegExp(`\\b${local}\\b`).test(expression)) {
|
|
2798
|
+
for (const [local, exportName] of Object.entries(loadShareBindings).reverse()) if (new RegExp(`\\b${local}\\b`).test(expression)) {
|
|
2748
2799
|
exportMap[exported] = {
|
|
2749
2800
|
type: "reexport",
|
|
2750
2801
|
exportName
|
|
@@ -3508,7 +3559,7 @@ function pluginProxyRemotes_default(options) {
|
|
|
3508
3559
|
const remoteModule = getRemoteVirtualModule(source, command);
|
|
3509
3560
|
addUsedRemote(remoteName, source);
|
|
3510
3561
|
refreshHostAutoInit();
|
|
3511
|
-
return remoteModule.
|
|
3562
|
+
return remoteModule.getImportId();
|
|
3512
3563
|
}
|
|
3513
3564
|
return {
|
|
3514
3565
|
name: "proxyRemotes",
|
|
@@ -4330,12 +4381,12 @@ function isFederationHtmlPreloadDependency(dep, includeSharedRuntime = false) {
|
|
|
4330
4381
|
return includeSharedRuntime && (file.includes("preload-helper") || file.includes("rolldown-runtime") || file.startsWith("dist-"));
|
|
4331
4382
|
}
|
|
4332
4383
|
/**
|
|
4333
|
-
* Plugin that runs FIRST to
|
|
4334
|
-
* This prevents 504 "Outdated Optimize Dep" errors by ensuring
|
|
4384
|
+
* Plugin that runs FIRST to register generated virtual modules in the config hook.
|
|
4385
|
+
* This prevents 504 "Outdated Optimize Dep" errors by ensuring ids are known
|
|
4335
4386
|
* before Vite's optimization phase.
|
|
4336
4387
|
*/
|
|
4337
4388
|
function createEarlyVirtualModulesPlugin(options) {
|
|
4338
|
-
const { shared, remotes
|
|
4389
|
+
const { shared, remotes } = options;
|
|
4339
4390
|
const isLitShare = (pkg) => pkg === "lit" || pkg.startsWith("lit/");
|
|
4340
4391
|
return {
|
|
4341
4392
|
name: "vite:module-federation-early-init",
|
|
@@ -4345,9 +4396,6 @@ function createEarlyVirtualModulesPlugin(options) {
|
|
|
4345
4396
|
const root = config.root || process.cwd();
|
|
4346
4397
|
setPackageDetectionCwd(root);
|
|
4347
4398
|
const isVinext = hasPackageDependency("vinext");
|
|
4348
|
-
initVirtualModuleInfrastructure(root, virtualModuleDir);
|
|
4349
|
-
VirtualModule.setRoot(root);
|
|
4350
|
-
VirtualModule.ensureVirtualPackageExists();
|
|
4351
4399
|
initVirtualModules(_command, getRemoteEntryId(options));
|
|
4352
4400
|
const isRolldown = getIsRolldown(this);
|
|
4353
4401
|
if (remotes && Object.keys(remotes).length > 0) {
|
|
@@ -4393,6 +4441,10 @@ function createEarlyVirtualModulesPlugin(options) {
|
|
|
4393
4441
|
optimizeDeps.esbuildOptions.plugins.push({
|
|
4394
4442
|
name: "module-federation:optimize-shared-proxy",
|
|
4395
4443
|
setup(build) {
|
|
4444
|
+
build.onResolve({ filter: /^virtual:mf:/ }, (args) => ({
|
|
4445
|
+
path: args.path,
|
|
4446
|
+
external: true
|
|
4447
|
+
}));
|
|
4396
4448
|
build.onResolve({ filter: /.*/ }, (args) => {
|
|
4397
4449
|
if (!args.importer || args.namespace === "mf-shared") return;
|
|
4398
4450
|
if (isSharedResolverInternalImporter(args.importer)) return;
|
|
@@ -4424,7 +4476,6 @@ export default __mfShared.default ?? __mfShared;`
|
|
|
4424
4476
|
}
|
|
4425
4477
|
});
|
|
4426
4478
|
}
|
|
4427
|
-
config.optimizeDeps.include.push(virtualRuntimeInitStatus.getImportId());
|
|
4428
4479
|
}
|
|
4429
4480
|
for (const key of Object.keys(shared)) {
|
|
4430
4481
|
const shareItem = shared[key];
|
|
@@ -4435,7 +4486,6 @@ export default __mfShared.default ?? __mfShared;`
|
|
|
4435
4486
|
for (const subpath of getCommonSharedSubpaths(key)) {
|
|
4436
4487
|
writePreBuildLibPath(subpath, shareItem);
|
|
4437
4488
|
optimizeDeps.include.push(subpath);
|
|
4438
|
-
optimizeDeps.include.push(getPreBuildLibImportId(subpath));
|
|
4439
4489
|
}
|
|
4440
4490
|
}
|
|
4441
4491
|
continue;
|
|
@@ -4452,14 +4502,11 @@ export default __mfShared.default ?? __mfShared;`
|
|
|
4452
4502
|
const optimizeDeps = config.optimizeDeps ??= {};
|
|
4453
4503
|
optimizeDeps.include ??= [];
|
|
4454
4504
|
optimizeDeps.exclude ??= [];
|
|
4455
|
-
|
|
4456
|
-
|
|
4457
|
-
if (!isRolldown && !shouldBypassOptimizeDep) optimizeDeps.include.push(getLoadShareImportId(key, isRolldown));
|
|
4458
|
-
optimizeDeps.include.push(getPreBuildLibImportId(key));
|
|
4505
|
+
if (isLitShare(key)) optimizeDeps.exclude.push(key);
|
|
4506
|
+
else optimizeDeps.include.push(key);
|
|
4459
4507
|
for (const subpath of getCommonSharedSubpaths(key)) {
|
|
4460
4508
|
writePreBuildLibPath(subpath, shareItem);
|
|
4461
4509
|
optimizeDeps.include.push(subpath);
|
|
4462
|
-
optimizeDeps.include.push(getPreBuildLibImportId(subpath));
|
|
4463
4510
|
}
|
|
4464
4511
|
}
|
|
4465
4512
|
}
|
|
@@ -4479,6 +4526,21 @@ function federation(mfUserOptions) {
|
|
|
4479
4526
|
let command;
|
|
4480
4527
|
let desiredRolldownOutput;
|
|
4481
4528
|
return [
|
|
4529
|
+
{
|
|
4530
|
+
name: "vite:module-federation-virtual-modules",
|
|
4531
|
+
enforce: "pre",
|
|
4532
|
+
resolveId(id) {
|
|
4533
|
+
const virtualModule = VirtualModule.findById(id);
|
|
4534
|
+
if (!virtualModule) return;
|
|
4535
|
+
return virtualModule.getResolvedId();
|
|
4536
|
+
},
|
|
4537
|
+
load(id) {
|
|
4538
|
+
const virtualModule = VirtualModule.findById(id);
|
|
4539
|
+
if (!virtualModule) return;
|
|
4540
|
+
if (command === "build" && (id.includes("__loadShare__") || id.includes("__loadRemote__"))) return;
|
|
4541
|
+
return virtualModule.code;
|
|
4542
|
+
}
|
|
4543
|
+
},
|
|
4482
4544
|
createEarlyVirtualModulesPlugin(options),
|
|
4483
4545
|
...isVinext ? [{
|
|
4484
4546
|
name: "module-federation-vinext-react-server-build-alias",
|
|
@@ -4503,9 +4565,7 @@ function federation(mfUserOptions) {
|
|
|
4503
4565
|
config(_config, env) {
|
|
4504
4566
|
command = env.command;
|
|
4505
4567
|
},
|
|
4506
|
-
configResolved(
|
|
4507
|
-
VirtualModule.setRoot(config.root);
|
|
4508
|
-
VirtualModule.ensureVirtualPackageExists();
|
|
4568
|
+
configResolved() {
|
|
4509
4569
|
initVirtualModules(command, remoteEntryId);
|
|
4510
4570
|
}
|
|
4511
4571
|
},
|
|
@@ -4648,9 +4708,8 @@ function federation(mfUserOptions) {
|
|
|
4648
4708
|
}
|
|
4649
4709
|
},
|
|
4650
4710
|
load(id) {
|
|
4651
|
-
if (id.startsWith("\0")) return;
|
|
4652
4711
|
if (id.includes("__loadShare__") || id.includes("__loadRemote__")) {
|
|
4653
|
-
let code = (0, fs.readFileSync)(id, "utf-8");
|
|
4712
|
+
let code = VirtualModule.findById(id)?.code ?? (0, fs.readFileSync)(id, "utf-8");
|
|
4654
4713
|
code = code.replace(/import\s+["'][^"']*__prebuild__[^"']*["']\s*;?/g, "");
|
|
4655
4714
|
code = code.replace(/export\s+\*\s+from\s+["'][^"']*__prebuild__[^"']*["']\s*;?/g, "");
|
|
4656
4715
|
/**
|
|
@@ -4669,7 +4728,10 @@ function federation(mfUserOptions) {
|
|
|
4669
4728
|
*
|
|
4670
4729
|
* @see https://rollupjs.org/plugin-development/#synthetic-named-exports
|
|
4671
4730
|
*/
|
|
4672
|
-
if (
|
|
4731
|
+
if (!/\bexport\s+const\s+__moduleExports\b/.test(code)) {
|
|
4732
|
+
const nextCode = code.replace("export default exportModule", "export const __moduleExports = exportModule;\nexport default exportModule.__esModule ? exportModule.default : exportModule");
|
|
4733
|
+
code = nextCode === code ? `${code}\nexport const __moduleExports = exportModule;\n` : nextCode;
|
|
4734
|
+
}
|
|
4673
4735
|
if (getIsRolldown(this)) return { code };
|
|
4674
4736
|
return {
|
|
4675
4737
|
code,
|
|
@@ -4734,14 +4796,9 @@ function federation(mfUserOptions) {
|
|
|
4734
4796
|
config.build ||= {};
|
|
4735
4797
|
config.build.commonjsOptions ||= {};
|
|
4736
4798
|
config.build.commonjsOptions.strictRequires ??= "auto";
|
|
4737
|
-
const virtualDir = options.virtualModuleDir;
|
|
4738
4799
|
config.optimizeDeps ||= {};
|
|
4739
4800
|
config.optimizeDeps.include ||= [];
|
|
4740
4801
|
config.optimizeDeps.include.push("@module-federation/runtime");
|
|
4741
|
-
if (!isRolldown) config.optimizeDeps.include.push(virtualDir);
|
|
4742
|
-
config.ssr ||= {};
|
|
4743
|
-
config.ssr.noExternal ||= [];
|
|
4744
|
-
if (Array.isArray(config.ssr.noExternal)) config.ssr.noExternal.push(virtualDir);
|
|
4745
4802
|
options.runtimePlugins.forEach((p) => {
|
|
4746
4803
|
const pluginPath = typeof p === "string" ? p : p[0];
|
|
4747
4804
|
if (pluginPath && !pluginPath.startsWith(".") && !pluginPath.startsWith("/") && !pluginPath.startsWith("\0") && !pluginPath.startsWith("virtual:")) config.optimizeDeps.include.push(pluginPath);
|
|
@@ -4749,9 +4806,6 @@ function federation(mfUserOptions) {
|
|
|
4749
4806
|
if (isRolldown) {
|
|
4750
4807
|
config.build ??= {};
|
|
4751
4808
|
config.build.target ??= "esnext";
|
|
4752
|
-
} else {
|
|
4753
|
-
config.optimizeDeps.needsInterop ||= [];
|
|
4754
|
-
config.optimizeDeps.needsInterop.push(virtualDir);
|
|
4755
4809
|
}
|
|
4756
4810
|
const isAstro = hasPackageDependency("astro");
|
|
4757
4811
|
const resolvedTarget = options.target ?? (config.build?.ssr ? "node" : "web");
|
package/lib/index.mjs
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { createRequire } from "node:module";
|
|
2
2
|
import * as fs$1 from "fs";
|
|
3
|
-
import fs, { existsSync,
|
|
3
|
+
import fs, { existsSync, readFileSync, readdirSync, realpathSync, statSync, writeFileSync } from "fs";
|
|
4
4
|
import { createRequire as createRequire$1 } from "module";
|
|
5
5
|
import * as path$1 from "pathe";
|
|
6
|
-
import path, { basename
|
|
6
|
+
import path, { basename } from "pathe";
|
|
7
7
|
import { normalizeOptions } from "@module-federation/sdk";
|
|
8
8
|
import { consumeTypesAPI, generateTypesAPI, isTSProject, normalizeConsumeTypesOptions, normalizeDtsOptions, normalizeGenerateTypesOptions } from "@module-federation/dts-plugin";
|
|
9
9
|
import { rpc } from "@module-federation/dts-plugin/core";
|
|
10
10
|
import { fileURLToPath } from "url";
|
|
11
|
-
import { init, parse
|
|
11
|
+
import { init, parse } from "es-module-lexer";
|
|
12
12
|
//#region \0rolldown/runtime.js
|
|
13
13
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
14
14
|
//#endregion
|
|
@@ -524,7 +524,7 @@ function normalizeShareItem(key, shareItem) {
|
|
|
524
524
|
shareConfig: {
|
|
525
525
|
import: shareItem.import,
|
|
526
526
|
singleton: shareItem.singleton || false,
|
|
527
|
-
requiredVersion: shareItem.requiredVersion || (version ? `^${version}` : "*"),
|
|
527
|
+
requiredVersion: shareItem.requiredVersion || (isImportFalse ? "*" : version ? `^${version}` : "*"),
|
|
528
528
|
strictVersion: !!shareItem.strictVersion
|
|
529
529
|
}
|
|
530
530
|
};
|
|
@@ -641,35 +641,6 @@ function normalizeModuleFederationOptions(options) {
|
|
|
641
641
|
}
|
|
642
642
|
//#endregion
|
|
643
643
|
//#region src/utils/VirtualModule.ts
|
|
644
|
-
/**
|
|
645
|
-
* Initialize virtual module infrastructure BEFORE VirtualModule class is used.
|
|
646
|
-
* This must be called in the config hook to ensure the directory exists
|
|
647
|
-
* before Vite's optimization phase.
|
|
648
|
-
*/
|
|
649
|
-
function initVirtualModuleInfrastructure(root, virtualModuleDir = "__mf__virtual") {
|
|
650
|
-
const virtualPackagePath = join(join(root, "node_modules"), virtualModuleDir);
|
|
651
|
-
mkdirSync(virtualPackagePath, { recursive: true });
|
|
652
|
-
writeFileSync(join(virtualPackagePath, "empty.js"), "");
|
|
653
|
-
writeFileSync(join(virtualPackagePath, "package.json"), JSON.stringify({
|
|
654
|
-
name: virtualModuleDir,
|
|
655
|
-
main: "empty.js"
|
|
656
|
-
}));
|
|
657
|
-
}
|
|
658
|
-
let rootDir;
|
|
659
|
-
function findNodeModulesDir(root = process.cwd()) {
|
|
660
|
-
let currentDir = root;
|
|
661
|
-
while (currentDir !== parse(currentDir).root) {
|
|
662
|
-
const nodeModulesPath = join(currentDir, "node_modules");
|
|
663
|
-
if (existsSync(nodeModulesPath)) return nodeModulesPath;
|
|
664
|
-
currentDir = dirname(currentDir);
|
|
665
|
-
}
|
|
666
|
-
return "";
|
|
667
|
-
}
|
|
668
|
-
let cachedNodeModulesDir;
|
|
669
|
-
function getNodeModulesDir() {
|
|
670
|
-
if (!cachedNodeModulesDir) cachedNodeModulesDir = findNodeModulesDir(rootDir);
|
|
671
|
-
return cachedNodeModulesDir;
|
|
672
|
-
}
|
|
673
644
|
function getSuffix(name) {
|
|
674
645
|
const base = basename(name);
|
|
675
646
|
const dotIndex = base.lastIndexOf(".");
|
|
@@ -678,9 +649,6 @@ function getSuffix(name) {
|
|
|
678
649
|
}
|
|
679
650
|
const patternMap = {};
|
|
680
651
|
const cacheMap = {};
|
|
681
|
-
/**
|
|
682
|
-
* Physically generate files as virtual modules under node_modules/__mf__virtual/*
|
|
683
|
-
*/
|
|
684
652
|
function assertModuleFound(tag, str = "") {
|
|
685
653
|
const module = VirtualModule.findModule(tag, str);
|
|
686
654
|
if (!module) throw createModuleFederationError(`Module Federation shared module '${str}' not found. Please ensure it's installed as a dependency in your package.json.`);
|
|
@@ -691,33 +659,16 @@ var VirtualModule = class {
|
|
|
691
659
|
tag;
|
|
692
660
|
suffix;
|
|
693
661
|
inited = false;
|
|
694
|
-
|
|
695
|
-
* Set the root path for finding node_modules
|
|
696
|
-
* @param root - Root path
|
|
697
|
-
*/
|
|
698
|
-
static setRoot(root) {
|
|
699
|
-
rootDir = root;
|
|
700
|
-
cachedNodeModulesDir = void 0;
|
|
701
|
-
}
|
|
702
|
-
/**
|
|
703
|
-
* Ensure virtual package directory exists
|
|
704
|
-
*/
|
|
705
|
-
static ensureVirtualPackageExists() {
|
|
706
|
-
const nodeModulesDir = getNodeModulesDir();
|
|
707
|
-
const { virtualModuleDir } = getNormalizeModuleFederationOptions();
|
|
708
|
-
const virtualPackagePath = resolve(nodeModulesDir, virtualModuleDir);
|
|
709
|
-
mkdirSync(virtualPackagePath, { recursive: true });
|
|
710
|
-
writeFileSync(resolve(virtualPackagePath, "empty.js"), "");
|
|
711
|
-
writeFileSync(resolve(virtualPackagePath, "package.json"), JSON.stringify({
|
|
712
|
-
name: virtualModuleDir,
|
|
713
|
-
main: "empty.js"
|
|
714
|
-
}));
|
|
715
|
-
}
|
|
662
|
+
code;
|
|
716
663
|
static findModule(tag, str = "") {
|
|
717
664
|
if (!patternMap[tag]) patternMap[tag] = new RegExp(`(.*${packageNameEncode(tag)}(.+?)${packageNameEncode(tag)}.*)`);
|
|
718
665
|
const moduleName = (str.match(patternMap[tag]) || [])[2];
|
|
719
666
|
if (moduleName) return cacheMap[tag][packageNameDecode(moduleName)];
|
|
720
667
|
}
|
|
668
|
+
static findById(id) {
|
|
669
|
+
const normalized = id.replace(/^\0+/, "").replace(/^\/@id\//, "").replace(/^__x00__/, "").replace(/[?#].*$/, "");
|
|
670
|
+
for (const modules of Object.values(cacheMap)) for (const module of Object.values(modules)) if (module.getImportId() === normalized) return module;
|
|
671
|
+
}
|
|
721
672
|
constructor(name, tag = "__mf_v__", suffix = "") {
|
|
722
673
|
this.name = name;
|
|
723
674
|
this.tag = tag;
|
|
@@ -725,24 +676,20 @@ var VirtualModule = class {
|
|
|
725
676
|
if (!cacheMap[this.tag]) cacheMap[this.tag] = {};
|
|
726
677
|
cacheMap[this.tag][this.name] = this;
|
|
727
678
|
}
|
|
728
|
-
getPath() {
|
|
729
|
-
return resolve(getNodeModulesDir(), this.getImportId());
|
|
730
|
-
}
|
|
731
679
|
getImportId() {
|
|
732
|
-
const { internalName: mfName
|
|
733
|
-
return
|
|
680
|
+
const { internalName: mfName } = getNormalizeModuleFederationOptions();
|
|
681
|
+
return `virtual:mf:${packageNameEncode(`${mfName}${this.tag}${this.name}${this.tag}`)}${this.suffix}`;
|
|
682
|
+
}
|
|
683
|
+
getResolvedId() {
|
|
684
|
+
return `\0${this.getImportId()}`;
|
|
734
685
|
}
|
|
735
686
|
writeSync(code, force) {
|
|
736
687
|
if (!force && this.inited) return;
|
|
737
688
|
if (!this.inited) this.inited = true;
|
|
738
|
-
|
|
739
|
-
mkdirSync(dirname(path), { recursive: true });
|
|
740
|
-
writeFileSync(path, code);
|
|
689
|
+
this.code = code;
|
|
741
690
|
}
|
|
742
691
|
write(code) {
|
|
743
|
-
|
|
744
|
-
mkdirSync(dirname(path), { recursive: true });
|
|
745
|
-
writeFile(path, code, function() {});
|
|
692
|
+
this.writeSync(code, true);
|
|
746
693
|
}
|
|
747
694
|
};
|
|
748
695
|
//#endregion
|
|
@@ -944,6 +891,14 @@ globalThis[__mfCacheGlobalKey].remote ||= {};
|
|
|
944
891
|
const __mfModuleCache = globalThis[__mfCacheGlobalKey];
|
|
945
892
|
`;
|
|
946
893
|
}
|
|
894
|
+
function getRuntimeInitPromiseBootstrapCode() {
|
|
895
|
+
return getRuntimeInitStateBootstrapCode({
|
|
896
|
+
globalKeyVar: "__mfPromiseGlobalKey",
|
|
897
|
+
stateVar: "__mfPromiseState",
|
|
898
|
+
exposedConst: "initPromise",
|
|
899
|
+
exposedProperty: "initPromise"
|
|
900
|
+
});
|
|
901
|
+
}
|
|
947
902
|
function getRuntimeInitResolveBootstrapCode() {
|
|
948
903
|
return getRuntimeInitStateBootstrapCode({
|
|
949
904
|
globalKeyVar: "__mfResolveGlobalKey",
|
|
@@ -1188,6 +1143,16 @@ function writePreBuildLibPath(pkg, shareItem) {
|
|
|
1188
1143
|
export const jsx = __mfPrebuildExports.jsx;
|
|
1189
1144
|
export const jsxs = __mfPrebuildExports.jsxs;
|
|
1190
1145
|
export default __mfPrebuildExports;
|
|
1146
|
+
`, true);
|
|
1147
|
+
return;
|
|
1148
|
+
}
|
|
1149
|
+
const namedExports = getPackageNamedExports(pkg);
|
|
1150
|
+
if (namedExports.length > 0) {
|
|
1151
|
+
preBuildCacheMap[pkg].writeSync(`
|
|
1152
|
+
import * as __mfPrebuildNamespace from ${escapeGeneratedStringLiteral(importSource)};
|
|
1153
|
+
const __mfPrebuildExports = __mfPrebuildNamespace;
|
|
1154
|
+
${namedExports.map((name) => `export const ${name} = __mfPrebuildExports[${escapeGeneratedStringLiteral(name)}];`).join("\n ")}
|
|
1155
|
+
export default __mfPrebuildExports;
|
|
1191
1156
|
`, true);
|
|
1192
1157
|
return;
|
|
1193
1158
|
}
|
|
@@ -1215,25 +1180,62 @@ function getLoadShareImportId(pkg, _isRolldown) {
|
|
|
1215
1180
|
}
|
|
1216
1181
|
function getLoadShareModulePath(pkg, isRolldown) {
|
|
1217
1182
|
if (!loadShareCacheMap[pkg]) getLoadShareImportId(pkg, isRolldown);
|
|
1218
|
-
return loadShareCacheMap[pkg].
|
|
1183
|
+
return loadShareCacheMap[pkg].getImportId();
|
|
1219
1184
|
}
|
|
1185
|
+
function generateDeferredHostProvidedExports(namedExports, pkg) {
|
|
1186
|
+
const namedExportVars = namedExports.map((_name, i) => `__mf_${i}`);
|
|
1187
|
+
const declarations = ["let __mf_default;", ...namedExportVars.map((name) => `let ${name};`)].join("\n ");
|
|
1188
|
+
const assignments = [...namedExports.map((name, i) => `${namedExportVars[i]} = exportModule[${escapeGeneratedStringLiteral(name)}];`), "__mf_default = exportModule.default ?? exportModule;"].join("\n ");
|
|
1189
|
+
const namedExportLine = namedExports.length > 0 ? `\n export { ${namedExports.map((name, i) => `${namedExportVars[i]} as ${name}`).join(", ")} };` : "";
|
|
1190
|
+
return `${declarations}
|
|
1191
|
+
const __mfApplyHostProvidedExports = (exportModule) => {
|
|
1192
|
+
${assignments}
|
|
1193
|
+
};
|
|
1194
|
+
let exportModule = __mfModuleCache.share[${escapeGeneratedStringLiteral(pkg)}];
|
|
1195
|
+
if (exportModule === undefined) {
|
|
1196
|
+
initPromise.then(() => {
|
|
1197
|
+
exportModule = __mfModuleCache.share[${escapeGeneratedStringLiteral(pkg)}];
|
|
1198
|
+
if (exportModule === undefined) {
|
|
1199
|
+
throw new Error("[Module Federation] Shared module ${pkg} was imported before federation bootstrap finished.");
|
|
1200
|
+
}
|
|
1201
|
+
__mfApplyHostProvidedExports(exportModule);
|
|
1202
|
+
});
|
|
1203
|
+
} else {
|
|
1204
|
+
__mfApplyHostProvidedExports(exportModule);
|
|
1205
|
+
}
|
|
1206
|
+
export { __mf_default as default };${namedExportLine}`;
|
|
1207
|
+
}
|
|
1208
|
+
function generateShareModuleUnwrapCode({ source, preserveNamedExports, stopWithReturn }) {
|
|
1209
|
+
return `let current = ${source};
|
|
1210
|
+
for (let i = 0; i < 5; i++) {
|
|
1211
|
+
const defaultExport = current?.default;
|
|
1212
|
+
${stopWithReturn ? `if (!defaultExport || typeof defaultExport !== "object") return ${stopWithReturn};` : `if (!defaultExport || typeof defaultExport !== "object") break;`}${preserveNamedExports ? `
|
|
1213
|
+
const namedValues = Object.keys(current).filter((key) => key !== "default").map((key) => current[key]);
|
|
1214
|
+
if (namedValues.length > 0 && namedValues.some((value) => value !== undefined)) break;` : ""}
|
|
1215
|
+
current = defaultExport;
|
|
1216
|
+
}
|
|
1217
|
+
return current;`;
|
|
1218
|
+
}
|
|
1219
|
+
const normalizeLocalShareModuleCode = `const __mfNormalizeShareModule = (mod) => {
|
|
1220
|
+
${generateShareModuleUnwrapCode({
|
|
1221
|
+
source: "mod",
|
|
1222
|
+
preserveNamedExports: true
|
|
1223
|
+
})}
|
|
1224
|
+
};`;
|
|
1220
1225
|
function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
|
|
1221
1226
|
if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, ".mjs");
|
|
1222
1227
|
const importLine = getRuntimeModuleCacheBootstrapCode();
|
|
1223
1228
|
if (shareItem.shareConfig.import === false) {
|
|
1224
1229
|
const namedExports = getPackageNamedExports(pkg);
|
|
1225
1230
|
let exportLine;
|
|
1226
|
-
if (namedExports.length > 0) exportLine =
|
|
1231
|
+
if (namedExports.length > 0) exportLine = generateDeferredHostProvidedExports(namedExports, pkg);
|
|
1227
1232
|
else {
|
|
1228
1233
|
mfWarn(`Shared dependency "${pkg}" has import: false but is not installed locally.\n Named imports (e.g. import { ... } from '${pkg}') will not work in production builds.\n Install it as a devDependency to enable named export detection.`);
|
|
1229
|
-
exportLine =
|
|
1234
|
+
exportLine = generateDeferredHostProvidedExports([], pkg);
|
|
1230
1235
|
}
|
|
1231
1236
|
loadShareCacheMap[pkg].writeSync(`
|
|
1237
|
+
${getRuntimeInitPromiseBootstrapCode()}
|
|
1232
1238
|
${importLine}
|
|
1233
|
-
const exportModule = __mfModuleCache.share[${escapeGeneratedStringLiteral(pkg)}]
|
|
1234
|
-
if (exportModule === undefined) {
|
|
1235
|
-
throw new Error("[Module Federation] Shared module ${pkg} was imported before federation bootstrap finished.")
|
|
1236
|
-
}
|
|
1237
1239
|
${exportLine}
|
|
1238
1240
|
`, true);
|
|
1239
1241
|
return;
|
|
@@ -1248,8 +1250,20 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
|
|
|
1248
1250
|
const usesLazyLocalFallback = isWorkspacePackage && shareItem.shareConfig.singleton === true;
|
|
1249
1251
|
const namedExports = getPackageNamedExports(pkg);
|
|
1250
1252
|
let exportLine;
|
|
1251
|
-
if (namedExports.length > 0)
|
|
1252
|
-
|
|
1253
|
+
if (namedExports.length > 0) {
|
|
1254
|
+
const destructure = `const { ${namedExports.map((name, i) => `${name}: __mf_${i}`).join(", ")} } = exportModule;`;
|
|
1255
|
+
const namedExportLine = `export { ${namedExports.map((name, i) => `__mf_${i} as ${name}`).join(", ")} };`;
|
|
1256
|
+
exportLine = `const __mfDefaultExport = (() => {
|
|
1257
|
+
${generateShareModuleUnwrapCode({
|
|
1258
|
+
source: "exportModule",
|
|
1259
|
+
preserveNamedExports: false,
|
|
1260
|
+
stopWithReturn: "defaultExport ?? current"
|
|
1261
|
+
})}
|
|
1262
|
+
})();
|
|
1263
|
+
export default __mfDefaultExport;
|
|
1264
|
+
${destructure}
|
|
1265
|
+
${namedExportLine}`;
|
|
1266
|
+
} else if (usesLazyLocalFallback) exportLine = `export default exportModule.default ?? exportModule`;
|
|
1253
1267
|
else exportLine = `export default exportModule.default ?? exportModule\n export * from ${escapeGeneratedStringLiteral(sharedImportSource)}`;
|
|
1254
1268
|
const prebuildImportLine = usesLazyLocalFallback || isWorkspacePackage && command !== "build" ? "" : `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(skipServePrebuildWarmup ? devImportSource : sharedImportSource)};`;
|
|
1255
1269
|
const devDynamicImportLine = isWorkspacePackage ? "" : command !== "build" && !skipServePrebuildWarmup ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
|
|
@@ -1257,10 +1271,11 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
|
|
|
1257
1271
|
${prebuildImportLine}
|
|
1258
1272
|
${devDynamicImportLine}
|
|
1259
1273
|
${importLine}
|
|
1274
|
+
${normalizeLocalShareModuleCode}
|
|
1260
1275
|
let exportModule = __mfModuleCache.share[${escapeGeneratedStringLiteral(pkg)}]
|
|
1261
1276
|
if (exportModule === undefined) {
|
|
1262
|
-
${usesLazyLocalFallback ? `exportModule = await import(${escapeGeneratedStringLiteral(lazyLocalFallbackSource)});
|
|
1263
|
-
__mfModuleCache.share[${escapeGeneratedStringLiteral(pkg)}] = exportModule;` : `exportModule = __mfLocalShare;
|
|
1277
|
+
${usesLazyLocalFallback ? `exportModule = __mfNormalizeShareModule(await import(${escapeGeneratedStringLiteral(lazyLocalFallbackSource)}));
|
|
1278
|
+
__mfModuleCache.share[${escapeGeneratedStringLiteral(pkg)}] = exportModule;` : `exportModule = __mfNormalizeShareModule(__mfLocalShare);
|
|
1264
1279
|
__mfModuleCache.share[${escapeGeneratedStringLiteral(pkg)}] = exportModule;`}
|
|
1265
1280
|
}
|
|
1266
1281
|
${exportLine}
|
|
@@ -1418,9 +1433,9 @@ function getShareItemForPreload(pkg) {
|
|
|
1418
1433
|
function generateSharedCacheSeedItem(pkg, importPath) {
|
|
1419
1434
|
return `if (__mfModuleCache.share[${JSON.stringify(pkg)}] === undefined) {
|
|
1420
1435
|
const mod = await import(${JSON.stringify(importPath)});
|
|
1421
|
-
|
|
1422
|
-
|
|
1423
|
-
|
|
1436
|
+
${normalizeRuntimeShareCode}
|
|
1437
|
+
const normalizedModule = __mfNormalizeRuntimeShare(mod);
|
|
1438
|
+
const exportModule = normalizedModule === mod ? {...mod} : normalizedModule;
|
|
1424
1439
|
Object.defineProperty(exportModule, "__esModule", {
|
|
1425
1440
|
value: true,
|
|
1426
1441
|
enumerable: false
|
|
@@ -1428,6 +1443,17 @@ function generateSharedCacheSeedItem(pkg, importPath) {
|
|
|
1428
1443
|
__mfModuleCache.share[${JSON.stringify(pkg)}] = exportModule;
|
|
1429
1444
|
}`;
|
|
1430
1445
|
}
|
|
1446
|
+
const normalizeRuntimeShareCode = `const __mfNormalizeRuntimeShare = (mod) => {
|
|
1447
|
+
let current = mod;
|
|
1448
|
+
for (let i = 0; i < 5; i++) {
|
|
1449
|
+
const defaultExport = current?.default;
|
|
1450
|
+
if (!defaultExport || typeof defaultExport !== "object") break;
|
|
1451
|
+
const namedValues = Object.keys(current).filter((key) => key !== "default").map((key) => current[key]);
|
|
1452
|
+
if (namedValues.length > 0 && namedValues.some((value) => value !== undefined)) break;
|
|
1453
|
+
current = defaultExport;
|
|
1454
|
+
}
|
|
1455
|
+
return current;
|
|
1456
|
+
};`;
|
|
1431
1457
|
function generateDirectSharedCacheSeedCode(command = "build") {
|
|
1432
1458
|
return getOrderedUsedShares().map((pkg) => {
|
|
1433
1459
|
const shareItem = getShareItemForPreload(pkg);
|
|
@@ -1450,7 +1476,8 @@ function getHostAutoInitSharedSeedItems() {
|
|
|
1450
1476
|
return priority(a.pkg) - priority(b.pkg) || Number(aIsLocal) - Number(bIsLocal) || a.pkg.localeCompare(b.pkg);
|
|
1451
1477
|
});
|
|
1452
1478
|
}
|
|
1453
|
-
function generateHostAutoInitSharedCacheSeedCode() {
|
|
1479
|
+
function generateHostAutoInitSharedCacheSeedCode(command = "build") {
|
|
1480
|
+
if (command === "build") return "";
|
|
1454
1481
|
return getHostAutoInitSharedSeedItems().map(({ pkg, shareItem }) => {
|
|
1455
1482
|
if (!shareItem) return null;
|
|
1456
1483
|
return generateSharedCacheSeedItem(pkg, getBrowserImportPath(getDirectSharedCacheSeedImportPath(pkg, shareItem)));
|
|
@@ -1482,14 +1509,13 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
1482
1509
|
if (typeof __VUE_HMR_RUNTIME__ === 'undefined') {
|
|
1483
1510
|
globalThis.__VUE_HMR_RUNTIME__ = { createRecord() {}, rerender() {}, reload() {} };
|
|
1484
1511
|
}
|
|
1485
|
-
import {
|
|
1512
|
+
import {init as runtimeInit, loadRemote} from "@module-federation/runtime";
|
|
1486
1513
|
${pluginImportNames.map((item) => item[1]).join("\n")}
|
|
1487
1514
|
${command === "build" ? getRuntimeInitResolveBootstrapCode() : getRuntimeInitBootstrapCode() + "\n const { initResolve } = globalThis[globalKey];"}
|
|
1488
1515
|
${getRuntimeModuleCacheBootstrapCode()}
|
|
1489
1516
|
const initTokens = {}
|
|
1490
1517
|
const shareScopeName = ${JSON.stringify(options.shareScope)}
|
|
1491
1518
|
const mfName = ${JSON.stringify(options.internalName)}
|
|
1492
|
-
let runtimeInstance
|
|
1493
1519
|
let localSharedImportMapPromise
|
|
1494
1520
|
let exposesMapPromise
|
|
1495
1521
|
const shouldRetrySharedInitError = ${command !== "build"} && ((error) => {
|
|
@@ -1532,19 +1558,13 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
1532
1558
|
async function init(shared = {}, initScope = []) {
|
|
1533
1559
|
const {usedShared, usedRemotes} = await getLocalSharedImportMap()
|
|
1534
1560
|
${generateDirectSharedCacheSeedCode(command)}
|
|
1535
|
-
const
|
|
1561
|
+
const initRes = runtimeInit({
|
|
1536
1562
|
name: mfName,
|
|
1537
1563
|
remotes: usedRemotes,
|
|
1538
1564
|
shared: usedShared,
|
|
1539
1565
|
plugins: [${pluginImportNames.map((item) => `${item[0]}(${item[2]})`).join(", ")}],
|
|
1540
1566
|
${options.shareStrategy ? `shareStrategy: '${options.shareStrategy}'` : ""}
|
|
1541
|
-
};
|
|
1542
|
-
if (!runtimeInstance) {
|
|
1543
|
-
runtimeInstance = createInstance(runtimeOptions);
|
|
1544
|
-
} else {
|
|
1545
|
-
runtimeInstance.initOptions(runtimeOptions);
|
|
1546
|
-
}
|
|
1547
|
-
const initRes = runtimeInstance;
|
|
1567
|
+
});
|
|
1548
1568
|
// handling circular init calls
|
|
1549
1569
|
var initToken = initTokens[shareScopeName];
|
|
1550
1570
|
if (!initToken)
|
|
@@ -1564,6 +1584,17 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
|
|
|
1564
1584
|
} catch (e) {
|
|
1565
1585
|
console.error('[Module Federation]', e)
|
|
1566
1586
|
}
|
|
1587
|
+
for (const [pkg, share] of Object.entries(usedShared)) {
|
|
1588
|
+
if (share.shareConfig?.import !== false || __mfModuleCache.share[pkg] !== undefined) continue;
|
|
1589
|
+
${normalizeRuntimeShareCode}
|
|
1590
|
+
const versions = shared?.[pkg];
|
|
1591
|
+
const provider = versions && versions[Object.keys(versions)[0]];
|
|
1592
|
+
if (!provider) continue;
|
|
1593
|
+
const factory = provider.lib || (provider.loading ? await provider.loading : await provider.get?.());
|
|
1594
|
+
const mod = typeof factory === "function" ? factory() : factory;
|
|
1595
|
+
const resolved = await Promise.resolve(mod);
|
|
1596
|
+
__mfModuleCache.share[pkg] = __mfNormalizeRuntimeShare(resolved);
|
|
1597
|
+
}
|
|
1567
1598
|
return initRes
|
|
1568
1599
|
}
|
|
1569
1600
|
|
|
@@ -1588,10 +1619,11 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build") {
|
|
|
1588
1619
|
async function initHost() {
|
|
1589
1620
|
if (!hostInitPromise) {
|
|
1590
1621
|
hostInitPromise = (async () => {
|
|
1591
|
-
${generateHostAutoInitSharedCacheSeedCode()}
|
|
1622
|
+
${generateHostAutoInitSharedCacheSeedCode(_command)}
|
|
1592
1623
|
const remoteEntry = await import(${remoteEntryImport});
|
|
1593
1624
|
const runtime = await remoteEntry.init();
|
|
1594
1625
|
const usedShared = ${generateUsedSharedPreloadConfig()};
|
|
1626
|
+
${normalizeRuntimeShareCode}
|
|
1595
1627
|
for (const [pkg, share] of Object.entries(usedShared)) {
|
|
1596
1628
|
if (__mfModuleCache.share[pkg] !== undefined) {
|
|
1597
1629
|
continue;
|
|
@@ -1601,7 +1633,7 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build") {
|
|
|
1601
1633
|
}).then((factory) => {
|
|
1602
1634
|
const mod = typeof factory === "function" ? factory() : factory;
|
|
1603
1635
|
return Promise.resolve(mod).then((resolved) => {
|
|
1604
|
-
__mfModuleCache.share[pkg] = resolved;
|
|
1636
|
+
__mfModuleCache.share[pkg] = __mfNormalizeRuntimeShare(resolved);
|
|
1605
1637
|
});
|
|
1606
1638
|
});
|
|
1607
1639
|
}
|
|
@@ -1630,7 +1662,7 @@ function getHostAutoInitImportId() {
|
|
|
1630
1662
|
return hostAutoInitModule.getImportId();
|
|
1631
1663
|
}
|
|
1632
1664
|
function getHostAutoInitPath() {
|
|
1633
|
-
return hostAutoInitModule.
|
|
1665
|
+
return hostAutoInitModule.getImportId();
|
|
1634
1666
|
}
|
|
1635
1667
|
//#endregion
|
|
1636
1668
|
//#region src/virtualModules/virtualRemotes.ts
|
|
@@ -1653,7 +1685,9 @@ function getUsedRemotesMap() {
|
|
|
1653
1685
|
}
|
|
1654
1686
|
function generateRemotes(id, command) {
|
|
1655
1687
|
const useReactProxy = command === "serve" && hasPackageDependency("react");
|
|
1656
|
-
const reactImportLine = useReactProxy ? `import
|
|
1688
|
+
const reactImportLine = useReactProxy ? `import __mfReactDefault from "react";
|
|
1689
|
+
import * as __mfReactNamespace from "react";
|
|
1690
|
+
const __mfReact = __mfReactDefault ?? __mfReactNamespace.default ?? __mfReactNamespace;` : "";
|
|
1657
1691
|
const importLine = command === "build" ? `${getRuntimeModuleCacheBootstrapCode()}
|
|
1658
1692
|
import { hostInitPromise as __mfHostInitPromise } from ${JSON.stringify(getHostAutoInitPath())};` : `${getRuntimeInitBootstrapCode()}
|
|
1659
1693
|
const { initPromise, moduleCache: __mfModuleCache } = globalThis[globalKey];`;
|
|
@@ -1663,13 +1697,13 @@ function generateRemotes(id, command) {
|
|
|
1663
1697
|
}
|
|
1664
1698
|
export const __moduleExports = exportModule;
|
|
1665
1699
|
export const __mf_remote_pending = Promise.resolve(exportModule);
|
|
1666
|
-
export default exportModule?.__esModule ? exportModule.default : exportModule.default ?? exportModule` : command === "build" ? `if (__mfRemotePending) {
|
|
1700
|
+
export default exportModule?.__mf_is_remote_proxy ? exportModule : exportModule?.__esModule ? exportModule.default : exportModule.default ?? exportModule` : command === "build" ? `if (__mfRemotePending) {
|
|
1667
1701
|
const mod = await __mfRemotePending;
|
|
1668
1702
|
if (mod !== undefined) exportModule = mod;
|
|
1669
1703
|
}
|
|
1670
1704
|
export const __moduleExports = exportModule;
|
|
1671
1705
|
export const __mf_remote_pending = Promise.resolve(exportModule);
|
|
1672
|
-
export default exportModule?.__esModule ? exportModule.default : exportModule.default ?? exportModule` : "export default exportModule";
|
|
1706
|
+
export default exportModule?.__mf_is_remote_proxy ? exportModule : exportModule?.__esModule ? exportModule.default : exportModule.default ?? exportModule` : "export default exportModule";
|
|
1673
1707
|
return `
|
|
1674
1708
|
${reactImportLine}
|
|
1675
1709
|
${importLine}
|
|
@@ -1869,6 +1903,9 @@ ${importHelper}(async () => {
|
|
|
1869
1903
|
if (inject === "html" && hasPackageDependency("@sveltejs/kit")) return false;
|
|
1870
1904
|
return inject === "entry" || !htmlFilePath;
|
|
1871
1905
|
}
|
|
1906
|
+
function normalizeDevHtmlProxyId(id) {
|
|
1907
|
+
return id.replace(/^\0/, "").replace(/^\/@id\//, "").replace(/^__x00__/, "");
|
|
1908
|
+
}
|
|
1872
1909
|
return [{
|
|
1873
1910
|
name: "add-entry",
|
|
1874
1911
|
apply: "serve",
|
|
@@ -1887,7 +1924,20 @@ ${importHelper}(async () => {
|
|
|
1887
1924
|
}
|
|
1888
1925
|
},
|
|
1889
1926
|
configureServer(server) {
|
|
1890
|
-
server.middlewares.use((req,
|
|
1927
|
+
server.middlewares.use((req, res, next) => {
|
|
1928
|
+
const rawUrl = req.url?.split("#")[0] ?? "";
|
|
1929
|
+
if (normalizeDevHtmlProxyId(rawUrl.split("?")[0]) === DEV_HTML_PROXY_PREFIX.slice(0, -1)) {
|
|
1930
|
+
const query = rawUrl.slice(rawUrl.indexOf("?") + 1);
|
|
1931
|
+
const params = new URLSearchParams(query);
|
|
1932
|
+
const initSrc = params.get("init");
|
|
1933
|
+
const entrySrc = params.get("entry");
|
|
1934
|
+
if (initSrc && entrySrc) {
|
|
1935
|
+
res.statusCode = 200;
|
|
1936
|
+
res.setHeader("Content-Type", "application/javascript");
|
|
1937
|
+
res.end(getBootstrapSource(initSrc, entrySrc));
|
|
1938
|
+
return;
|
|
1939
|
+
}
|
|
1940
|
+
}
|
|
1891
1941
|
if (!fileName) {
|
|
1892
1942
|
next();
|
|
1893
1943
|
return;
|
|
@@ -1904,7 +1954,7 @@ ${importHelper}(async () => {
|
|
|
1904
1954
|
const base = viteConfig.base.replace(/\/$/, "");
|
|
1905
1955
|
const stripBase = (p) => base && p.startsWith(base + "/") ? p.slice(base.length) : p;
|
|
1906
1956
|
const html = rewriteEntryScripts(c, (originalSrc) => {
|
|
1907
|
-
return `/@id
|
|
1957
|
+
return `/@id/__x00__${DEV_HTML_PROXY_PREFIX}${new URLSearchParams({
|
|
1908
1958
|
init: sanitizeDevEntryPath(stripBase(devEntryPath)),
|
|
1909
1959
|
entry: sanitizeDevEntryPath(stripBase(originalSrc))
|
|
1910
1960
|
}).toString()}`;
|
|
@@ -1913,11 +1963,12 @@ ${importHelper}(async () => {
|
|
|
1913
1963
|
}
|
|
1914
1964
|
},
|
|
1915
1965
|
resolveId(id) {
|
|
1916
|
-
if (id.startsWith(DEV_HTML_PROXY_PREFIX)) return id;
|
|
1966
|
+
if (normalizeDevHtmlProxyId(id).startsWith(DEV_HTML_PROXY_PREFIX)) return id;
|
|
1917
1967
|
},
|
|
1918
1968
|
load(id) {
|
|
1919
|
-
|
|
1920
|
-
|
|
1969
|
+
const normalizedId = normalizeDevHtmlProxyId(id);
|
|
1970
|
+
if (!normalizedId.startsWith(DEV_HTML_PROXY_PREFIX)) return;
|
|
1971
|
+
const params = new URLSearchParams(normalizedId.slice(28));
|
|
1921
1972
|
const initSrc = params.get("init");
|
|
1922
1973
|
const entrySrc = params.get("entry");
|
|
1923
1974
|
if (!initSrc || !entrySrc) return;
|
|
@@ -2724,7 +2775,7 @@ function collectSystemProxyInfos(proxyChunks, loadShareTag) {
|
|
|
2724
2775
|
for (const m of proxyInfo.code.matchAll(/exports\(\s*["']([^"']+)["']\s*,([\s\S]*?)\);/g)) {
|
|
2725
2776
|
const exported = m[1];
|
|
2726
2777
|
const expression = m[2];
|
|
2727
|
-
for (const [local, exportName] of Object.entries(loadShareBindings)) if (new RegExp(`\\b${local}\\b`).test(expression)) {
|
|
2778
|
+
for (const [local, exportName] of Object.entries(loadShareBindings).reverse()) if (new RegExp(`\\b${local}\\b`).test(expression)) {
|
|
2728
2779
|
exportMap[exported] = {
|
|
2729
2780
|
type: "reexport",
|
|
2730
2781
|
exportName
|
|
@@ -3488,7 +3539,7 @@ function pluginProxyRemotes_default(options) {
|
|
|
3488
3539
|
const remoteModule = getRemoteVirtualModule(source, command);
|
|
3489
3540
|
addUsedRemote(remoteName, source);
|
|
3490
3541
|
refreshHostAutoInit();
|
|
3491
|
-
return remoteModule.
|
|
3542
|
+
return remoteModule.getImportId();
|
|
3492
3543
|
}
|
|
3493
3544
|
return {
|
|
3494
3545
|
name: "proxyRemotes",
|
|
@@ -3890,7 +3941,7 @@ async function collectFromEsLexer(code, isRemoteImport) {
|
|
|
3890
3941
|
await init;
|
|
3891
3942
|
let imports;
|
|
3892
3943
|
try {
|
|
3893
|
-
[imports] = parse
|
|
3944
|
+
[imports] = parse(code);
|
|
3894
3945
|
} catch {
|
|
3895
3946
|
return;
|
|
3896
3947
|
}
|
|
@@ -4310,12 +4361,12 @@ function isFederationHtmlPreloadDependency(dep, includeSharedRuntime = false) {
|
|
|
4310
4361
|
return includeSharedRuntime && (file.includes("preload-helper") || file.includes("rolldown-runtime") || file.startsWith("dist-"));
|
|
4311
4362
|
}
|
|
4312
4363
|
/**
|
|
4313
|
-
* Plugin that runs FIRST to
|
|
4314
|
-
* This prevents 504 "Outdated Optimize Dep" errors by ensuring
|
|
4364
|
+
* Plugin that runs FIRST to register generated virtual modules in the config hook.
|
|
4365
|
+
* This prevents 504 "Outdated Optimize Dep" errors by ensuring ids are known
|
|
4315
4366
|
* before Vite's optimization phase.
|
|
4316
4367
|
*/
|
|
4317
4368
|
function createEarlyVirtualModulesPlugin(options) {
|
|
4318
|
-
const { shared, remotes
|
|
4369
|
+
const { shared, remotes } = options;
|
|
4319
4370
|
const isLitShare = (pkg) => pkg === "lit" || pkg.startsWith("lit/");
|
|
4320
4371
|
return {
|
|
4321
4372
|
name: "vite:module-federation-early-init",
|
|
@@ -4325,9 +4376,6 @@ function createEarlyVirtualModulesPlugin(options) {
|
|
|
4325
4376
|
const root = config.root || process.cwd();
|
|
4326
4377
|
setPackageDetectionCwd(root);
|
|
4327
4378
|
const isVinext = hasPackageDependency("vinext");
|
|
4328
|
-
initVirtualModuleInfrastructure(root, virtualModuleDir);
|
|
4329
|
-
VirtualModule.setRoot(root);
|
|
4330
|
-
VirtualModule.ensureVirtualPackageExists();
|
|
4331
4379
|
initVirtualModules(_command, getRemoteEntryId(options));
|
|
4332
4380
|
const isRolldown = getIsRolldown(this);
|
|
4333
4381
|
if (remotes && Object.keys(remotes).length > 0) {
|
|
@@ -4373,6 +4421,10 @@ function createEarlyVirtualModulesPlugin(options) {
|
|
|
4373
4421
|
optimizeDeps.esbuildOptions.plugins.push({
|
|
4374
4422
|
name: "module-federation:optimize-shared-proxy",
|
|
4375
4423
|
setup(build) {
|
|
4424
|
+
build.onResolve({ filter: /^virtual:mf:/ }, (args) => ({
|
|
4425
|
+
path: args.path,
|
|
4426
|
+
external: true
|
|
4427
|
+
}));
|
|
4376
4428
|
build.onResolve({ filter: /.*/ }, (args) => {
|
|
4377
4429
|
if (!args.importer || args.namespace === "mf-shared") return;
|
|
4378
4430
|
if (isSharedResolverInternalImporter(args.importer)) return;
|
|
@@ -4404,7 +4456,6 @@ export default __mfShared.default ?? __mfShared;`
|
|
|
4404
4456
|
}
|
|
4405
4457
|
});
|
|
4406
4458
|
}
|
|
4407
|
-
config.optimizeDeps.include.push(virtualRuntimeInitStatus.getImportId());
|
|
4408
4459
|
}
|
|
4409
4460
|
for (const key of Object.keys(shared)) {
|
|
4410
4461
|
const shareItem = shared[key];
|
|
@@ -4415,7 +4466,6 @@ export default __mfShared.default ?? __mfShared;`
|
|
|
4415
4466
|
for (const subpath of getCommonSharedSubpaths(key)) {
|
|
4416
4467
|
writePreBuildLibPath(subpath, shareItem);
|
|
4417
4468
|
optimizeDeps.include.push(subpath);
|
|
4418
|
-
optimizeDeps.include.push(getPreBuildLibImportId(subpath));
|
|
4419
4469
|
}
|
|
4420
4470
|
}
|
|
4421
4471
|
continue;
|
|
@@ -4432,14 +4482,11 @@ export default __mfShared.default ?? __mfShared;`
|
|
|
4432
4482
|
const optimizeDeps = config.optimizeDeps ??= {};
|
|
4433
4483
|
optimizeDeps.include ??= [];
|
|
4434
4484
|
optimizeDeps.exclude ??= [];
|
|
4435
|
-
|
|
4436
|
-
|
|
4437
|
-
if (!isRolldown && !shouldBypassOptimizeDep) optimizeDeps.include.push(getLoadShareImportId(key, isRolldown));
|
|
4438
|
-
optimizeDeps.include.push(getPreBuildLibImportId(key));
|
|
4485
|
+
if (isLitShare(key)) optimizeDeps.exclude.push(key);
|
|
4486
|
+
else optimizeDeps.include.push(key);
|
|
4439
4487
|
for (const subpath of getCommonSharedSubpaths(key)) {
|
|
4440
4488
|
writePreBuildLibPath(subpath, shareItem);
|
|
4441
4489
|
optimizeDeps.include.push(subpath);
|
|
4442
|
-
optimizeDeps.include.push(getPreBuildLibImportId(subpath));
|
|
4443
4490
|
}
|
|
4444
4491
|
}
|
|
4445
4492
|
}
|
|
@@ -4459,6 +4506,21 @@ function federation(mfUserOptions) {
|
|
|
4459
4506
|
let command;
|
|
4460
4507
|
let desiredRolldownOutput;
|
|
4461
4508
|
return [
|
|
4509
|
+
{
|
|
4510
|
+
name: "vite:module-federation-virtual-modules",
|
|
4511
|
+
enforce: "pre",
|
|
4512
|
+
resolveId(id) {
|
|
4513
|
+
const virtualModule = VirtualModule.findById(id);
|
|
4514
|
+
if (!virtualModule) return;
|
|
4515
|
+
return virtualModule.getResolvedId();
|
|
4516
|
+
},
|
|
4517
|
+
load(id) {
|
|
4518
|
+
const virtualModule = VirtualModule.findById(id);
|
|
4519
|
+
if (!virtualModule) return;
|
|
4520
|
+
if (command === "build" && (id.includes("__loadShare__") || id.includes("__loadRemote__"))) return;
|
|
4521
|
+
return virtualModule.code;
|
|
4522
|
+
}
|
|
4523
|
+
},
|
|
4462
4524
|
createEarlyVirtualModulesPlugin(options),
|
|
4463
4525
|
...isVinext ? [{
|
|
4464
4526
|
name: "module-federation-vinext-react-server-build-alias",
|
|
@@ -4483,9 +4545,7 @@ function federation(mfUserOptions) {
|
|
|
4483
4545
|
config(_config, env) {
|
|
4484
4546
|
command = env.command;
|
|
4485
4547
|
},
|
|
4486
|
-
configResolved(
|
|
4487
|
-
VirtualModule.setRoot(config.root);
|
|
4488
|
-
VirtualModule.ensureVirtualPackageExists();
|
|
4548
|
+
configResolved() {
|
|
4489
4549
|
initVirtualModules(command, remoteEntryId);
|
|
4490
4550
|
}
|
|
4491
4551
|
},
|
|
@@ -4628,9 +4688,8 @@ function federation(mfUserOptions) {
|
|
|
4628
4688
|
}
|
|
4629
4689
|
},
|
|
4630
4690
|
load(id) {
|
|
4631
|
-
if (id.startsWith("\0")) return;
|
|
4632
4691
|
if (id.includes("__loadShare__") || id.includes("__loadRemote__")) {
|
|
4633
|
-
let code = readFileSync(id, "utf-8");
|
|
4692
|
+
let code = VirtualModule.findById(id)?.code ?? readFileSync(id, "utf-8");
|
|
4634
4693
|
code = code.replace(/import\s+["'][^"']*__prebuild__[^"']*["']\s*;?/g, "");
|
|
4635
4694
|
code = code.replace(/export\s+\*\s+from\s+["'][^"']*__prebuild__[^"']*["']\s*;?/g, "");
|
|
4636
4695
|
/**
|
|
@@ -4649,7 +4708,10 @@ function federation(mfUserOptions) {
|
|
|
4649
4708
|
*
|
|
4650
4709
|
* @see https://rollupjs.org/plugin-development/#synthetic-named-exports
|
|
4651
4710
|
*/
|
|
4652
|
-
if (
|
|
4711
|
+
if (!/\bexport\s+const\s+__moduleExports\b/.test(code)) {
|
|
4712
|
+
const nextCode = code.replace("export default exportModule", "export const __moduleExports = exportModule;\nexport default exportModule.__esModule ? exportModule.default : exportModule");
|
|
4713
|
+
code = nextCode === code ? `${code}\nexport const __moduleExports = exportModule;\n` : nextCode;
|
|
4714
|
+
}
|
|
4653
4715
|
if (getIsRolldown(this)) return { code };
|
|
4654
4716
|
return {
|
|
4655
4717
|
code,
|
|
@@ -4714,14 +4776,9 @@ function federation(mfUserOptions) {
|
|
|
4714
4776
|
config.build ||= {};
|
|
4715
4777
|
config.build.commonjsOptions ||= {};
|
|
4716
4778
|
config.build.commonjsOptions.strictRequires ??= "auto";
|
|
4717
|
-
const virtualDir = options.virtualModuleDir;
|
|
4718
4779
|
config.optimizeDeps ||= {};
|
|
4719
4780
|
config.optimizeDeps.include ||= [];
|
|
4720
4781
|
config.optimizeDeps.include.push("@module-federation/runtime");
|
|
4721
|
-
if (!isRolldown) config.optimizeDeps.include.push(virtualDir);
|
|
4722
|
-
config.ssr ||= {};
|
|
4723
|
-
config.ssr.noExternal ||= [];
|
|
4724
|
-
if (Array.isArray(config.ssr.noExternal)) config.ssr.noExternal.push(virtualDir);
|
|
4725
4782
|
options.runtimePlugins.forEach((p) => {
|
|
4726
4783
|
const pluginPath = typeof p === "string" ? p : p[0];
|
|
4727
4784
|
if (pluginPath && !pluginPath.startsWith(".") && !pluginPath.startsWith("/") && !pluginPath.startsWith("\0") && !pluginPath.startsWith("virtual:")) config.optimizeDeps.include.push(pluginPath);
|
|
@@ -4729,9 +4786,6 @@ function federation(mfUserOptions) {
|
|
|
4729
4786
|
if (isRolldown) {
|
|
4730
4787
|
config.build ??= {};
|
|
4731
4788
|
config.build.target ??= "esnext";
|
|
4732
|
-
} else {
|
|
4733
|
-
config.optimizeDeps.needsInterop ||= [];
|
|
4734
|
-
config.optimizeDeps.needsInterop.push(virtualDir);
|
|
4735
4789
|
}
|
|
4736
4790
|
const isAstro = hasPackageDependency("astro");
|
|
4737
4791
|
const resolvedTarget = options.target ?? (config.build?.ssr ? "node" : "web");
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@module-federation/vite",
|
|
3
|
-
"version": "1.15.
|
|
3
|
+
"version": "1.15.3",
|
|
4
4
|
"description": "Vite plugin for Module Federation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.cjs",
|
|
@@ -84,6 +84,7 @@
|
|
|
84
84
|
"oxfmt": "^0.36.0",
|
|
85
85
|
"rollup": "^4.47.1",
|
|
86
86
|
"tsdown": "^0.21.0",
|
|
87
|
+
"typescript": "5.9.3",
|
|
87
88
|
"vite": "^8.0.10",
|
|
88
89
|
"vitest": "^4.0.18"
|
|
89
90
|
}
|