@module-federation/vite 1.15.2 → 1.15.4

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.
Files changed (3) hide show
  1. package/lib/index.cjs +189 -131
  2. package/lib/index.mjs +193 -135
  3. 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, virtualModuleDir } = getNormalizeModuleFederationOptions();
753
- return `${virtualModuleDir}/${packageNameEncode(`${mfName}${this.tag}${this.name}${this.tag}`)}${this.suffix}`;
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
- const path = this.getPath();
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
- const path = this.getPath();
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,20 @@ 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
+ const namedExportVars = namedExports.map((_name, i) => `__mf_${i}`);
1172
+ const declarations = namedExports.map((name, i) => `const ${namedExportVars[i]} = __mfPrebuildExports[${escapeGeneratedStringLiteral(name)}];`).join("\n ");
1173
+ const namedExportLine = `export { ${namedExports.map((name, i) => `${namedExportVars[i]} as ${name}`).join(", ")} };`;
1174
+ preBuildCacheMap[pkg].writeSync(`
1175
+ import * as __mfPrebuildNamespace from ${escapeGeneratedStringLiteral(importSource)};
1176
+ const __mfPrebuildExports = __mfPrebuildNamespace;
1177
+ ${declarations}
1178
+ ${namedExportLine}
1179
+ export default __mfPrebuildExports;
1211
1180
  `, true);
1212
1181
  return;
1213
1182
  }
@@ -1235,25 +1204,62 @@ function getLoadShareImportId(pkg, _isRolldown) {
1235
1204
  }
1236
1205
  function getLoadShareModulePath(pkg, isRolldown) {
1237
1206
  if (!loadShareCacheMap[pkg]) getLoadShareImportId(pkg, isRolldown);
1238
- return loadShareCacheMap[pkg].getPath();
1207
+ return loadShareCacheMap[pkg].getImportId();
1239
1208
  }
1209
+ function generateDeferredHostProvidedExports(namedExports, pkg) {
1210
+ const namedExportVars = namedExports.map((_name, i) => `__mf_${i}`);
1211
+ const declarations = ["let __mf_default;", ...namedExportVars.map((name) => `let ${name};`)].join("\n ");
1212
+ const assignments = [...namedExports.map((name, i) => `${namedExportVars[i]} = exportModule[${escapeGeneratedStringLiteral(name)}];`), "__mf_default = exportModule.default ?? exportModule;"].join("\n ");
1213
+ const namedExportLine = namedExports.length > 0 ? `\n export { ${namedExports.map((name, i) => `${namedExportVars[i]} as ${name}`).join(", ")} };` : "";
1214
+ return `${declarations}
1215
+ const __mfApplyHostProvidedExports = (exportModule) => {
1216
+ ${assignments}
1217
+ };
1218
+ let exportModule = __mfModuleCache.share[${escapeGeneratedStringLiteral(pkg)}];
1219
+ if (exportModule === undefined) {
1220
+ initPromise.then(() => {
1221
+ exportModule = __mfModuleCache.share[${escapeGeneratedStringLiteral(pkg)}];
1222
+ if (exportModule === undefined) {
1223
+ throw new Error("[Module Federation] Shared module ${pkg} was imported before federation bootstrap finished.");
1224
+ }
1225
+ __mfApplyHostProvidedExports(exportModule);
1226
+ });
1227
+ } else {
1228
+ __mfApplyHostProvidedExports(exportModule);
1229
+ }
1230
+ export { __mf_default as default };${namedExportLine}`;
1231
+ }
1232
+ function generateShareModuleUnwrapCode({ source, preserveNamedExports, stopWithReturn }) {
1233
+ return `let current = ${source};
1234
+ for (let i = 0; i < 5; i++) {
1235
+ const defaultExport = current?.default;
1236
+ ${stopWithReturn ? `if (!defaultExport || typeof defaultExport !== "object") return ${stopWithReturn};` : `if (!defaultExport || typeof defaultExport !== "object") break;`}${preserveNamedExports ? `
1237
+ const namedValues = Object.keys(current).filter((key) => key !== "default").map((key) => current[key]);
1238
+ if (namedValues.length > 0 && namedValues.some((value) => value !== undefined)) break;` : ""}
1239
+ current = defaultExport;
1240
+ }
1241
+ return current;`;
1242
+ }
1243
+ const normalizeLocalShareModuleCode = `const __mfNormalizeShareModule = (mod) => {
1244
+ ${generateShareModuleUnwrapCode({
1245
+ source: "mod",
1246
+ preserveNamedExports: true
1247
+ })}
1248
+ };`;
1240
1249
  function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
1241
1250
  if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, ".mjs");
1242
1251
  const importLine = getRuntimeModuleCacheBootstrapCode();
1243
1252
  if (shareItem.shareConfig.import === false) {
1244
1253
  const namedExports = getPackageNamedExports(pkg);
1245
1254
  let exportLine;
1246
- if (namedExports.length > 0) exportLine = `export default exportModule.default ?? exportModule;\n ${`const { ${namedExports.map((name, i) => `${name}: __mf_${i}`).join(", ")} } = exportModule;`}\n ${`export { ${namedExports.map((name, i) => `__mf_${i} as ${name}`).join(", ")} };`}`;
1255
+ if (namedExports.length > 0) exportLine = generateDeferredHostProvidedExports(namedExports, pkg);
1247
1256
  else {
1248
1257
  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 = "export default exportModule.default ?? exportModule";
1258
+ exportLine = generateDeferredHostProvidedExports([], pkg);
1250
1259
  }
1251
1260
  loadShareCacheMap[pkg].writeSync(`
1261
+ ${getRuntimeInitPromiseBootstrapCode()}
1252
1262
  ${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
1263
  ${exportLine}
1258
1264
  `, true);
1259
1265
  return;
@@ -1268,8 +1274,20 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
1268
1274
  const usesLazyLocalFallback = isWorkspacePackage && shareItem.shareConfig.singleton === true;
1269
1275
  const namedExports = getPackageNamedExports(pkg);
1270
1276
  let exportLine;
1271
- if (namedExports.length > 0) exportLine = `export default exportModule.default ?? exportModule;\n ${`const { ${namedExports.map((name, i) => `${name}: __mf_${i}`).join(", ")} } = exportModule;`}\n ${`export { ${namedExports.map((name, i) => `__mf_${i} as ${name}`).join(", ")} };`}`;
1272
- else if (usesLazyLocalFallback) exportLine = `export default exportModule.default ?? exportModule`;
1277
+ if (namedExports.length > 0) {
1278
+ const destructure = `const { ${namedExports.map((name, i) => `${name}: __mf_${i}`).join(", ")} } = exportModule;`;
1279
+ const namedExportLine = `export { ${namedExports.map((name, i) => `__mf_${i} as ${name}`).join(", ")} };`;
1280
+ exportLine = `const __mfDefaultExport = (() => {
1281
+ ${generateShareModuleUnwrapCode({
1282
+ source: "exportModule",
1283
+ preserveNamedExports: false,
1284
+ stopWithReturn: "defaultExport ?? current"
1285
+ })}
1286
+ })();
1287
+ export default __mfDefaultExport;
1288
+ ${destructure}
1289
+ ${namedExportLine}`;
1290
+ } else if (usesLazyLocalFallback) exportLine = `export default exportModule.default ?? exportModule`;
1273
1291
  else exportLine = `export default exportModule.default ?? exportModule\n export * from ${escapeGeneratedStringLiteral(sharedImportSource)}`;
1274
1292
  const prebuildImportLine = usesLazyLocalFallback || isWorkspacePackage && command !== "build" ? "" : `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(skipServePrebuildWarmup ? devImportSource : sharedImportSource)};`;
1275
1293
  const devDynamicImportLine = isWorkspacePackage ? "" : command !== "build" && !skipServePrebuildWarmup ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
@@ -1277,10 +1295,11 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
1277
1295
  ${prebuildImportLine}
1278
1296
  ${devDynamicImportLine}
1279
1297
  ${importLine}
1298
+ ${normalizeLocalShareModuleCode}
1280
1299
  let exportModule = __mfModuleCache.share[${escapeGeneratedStringLiteral(pkg)}]
1281
1300
  if (exportModule === undefined) {
1282
- ${usesLazyLocalFallback ? `exportModule = await import(${escapeGeneratedStringLiteral(lazyLocalFallbackSource)});
1283
- __mfModuleCache.share[${escapeGeneratedStringLiteral(pkg)}] = exportModule;` : `exportModule = __mfLocalShare;
1301
+ ${usesLazyLocalFallback ? `exportModule = __mfNormalizeShareModule(await import(${escapeGeneratedStringLiteral(lazyLocalFallbackSource)}));
1302
+ __mfModuleCache.share[${escapeGeneratedStringLiteral(pkg)}] = exportModule;` : `exportModule = __mfNormalizeShareModule(__mfLocalShare);
1284
1303
  __mfModuleCache.share[${escapeGeneratedStringLiteral(pkg)}] = exportModule;`}
1285
1304
  }
1286
1305
  ${exportLine}
@@ -1438,9 +1457,9 @@ function getShareItemForPreload(pkg) {
1438
1457
  function generateSharedCacheSeedItem(pkg, importPath) {
1439
1458
  return `if (__mfModuleCache.share[${JSON.stringify(pkg)}] === undefined) {
1440
1459
  const mod = await import(${JSON.stringify(importPath)});
1441
- const exportModule = ${JSON.stringify(shouldUseDirectReactImport())} && ${JSON.stringify(pkg)} === "react"
1442
- ? (mod?.default ?? mod)
1443
- : {...mod};
1460
+ ${normalizeRuntimeShareCode}
1461
+ const normalizedModule = __mfNormalizeRuntimeShare(mod);
1462
+ const exportModule = normalizedModule === mod ? {...mod} : normalizedModule;
1444
1463
  Object.defineProperty(exportModule, "__esModule", {
1445
1464
  value: true,
1446
1465
  enumerable: false
@@ -1448,6 +1467,17 @@ function generateSharedCacheSeedItem(pkg, importPath) {
1448
1467
  __mfModuleCache.share[${JSON.stringify(pkg)}] = exportModule;
1449
1468
  }`;
1450
1469
  }
1470
+ const normalizeRuntimeShareCode = `const __mfNormalizeRuntimeShare = (mod) => {
1471
+ let current = mod;
1472
+ for (let i = 0; i < 5; i++) {
1473
+ const defaultExport = current?.default;
1474
+ if (!defaultExport || typeof defaultExport !== "object") break;
1475
+ const namedValues = Object.keys(current).filter((key) => key !== "default").map((key) => current[key]);
1476
+ if (namedValues.length > 0 && namedValues.some((value) => value !== undefined)) break;
1477
+ current = defaultExport;
1478
+ }
1479
+ return current;
1480
+ };`;
1451
1481
  function generateDirectSharedCacheSeedCode(command = "build") {
1452
1482
  return getOrderedUsedShares().map((pkg) => {
1453
1483
  const shareItem = getShareItemForPreload(pkg);
@@ -1470,7 +1500,8 @@ function getHostAutoInitSharedSeedItems() {
1470
1500
  return priority(a.pkg) - priority(b.pkg) || Number(aIsLocal) - Number(bIsLocal) || a.pkg.localeCompare(b.pkg);
1471
1501
  });
1472
1502
  }
1473
- function generateHostAutoInitSharedCacheSeedCode() {
1503
+ function generateHostAutoInitSharedCacheSeedCode(command = "build") {
1504
+ if (command === "build") return "";
1474
1505
  return getHostAutoInitSharedSeedItems().map(({ pkg, shareItem }) => {
1475
1506
  if (!shareItem) return null;
1476
1507
  return generateSharedCacheSeedItem(pkg, getBrowserImportPath(getDirectSharedCacheSeedImportPath(pkg, shareItem)));
@@ -1502,14 +1533,13 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1502
1533
  if (typeof __VUE_HMR_RUNTIME__ === 'undefined') {
1503
1534
  globalThis.__VUE_HMR_RUNTIME__ = { createRecord() {}, rerender() {}, reload() {} };
1504
1535
  }
1505
- import {createInstance, loadRemote} from "@module-federation/runtime";
1536
+ import {init as runtimeInit, loadRemote} from "@module-federation/runtime";
1506
1537
  ${pluginImportNames.map((item) => item[1]).join("\n")}
1507
1538
  ${command === "build" ? getRuntimeInitResolveBootstrapCode() : getRuntimeInitBootstrapCode() + "\n const { initResolve } = globalThis[globalKey];"}
1508
1539
  ${getRuntimeModuleCacheBootstrapCode()}
1509
1540
  const initTokens = {}
1510
1541
  const shareScopeName = ${JSON.stringify(options.shareScope)}
1511
1542
  const mfName = ${JSON.stringify(options.internalName)}
1512
- let runtimeInstance
1513
1543
  let localSharedImportMapPromise
1514
1544
  let exposesMapPromise
1515
1545
  const shouldRetrySharedInitError = ${command !== "build"} && ((error) => {
@@ -1552,19 +1582,13 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1552
1582
  async function init(shared = {}, initScope = []) {
1553
1583
  const {usedShared, usedRemotes} = await getLocalSharedImportMap()
1554
1584
  ${generateDirectSharedCacheSeedCode(command)}
1555
- const runtimeOptions = {
1585
+ const initRes = runtimeInit({
1556
1586
  name: mfName,
1557
1587
  remotes: usedRemotes,
1558
1588
  shared: usedShared,
1559
1589
  plugins: [${pluginImportNames.map((item) => `${item[0]}(${item[2]})`).join(", ")}],
1560
1590
  ${options.shareStrategy ? `shareStrategy: '${options.shareStrategy}'` : ""}
1561
- };
1562
- if (!runtimeInstance) {
1563
- runtimeInstance = createInstance(runtimeOptions);
1564
- } else {
1565
- runtimeInstance.initOptions(runtimeOptions);
1566
- }
1567
- const initRes = runtimeInstance;
1591
+ });
1568
1592
  // handling circular init calls
1569
1593
  var initToken = initTokens[shareScopeName];
1570
1594
  if (!initToken)
@@ -1584,6 +1608,17 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1584
1608
  } catch (e) {
1585
1609
  console.error('[Module Federation]', e)
1586
1610
  }
1611
+ for (const [pkg, share] of Object.entries(usedShared)) {
1612
+ if (share.shareConfig?.import !== false || __mfModuleCache.share[pkg] !== undefined) continue;
1613
+ ${normalizeRuntimeShareCode}
1614
+ const versions = shared?.[pkg];
1615
+ const provider = versions && versions[Object.keys(versions)[0]];
1616
+ if (!provider) continue;
1617
+ const factory = provider.lib || (provider.loading ? await provider.loading : await provider.get?.());
1618
+ const mod = typeof factory === "function" ? factory() : factory;
1619
+ const resolved = await Promise.resolve(mod);
1620
+ __mfModuleCache.share[pkg] = __mfNormalizeRuntimeShare(resolved);
1621
+ }
1587
1622
  return initRes
1588
1623
  }
1589
1624
 
@@ -1608,10 +1643,11 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build") {
1608
1643
  async function initHost() {
1609
1644
  if (!hostInitPromise) {
1610
1645
  hostInitPromise = (async () => {
1611
- ${generateHostAutoInitSharedCacheSeedCode()}
1646
+ ${generateHostAutoInitSharedCacheSeedCode(_command)}
1612
1647
  const remoteEntry = await import(${remoteEntryImport});
1613
1648
  const runtime = await remoteEntry.init();
1614
1649
  const usedShared = ${generateUsedSharedPreloadConfig()};
1650
+ ${normalizeRuntimeShareCode}
1615
1651
  for (const [pkg, share] of Object.entries(usedShared)) {
1616
1652
  if (__mfModuleCache.share[pkg] !== undefined) {
1617
1653
  continue;
@@ -1621,7 +1657,7 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build") {
1621
1657
  }).then((factory) => {
1622
1658
  const mod = typeof factory === "function" ? factory() : factory;
1623
1659
  return Promise.resolve(mod).then((resolved) => {
1624
- __mfModuleCache.share[pkg] = resolved;
1660
+ __mfModuleCache.share[pkg] = __mfNormalizeRuntimeShare(resolved);
1625
1661
  });
1626
1662
  });
1627
1663
  }
@@ -1650,7 +1686,7 @@ function getHostAutoInitImportId() {
1650
1686
  return hostAutoInitModule.getImportId();
1651
1687
  }
1652
1688
  function getHostAutoInitPath() {
1653
- return hostAutoInitModule.getPath();
1689
+ return hostAutoInitModule.getImportId();
1654
1690
  }
1655
1691
  //#endregion
1656
1692
  //#region src/virtualModules/virtualRemotes.ts
@@ -1673,7 +1709,9 @@ function getUsedRemotesMap() {
1673
1709
  }
1674
1710
  function generateRemotes(id, command) {
1675
1711
  const useReactProxy = command === "serve" && hasPackageDependency("react");
1676
- const reactImportLine = useReactProxy ? `import * as __mfReact from "react";` : "";
1712
+ const reactImportLine = useReactProxy ? `import __mfReactDefault from "react";
1713
+ import * as __mfReactNamespace from "react";
1714
+ const __mfReact = __mfReactDefault ?? __mfReactNamespace.default ?? __mfReactNamespace;` : "";
1677
1715
  const importLine = command === "build" ? `${getRuntimeModuleCacheBootstrapCode()}
1678
1716
  import { hostInitPromise as __mfHostInitPromise } from ${JSON.stringify(getHostAutoInitPath())};` : `${getRuntimeInitBootstrapCode()}
1679
1717
  const { initPromise, moduleCache: __mfModuleCache } = globalThis[globalKey];`;
@@ -1683,13 +1721,13 @@ function generateRemotes(id, command) {
1683
1721
  }
1684
1722
  export const __moduleExports = exportModule;
1685
1723
  export const __mf_remote_pending = Promise.resolve(exportModule);
1686
- export default exportModule?.__esModule ? exportModule.default : exportModule.default ?? exportModule` : command === "build" ? `if (__mfRemotePending) {
1724
+ export default exportModule?.__mf_is_remote_proxy ? exportModule : exportModule?.__esModule ? exportModule.default : exportModule.default ?? exportModule` : command === "build" ? `if (__mfRemotePending) {
1687
1725
  const mod = await __mfRemotePending;
1688
1726
  if (mod !== undefined) exportModule = mod;
1689
1727
  }
1690
1728
  export const __moduleExports = exportModule;
1691
1729
  export const __mf_remote_pending = Promise.resolve(exportModule);
1692
- export default exportModule?.__esModule ? exportModule.default : exportModule.default ?? exportModule` : "export default exportModule";
1730
+ export default exportModule?.__mf_is_remote_proxy ? exportModule : exportModule?.__esModule ? exportModule.default : exportModule.default ?? exportModule` : "export default exportModule";
1693
1731
  return `
1694
1732
  ${reactImportLine}
1695
1733
  ${importLine}
@@ -1889,6 +1927,9 @@ ${importHelper}(async () => {
1889
1927
  if (inject === "html" && hasPackageDependency("@sveltejs/kit")) return false;
1890
1928
  return inject === "entry" || !htmlFilePath;
1891
1929
  }
1930
+ function normalizeDevHtmlProxyId(id) {
1931
+ return id.replace(/^\0/, "").replace(/^\/@id\//, "").replace(/^__x00__/, "");
1932
+ }
1892
1933
  return [{
1893
1934
  name: "add-entry",
1894
1935
  apply: "serve",
@@ -1907,7 +1948,20 @@ ${importHelper}(async () => {
1907
1948
  }
1908
1949
  },
1909
1950
  configureServer(server) {
1910
- server.middlewares.use((req, _res, next) => {
1951
+ server.middlewares.use((req, res, next) => {
1952
+ const rawUrl = req.url?.split("#")[0] ?? "";
1953
+ if (normalizeDevHtmlProxyId(rawUrl.split("?")[0]) === DEV_HTML_PROXY_PREFIX.slice(0, -1)) {
1954
+ const query = rawUrl.slice(rawUrl.indexOf("?") + 1);
1955
+ const params = new URLSearchParams(query);
1956
+ const initSrc = params.get("init");
1957
+ const entrySrc = params.get("entry");
1958
+ if (initSrc && entrySrc) {
1959
+ res.statusCode = 200;
1960
+ res.setHeader("Content-Type", "application/javascript");
1961
+ res.end(getBootstrapSource(initSrc, entrySrc));
1962
+ return;
1963
+ }
1964
+ }
1911
1965
  if (!fileName) {
1912
1966
  next();
1913
1967
  return;
@@ -1924,7 +1978,7 @@ ${importHelper}(async () => {
1924
1978
  const base = viteConfig.base.replace(/\/$/, "");
1925
1979
  const stripBase = (p) => base && p.startsWith(base + "/") ? p.slice(base.length) : p;
1926
1980
  const html = rewriteEntryScripts(c, (originalSrc) => {
1927
- return `/@id/${DEV_HTML_PROXY_PREFIX}${new URLSearchParams({
1981
+ return `/@id/__x00__${DEV_HTML_PROXY_PREFIX}${new URLSearchParams({
1928
1982
  init: sanitizeDevEntryPath(stripBase(devEntryPath)),
1929
1983
  entry: sanitizeDevEntryPath(stripBase(originalSrc))
1930
1984
  }).toString()}`;
@@ -1933,11 +1987,12 @@ ${importHelper}(async () => {
1933
1987
  }
1934
1988
  },
1935
1989
  resolveId(id) {
1936
- if (id.startsWith(DEV_HTML_PROXY_PREFIX)) return id;
1990
+ if (normalizeDevHtmlProxyId(id).startsWith(DEV_HTML_PROXY_PREFIX)) return id;
1937
1991
  },
1938
1992
  load(id) {
1939
- if (!id.startsWith(DEV_HTML_PROXY_PREFIX)) return;
1940
- const params = new URLSearchParams(id.slice(28));
1993
+ const normalizedId = normalizeDevHtmlProxyId(id);
1994
+ if (!normalizedId.startsWith(DEV_HTML_PROXY_PREFIX)) return;
1995
+ const params = new URLSearchParams(normalizedId.slice(28));
1941
1996
  const initSrc = params.get("init");
1942
1997
  const entrySrc = params.get("entry");
1943
1998
  if (!initSrc || !entrySrc) return;
@@ -2744,7 +2799,7 @@ function collectSystemProxyInfos(proxyChunks, loadShareTag) {
2744
2799
  for (const m of proxyInfo.code.matchAll(/exports\(\s*["']([^"']+)["']\s*,([\s\S]*?)\);/g)) {
2745
2800
  const exported = m[1];
2746
2801
  const expression = m[2];
2747
- for (const [local, exportName] of Object.entries(loadShareBindings)) if (new RegExp(`\\b${local}\\b`).test(expression)) {
2802
+ for (const [local, exportName] of Object.entries(loadShareBindings).reverse()) if (new RegExp(`\\b${local}\\b`).test(expression)) {
2748
2803
  exportMap[exported] = {
2749
2804
  type: "reexport",
2750
2805
  exportName
@@ -3508,7 +3563,7 @@ function pluginProxyRemotes_default(options) {
3508
3563
  const remoteModule = getRemoteVirtualModule(source, command);
3509
3564
  addUsedRemote(remoteName, source);
3510
3565
  refreshHostAutoInit();
3511
- return remoteModule.getPath();
3566
+ return remoteModule.getImportId();
3512
3567
  }
3513
3568
  return {
3514
3569
  name: "proxyRemotes",
@@ -4330,12 +4385,12 @@ function isFederationHtmlPreloadDependency(dep, includeSharedRuntime = false) {
4330
4385
  return includeSharedRuntime && (file.includes("preload-helper") || file.includes("rolldown-runtime") || file.startsWith("dist-"));
4331
4386
  }
4332
4387
  /**
4333
- * Plugin that runs FIRST to create virtual module files in the config hook.
4334
- * This prevents 504 "Outdated Optimize Dep" errors by ensuring files exist
4388
+ * Plugin that runs FIRST to register generated virtual modules in the config hook.
4389
+ * This prevents 504 "Outdated Optimize Dep" errors by ensuring ids are known
4335
4390
  * before Vite's optimization phase.
4336
4391
  */
4337
4392
  function createEarlyVirtualModulesPlugin(options) {
4338
- const { shared, remotes, virtualModuleDir } = options;
4393
+ const { shared, remotes } = options;
4339
4394
  const isLitShare = (pkg) => pkg === "lit" || pkg.startsWith("lit/");
4340
4395
  return {
4341
4396
  name: "vite:module-federation-early-init",
@@ -4345,9 +4400,6 @@ function createEarlyVirtualModulesPlugin(options) {
4345
4400
  const root = config.root || process.cwd();
4346
4401
  setPackageDetectionCwd(root);
4347
4402
  const isVinext = hasPackageDependency("vinext");
4348
- initVirtualModuleInfrastructure(root, virtualModuleDir);
4349
- VirtualModule.setRoot(root);
4350
- VirtualModule.ensureVirtualPackageExists();
4351
4403
  initVirtualModules(_command, getRemoteEntryId(options));
4352
4404
  const isRolldown = getIsRolldown(this);
4353
4405
  if (remotes && Object.keys(remotes).length > 0) {
@@ -4393,6 +4445,10 @@ function createEarlyVirtualModulesPlugin(options) {
4393
4445
  optimizeDeps.esbuildOptions.plugins.push({
4394
4446
  name: "module-federation:optimize-shared-proxy",
4395
4447
  setup(build) {
4448
+ build.onResolve({ filter: /^virtual:mf:/ }, (args) => ({
4449
+ path: args.path,
4450
+ external: true
4451
+ }));
4396
4452
  build.onResolve({ filter: /.*/ }, (args) => {
4397
4453
  if (!args.importer || args.namespace === "mf-shared") return;
4398
4454
  if (isSharedResolverInternalImporter(args.importer)) return;
@@ -4424,7 +4480,6 @@ export default __mfShared.default ?? __mfShared;`
4424
4480
  }
4425
4481
  });
4426
4482
  }
4427
- config.optimizeDeps.include.push(virtualRuntimeInitStatus.getImportId());
4428
4483
  }
4429
4484
  for (const key of Object.keys(shared)) {
4430
4485
  const shareItem = shared[key];
@@ -4435,7 +4490,6 @@ export default __mfShared.default ?? __mfShared;`
4435
4490
  for (const subpath of getCommonSharedSubpaths(key)) {
4436
4491
  writePreBuildLibPath(subpath, shareItem);
4437
4492
  optimizeDeps.include.push(subpath);
4438
- optimizeDeps.include.push(getPreBuildLibImportId(subpath));
4439
4493
  }
4440
4494
  }
4441
4495
  continue;
@@ -4452,14 +4506,11 @@ export default __mfShared.default ?? __mfShared;`
4452
4506
  const optimizeDeps = config.optimizeDeps ??= {};
4453
4507
  optimizeDeps.include ??= [];
4454
4508
  optimizeDeps.exclude ??= [];
4455
- const shouldBypassOptimizeDep = isLitShare(key);
4456
- if (shouldBypassOptimizeDep) optimizeDeps.exclude.push(key);
4457
- if (!isRolldown && !shouldBypassOptimizeDep) optimizeDeps.include.push(getLoadShareImportId(key, isRolldown));
4458
- optimizeDeps.include.push(getPreBuildLibImportId(key));
4509
+ if (isLitShare(key)) optimizeDeps.exclude.push(key);
4510
+ else optimizeDeps.include.push(key);
4459
4511
  for (const subpath of getCommonSharedSubpaths(key)) {
4460
4512
  writePreBuildLibPath(subpath, shareItem);
4461
4513
  optimizeDeps.include.push(subpath);
4462
- optimizeDeps.include.push(getPreBuildLibImportId(subpath));
4463
4514
  }
4464
4515
  }
4465
4516
  }
@@ -4479,6 +4530,21 @@ function federation(mfUserOptions) {
4479
4530
  let command;
4480
4531
  let desiredRolldownOutput;
4481
4532
  return [
4533
+ {
4534
+ name: "vite:module-federation-virtual-modules",
4535
+ enforce: "pre",
4536
+ resolveId(id) {
4537
+ const virtualModule = VirtualModule.findById(id);
4538
+ if (!virtualModule) return;
4539
+ return virtualModule.getResolvedId();
4540
+ },
4541
+ load(id) {
4542
+ const virtualModule = VirtualModule.findById(id);
4543
+ if (!virtualModule) return;
4544
+ if (command === "build" && (id.includes("__loadShare__") || id.includes("__loadRemote__"))) return;
4545
+ return virtualModule.code;
4546
+ }
4547
+ },
4482
4548
  createEarlyVirtualModulesPlugin(options),
4483
4549
  ...isVinext ? [{
4484
4550
  name: "module-federation-vinext-react-server-build-alias",
@@ -4503,9 +4569,7 @@ function federation(mfUserOptions) {
4503
4569
  config(_config, env) {
4504
4570
  command = env.command;
4505
4571
  },
4506
- configResolved(config) {
4507
- VirtualModule.setRoot(config.root);
4508
- VirtualModule.ensureVirtualPackageExists();
4572
+ configResolved() {
4509
4573
  initVirtualModules(command, remoteEntryId);
4510
4574
  }
4511
4575
  },
@@ -4648,9 +4712,8 @@ function federation(mfUserOptions) {
4648
4712
  }
4649
4713
  },
4650
4714
  load(id) {
4651
- if (id.startsWith("\0")) return;
4652
4715
  if (id.includes("__loadShare__") || id.includes("__loadRemote__")) {
4653
- let code = (0, fs.readFileSync)(id, "utf-8");
4716
+ let code = VirtualModule.findById(id)?.code ?? (0, fs.readFileSync)(id, "utf-8");
4654
4717
  code = code.replace(/import\s+["'][^"']*__prebuild__[^"']*["']\s*;?/g, "");
4655
4718
  code = code.replace(/export\s+\*\s+from\s+["'][^"']*__prebuild__[^"']*["']\s*;?/g, "");
4656
4719
  /**
@@ -4669,7 +4732,10 @@ function federation(mfUserOptions) {
4669
4732
  *
4670
4733
  * @see https://rollupjs.org/plugin-development/#synthetic-named-exports
4671
4734
  */
4672
- if (!code.includes("__moduleExports")) code = code.replace("export default exportModule", "export const __moduleExports = exportModule;\nexport default exportModule.__esModule ? exportModule.default : exportModule");
4735
+ if (!/\bexport\s+const\s+__moduleExports\b/.test(code)) {
4736
+ const nextCode = code.replace("export default exportModule", "export const __moduleExports = exportModule;\nexport default exportModule.__esModule ? exportModule.default : exportModule");
4737
+ code = nextCode === code ? `${code}\nexport const __moduleExports = exportModule;\n` : nextCode;
4738
+ }
4673
4739
  if (getIsRolldown(this)) return { code };
4674
4740
  return {
4675
4741
  code,
@@ -4734,14 +4800,9 @@ function federation(mfUserOptions) {
4734
4800
  config.build ||= {};
4735
4801
  config.build.commonjsOptions ||= {};
4736
4802
  config.build.commonjsOptions.strictRequires ??= "auto";
4737
- const virtualDir = options.virtualModuleDir;
4738
4803
  config.optimizeDeps ||= {};
4739
4804
  config.optimizeDeps.include ||= [];
4740
4805
  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
4806
  options.runtimePlugins.forEach((p) => {
4746
4807
  const pluginPath = typeof p === "string" ? p : p[0];
4747
4808
  if (pluginPath && !pluginPath.startsWith(".") && !pluginPath.startsWith("/") && !pluginPath.startsWith("\0") && !pluginPath.startsWith("virtual:")) config.optimizeDeps.include.push(pluginPath);
@@ -4749,9 +4810,6 @@ function federation(mfUserOptions) {
4749
4810
  if (isRolldown) {
4750
4811
  config.build ??= {};
4751
4812
  config.build.target ??= "esnext";
4752
- } else {
4753
- config.optimizeDeps.needsInterop ||= [];
4754
- config.optimizeDeps.needsInterop.push(virtualDir);
4755
4813
  }
4756
4814
  const isAstro = hasPackageDependency("astro");
4757
4815
  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, mkdirSync, readFileSync, readdirSync, realpathSync, statSync, writeFile, writeFileSync } from "fs";
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, dirname, join, parse, resolve } from "pathe";
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 as parse$1 } from "es-module-lexer";
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, virtualModuleDir } = getNormalizeModuleFederationOptions();
733
- return `${virtualModuleDir}/${packageNameEncode(`${mfName}${this.tag}${this.name}${this.tag}`)}${this.suffix}`;
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
- const path = this.getPath();
739
- mkdirSync(dirname(path), { recursive: true });
740
- writeFileSync(path, code);
689
+ this.code = code;
741
690
  }
742
691
  write(code) {
743
- const path = this.getPath();
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,20 @@ 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
+ const namedExportVars = namedExports.map((_name, i) => `__mf_${i}`);
1152
+ const declarations = namedExports.map((name, i) => `const ${namedExportVars[i]} = __mfPrebuildExports[${escapeGeneratedStringLiteral(name)}];`).join("\n ");
1153
+ const namedExportLine = `export { ${namedExports.map((name, i) => `${namedExportVars[i]} as ${name}`).join(", ")} };`;
1154
+ preBuildCacheMap[pkg].writeSync(`
1155
+ import * as __mfPrebuildNamespace from ${escapeGeneratedStringLiteral(importSource)};
1156
+ const __mfPrebuildExports = __mfPrebuildNamespace;
1157
+ ${declarations}
1158
+ ${namedExportLine}
1159
+ export default __mfPrebuildExports;
1191
1160
  `, true);
1192
1161
  return;
1193
1162
  }
@@ -1215,25 +1184,62 @@ function getLoadShareImportId(pkg, _isRolldown) {
1215
1184
  }
1216
1185
  function getLoadShareModulePath(pkg, isRolldown) {
1217
1186
  if (!loadShareCacheMap[pkg]) getLoadShareImportId(pkg, isRolldown);
1218
- return loadShareCacheMap[pkg].getPath();
1187
+ return loadShareCacheMap[pkg].getImportId();
1219
1188
  }
1189
+ function generateDeferredHostProvidedExports(namedExports, pkg) {
1190
+ const namedExportVars = namedExports.map((_name, i) => `__mf_${i}`);
1191
+ const declarations = ["let __mf_default;", ...namedExportVars.map((name) => `let ${name};`)].join("\n ");
1192
+ const assignments = [...namedExports.map((name, i) => `${namedExportVars[i]} = exportModule[${escapeGeneratedStringLiteral(name)}];`), "__mf_default = exportModule.default ?? exportModule;"].join("\n ");
1193
+ const namedExportLine = namedExports.length > 0 ? `\n export { ${namedExports.map((name, i) => `${namedExportVars[i]} as ${name}`).join(", ")} };` : "";
1194
+ return `${declarations}
1195
+ const __mfApplyHostProvidedExports = (exportModule) => {
1196
+ ${assignments}
1197
+ };
1198
+ let exportModule = __mfModuleCache.share[${escapeGeneratedStringLiteral(pkg)}];
1199
+ if (exportModule === undefined) {
1200
+ initPromise.then(() => {
1201
+ exportModule = __mfModuleCache.share[${escapeGeneratedStringLiteral(pkg)}];
1202
+ if (exportModule === undefined) {
1203
+ throw new Error("[Module Federation] Shared module ${pkg} was imported before federation bootstrap finished.");
1204
+ }
1205
+ __mfApplyHostProvidedExports(exportModule);
1206
+ });
1207
+ } else {
1208
+ __mfApplyHostProvidedExports(exportModule);
1209
+ }
1210
+ export { __mf_default as default };${namedExportLine}`;
1211
+ }
1212
+ function generateShareModuleUnwrapCode({ source, preserveNamedExports, stopWithReturn }) {
1213
+ return `let current = ${source};
1214
+ for (let i = 0; i < 5; i++) {
1215
+ const defaultExport = current?.default;
1216
+ ${stopWithReturn ? `if (!defaultExport || typeof defaultExport !== "object") return ${stopWithReturn};` : `if (!defaultExport || typeof defaultExport !== "object") break;`}${preserveNamedExports ? `
1217
+ const namedValues = Object.keys(current).filter((key) => key !== "default").map((key) => current[key]);
1218
+ if (namedValues.length > 0 && namedValues.some((value) => value !== undefined)) break;` : ""}
1219
+ current = defaultExport;
1220
+ }
1221
+ return current;`;
1222
+ }
1223
+ const normalizeLocalShareModuleCode = `const __mfNormalizeShareModule = (mod) => {
1224
+ ${generateShareModuleUnwrapCode({
1225
+ source: "mod",
1226
+ preserveNamedExports: true
1227
+ })}
1228
+ };`;
1220
1229
  function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
1221
1230
  if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, ".mjs");
1222
1231
  const importLine = getRuntimeModuleCacheBootstrapCode();
1223
1232
  if (shareItem.shareConfig.import === false) {
1224
1233
  const namedExports = getPackageNamedExports(pkg);
1225
1234
  let exportLine;
1226
- if (namedExports.length > 0) exportLine = `export default exportModule.default ?? exportModule;\n ${`const { ${namedExports.map((name, i) => `${name}: __mf_${i}`).join(", ")} } = exportModule;`}\n ${`export { ${namedExports.map((name, i) => `__mf_${i} as ${name}`).join(", ")} };`}`;
1235
+ if (namedExports.length > 0) exportLine = generateDeferredHostProvidedExports(namedExports, pkg);
1227
1236
  else {
1228
1237
  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 = "export default exportModule.default ?? exportModule";
1238
+ exportLine = generateDeferredHostProvidedExports([], pkg);
1230
1239
  }
1231
1240
  loadShareCacheMap[pkg].writeSync(`
1241
+ ${getRuntimeInitPromiseBootstrapCode()}
1232
1242
  ${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
1243
  ${exportLine}
1238
1244
  `, true);
1239
1245
  return;
@@ -1248,8 +1254,20 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
1248
1254
  const usesLazyLocalFallback = isWorkspacePackage && shareItem.shareConfig.singleton === true;
1249
1255
  const namedExports = getPackageNamedExports(pkg);
1250
1256
  let exportLine;
1251
- if (namedExports.length > 0) exportLine = `export default exportModule.default ?? exportModule;\n ${`const { ${namedExports.map((name, i) => `${name}: __mf_${i}`).join(", ")} } = exportModule;`}\n ${`export { ${namedExports.map((name, i) => `__mf_${i} as ${name}`).join(", ")} };`}`;
1252
- else if (usesLazyLocalFallback) exportLine = `export default exportModule.default ?? exportModule`;
1257
+ if (namedExports.length > 0) {
1258
+ const destructure = `const { ${namedExports.map((name, i) => `${name}: __mf_${i}`).join(", ")} } = exportModule;`;
1259
+ const namedExportLine = `export { ${namedExports.map((name, i) => `__mf_${i} as ${name}`).join(", ")} };`;
1260
+ exportLine = `const __mfDefaultExport = (() => {
1261
+ ${generateShareModuleUnwrapCode({
1262
+ source: "exportModule",
1263
+ preserveNamedExports: false,
1264
+ stopWithReturn: "defaultExport ?? current"
1265
+ })}
1266
+ })();
1267
+ export default __mfDefaultExport;
1268
+ ${destructure}
1269
+ ${namedExportLine}`;
1270
+ } else if (usesLazyLocalFallback) exportLine = `export default exportModule.default ?? exportModule`;
1253
1271
  else exportLine = `export default exportModule.default ?? exportModule\n export * from ${escapeGeneratedStringLiteral(sharedImportSource)}`;
1254
1272
  const prebuildImportLine = usesLazyLocalFallback || isWorkspacePackage && command !== "build" ? "" : `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(skipServePrebuildWarmup ? devImportSource : sharedImportSource)};`;
1255
1273
  const devDynamicImportLine = isWorkspacePackage ? "" : command !== "build" && !skipServePrebuildWarmup ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
@@ -1257,10 +1275,11 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
1257
1275
  ${prebuildImportLine}
1258
1276
  ${devDynamicImportLine}
1259
1277
  ${importLine}
1278
+ ${normalizeLocalShareModuleCode}
1260
1279
  let exportModule = __mfModuleCache.share[${escapeGeneratedStringLiteral(pkg)}]
1261
1280
  if (exportModule === undefined) {
1262
- ${usesLazyLocalFallback ? `exportModule = await import(${escapeGeneratedStringLiteral(lazyLocalFallbackSource)});
1263
- __mfModuleCache.share[${escapeGeneratedStringLiteral(pkg)}] = exportModule;` : `exportModule = __mfLocalShare;
1281
+ ${usesLazyLocalFallback ? `exportModule = __mfNormalizeShareModule(await import(${escapeGeneratedStringLiteral(lazyLocalFallbackSource)}));
1282
+ __mfModuleCache.share[${escapeGeneratedStringLiteral(pkg)}] = exportModule;` : `exportModule = __mfNormalizeShareModule(__mfLocalShare);
1264
1283
  __mfModuleCache.share[${escapeGeneratedStringLiteral(pkg)}] = exportModule;`}
1265
1284
  }
1266
1285
  ${exportLine}
@@ -1418,9 +1437,9 @@ function getShareItemForPreload(pkg) {
1418
1437
  function generateSharedCacheSeedItem(pkg, importPath) {
1419
1438
  return `if (__mfModuleCache.share[${JSON.stringify(pkg)}] === undefined) {
1420
1439
  const mod = await import(${JSON.stringify(importPath)});
1421
- const exportModule = ${JSON.stringify(shouldUseDirectReactImport())} && ${JSON.stringify(pkg)} === "react"
1422
- ? (mod?.default ?? mod)
1423
- : {...mod};
1440
+ ${normalizeRuntimeShareCode}
1441
+ const normalizedModule = __mfNormalizeRuntimeShare(mod);
1442
+ const exportModule = normalizedModule === mod ? {...mod} : normalizedModule;
1424
1443
  Object.defineProperty(exportModule, "__esModule", {
1425
1444
  value: true,
1426
1445
  enumerable: false
@@ -1428,6 +1447,17 @@ function generateSharedCacheSeedItem(pkg, importPath) {
1428
1447
  __mfModuleCache.share[${JSON.stringify(pkg)}] = exportModule;
1429
1448
  }`;
1430
1449
  }
1450
+ const normalizeRuntimeShareCode = `const __mfNormalizeRuntimeShare = (mod) => {
1451
+ let current = mod;
1452
+ for (let i = 0; i < 5; i++) {
1453
+ const defaultExport = current?.default;
1454
+ if (!defaultExport || typeof defaultExport !== "object") break;
1455
+ const namedValues = Object.keys(current).filter((key) => key !== "default").map((key) => current[key]);
1456
+ if (namedValues.length > 0 && namedValues.some((value) => value !== undefined)) break;
1457
+ current = defaultExport;
1458
+ }
1459
+ return current;
1460
+ };`;
1431
1461
  function generateDirectSharedCacheSeedCode(command = "build") {
1432
1462
  return getOrderedUsedShares().map((pkg) => {
1433
1463
  const shareItem = getShareItemForPreload(pkg);
@@ -1450,7 +1480,8 @@ function getHostAutoInitSharedSeedItems() {
1450
1480
  return priority(a.pkg) - priority(b.pkg) || Number(aIsLocal) - Number(bIsLocal) || a.pkg.localeCompare(b.pkg);
1451
1481
  });
1452
1482
  }
1453
- function generateHostAutoInitSharedCacheSeedCode() {
1483
+ function generateHostAutoInitSharedCacheSeedCode(command = "build") {
1484
+ if (command === "build") return "";
1454
1485
  return getHostAutoInitSharedSeedItems().map(({ pkg, shareItem }) => {
1455
1486
  if (!shareItem) return null;
1456
1487
  return generateSharedCacheSeedItem(pkg, getBrowserImportPath(getDirectSharedCacheSeedImportPath(pkg, shareItem)));
@@ -1482,14 +1513,13 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1482
1513
  if (typeof __VUE_HMR_RUNTIME__ === 'undefined') {
1483
1514
  globalThis.__VUE_HMR_RUNTIME__ = { createRecord() {}, rerender() {}, reload() {} };
1484
1515
  }
1485
- import {createInstance, loadRemote} from "@module-federation/runtime";
1516
+ import {init as runtimeInit, loadRemote} from "@module-federation/runtime";
1486
1517
  ${pluginImportNames.map((item) => item[1]).join("\n")}
1487
1518
  ${command === "build" ? getRuntimeInitResolveBootstrapCode() : getRuntimeInitBootstrapCode() + "\n const { initResolve } = globalThis[globalKey];"}
1488
1519
  ${getRuntimeModuleCacheBootstrapCode()}
1489
1520
  const initTokens = {}
1490
1521
  const shareScopeName = ${JSON.stringify(options.shareScope)}
1491
1522
  const mfName = ${JSON.stringify(options.internalName)}
1492
- let runtimeInstance
1493
1523
  let localSharedImportMapPromise
1494
1524
  let exposesMapPromise
1495
1525
  const shouldRetrySharedInitError = ${command !== "build"} && ((error) => {
@@ -1532,19 +1562,13 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1532
1562
  async function init(shared = {}, initScope = []) {
1533
1563
  const {usedShared, usedRemotes} = await getLocalSharedImportMap()
1534
1564
  ${generateDirectSharedCacheSeedCode(command)}
1535
- const runtimeOptions = {
1565
+ const initRes = runtimeInit({
1536
1566
  name: mfName,
1537
1567
  remotes: usedRemotes,
1538
1568
  shared: usedShared,
1539
1569
  plugins: [${pluginImportNames.map((item) => `${item[0]}(${item[2]})`).join(", ")}],
1540
1570
  ${options.shareStrategy ? `shareStrategy: '${options.shareStrategy}'` : ""}
1541
- };
1542
- if (!runtimeInstance) {
1543
- runtimeInstance = createInstance(runtimeOptions);
1544
- } else {
1545
- runtimeInstance.initOptions(runtimeOptions);
1546
- }
1547
- const initRes = runtimeInstance;
1571
+ });
1548
1572
  // handling circular init calls
1549
1573
  var initToken = initTokens[shareScopeName];
1550
1574
  if (!initToken)
@@ -1564,6 +1588,17 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1564
1588
  } catch (e) {
1565
1589
  console.error('[Module Federation]', e)
1566
1590
  }
1591
+ for (const [pkg, share] of Object.entries(usedShared)) {
1592
+ if (share.shareConfig?.import !== false || __mfModuleCache.share[pkg] !== undefined) continue;
1593
+ ${normalizeRuntimeShareCode}
1594
+ const versions = shared?.[pkg];
1595
+ const provider = versions && versions[Object.keys(versions)[0]];
1596
+ if (!provider) continue;
1597
+ const factory = provider.lib || (provider.loading ? await provider.loading : await provider.get?.());
1598
+ const mod = typeof factory === "function" ? factory() : factory;
1599
+ const resolved = await Promise.resolve(mod);
1600
+ __mfModuleCache.share[pkg] = __mfNormalizeRuntimeShare(resolved);
1601
+ }
1567
1602
  return initRes
1568
1603
  }
1569
1604
 
@@ -1588,10 +1623,11 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build") {
1588
1623
  async function initHost() {
1589
1624
  if (!hostInitPromise) {
1590
1625
  hostInitPromise = (async () => {
1591
- ${generateHostAutoInitSharedCacheSeedCode()}
1626
+ ${generateHostAutoInitSharedCacheSeedCode(_command)}
1592
1627
  const remoteEntry = await import(${remoteEntryImport});
1593
1628
  const runtime = await remoteEntry.init();
1594
1629
  const usedShared = ${generateUsedSharedPreloadConfig()};
1630
+ ${normalizeRuntimeShareCode}
1595
1631
  for (const [pkg, share] of Object.entries(usedShared)) {
1596
1632
  if (__mfModuleCache.share[pkg] !== undefined) {
1597
1633
  continue;
@@ -1601,7 +1637,7 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build") {
1601
1637
  }).then((factory) => {
1602
1638
  const mod = typeof factory === "function" ? factory() : factory;
1603
1639
  return Promise.resolve(mod).then((resolved) => {
1604
- __mfModuleCache.share[pkg] = resolved;
1640
+ __mfModuleCache.share[pkg] = __mfNormalizeRuntimeShare(resolved);
1605
1641
  });
1606
1642
  });
1607
1643
  }
@@ -1630,7 +1666,7 @@ function getHostAutoInitImportId() {
1630
1666
  return hostAutoInitModule.getImportId();
1631
1667
  }
1632
1668
  function getHostAutoInitPath() {
1633
- return hostAutoInitModule.getPath();
1669
+ return hostAutoInitModule.getImportId();
1634
1670
  }
1635
1671
  //#endregion
1636
1672
  //#region src/virtualModules/virtualRemotes.ts
@@ -1653,7 +1689,9 @@ function getUsedRemotesMap() {
1653
1689
  }
1654
1690
  function generateRemotes(id, command) {
1655
1691
  const useReactProxy = command === "serve" && hasPackageDependency("react");
1656
- const reactImportLine = useReactProxy ? `import * as __mfReact from "react";` : "";
1692
+ const reactImportLine = useReactProxy ? `import __mfReactDefault from "react";
1693
+ import * as __mfReactNamespace from "react";
1694
+ const __mfReact = __mfReactDefault ?? __mfReactNamespace.default ?? __mfReactNamespace;` : "";
1657
1695
  const importLine = command === "build" ? `${getRuntimeModuleCacheBootstrapCode()}
1658
1696
  import { hostInitPromise as __mfHostInitPromise } from ${JSON.stringify(getHostAutoInitPath())};` : `${getRuntimeInitBootstrapCode()}
1659
1697
  const { initPromise, moduleCache: __mfModuleCache } = globalThis[globalKey];`;
@@ -1663,13 +1701,13 @@ function generateRemotes(id, command) {
1663
1701
  }
1664
1702
  export const __moduleExports = exportModule;
1665
1703
  export const __mf_remote_pending = Promise.resolve(exportModule);
1666
- export default exportModule?.__esModule ? exportModule.default : exportModule.default ?? exportModule` : command === "build" ? `if (__mfRemotePending) {
1704
+ export default exportModule?.__mf_is_remote_proxy ? exportModule : exportModule?.__esModule ? exportModule.default : exportModule.default ?? exportModule` : command === "build" ? `if (__mfRemotePending) {
1667
1705
  const mod = await __mfRemotePending;
1668
1706
  if (mod !== undefined) exportModule = mod;
1669
1707
  }
1670
1708
  export const __moduleExports = exportModule;
1671
1709
  export const __mf_remote_pending = Promise.resolve(exportModule);
1672
- export default exportModule?.__esModule ? exportModule.default : exportModule.default ?? exportModule` : "export default exportModule";
1710
+ export default exportModule?.__mf_is_remote_proxy ? exportModule : exportModule?.__esModule ? exportModule.default : exportModule.default ?? exportModule` : "export default exportModule";
1673
1711
  return `
1674
1712
  ${reactImportLine}
1675
1713
  ${importLine}
@@ -1869,6 +1907,9 @@ ${importHelper}(async () => {
1869
1907
  if (inject === "html" && hasPackageDependency("@sveltejs/kit")) return false;
1870
1908
  return inject === "entry" || !htmlFilePath;
1871
1909
  }
1910
+ function normalizeDevHtmlProxyId(id) {
1911
+ return id.replace(/^\0/, "").replace(/^\/@id\//, "").replace(/^__x00__/, "");
1912
+ }
1872
1913
  return [{
1873
1914
  name: "add-entry",
1874
1915
  apply: "serve",
@@ -1887,7 +1928,20 @@ ${importHelper}(async () => {
1887
1928
  }
1888
1929
  },
1889
1930
  configureServer(server) {
1890
- server.middlewares.use((req, _res, next) => {
1931
+ server.middlewares.use((req, res, next) => {
1932
+ const rawUrl = req.url?.split("#")[0] ?? "";
1933
+ if (normalizeDevHtmlProxyId(rawUrl.split("?")[0]) === DEV_HTML_PROXY_PREFIX.slice(0, -1)) {
1934
+ const query = rawUrl.slice(rawUrl.indexOf("?") + 1);
1935
+ const params = new URLSearchParams(query);
1936
+ const initSrc = params.get("init");
1937
+ const entrySrc = params.get("entry");
1938
+ if (initSrc && entrySrc) {
1939
+ res.statusCode = 200;
1940
+ res.setHeader("Content-Type", "application/javascript");
1941
+ res.end(getBootstrapSource(initSrc, entrySrc));
1942
+ return;
1943
+ }
1944
+ }
1891
1945
  if (!fileName) {
1892
1946
  next();
1893
1947
  return;
@@ -1904,7 +1958,7 @@ ${importHelper}(async () => {
1904
1958
  const base = viteConfig.base.replace(/\/$/, "");
1905
1959
  const stripBase = (p) => base && p.startsWith(base + "/") ? p.slice(base.length) : p;
1906
1960
  const html = rewriteEntryScripts(c, (originalSrc) => {
1907
- return `/@id/${DEV_HTML_PROXY_PREFIX}${new URLSearchParams({
1961
+ return `/@id/__x00__${DEV_HTML_PROXY_PREFIX}${new URLSearchParams({
1908
1962
  init: sanitizeDevEntryPath(stripBase(devEntryPath)),
1909
1963
  entry: sanitizeDevEntryPath(stripBase(originalSrc))
1910
1964
  }).toString()}`;
@@ -1913,11 +1967,12 @@ ${importHelper}(async () => {
1913
1967
  }
1914
1968
  },
1915
1969
  resolveId(id) {
1916
- if (id.startsWith(DEV_HTML_PROXY_PREFIX)) return id;
1970
+ if (normalizeDevHtmlProxyId(id).startsWith(DEV_HTML_PROXY_PREFIX)) return id;
1917
1971
  },
1918
1972
  load(id) {
1919
- if (!id.startsWith(DEV_HTML_PROXY_PREFIX)) return;
1920
- const params = new URLSearchParams(id.slice(28));
1973
+ const normalizedId = normalizeDevHtmlProxyId(id);
1974
+ if (!normalizedId.startsWith(DEV_HTML_PROXY_PREFIX)) return;
1975
+ const params = new URLSearchParams(normalizedId.slice(28));
1921
1976
  const initSrc = params.get("init");
1922
1977
  const entrySrc = params.get("entry");
1923
1978
  if (!initSrc || !entrySrc) return;
@@ -2724,7 +2779,7 @@ function collectSystemProxyInfos(proxyChunks, loadShareTag) {
2724
2779
  for (const m of proxyInfo.code.matchAll(/exports\(\s*["']([^"']+)["']\s*,([\s\S]*?)\);/g)) {
2725
2780
  const exported = m[1];
2726
2781
  const expression = m[2];
2727
- for (const [local, exportName] of Object.entries(loadShareBindings)) if (new RegExp(`\\b${local}\\b`).test(expression)) {
2782
+ for (const [local, exportName] of Object.entries(loadShareBindings).reverse()) if (new RegExp(`\\b${local}\\b`).test(expression)) {
2728
2783
  exportMap[exported] = {
2729
2784
  type: "reexport",
2730
2785
  exportName
@@ -3488,7 +3543,7 @@ function pluginProxyRemotes_default(options) {
3488
3543
  const remoteModule = getRemoteVirtualModule(source, command);
3489
3544
  addUsedRemote(remoteName, source);
3490
3545
  refreshHostAutoInit();
3491
- return remoteModule.getPath();
3546
+ return remoteModule.getImportId();
3492
3547
  }
3493
3548
  return {
3494
3549
  name: "proxyRemotes",
@@ -3890,7 +3945,7 @@ async function collectFromEsLexer(code, isRemoteImport) {
3890
3945
  await init;
3891
3946
  let imports;
3892
3947
  try {
3893
- [imports] = parse$1(code);
3948
+ [imports] = parse(code);
3894
3949
  } catch {
3895
3950
  return;
3896
3951
  }
@@ -4310,12 +4365,12 @@ function isFederationHtmlPreloadDependency(dep, includeSharedRuntime = false) {
4310
4365
  return includeSharedRuntime && (file.includes("preload-helper") || file.includes("rolldown-runtime") || file.startsWith("dist-"));
4311
4366
  }
4312
4367
  /**
4313
- * Plugin that runs FIRST to create virtual module files in the config hook.
4314
- * This prevents 504 "Outdated Optimize Dep" errors by ensuring files exist
4368
+ * Plugin that runs FIRST to register generated virtual modules in the config hook.
4369
+ * This prevents 504 "Outdated Optimize Dep" errors by ensuring ids are known
4315
4370
  * before Vite's optimization phase.
4316
4371
  */
4317
4372
  function createEarlyVirtualModulesPlugin(options) {
4318
- const { shared, remotes, virtualModuleDir } = options;
4373
+ const { shared, remotes } = options;
4319
4374
  const isLitShare = (pkg) => pkg === "lit" || pkg.startsWith("lit/");
4320
4375
  return {
4321
4376
  name: "vite:module-federation-early-init",
@@ -4325,9 +4380,6 @@ function createEarlyVirtualModulesPlugin(options) {
4325
4380
  const root = config.root || process.cwd();
4326
4381
  setPackageDetectionCwd(root);
4327
4382
  const isVinext = hasPackageDependency("vinext");
4328
- initVirtualModuleInfrastructure(root, virtualModuleDir);
4329
- VirtualModule.setRoot(root);
4330
- VirtualModule.ensureVirtualPackageExists();
4331
4383
  initVirtualModules(_command, getRemoteEntryId(options));
4332
4384
  const isRolldown = getIsRolldown(this);
4333
4385
  if (remotes && Object.keys(remotes).length > 0) {
@@ -4373,6 +4425,10 @@ function createEarlyVirtualModulesPlugin(options) {
4373
4425
  optimizeDeps.esbuildOptions.plugins.push({
4374
4426
  name: "module-federation:optimize-shared-proxy",
4375
4427
  setup(build) {
4428
+ build.onResolve({ filter: /^virtual:mf:/ }, (args) => ({
4429
+ path: args.path,
4430
+ external: true
4431
+ }));
4376
4432
  build.onResolve({ filter: /.*/ }, (args) => {
4377
4433
  if (!args.importer || args.namespace === "mf-shared") return;
4378
4434
  if (isSharedResolverInternalImporter(args.importer)) return;
@@ -4404,7 +4460,6 @@ export default __mfShared.default ?? __mfShared;`
4404
4460
  }
4405
4461
  });
4406
4462
  }
4407
- config.optimizeDeps.include.push(virtualRuntimeInitStatus.getImportId());
4408
4463
  }
4409
4464
  for (const key of Object.keys(shared)) {
4410
4465
  const shareItem = shared[key];
@@ -4415,7 +4470,6 @@ export default __mfShared.default ?? __mfShared;`
4415
4470
  for (const subpath of getCommonSharedSubpaths(key)) {
4416
4471
  writePreBuildLibPath(subpath, shareItem);
4417
4472
  optimizeDeps.include.push(subpath);
4418
- optimizeDeps.include.push(getPreBuildLibImportId(subpath));
4419
4473
  }
4420
4474
  }
4421
4475
  continue;
@@ -4432,14 +4486,11 @@ export default __mfShared.default ?? __mfShared;`
4432
4486
  const optimizeDeps = config.optimizeDeps ??= {};
4433
4487
  optimizeDeps.include ??= [];
4434
4488
  optimizeDeps.exclude ??= [];
4435
- const shouldBypassOptimizeDep = isLitShare(key);
4436
- if (shouldBypassOptimizeDep) optimizeDeps.exclude.push(key);
4437
- if (!isRolldown && !shouldBypassOptimizeDep) optimizeDeps.include.push(getLoadShareImportId(key, isRolldown));
4438
- optimizeDeps.include.push(getPreBuildLibImportId(key));
4489
+ if (isLitShare(key)) optimizeDeps.exclude.push(key);
4490
+ else optimizeDeps.include.push(key);
4439
4491
  for (const subpath of getCommonSharedSubpaths(key)) {
4440
4492
  writePreBuildLibPath(subpath, shareItem);
4441
4493
  optimizeDeps.include.push(subpath);
4442
- optimizeDeps.include.push(getPreBuildLibImportId(subpath));
4443
4494
  }
4444
4495
  }
4445
4496
  }
@@ -4459,6 +4510,21 @@ function federation(mfUserOptions) {
4459
4510
  let command;
4460
4511
  let desiredRolldownOutput;
4461
4512
  return [
4513
+ {
4514
+ name: "vite:module-federation-virtual-modules",
4515
+ enforce: "pre",
4516
+ resolveId(id) {
4517
+ const virtualModule = VirtualModule.findById(id);
4518
+ if (!virtualModule) return;
4519
+ return virtualModule.getResolvedId();
4520
+ },
4521
+ load(id) {
4522
+ const virtualModule = VirtualModule.findById(id);
4523
+ if (!virtualModule) return;
4524
+ if (command === "build" && (id.includes("__loadShare__") || id.includes("__loadRemote__"))) return;
4525
+ return virtualModule.code;
4526
+ }
4527
+ },
4462
4528
  createEarlyVirtualModulesPlugin(options),
4463
4529
  ...isVinext ? [{
4464
4530
  name: "module-federation-vinext-react-server-build-alias",
@@ -4483,9 +4549,7 @@ function federation(mfUserOptions) {
4483
4549
  config(_config, env) {
4484
4550
  command = env.command;
4485
4551
  },
4486
- configResolved(config) {
4487
- VirtualModule.setRoot(config.root);
4488
- VirtualModule.ensureVirtualPackageExists();
4552
+ configResolved() {
4489
4553
  initVirtualModules(command, remoteEntryId);
4490
4554
  }
4491
4555
  },
@@ -4628,9 +4692,8 @@ function federation(mfUserOptions) {
4628
4692
  }
4629
4693
  },
4630
4694
  load(id) {
4631
- if (id.startsWith("\0")) return;
4632
4695
  if (id.includes("__loadShare__") || id.includes("__loadRemote__")) {
4633
- let code = readFileSync(id, "utf-8");
4696
+ let code = VirtualModule.findById(id)?.code ?? readFileSync(id, "utf-8");
4634
4697
  code = code.replace(/import\s+["'][^"']*__prebuild__[^"']*["']\s*;?/g, "");
4635
4698
  code = code.replace(/export\s+\*\s+from\s+["'][^"']*__prebuild__[^"']*["']\s*;?/g, "");
4636
4699
  /**
@@ -4649,7 +4712,10 @@ function federation(mfUserOptions) {
4649
4712
  *
4650
4713
  * @see https://rollupjs.org/plugin-development/#synthetic-named-exports
4651
4714
  */
4652
- if (!code.includes("__moduleExports")) code = code.replace("export default exportModule", "export const __moduleExports = exportModule;\nexport default exportModule.__esModule ? exportModule.default : exportModule");
4715
+ if (!/\bexport\s+const\s+__moduleExports\b/.test(code)) {
4716
+ const nextCode = code.replace("export default exportModule", "export const __moduleExports = exportModule;\nexport default exportModule.__esModule ? exportModule.default : exportModule");
4717
+ code = nextCode === code ? `${code}\nexport const __moduleExports = exportModule;\n` : nextCode;
4718
+ }
4653
4719
  if (getIsRolldown(this)) return { code };
4654
4720
  return {
4655
4721
  code,
@@ -4714,14 +4780,9 @@ function federation(mfUserOptions) {
4714
4780
  config.build ||= {};
4715
4781
  config.build.commonjsOptions ||= {};
4716
4782
  config.build.commonjsOptions.strictRequires ??= "auto";
4717
- const virtualDir = options.virtualModuleDir;
4718
4783
  config.optimizeDeps ||= {};
4719
4784
  config.optimizeDeps.include ||= [];
4720
4785
  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
4786
  options.runtimePlugins.forEach((p) => {
4726
4787
  const pluginPath = typeof p === "string" ? p : p[0];
4727
4788
  if (pluginPath && !pluginPath.startsWith(".") && !pluginPath.startsWith("/") && !pluginPath.startsWith("\0") && !pluginPath.startsWith("virtual:")) config.optimizeDeps.include.push(pluginPath);
@@ -4729,9 +4790,6 @@ function federation(mfUserOptions) {
4729
4790
  if (isRolldown) {
4730
4791
  config.build ??= {};
4731
4792
  config.build.target ??= "esnext";
4732
- } else {
4733
- config.optimizeDeps.needsInterop ||= [];
4734
- config.optimizeDeps.needsInterop.push(virtualDir);
4735
4793
  }
4736
4794
  const isAstro = hasPackageDependency("astro");
4737
4795
  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.2",
3
+ "version": "1.15.4",
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
  }