@module-federation/vite 1.16.11 → 1.16.13

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.js CHANGED
@@ -1,6 +1,6 @@
1
- import { _ as mfWarn, a as getIsRolldown, c as getPackageNameFromNodeModulePath, d as isNuxtProjectRoot, f as packageNameDecode, g as createModuleFederationError, h as setPackageDetectionCwd, i as getInstalledPackageJson, l as getSharedCacheKey, m as resolveImportPath, o as getPackageDetectionCwd, p as packageNameEncode, r as getInstalledPackageEntry, s as getPackageName, u as hasPackageDependency, v as normalizePathForImport, y as rebaseImport } from "./pluginDts-CrSsDUnT.js";
1
+ import { _ as createModuleFederationError, a as getIsRolldown, b as rebaseImport, c as getPackageNameFromNodeModulePath, d as isNuxtProjectRoot, f as packageNameDecode, g as sharedCacheHelperCode, h as setPackageDetectionCwd, i as getInstalledPackageJson, l as getSharedCacheDescriptor, m as resolveImportPath, o as getPackageDetectionCwd, p as packageNameEncode, r as getInstalledPackageEntry, s as getPackageName, u as hasPackageDependency, v as mfWarn, y as normalizePathForImport } from "./pluginDts-CTAHkt4C.js";
2
2
  import { createRequire } from "node:module";
3
- import * as fs$1 from "fs";
3
+ import * as fs$2 from "fs";
4
4
  import { existsSync, readFileSync, realpathSync, statSync, writeFileSync } from "fs";
5
5
  import { createRequire as createRequire$1 } from "module";
6
6
  import * as path$1 from "node:path";
@@ -8,6 +8,7 @@ import path, { basename } from "node:path";
8
8
  import { fileURLToPath, pathToFileURL } from "url";
9
9
  import { version } from "vite";
10
10
  import { createHash } from "node:crypto";
11
+ import * as fs$1 from "node:fs";
11
12
  import { existsSync as existsSync$1, readFileSync as readFileSync$1 } from "node:fs";
12
13
  import { pathToFileURL as pathToFileURL$1 } from "node:url";
13
14
  //#region src/utils/codeRewriter.ts
@@ -360,7 +361,7 @@ function normalizeShared(shared) {
360
361
  const result = {};
361
362
  const packageJsonPath = path$1.join(getPackageDetectionCwd(), "package.json");
362
363
  try {
363
- const packageJson = JSON.parse(fs$1.readFileSync(packageJsonPath, "utf-8"));
364
+ const packageJson = JSON.parse(fs$2.readFileSync(packageJsonPath, "utf-8"));
364
365
  if (packageJson.name === "@module-federation/vite") return result;
365
366
  Object.keys(packageJson.dependencies || {}).filter((key) => shouldAutoShareDependency(key)).forEach((key) => {
366
367
  result[key] = normalizeShareItem(key, {
@@ -434,7 +435,7 @@ function resolveRuntimeImplementation() {
434
435
  const fallback = resolveImportPath("@module-federation/runtime");
435
436
  try {
436
437
  const packageJsonPath = resolveImportPath("@module-federation/runtime/package.json");
437
- const packageJson = JSON.parse(fs$1.readFileSync(packageJsonPath, "utf-8"));
438
+ const packageJson = JSON.parse(fs$2.readFileSync(packageJsonPath, "utf-8"));
438
439
  const importExport = packageJson.exports?.["."];
439
440
  const exportImport = typeof importExport === "object" ? typeof importExport.import === "string" ? importExport.import : importExport.import?.default : void 0;
440
441
  const esmEntry = packageJson.module || exportImport;
@@ -573,6 +574,27 @@ var VirtualModule = class VirtualModule {
573
574
  }
574
575
  };
575
576
  //#endregion
577
+ //#region src/utils/ssrCapabilities.ts
578
+ /** A browser-safe generated expression that is true only in Node.js. */
579
+ const SERVER_ENV_GUARD = "typeof process !== 'undefined' && !!process.versions && !!process.versions.node";
580
+ /**
581
+ * Single source of truth for SSR-related feature gates.
582
+ *
583
+ * - Vite 8+ dev: ModuleRunner + FetchableDevEnvironment for `/__mf_ssr__/` entries.
584
+ * - Any Vite major on build/preview: HTTP fetch + temp-file import via ssrEntryLoader.
585
+ */
586
+ function getSsrCapabilities(viteMajor, command, hasRemotes) {
587
+ if (!hasRemotes) return {
588
+ enableSsrInitBootstrap: false,
589
+ injectSsrEntryLoader: false
590
+ };
591
+ const supported = command === "build" || command === "serve" && viteMajor >= 8;
592
+ return {
593
+ enableSsrInitBootstrap: supported,
594
+ injectSsrEntryLoader: supported
595
+ };
596
+ }
597
+ //#endregion
576
598
  //#region src/utils/serializeRuntimeOptions.ts
577
599
  /**
578
600
  * Serializes a JavaScript object into a string of source code that can be evaluated.
@@ -628,7 +650,7 @@ function getExposesCssMapPlaceholder() {
628
650
  function getVirtualExposesId(options) {
629
651
  return `virtual:mf-exposes:${`${options.internalName}__${options.filename}`.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
630
652
  }
631
- function generateExposes(options) {
653
+ function generateExposes(options, remoteDependencyMap = {}, command = "build") {
632
654
  return `
633
655
  const cssAssetMap = ${JSON.stringify(options.bundleAllCSS ? EXPOSES_CSS_MAP_PLACEHOLDER : {})};
634
656
  const injectedCssHrefs = new Set();
@@ -661,8 +683,12 @@ function generateExposes(options) {
661
683
  }
662
684
  injectedCssHrefs.add(href);
663
685
 
686
+ // Check for any existing stylesheet with the same href, not just
687
+ // MF-injected ones. This prevents duplicate <link> tags when Vite's
688
+ // own CSS module injection or MF runtime's createLink has already
689
+ // created a <link rel="stylesheet"> for the same URL.
664
690
  const existingLink = document.querySelector(
665
- \`link[rel="stylesheet"][data-mf-href="\${href}"]\`
691
+ \`link[rel="stylesheet"][href="\${href}"]\`
666
692
  );
667
693
  if (existingLink) {
668
694
  return Promise.resolve();
@@ -672,7 +698,6 @@ function generateExposes(options) {
672
698
  const link = document.createElement("link");
673
699
  link.rel = "stylesheet";
674
700
  link.href = href;
675
- link.setAttribute("data-mf-href", href);
676
701
  link.onload = () => resolve();
677
702
  link.onerror = () => reject(new Error(\`[Module Federation] Failed to load CSS asset: \${href}\`));
678
703
  document.head.appendChild(link);
@@ -683,12 +708,22 @@ function generateExposes(options) {
683
708
 
684
709
  export default {
685
710
  ${Object.keys(options.exposes).map((key) => {
711
+ const remoteDependencyPreloads = (remoteDependencyMap[key] ?? []).map((remoteId) => {
712
+ const virtualRemote = getRemoteVirtualModule(remoteId, command);
713
+ return `import(${JSON.stringify(virtualRemote.getImportId())})
714
+ .then((mod) => mod.__mf_remote_pending)`;
715
+ }).join(",");
686
716
  return `
687
717
  ${JSON.stringify(key)}: async () => {
688
718
  await injectCssAssets(${JSON.stringify(key)})
719
+ await Promise.all([${remoteDependencyPreloads}])
689
720
  const importModule = await importExposedModule(
690
721
  () => import(${JSON.stringify(options.exposes[key].import)})
691
722
  )
723
+ const dependencyPending = importModule && importModule.__mf_remote_dependency_pending;
724
+ if (dependencyPending && typeof dependencyPending.then === "function") {
725
+ await dependencyPending;
726
+ }
692
727
  const exportModule = {}
693
728
  Object.assign(exportModule, importModule)
694
729
  Object.defineProperty(exportModule, "__esModule", {
@@ -722,7 +757,7 @@ function setSsrRemotes(remotes) {
722
757
  }
723
758
  function getSsrNoopResolveCode(enableSsrInit, hostInitImportId, initResolveExpression = "initResolve") {
724
759
  if (!enableSsrInit) return "";
725
- return `if (typeof window === 'undefined') {
760
+ return `if (${SERVER_ENV_GUARD}) {
726
761
  var _noop = { loadRemote: function() { return Promise.resolve(undefined); }, loadShare: function() { return Promise.resolve(undefined); } };
727
762
  ${hostInitImportId ? `import(${JSON.stringify(hostInitImportId)})
728
763
  .then(function(mod) { return mod.hostInitPromise; })
@@ -781,7 +816,7 @@ globalThis[globalKey] = {
781
816
  };
782
817
  }
783
818
  ${enableSsrInit ? `
784
- if (typeof window === 'undefined' && !globalThis[globalKey].ssrInitStarted) {
819
+ if (${SERVER_ENV_GUARD} && !globalThis[globalKey].ssrInitStarted) {
785
820
  globalThis[globalKey].ssrInitStarted = true;
786
821
  ${getSsrNoopResolveCode(enableSsrInit, hostInitImportId, "globalThis[globalKey].initResolve")}
787
822
  }` : ""}
@@ -862,6 +897,9 @@ function escapeGeneratedStringLiteral(value) {
862
897
  }
863
898
  });
864
899
  }
900
+ function getSharedCacheDescriptorLiteral(pkg, shareItem) {
901
+ return JSON.stringify(getSharedCacheDescriptor(pkg, shareItem));
902
+ }
865
903
  function isValidJsIdentifier(name) {
866
904
  return JS_IDENTIFIER_REGEX.test(name);
867
905
  }
@@ -1031,7 +1069,7 @@ function getSharedNamedExports(pkg, shareItem) {
1031
1069
  }
1032
1070
  function getLocalProviderImportPath(pkg) {
1033
1071
  try {
1034
- const resolved = createRequire$1(pathToFileURL(path$1.join(getPackageDetectionCwd(), "package.json"))).resolve(pkg);
1072
+ const resolved = resolveWorkspaceEsmEntry(pkg, createRequire$1(pathToFileURL(path$1.join(getPackageDetectionCwd(), "package.json"))).resolve(pkg));
1035
1073
  return isWorkspaceFilePath(resolved) ? resolved : void 0;
1036
1074
  } catch {
1037
1075
  const resolved = getInstalledPackageEntry(pkg, {
@@ -1052,7 +1090,7 @@ function getProjectResolvedImportPath(pkg) {
1052
1090
  if (esmEntry) return esmEntry;
1053
1091
  }
1054
1092
  try {
1055
- return createRequire$1(pathToFileURL(path$1.join(getPackageDetectionCwd(), "package.json"))).resolve(pkg);
1093
+ return resolveWorkspaceEsmEntry(pkg, createRequire$1(pathToFileURL(path$1.join(getPackageDetectionCwd(), "package.json"))).resolve(pkg));
1056
1094
  } catch {
1057
1095
  return;
1058
1096
  }
@@ -1065,6 +1103,30 @@ function isWorkspaceFilePath(resolved) {
1065
1103
  } catch {}
1066
1104
  return !realResolved.includes("/node_modules/") && !realResolved.includes("\\node_modules\\");
1067
1105
  }
1106
+ /**
1107
+ * When createRequire resolves a workspace package to a CJS entry (e.g. dist/index.cjs),
1108
+ * re-resolve via getInstalledPackageEntry with ESM-preferring conditions.
1109
+ *
1110
+ * Workspace packages produce browser code, so they must use the ESM build — CJS files
1111
+ * contain `module.exports` which is undefined in the browser. createRequire().resolve()
1112
+ * follows Node.js CJS conditions ["node", "require"], which matches exports["."].require.default
1113
+ * and returns the .cjs path for packages with dual ESM/CJS exports.
1114
+ */
1115
+ function resolveWorkspaceEsmEntry(pkg, resolved, cwd = getPackageDetectionCwd()) {
1116
+ if (!isWorkspaceFilePath(resolved)) return resolved;
1117
+ const esmEntry = getInstalledPackageEntry(pkg, {
1118
+ cwd,
1119
+ conditions: [
1120
+ "browser",
1121
+ "import",
1122
+ "module",
1123
+ "default"
1124
+ ],
1125
+ resolveSubpathWithRequire: false
1126
+ });
1127
+ if (esmEntry && isWorkspaceFilePath(esmEntry)) return esmEntry;
1128
+ return resolved;
1129
+ }
1068
1130
  function isWorkspacePackageEntry(pkg, resolved) {
1069
1131
  if (!resolved || !path$1.isAbsolute(resolved) || !isWorkspaceFilePath(resolved)) return false;
1070
1132
  return !!getInstalledPackageJson(pkg, {
@@ -1117,7 +1179,7 @@ function isWorkspaceSingletonConsumedByPeer(pkg) {
1117
1179
  }
1118
1180
  function tryResolveImportFromPackageRoot(pkg, root) {
1119
1181
  try {
1120
- return createRequire$1(pathToFileURL(path$1.join(root, "package.json"))).resolve(pkg);
1182
+ return resolveWorkspaceEsmEntry(pkg, createRequire$1(pathToFileURL(path$1.join(root, "package.json"))).resolve(pkg), root);
1121
1183
  } catch {
1122
1184
  return;
1123
1185
  }
@@ -1143,11 +1205,18 @@ function writePreBuildLibPath(pkg, shareItem) {
1143
1205
  preBuildShareItemMap[pkg] = shareItem;
1144
1206
  const importSource = getConcreteSharedImportSource(pkg, shareItem) || pkg;
1145
1207
  if (pkg === "react/compiler-runtime") {
1208
+ const reactCacheDescriptor = getSharedCacheDescriptorLiteral("react", shareItem ?? {
1209
+ name: "react",
1210
+ from: "",
1211
+ scope: "default",
1212
+ shareConfig: { singleton: true }
1213
+ });
1146
1214
  preBuildCacheMap[pkg].writeSync(`
1215
+ ${sharedCacheHelperCode}
1147
1216
  const __mfCacheGlobalKey = "__mf_module_cache__";
1148
1217
  export const c = function(size) {
1149
1218
  const cache = globalThis[__mfCacheGlobalKey]?.share;
1150
- const sharedReact = cache?.['react'];
1219
+ const sharedReact = cache && __mfReadSharedCache(cache, ${reactCacheDescriptor});
1151
1220
  const reactExports = sharedReact?.default ?? sharedReact;
1152
1221
  const internals = reactExports?.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;
1153
1222
  return internals?.H?.useMemoCache(size);
@@ -1189,7 +1258,7 @@ function writePreBuildLibPath(pkg, shareItem) {
1189
1258
  const __mfPrebuildExports = __mfPrebuildNamespace;
1190
1259
  ${declarations}
1191
1260
  ${namedExportLine}
1192
- export default __mfPrebuildExports;
1261
+ export default __mfPrebuildNamespace.default ?? __mfPrebuildNamespace;
1193
1262
  `, true);
1194
1263
  return;
1195
1264
  }
@@ -1244,45 +1313,47 @@ function materializeCachedLoadShareModule(options) {
1244
1313
  options.addUsedShares(pkg);
1245
1314
  options.writeLocalSharedImportMap();
1246
1315
  }
1247
- function generateEagerWorkspaceSingletonExports(namedExports, importSource, cacheKey) {
1248
- const namedExportLine = namedExports.length > 0 ? `\n export { ${namedExports.join(", ")} } from ${escapeGeneratedStringLiteral(importSource)};` : "";
1316
+ function generateEagerWorkspaceSingletonExports(namedExports, importSource, cacheDescriptor) {
1317
+ const namedExportVars = namedExports.map((_name, i) => `__mf_${i}`);
1318
+ const namedExportAssignments = namedExports.length > 0 ? `\n ${namedExports.map((name, i) => `const ${namedExportVars[i]} = exportModule[${escapeGeneratedStringLiteral(name)}];`).join("\n ")}` : "";
1319
+ const namedExportLine = namedExports.length > 0 ? `\n export { ${namedExports.map((name, i) => `${namedExportVars[i]} as ${name}`).join(", ")} };` : "";
1249
1320
  return `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(importSource)};
1250
- let exportModule = __mfModuleCache.share[${escapeGeneratedStringLiteral(cacheKey)}];
1321
+ let exportModule = __mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor});
1251
1322
  if (exportModule === undefined) {
1252
1323
  Promise.resolve().then(() => {
1253
- if (__mfModuleCache.share[${escapeGeneratedStringLiteral(cacheKey)}] === undefined) {
1254
- __mfModuleCache.share[${escapeGeneratedStringLiteral(cacheKey)}] = __mfNormalizeShareModule(__mfLocalShare);
1324
+ if (__mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor}) === undefined) {
1325
+ __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, __mfNormalizeShareModule(__mfLocalShare));
1255
1326
  }
1256
1327
  });
1257
1328
  exportModule = __mfLocalShare;
1258
1329
  }
1259
- const __mf_default = exportModule.default ?? exportModule;
1330
+ const __mf_default = exportModule.default ?? exportModule;${namedExportAssignments}
1260
1331
  export { __mf_default as default };${namedExportLine}`;
1261
1332
  }
1262
- function generateLazyWorkspaceSingletonExports(namedExports, importSource, cacheKey, eagerLocalFallback) {
1333
+ function generateLazyWorkspaceSingletonExports(namedExports, importSource, cacheDescriptor, eagerLocalFallback) {
1263
1334
  const namedExportVars = namedExports.map((_name, i) => `__mf_${i}`);
1264
1335
  const declarations = namedExports.length > 0 ? ["let __mf_default;", ...namedExportVars.map((name) => `let ${name};`)].join("\n ") : "let __mf_default;";
1265
1336
  const assignments = namedExports.length > 0 ? [...namedExports.map((name, i) => `${namedExportVars[i]} = mod[${escapeGeneratedStringLiteral(name)}];`), "__mf_default = mod.default ?? mod;"].join("\n ") : "__mf_default = mod.default ?? mod;";
1266
1337
  const namedExportLine = namedExports.length > 0 ? `\n export { ${namedExports.map((name, i) => `${namedExportVars[i]} as ${name}`).join(", ")} };` : "";
1267
1338
  const applyLocalFallback = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
1268
- __mfModuleCache.share[${escapeGeneratedStringLiteral(cacheKey)}] = exportModule;
1339
+ __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule);
1269
1340
  __mfApplyLazyShareExports(exportModule);`;
1270
1341
  const body = `${declarations}
1271
1342
  const __mfApplyLazyShareExports = (mod) => {
1272
1343
  ${assignments}
1273
1344
  };
1274
- let exportModule = __mfModuleCache.share[${escapeGeneratedStringLiteral(cacheKey)}];
1345
+ let exportModule = __mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor});
1275
1346
  if (exportModule === undefined) {
1276
1347
  ${eagerLocalFallback ? applyLocalFallback : `if (import.meta.env.SSR) {
1277
1348
  ${applyLocalFallback}
1278
1349
  } else {
1279
- initPromise.then(() =>
1350
+ (__mfModuleCache.pendingShareLoads ||= []).push(initPromise.then(() =>
1280
1351
  import(${escapeGeneratedStringLiteral(importSource)}).then((mod) => {
1281
1352
  exportModule = __mfNormalizeShareModule(mod);
1282
- __mfModuleCache.share[${escapeGeneratedStringLiteral(cacheKey)}] = exportModule;
1353
+ __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule);
1283
1354
  __mfApplyLazyShareExports(exportModule);
1284
1355
  })
1285
- );
1356
+ ));
1286
1357
  }`}
1287
1358
  } else {
1288
1359
  __mfApplyLazyShareExports(exportModule);
@@ -1301,28 +1372,25 @@ function prependWorkspaceSingletonSsrImport(code) {
1301
1372
  const quote = importMatch[1];
1302
1373
  return `import * as __mfLocalShare from ${quote}${importMatch[2]}${quote};\n${code}`;
1303
1374
  }
1304
- function generateDeferredHostProvidedExports(namedExports, pkg, cacheKey) {
1375
+ function generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor) {
1305
1376
  const namedExportVars = namedExports.map((_name, i) => `__mf_${i}`);
1306
- const declarations = ["let __mf_default;", ...namedExportVars.map((name) => `let ${name};`)].join("\n ");
1307
- const assignments = [...namedExports.map((name, i) => `${namedExportVars[i]} = exportModule[${escapeGeneratedStringLiteral(name)}];`), "__mf_default = exportModule.default ?? exportModule;"].join("\n ");
1308
- const namedExportLine = namedExports.length > 0 ? `\n export { ${namedExports.map((name, i) => `${namedExportVars[i]} as ${name}`).join(", ")} };` : "";
1309
- return `${declarations}
1377
+ return `${["let __mf_default;", ...namedExportVars.map((name) => `let ${name};`)].join("\n ")}
1310
1378
  const __mfApplyHostProvidedExports = (exportModule) => {
1311
- ${assignments}
1379
+ ${[...namedExports.map((name, i) => `${namedExportVars[i]} = exportModule[${escapeGeneratedStringLiteral(name)}];`), "__mf_default = exportModule.default ?? exportModule;"].join("\n ")}
1312
1380
  };
1313
- let exportModule = __mfModuleCache.share[${escapeGeneratedStringLiteral(cacheKey)}];
1381
+ let exportModule = __mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor});
1314
1382
  if (exportModule === undefined) {
1315
- initPromise.then(() => {
1316
- exportModule = __mfModuleCache.share[${escapeGeneratedStringLiteral(cacheKey)}];
1383
+ (__mfModuleCache.pendingShareLoads ||= []).push(initPromise.then(() => {
1384
+ exportModule = __mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor});
1317
1385
  if (exportModule === undefined) {
1318
1386
  throw new Error("[Module Federation] Shared module ${pkg} was imported before federation bootstrap finished.");
1319
1387
  }
1320
1388
  __mfApplyHostProvidedExports(exportModule);
1321
- });
1389
+ }));
1322
1390
  } else {
1323
1391
  __mfApplyHostProvidedExports(exportModule);
1324
1392
  }
1325
- export { __mf_default as default };${namedExportLine}`;
1393
+ export { __mf_default as default };${namedExports.length > 0 ? `\n export { ${namedExports.map((name, i) => `${namedExportVars[i]} as ${name}`).join(", ")} };` : ""}`;
1326
1394
  }
1327
1395
  function generateShareModuleUnwrapCode({ source, preserveNamedExports, stopWithReturn }) {
1328
1396
  return `let current = ${source};
@@ -1344,18 +1412,19 @@ const normalizeLocalShareModuleCode = `const __mfNormalizeShareModule = (mod) =>
1344
1412
  function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
1345
1413
  if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, ".js");
1346
1414
  let importLine = getRuntimeModuleCacheBootstrapCode();
1347
- const cacheKey = getSharedCacheKey(pkg, shareItem);
1415
+ const cacheDescriptor = getSharedCacheDescriptorLiteral(pkg, shareItem);
1348
1416
  if (shareItem.shareConfig.import === false) {
1349
1417
  const namedExports = getPackageNamedExports(pkg);
1350
1418
  let exportLine;
1351
- if (namedExports.length > 0) exportLine = generateDeferredHostProvidedExports(namedExports, pkg, cacheKey);
1419
+ if (namedExports.length > 0) exportLine = generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor);
1352
1420
  else {
1353
1421
  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.`);
1354
- exportLine = generateDeferredHostProvidedExports([], pkg, cacheKey);
1422
+ exportLine = generateDeferredHostProvidedExports([], pkg, cacheDescriptor);
1355
1423
  }
1356
1424
  loadShareCacheMap[pkg].writeSync(`
1357
1425
  ${getRuntimeInitPromiseBootstrapCode()}
1358
1426
  ${importLine}
1427
+ ${sharedCacheHelperCode}
1359
1428
  ${exportLine}
1360
1429
  `, true);
1361
1430
  return;
@@ -1372,10 +1441,10 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
1372
1441
  const namedExports = getSharedNamedExports(pkg, shareItem);
1373
1442
  let exportLine;
1374
1443
  let initBlock = "";
1375
- if (usesEagerWorkspaceFallback) exportLine = generateEagerWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheKey);
1444
+ if (usesEagerWorkspaceFallback) exportLine = generateEagerWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor);
1376
1445
  else if (isWorkspaceSingleton) {
1377
1446
  importLine = `${getRuntimeInitPromiseBootstrapCode()}\n ${importLine}`;
1378
- exportLine = generateLazyWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheKey, command !== "build");
1447
+ exportLine = generateLazyWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor, command !== "build");
1379
1448
  } else if (namedExports.length > 0) {
1380
1449
  const destructure = `const { ${namedExports.map((name, i) => `${name}: __mf_${i}`).join(", ")} } = exportModule;`;
1381
1450
  const namedExportLine = `export { ${namedExports.map((name, i) => `__mf_${i} as ${name}`).join(", ")} };`;
@@ -1390,11 +1459,11 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
1390
1459
  ${destructure}
1391
1460
  ${namedExportLine}`;
1392
1461
  initBlock = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
1393
- __mfModuleCache.share[${escapeGeneratedStringLiteral(cacheKey)}] = exportModule;`;
1462
+ __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule);`;
1394
1463
  } else {
1395
1464
  exportLine = `export default exportModule.default ?? exportModule\n export * from ${escapeGeneratedStringLiteral(sharedImportSource)}`;
1396
1465
  initBlock = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
1397
- __mfModuleCache.share[${escapeGeneratedStringLiteral(cacheKey)}] = exportModule;`;
1466
+ __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule);`;
1398
1467
  }
1399
1468
  const prebuildImportLine = isWorkspaceSingleton || isWorkspacePackage && command !== "build" ? "" : `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(skipServePrebuildWarmup ? devImportSource : sharedImportSource)};`;
1400
1469
  const devDynamicImportLine = isWorkspacePackage ? "" : command !== "build" && !skipServePrebuildWarmup ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
@@ -1402,14 +1471,16 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown) {
1402
1471
  ${prebuildImportLine}
1403
1472
  ${devDynamicImportLine}
1404
1473
  ${importLine}
1474
+ ${sharedCacheHelperCode}
1405
1475
  ${normalizeLocalShareModuleCode}
1406
1476
  ${exportLine}
1407
1477
  ` : `
1408
1478
  ${prebuildImportLine}
1409
1479
  ${devDynamicImportLine}
1410
1480
  ${importLine}
1481
+ ${sharedCacheHelperCode}
1411
1482
  ${normalizeLocalShareModuleCode}
1412
- let exportModule = __mfModuleCache.share[${escapeGeneratedStringLiteral(cacheKey)}]
1483
+ let exportModule = __mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor})
1413
1484
  if (exportModule === undefined) {
1414
1485
  ${initBlock}
1415
1486
  }
@@ -1596,8 +1667,8 @@ function getShareItemForPreload(pkg) {
1596
1667
  if (isExplicitSharedKey(wildcardKey)) return shared[wildcardKey];
1597
1668
  }
1598
1669
  function generateSharedCacheSeedItem(pkg, shareItem, importPath) {
1599
- const cacheKey = getSharedCacheKey(pkg, shareItem);
1600
- return `if (__mfModuleCache.share[${JSON.stringify(cacheKey)}] === undefined) {
1670
+ const cacheDescriptor = getSharedCacheDescriptor(pkg, shareItem);
1671
+ return `if (__mfReadSharedCache(__mfModuleCache.share, ${JSON.stringify(cacheDescriptor)}) === undefined) {
1601
1672
  const mod = await import(${JSON.stringify(importPath)});
1602
1673
  ${normalizeRuntimeShareCode}
1603
1674
  const normalizedModule = __mfNormalizeRuntimeShare(mod);
@@ -1606,14 +1677,9 @@ function generateSharedCacheSeedItem(pkg, shareItem, importPath) {
1606
1677
  value: true,
1607
1678
  enumerable: false
1608
1679
  });
1609
- __mfModuleCache.share[${JSON.stringify(cacheKey)}] = exportModule;
1680
+ __mfWriteSharedCache(__mfModuleCache.share, ${JSON.stringify(cacheDescriptor)}, exportModule);
1610
1681
  }`;
1611
1682
  }
1612
- const sharedCacheKeyHelperCode = `const __mfGetSharedCacheKey = (pkg, singleton, version, scope) => {
1613
- const normalizedScope = Array.isArray(scope) ? scope[0] : scope;
1614
- const prefix = (normalizedScope || "default") + ":";
1615
- return singleton || !version ? prefix + pkg : prefix + pkg + "@" + version;
1616
- };`;
1617
1683
  const normalizeRuntimeShareCode = `const __mfNormalizeRuntimeShare = (mod) => {
1618
1684
  let current = mod;
1619
1685
  for (let i = 0; i < 5; i++) {
@@ -1767,7 +1833,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1767
1833
  }
1768
1834
 
1769
1835
  async function init(shared = {}, initScope = []) {
1770
- ${sharedCacheKeyHelperCode}
1836
+ ${sharedCacheHelperCode}
1771
1837
  const {usedShared, usedRemotes} = await getLocalSharedImportMap()
1772
1838
  try {
1773
1839
  const allInstances = globalThis.__FEDERATION__?.__SHARE__;
@@ -1786,16 +1852,16 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1786
1852
  : Object.entries(versionMap);
1787
1853
  for (const [version, provider] of providerEntries) {
1788
1854
  if (!provider.lib) continue;
1789
- const cacheKey = __mfGetSharedCacheKey(pkg, provider.shareConfig?.singleton, version, ${JSON.stringify(options.shareScope)});
1790
- if (__mfModuleCache.share[cacheKey] !== undefined) continue;
1855
+ const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, provider.shareConfig?.singleton, version, ${JSON.stringify(options.shareScope)});
1856
+ if (__mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined) continue;
1791
1857
  const mod = typeof provider.lib === "function" ? provider.lib() : provider.lib;
1792
1858
  const resolved = await Promise.resolve(mod);
1793
1859
  const normalized = __mfNormalizeRuntimeShare(resolved);
1794
- __mfModuleCache.share[cacheKey] = normalized;
1860
+ __mfWriteSharedCache(__mfModuleCache.share, cacheDescriptor, normalized);
1795
1861
  if (provider.shareConfig?.singleton && usedShare) {
1796
- const usedCacheKey = __mfGetSharedCacheKey(pkg, usedShare.shareConfig?.singleton, usedShare.version, usedShare.scope);
1797
- if (__mfModuleCache.share[usedCacheKey] === undefined) {
1798
- __mfModuleCache.share[usedCacheKey] = normalized;
1862
+ const usedCacheDescriptor = __mfGetSharedCacheDescriptor(pkg, usedShare.shareConfig?.singleton, usedShare.version, usedShare.scope);
1863
+ if (__mfReadSharedCache(__mfModuleCache.share, usedCacheDescriptor) === undefined) {
1864
+ __mfWriteSharedCache(__mfModuleCache.share, usedCacheDescriptor, normalized);
1799
1865
  }
1800
1866
  }
1801
1867
  }
@@ -1806,11 +1872,12 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1806
1872
  console.error('[Module Federation] Failed to bridge external shared modules', e)
1807
1873
  }
1808
1874
  for (const [pkg, share] of Object.entries(usedShared)) {
1809
- const cacheKey = __mfGetSharedCacheKey(pkg, share.shareConfig?.singleton, share.version, share.scope);
1810
- if (__mfModuleCache.share[cacheKey] !== undefined) continue;
1811
- const singletonCacheKey = __mfGetSharedCacheKey(pkg, true, share.version, share.scope);
1812
- if (__mfModuleCache.share[singletonCacheKey] !== undefined) {
1813
- __mfModuleCache.share[cacheKey] = __mfModuleCache.share[singletonCacheKey];
1875
+ const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, share.shareConfig?.singleton, share.version, share.scope);
1876
+ if (__mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined) continue;
1877
+ const singletonCacheDescriptor = __mfGetSharedCacheDescriptor(pkg, true, share.version, share.scope);
1878
+ const singletonModule = __mfReadSharedCache(__mfModuleCache.share, singletonCacheDescriptor);
1879
+ if (singletonModule !== undefined) {
1880
+ __mfWriteSharedCache(__mfModuleCache.share, cacheDescriptor, singletonModule);
1814
1881
  }
1815
1882
  }
1816
1883
  ${generateDirectSharedCacheSeedCode(command)}
@@ -1836,7 +1903,6 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1836
1903
  if (initScope.indexOf(initToken) >= 0) return;
1837
1904
  initScope.push(initToken);
1838
1905
  initRes.initShareScopeMap('${options.shareScope}', shared);
1839
- initResolve(initRes)
1840
1906
  try {
1841
1907
  await retrySharedInit(async () => {
1842
1908
  await Promise.all(await initRes.initializeSharing('${options.shareScope}', {
@@ -1849,8 +1915,8 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1849
1915
  console.error('[Module Federation]', e)
1850
1916
  }
1851
1917
  for (const [pkg, share] of Object.entries(usedShared)) {
1852
- const cacheKey = __mfGetSharedCacheKey(pkg, share.shareConfig?.singleton, share.version, share.scope);
1853
- if (share.shareConfig?.import !== false || __mfModuleCache.share[cacheKey] !== undefined) continue;
1918
+ const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, share.shareConfig?.singleton, share.version, share.scope);
1919
+ if (share.shareConfig?.import !== false || __mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined) continue;
1854
1920
  ${normalizeRuntimeShareCode}
1855
1921
  const versions = shared?.[pkg];
1856
1922
  const provider = __mfSelectSharedProvider(versions, pkg, share, '${options.shareStrategy}');
@@ -1858,8 +1924,9 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1858
1924
  const factory = provider.lib || (provider.loading ? await provider.loading : await provider.get?.());
1859
1925
  const mod = typeof factory === "function" ? factory() : factory;
1860
1926
  const resolved = await Promise.resolve(mod);
1861
- __mfModuleCache.share[cacheKey] = __mfNormalizeRuntimeShare(resolved);
1927
+ __mfWriteSharedCache(__mfModuleCache.share, cacheDescriptor, __mfNormalizeRuntimeShare(resolved));
1862
1928
  }
1929
+ initResolve(initRes)
1863
1930
  return initRes
1864
1931
  }
1865
1932
 
@@ -1885,16 +1952,16 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build") {
1885
1952
  async function initHost() {
1886
1953
  if (!hostInitPromise) {
1887
1954
  hostInitPromise = (async () => {
1955
+ ${sharedCacheHelperCode}
1888
1956
  ${generateHostAutoInitSharedCacheSeedCode(_command)}
1889
1957
  const remoteEntry = await import(${remoteEntryImport});
1890
1958
  const runtime = await remoteEntry.init();
1891
1959
  const usedShared = ${generateUsedSharedPreloadConfig()};
1892
- ${sharedCacheKeyHelperCode}
1893
1960
  ${normalizeRuntimeShareCode}
1894
1961
  ${shouldPreloadShares ? `
1895
1962
  for (const [pkg, share] of Object.entries(usedShared)) {
1896
- const cacheKey = __mfGetSharedCacheKey(pkg, share.shareConfig?.singleton, share.version, share.scope);
1897
- if (__mfModuleCache.share[cacheKey] !== undefined) {
1963
+ const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, share.shareConfig?.singleton, share.version, share.scope);
1964
+ if (__mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined) {
1898
1965
  continue;
1899
1966
  }
1900
1967
  await runtime.loadShare(pkg, {
@@ -1902,7 +1969,7 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build") {
1902
1969
  }).then((factory) => {
1903
1970
  const mod = typeof factory === "function" ? factory() : factory;
1904
1971
  return Promise.resolve(mod).then((resolved) => {
1905
- __mfModuleCache.share[cacheKey] = __mfNormalizeRuntimeShare(resolved);
1972
+ __mfWriteSharedCache(__mfModuleCache.share, cacheDescriptor, __mfNormalizeRuntimeShare(resolved));
1906
1973
  });
1907
1974
  });
1908
1975
  }
@@ -2162,7 +2229,7 @@ function generateRemotes(id, command, enableSsrInit = false, consumer = "unified
2162
2229
  const eagerLoadClientRemote = shouldEagerLoadClientRemoteInDev(command, enableSsrInit);
2163
2230
  const eagerClientInit = eagerLoadClientRemote ? getEagerDeferredClientInit() : deferredClientInit;
2164
2231
  const loadedFirstClientInit = eagerLoadClientRemote ? getEagerDeferredClientInit() : deferredClientInit;
2165
- const environmentSplitInit = (clientInit, serverInit) => consumer === "client" ? clientInit : consumer === "server" ? serverInit : `if (typeof window === "undefined") {
2232
+ const environmentSplitInit = (clientInit, serverInit) => consumer === "client" ? clientInit : consumer === "server" ? serverInit : `if (${SERVER_ENV_GUARD}) {
2166
2233
  ${serverInit}
2167
2234
  } else {
2168
2235
  ${clientInit}
@@ -2218,10 +2285,10 @@ function injectHostInitPreloads(html, bundle, resolvePath) {
2218
2285
  function getFirstHtmlEntryFile(entryFiles) {
2219
2286
  return entryFiles.find((file) => file.endsWith(".html"));
2220
2287
  }
2221
- function stripQueryAndHash(file) {
2288
+ function stripQueryAndHash$1(file) {
2222
2289
  return file.split(/[?#]/)[0];
2223
2290
  }
2224
- function resolveDevHashEntryFileName(fileName) {
2291
+ function resolveDevHashEntryFileName$1(fileName) {
2225
2292
  if (!fileName.includes("[hash")) return fileName;
2226
2293
  const normalized = fileName.replace(/(?:[._-]?\[hash(?::\d+)?\])/g, "");
2227
2294
  const baseName = path$1.basename(normalized);
@@ -2298,8 +2365,8 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
2298
2365
  });
2299
2366
  }
2300
2367
  function walkFiles(dir, predicate) {
2301
- if (!fs$1.existsSync(dir)) return [];
2302
- return fs$1.readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
2368
+ if (!fs$2.existsSync(dir)) return [];
2369
+ return fs$2.readdirSync(dir, { withFileTypes: true }).flatMap((entry) => {
2303
2370
  const entryPath = path$1.join(dir, entry.name);
2304
2371
  if (entry.isDirectory()) return walkFiles(entryPath, predicate);
2305
2372
  return entry.isFile() && predicate(entry.name) ? [entryPath] : [];
@@ -2315,17 +2382,17 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
2315
2382
  function patchSvelteKitStaticHtml() {
2316
2383
  const buildDir = path$1.resolve(viteConfig.root, "build");
2317
2384
  let initFile = emittedFileName ? path$1.resolve(buildDir, emittedFileName) : void 0;
2318
- if (!initFile || !fs$1.existsSync(initFile)) initFile = walkFiles(buildDir, (fileName) => fileName.endsWith(".js")).find((file) => {
2319
- const code = fs$1.readFileSync(file, "utf-8");
2385
+ if (!initFile || !fs$2.existsSync(initFile)) initFile = walkFiles(buildDir, (fileName) => fileName.endsWith(".js")).find((file) => {
2386
+ const code = fs$2.readFileSync(file, "utf-8");
2320
2387
  return code.includes("hostInitPromise") && code.includes("initHost");
2321
2388
  });
2322
2389
  if (!initFile) return false;
2323
2390
  let patched = false;
2324
2391
  for (const htmlFile of walkHtmlFiles(buildDir)) {
2325
- const html = fs$1.readFileSync(htmlFile, "utf-8");
2392
+ const html = fs$2.readFileSync(htmlFile, "utf-8");
2326
2393
  const rewritten = rewriteSvelteKitInlineStart(html, toRelativeImport(htmlFile, initFile));
2327
2394
  if (rewritten !== html) {
2328
- fs$1.writeFileSync(htmlFile, rewritten);
2395
+ fs$2.writeFileSync(htmlFile, rewritten);
2329
2396
  patched = true;
2330
2397
  }
2331
2398
  }
@@ -2365,6 +2432,9 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
2365
2432
  await __mfHostInit.__tla;
2366
2433
  const { initHost } = __mfHostInit;
2367
2434
  ${preloadBlock}
2435
+ if (__mfModuleCache.pendingShareLoads) {
2436
+ await Promise.all(__mfModuleCache.pendingShareLoads);
2437
+ }
2368
2438
  })().then(() => ${importExpression(entrySrc)});
2369
2439
  `;
2370
2440
  return [
@@ -2402,12 +2472,12 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
2402
2472
  if (!entryFiles.includes(normalized)) entryFiles.push(normalized);
2403
2473
  }
2404
2474
  function addHtmlScriptEntries(htmlPath) {
2405
- if (!fs$1.existsSync(htmlPath)) return;
2406
- const htmlContent = fs$1.readFileSync(htmlPath, "utf-8");
2475
+ if (!fs$2.existsSync(htmlPath)) return;
2476
+ const htmlContent = fs$2.readFileSync(htmlPath, "utf-8");
2407
2477
  const scriptRegex = /<script\b(?=[^>]*\btype=["']module["'])(?=[^>]*\bsrc=["']([^"']+)["'])[^>]*>/gi;
2408
2478
  let match;
2409
2479
  while ((match = scriptRegex.exec(htmlContent)) !== null) {
2410
- const scriptSrc = stripQueryAndHash(match[1]);
2480
+ const scriptSrc = stripQueryAndHash$1(match[1]);
2411
2481
  if (/^(?:[a-z]+:)?\/\//i.test(scriptSrc)) continue;
2412
2482
  addEntryFile(scriptSrc);
2413
2483
  addEntryFile(scriptSrc.startsWith("/") ? path$1.resolve(viteConfig.root, scriptSrc.slice(1)) : path$1.resolve(path$1.dirname(htmlPath), scriptSrc));
@@ -2450,7 +2520,7 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
2450
2520
  next();
2451
2521
  return;
2452
2522
  }
2453
- const devFileName = resolveDevHashEntryFileName(fileName);
2523
+ const devFileName = resolveDevHashEntryFileName$1(fileName);
2454
2524
  if (devFileName !== fileName && req.url?.startsWith((viteConfig.base + devFileName).replace(/^\/?/, "/"))) req.url = req.url.replace(devFileName, fileName);
2455
2525
  if (req.url && req.url.startsWith((viteConfig.base + fileName).replace(/^\/?/, "/"))) req.url = devEntryPath;
2456
2526
  next();
@@ -2634,9 +2704,9 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
2634
2704
  const injection = `await import(${JSON.stringify(getEntryPath())}).then(({ initHost }) => initHost());\n `;
2635
2705
  return mapCodeToCodeWithSourcemap(code.replace("vueApp.mount(vueAppRootContainer);", `${injection}vueApp.mount(vueAppRootContainer);`));
2636
2706
  }
2637
- const isHydrationEntryFallback = inject === "entry" && entryFiles.length === 0 && (!htmlFilePath || !fs$1.existsSync(htmlFilePath)) && !clientInjected && !isFederationInternalVirtualId(id) && !id.includes("node_modules") && (id.startsWith("\0") || /\.(js|ts|mjs|vue|jsx|tsx)(\?|$)/.test(id)) && (/hydrateRoot|createRoot|ReactDOM\.render/.test(code) || /\.mount\s*\(\s*['"#]/.test(code) || /\.mount\s*\(/.test(code) && /createSSRApp|createApp/.test(code));
2707
+ const isHydrationEntryFallback = inject === "entry" && entryFiles.length === 0 && (!htmlFilePath || !fs$2.existsSync(htmlFilePath)) && !clientInjected && !isFederationInternalVirtualId(id) && !id.includes("node_modules") && (id.startsWith("\0") || /\.(js|ts|mjs|vue|jsx|tsx)(\?|$)/.test(id)) && (/hydrateRoot|createRoot|ReactDOM\.render/.test(code) || /\.mount\s*\(\s*['"#]/.test(code) || /\.mount\s*\(/.test(code) && /createSSRApp|createApp/.test(code));
2638
2708
  const isNuxtEntryAsyncModule = /(?:^|\/)nuxt\/dist\/app\/entry\.async\.js(?:\?|$)/.test(id) && code.includes("entry();");
2639
- const isNuxtClientEntryFallback = _command === "serve" && inject === "entry" && (!htmlFilePath || !fs$1.existsSync(htmlFilePath)) && !clientInjected && !hasEntryBootstrapParam(id) && !id.includes("node_modules/.vite") && isNuxtEntryAsyncModule && !entryFiles.some((file) => projectId === file);
2709
+ const isNuxtClientEntryFallback = _command === "serve" && inject === "entry" && (!htmlFilePath || !fs$2.existsSync(htmlFilePath)) && !clientInjected && !hasEntryBootstrapParam(id) && !id.includes("node_modules/.vite") && isNuxtEntryAsyncModule && !entryFiles.some((file) => projectId === file);
2640
2710
  if (!(_command === "serve" && isNuxtEntryAsyncModule) && (injectedTransformIds.has(projectId) || injectEntry() && entryFiles.some((file) => projectId === file) || _command === "serve" && inject === "html" && !isVinext && !clientInjected && !skipHtmlDevFallback && !id.startsWith("\0") && !id.includes("node_modules") && /\.(js|ts|mjs|vue|jsx|tsx)(\?|$)/.test(id) || isHydrationEntryFallback || isNuxtClientEntryFallback)) {
2641
2711
  clientInjected = true;
2642
2712
  injectedTransformIds.add(projectId);
@@ -3783,6 +3853,7 @@ const Manifest = () => {
3783
3853
  },
3784
3854
  async generateBundle(_options, bundle) {
3785
3855
  if (!mfManifestName) return;
3856
+ if (this.environment?.name === "ssr") return;
3786
3857
  let filesMap = {};
3787
3858
  const foundRemoteEntryFile = findRemoteEntryFile(mfOptions.filename, bundle);
3788
3859
  const expectedSsrRemoteEntryFile = getSsrRemoteEntryFileName(foundRemoteEntryFile || mfOptions.filename);
@@ -4033,8 +4104,39 @@ function pluginModuleParseEnd_default(excludeFn, options) {
4033
4104
  }
4034
4105
  //#endregion
4035
4106
  //#region src/plugins/pluginProxyRemoteEntry.ts
4107
+ function resolveDevHashEntryFileName(fileName) {
4108
+ if (!fileName.includes("[hash")) return fileName;
4109
+ const normalized = fileName.replace(/(?:[._-]?\[hash(?::\d+)?\])/g, "");
4110
+ const baseName = path$1.basename(normalized);
4111
+ return path$1.extname(baseName) ? normalized : `${normalized}.js`;
4112
+ }
4036
4113
  function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposesId }) {
4037
4114
  let viteConfig, _command, root;
4115
+ let exposeRemoteDependencies = {};
4116
+ function isRemoteImport(source) {
4117
+ return Object.keys(options.remotes).some((name) => source === name || source.startsWith(name + "/"));
4118
+ }
4119
+ function collectRemoteDependencies(code) {
4120
+ const dependencies = /* @__PURE__ */ new Set();
4121
+ for (const match of code.matchAll(/(?:^|[;\n\r])\s*import\s+(?:[\s\S]*?\s+from\s+)?["']([^"']+)["']|import\(\s*["']([^"']+)["']\s*\)/g)) {
4122
+ const source = match[1] || match[2];
4123
+ if (source && isRemoteImport(source)) dependencies.add(source);
4124
+ }
4125
+ return Array.from(dependencies).sort();
4126
+ }
4127
+ async function refreshExposeRemoteDependencies(ctx) {
4128
+ const next = {};
4129
+ for (const [exposeKey, expose] of Object.entries(options.exposes)) {
4130
+ const resolved = await ctx.resolve(expose.import);
4131
+ if (!resolved?.id || resolved.id.includes("\0")) continue;
4132
+ try {
4133
+ next[exposeKey] = collectRemoteDependencies(readFileSync$1(resolved.id, "utf8"));
4134
+ } catch {
4135
+ next[exposeKey] = [];
4136
+ }
4137
+ }
4138
+ exposeRemoteDependencies = next;
4139
+ }
4038
4140
  return {
4039
4141
  name: "proxyRemoteEntry",
4040
4142
  enforce: "post",
@@ -4046,6 +4148,7 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
4046
4148
  _command = command;
4047
4149
  },
4048
4150
  async buildStart() {
4151
+ await refreshExposeRemoteDependencies(this);
4049
4152
  if (_command !== "build") return;
4050
4153
  for (const expose of Object.values(options.exposes)) {
4051
4154
  const resolved = await this.resolve(expose.import);
@@ -4067,19 +4170,19 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
4067
4170
  },
4068
4171
  load(id) {
4069
4172
  if (id === remoteEntryId) return parsePromise.then((_) => generateRemoteEntry(options, virtualExposesId, _command));
4070
- if (id === virtualExposesId) return generateExposes(options);
4173
+ if (id === virtualExposesId) return generateExposes(options, exposeRemoteDependencies, _command);
4071
4174
  if (_command === "serve" && id.includes(getHostAutoInitPath())) return id;
4072
4175
  },
4073
4176
  transform(code, id) {
4074
4177
  return mapCodeToCodeWithSourcemap((() => {
4075
4178
  if (!filterId(id)) return;
4076
4179
  if (id.includes(remoteEntryId)) return parsePromise.then((_) => generateRemoteEntry(options, virtualExposesId, _command));
4077
- if (id === virtualExposesId) return generateExposes(options);
4180
+ if (id === virtualExposesId) return generateExposes(options, exposeRemoteDependencies, _command);
4078
4181
  if (id.includes(getHostAutoInitPath())) {
4079
4182
  if (_command === "serve") {
4080
4183
  const host = typeof viteConfig.server?.host === "string" && viteConfig.server.host !== "0.0.0.0" ? viteConfig.server.host : "localhost";
4081
4184
  const resolvedPublicPath = resolvePublicPath(options, viteConfig.base);
4082
- const publicPath = JSON.stringify((resolvedPublicPath === "auto" ? "/" : resolvedPublicPath) + options.filename);
4185
+ const publicPath = JSON.stringify((resolvedPublicPath === "auto" ? "/" : resolvedPublicPath) + resolveDevHashEntryFileName(options.filename));
4083
4186
  const fallbackOrigin = `//${host}:${viteConfig.server?.port}`;
4084
4187
  const ssrRemoteEntry = "data:text/javascript," + encodeURIComponent("export async function init(){return {loadRemote:async()=>({}),loadShare:async()=>({})}}");
4085
4188
  return `
@@ -4145,25 +4248,6 @@ function resolveRemoteConsumer(ctx, hasMultiEnvironment) {
4145
4248
  return "server";
4146
4249
  }
4147
4250
  //#endregion
4148
- //#region src/utils/ssrCapabilities.ts
4149
- /**
4150
- * Single source of truth for SSR-related feature gates.
4151
- *
4152
- * - Vite 8+ dev: ModuleRunner + FetchableDevEnvironment for `/__mf_ssr__/` entries.
4153
- * - Any Vite major on build/preview: HTTP fetch + temp-file import via ssrEntryLoader.
4154
- */
4155
- function getSsrCapabilities(viteMajor, command, hasRemotes) {
4156
- if (!hasRemotes) return {
4157
- enableSsrInitBootstrap: false,
4158
- injectSsrEntryLoader: false
4159
- };
4160
- const supported = command === "build" || command === "serve" && viteMajor >= 8;
4161
- return {
4162
- enableSsrInitBootstrap: supported,
4163
- injectSsrEntryLoader: supported
4164
- };
4165
- }
4166
- //#endregion
4167
4251
  //#region src/plugins/pluginProxyRemotes.ts
4168
4252
  function isNodeModulesImporter(importer) {
4169
4253
  return importer?.includes("/node_modules/") || importer?.includes("\\node_modules\\");
@@ -4537,26 +4621,7 @@ function applyRewrites(code, imports, id) {
4537
4621
  const ms = new CodeRewriter(code);
4538
4622
  let changed = false;
4539
4623
  let counter = 0;
4540
- let namedProxyHelperDeclared = false;
4541
4624
  const dependencyPendingIds = [];
4542
- const namedProxyHelper = `function __mfCreateNamedRemoteProxy(ns, key) {
4543
- const target = function (...args) {
4544
- const value = ns[key];
4545
- return typeof value === "function" ? value.apply(this, args) : value;
4546
- };
4547
- return new Proxy(target, {
4548
- get(_target, prop) {
4549
- if (prop === "then") return undefined;
4550
- const value = ns[key];
4551
- if (prop === Symbol.toPrimitive) return () => value;
4552
- const item = value == null ? undefined : value[prop];
4553
- return typeof item === "function" ? item.bind(value) : item;
4554
- },
4555
- apply(target, thisArg, args) {
4556
- return target.apply(thisArg, args);
4557
- }
4558
- });
4559
- }`;
4560
4625
  for (const imp of imports) switch (imp.kind) {
4561
4626
  case "static": {
4562
4627
  const src = JSON.stringify(imp.source);
@@ -4574,20 +4639,8 @@ function applyRewrites(code, imports, id) {
4574
4639
  importParts.push(`__mf_remote_pending as ${pendingId}`);
4575
4640
  let rewrite = `import { ${importParts.join(", ")} } from ${src};`;
4576
4641
  if (imp.named.length > 0) {
4577
- const isProxyId = `__mf_is_proxy_${counter++}`;
4578
- const tempNames = imp.named.map((_s) => `__mf_named_${counter++}`);
4579
- const destructParts = imp.named.map((s, index) => `${s.imported}: ${tempNames[index]}`);
4580
- const bindingLines = imp.named.map((s, index) => {
4581
- const temp = tempNames[index];
4582
- return `const ${s.local} = ${isProxyId} ? __mfCreateNamedRemoteProxy(${nsId}, ${JSON.stringify(s.imported)}) : ${temp};`;
4583
- });
4584
- if (!namedProxyHelperDeclared) {
4585
- rewrite += `\n${namedProxyHelper}`;
4586
- namedProxyHelperDeclared = true;
4587
- }
4588
- rewrite += `\nconst ${isProxyId} = ${nsId} && ${nsId}.__mf_is_remote_proxy;`;
4589
- rewrite += `\nconst { ${destructParts.join(", ")} } = ${isProxyId} ? {} : ${nsId};`;
4590
- rewrite += `\n${bindingLines.join("\n")}`;
4642
+ const destructParts = imp.named.map((s) => `${s.imported}: ${s.local}`);
4643
+ rewrite += `\nconst { ${destructParts.join(", ")} } = ${nsId};`;
4591
4644
  }
4592
4645
  ms.overwrite(imp.start, imp.end, rewrite);
4593
4646
  }
@@ -4844,6 +4897,104 @@ function pluginRemoteNamedExports(options) {
4844
4897
  }
4845
4898
  //#endregion
4846
4899
  //#region src/plugins/pluginSSRRemoteEntry.ts
4900
+ const MAX_RUNNER_BODY_BYTES = 1024 * 1024;
4901
+ const ALLOWED_RUNNER_INVOKE_NAMES = new Set(["fetchModule", "getBuiltins"]);
4902
+ const VITE_FS_PREFIX = "/@fs/";
4903
+ function isPlainObject(value) {
4904
+ return !!value && typeof value === "object" && !Array.isArray(value);
4905
+ }
4906
+ function stripQueryAndHash(id) {
4907
+ const queryIndex = id.indexOf("?");
4908
+ const hashIndex = id.indexOf("#");
4909
+ const endIndex = queryIndex === -1 ? hashIndex : hashIndex === -1 ? queryIndex : Math.min(queryIndex, hashIndex);
4910
+ return endIndex === -1 ? id : id.slice(0, endIndex);
4911
+ }
4912
+ function decodeRunnerFilePath(filePath) {
4913
+ try {
4914
+ return decodeURIComponent(filePath);
4915
+ } catch {
4916
+ return;
4917
+ }
4918
+ }
4919
+ function hasRelativeTraversal(id) {
4920
+ return id.split(/[\\/]+/).includes("..");
4921
+ }
4922
+ function getRealPathIfExists(filePath) {
4923
+ try {
4924
+ return fs$1.realpathSync.native(filePath);
4925
+ } catch {
4926
+ return;
4927
+ }
4928
+ }
4929
+ function isPathWithinDirectory(filePath, directory) {
4930
+ const realFilePath = getRealPathIfExists(filePath) ?? path$1.resolve(filePath);
4931
+ const realDirectory = getRealPathIfExists(directory) ?? path$1.resolve(directory);
4932
+ const relative = path$1.relative(realDirectory, realFilePath);
4933
+ return relative === "" || !relative.startsWith("..") && !path$1.isAbsolute(relative);
4934
+ }
4935
+ function getRunnerAllowedDirectories(config) {
4936
+ return [config.root, ...config.server?.fs?.allow ?? []].map((directory) => path$1.resolve(directory));
4937
+ }
4938
+ function isPathWithinAllowedDirectories(filePath, allowedDirectories) {
4939
+ return allowedDirectories.some((directory) => isPathWithinDirectory(filePath, directory));
4940
+ }
4941
+ function isSafeRunnerFetchModuleId(id, config) {
4942
+ if (typeof id !== "string" || !id || id.includes("\0")) return false;
4943
+ const decoded = decodeViteId(id).replace(/^\0+/, "");
4944
+ if (!decoded || decoded.startsWith("virtual:")) return !!decoded;
4945
+ if (/^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(decoded) || decoded.startsWith("//")) return false;
4946
+ const cleanId = decodeRunnerFilePath(stripQueryAndHash(decoded));
4947
+ if (!cleanId || hasRelativeTraversal(cleanId)) return false;
4948
+ const allowedDirectories = getRunnerAllowedDirectories(config);
4949
+ if (cleanId.startsWith(VITE_FS_PREFIX)) {
4950
+ const fsPath = cleanId.slice(5);
4951
+ return path$1.isAbsolute(fsPath) && isPathWithinAllowedDirectories(fsPath, allowedDirectories);
4952
+ }
4953
+ if (path$1.isAbsolute(cleanId)) {
4954
+ if (isPathWithinAllowedDirectories(cleanId, allowedDirectories)) return true;
4955
+ return !fs$1.existsSync(cleanId);
4956
+ }
4957
+ return true;
4958
+ }
4959
+ function isRunnerInvokePayload(payload, config) {
4960
+ if (!payload || typeof payload !== "object") return false;
4961
+ if (payload.type !== "custom" || payload.event !== "vite:invoke") return false;
4962
+ const data = payload.data;
4963
+ if (!data || typeof data !== "object") return false;
4964
+ const name = data.name;
4965
+ const args = data.data;
4966
+ if (typeof name !== "string" || !ALLOWED_RUNNER_INVOKE_NAMES.has(name) || !Array.isArray(args)) return false;
4967
+ if (name === "getBuiltins") return args.length === 0;
4968
+ if (args.length < 1 || args.length > 3) return false;
4969
+ const [id, importer, opts] = args;
4970
+ return isSafeRunnerFetchModuleId(id, config) && (importer === void 0 || importer === null || isSafeRunnerFetchModuleId(importer, config)) && (opts === void 0 || isPlainObject(opts));
4971
+ }
4972
+ function readBoundedRunnerBody(req, res) {
4973
+ return new Promise((resolve) => {
4974
+ const chunks = [];
4975
+ let size = 0;
4976
+ let done = false;
4977
+ const fail = (statusCode, message) => {
4978
+ if (done) return;
4979
+ done = true;
4980
+ res.statusCode = statusCode;
4981
+ res.end(message);
4982
+ resolve(void 0);
4983
+ };
4984
+ req.on("data", (chunk) => {
4985
+ if (done) return;
4986
+ size += chunk.length;
4987
+ if (size > MAX_RUNNER_BODY_BYTES) return fail(413, "Payload too large");
4988
+ chunks.push(chunk);
4989
+ });
4990
+ req.on("end", () => {
4991
+ if (done) return;
4992
+ done = true;
4993
+ resolve(Buffer.concat(chunks));
4994
+ });
4995
+ req.on("error", () => fail(400, "Bad request"));
4996
+ });
4997
+ }
4847
4998
  /**
4848
4999
  * Emits a Node-compatible SSR remote entry alongside the browser entry.
4849
5000
  *
@@ -4861,6 +5012,9 @@ function pluginSSRRemoteEntry(options) {
4861
5012
  const virtualExposesSSRId = getVirtualExposesSSRId(options);
4862
5013
  let isRolldown = false;
4863
5014
  let ssrOutputFilename = "";
5015
+ let ssrOutputFiles = /* @__PURE__ */ new Set();
5016
+ let ssrOutputDir = "";
5017
+ let clientOutputDir = "";
4864
5018
  const ssrOnlyExternals = [
4865
5019
  "@module-federation/runtime",
4866
5020
  "@module-federation/runtime-core",
@@ -4912,6 +5066,7 @@ function pluginSSRRemoteEntry(options) {
4912
5066
  }
4913
5067
  }, {
4914
5068
  name: "mf:ssr-remote-entry",
5069
+ sharedDuringBuild: true,
4915
5070
  configResolved(config) {
4916
5071
  viteConfig = config;
4917
5072
  isNuxtProject = isNuxtProjectRoot(config.root);
@@ -4926,7 +5081,8 @@ function pluginSSRRemoteEntry(options) {
4926
5081
  });
4927
5082
  const ssrEnv = server.environments?.ssr;
4928
5083
  const clientEnv = server.environments?.client;
4929
- if (typeof (ssrEnv?.fetchModule ?? clientEnv?.fetchModule) === "function") server.middlewares.use("/__mf_runner__", async (req, res) => {
5084
+ const runnerEnv = typeof ssrEnv?.hot?.handleInvoke === "function" ? ssrEnv : typeof clientEnv?.hot?.handleInvoke === "function" ? clientEnv : void 0;
5085
+ if (typeof (ssrEnv?.fetchModule ?? clientEnv?.fetchModule) === "function" && runnerEnv) server.middlewares.use("/__mf_runner__", async (req, res) => {
4930
5086
  res.setHeader("Access-Control-Allow-Origin", "*");
4931
5087
  if (req.method === "OPTIONS") {
4932
5088
  res.setHeader("Access-Control-Allow-Methods", "POST");
@@ -4941,46 +5097,37 @@ function pluginSSRRemoteEntry(options) {
4941
5097
  return;
4942
5098
  }
4943
5099
  try {
4944
- const chunks = [];
4945
- await new Promise((resolve, reject) => {
4946
- req.on("data", (chunk) => chunks.push(chunk));
4947
- req.on("end", resolve);
4948
- req.on("error", reject);
4949
- });
4950
- const body = JSON.parse(Buffer.concat(chunks).toString("utf8"));
4951
- if (body.name === "getBuiltins") {
4952
- const builtins = (clientEnv ?? ssrEnv)?.config?.resolve?.builtins ?? [];
4953
- res.setHeader("Content-Type", "application/json");
4954
- res.end(JSON.stringify({ result: builtins }));
5100
+ const rawBody = await readBoundedRunnerBody(req, res);
5101
+ if (!rawBody) return;
5102
+ let body;
5103
+ try {
5104
+ body = JSON.parse(rawBody.toString("utf8"));
5105
+ } catch {
5106
+ res.statusCode = 400;
5107
+ res.end(JSON.stringify({ error: { message: "Invalid JSON" } }));
4955
5108
  return;
4956
5109
  }
4957
- if (body.name !== "fetchModule") {
5110
+ if (!isRunnerInvokePayload(body, server.config)) {
4958
5111
  res.statusCode = 400;
4959
- res.end(JSON.stringify({ error: { message: `Unsupported invoke: ${body.name}` } }));
5112
+ res.end(JSON.stringify({ error: { message: "Invalid runner invoke" } }));
4960
5113
  return;
4961
5114
  }
4962
- const [id, importer, opts] = body.data;
4963
- const fetchEnv = ssrEnv ?? clientEnv;
4964
- const fetchFn = fetchEnv.fetchModule.bind(fetchEnv);
4965
- let result;
4966
- try {
4967
- result = await fetchFn(id, importer, opts);
4968
- } catch (fetchErr) {
4969
- const bareId = decodeViteId(id);
4970
- try {
5115
+ let result = await runnerEnv.hot.handleInvoke(body);
5116
+ if ("error" in result && body.data.name === "fetchModule") {
5117
+ const id = body.data.data[0];
5118
+ const bareId = typeof id === "string" ? decodeViteId(id).replace(/^\0/, "") : "";
5119
+ if (bareId && !bareId.startsWith(".") && !bareId.startsWith("/") && !bareId.startsWith("file:") && !/^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(bareId)) try {
4971
5120
  const { createRequire } = await import("module");
4972
5121
  const path = await import("path");
4973
5122
  const { pathToFileURL } = await import("url");
4974
- result = {
4975
- externalize: pathToFileURL(createRequire(pathToFileURL(path.join(server.config.root, "package.json"))).resolve(bareId.replace(/^\0/, ""))).href,
5123
+ result = { result: {
5124
+ externalize: pathToFileURL(createRequire(pathToFileURL(path.join(server.config.root, "package.json"))).resolve(bareId)).href,
4976
5125
  type: "module"
4977
- };
4978
- } catch {
4979
- throw fetchErr;
4980
- }
5126
+ } };
5127
+ } catch {}
4981
5128
  }
4982
5129
  res.setHeader("Content-Type", "application/json");
4983
- res.end(JSON.stringify({ result }));
5130
+ res.end(JSON.stringify(result));
4984
5131
  } catch (e) {
4985
5132
  res.setHeader("Content-Type", "application/json");
4986
5133
  res.end(JSON.stringify({ error: { message: String(e instanceof Error ? e.message : e) } }));
@@ -5041,11 +5188,62 @@ function pluginSSRRemoteEntry(options) {
5041
5188
  const exposesChunk = findNuxtExposesChunk(bundle);
5042
5189
  const ssrAsset = bundle[ssrOutputFilename];
5043
5190
  if (exposesChunk && ssrAsset?.type === "asset" && typeof ssrAsset.source === "string") ssrAsset.source = ssrAsset.source.replace(/import\("virtual:mf-exposes-ssr:[^"]+"\)/g, `import("./${exposesChunk}")`);
5191
+ if (this.environment?.name === "ssr") ssrOutputFiles = collectEntryOutputFiles(bundle, ssrOutputFilename);
5044
5192
  if (!isRolldown) return;
5045
5193
  const chunk = bundle[ssrOutputFilename];
5046
5194
  if (!chunk || chunk.type !== "chunk") return;
5195
+ },
5196
+ writeBundle(outputOptions) {
5197
+ const environmentName = this.environment?.name;
5198
+ if (environmentName === "ssr" && outputOptions.dir) ssrOutputDir = outputOptions.dir;
5199
+ else if (environmentName === "client" && outputOptions.dir) clientOutputDir = outputOptions.dir;
5200
+ publishSsrOutputFiles(ssrOutputDir, clientOutputDir || viteConfig?.environments?.client?.build?.outDir);
5047
5201
  }
5048
5202
  }];
5203
+ function publishSsrOutputFiles(ssrOutDir, clientOutDir) {
5204
+ if (ssrOutputFiles.size === 0 || !ssrOutDir || !clientOutDir) return;
5205
+ const root = viteConfig?.root ?? process.cwd();
5206
+ const ssrDir = path$1.resolve(root, ssrOutDir);
5207
+ const clientDir = path$1.resolve(root, clientOutDir);
5208
+ if (ssrDir === clientDir || !fs$1.existsSync(ssrDir)) return;
5209
+ fs$1.mkdirSync(clientDir, { recursive: true });
5210
+ for (const fileName of ssrOutputFiles) {
5211
+ const source = path$1.resolve(ssrDir, fileName);
5212
+ const destination = path$1.resolve(clientDir, fileName);
5213
+ if (!isWithinDirectory(source, ssrDir) || !isWithinDirectory(destination, clientDir)) continue;
5214
+ if (!fs$1.existsSync(source) || fs$1.existsSync(destination)) continue;
5215
+ fs$1.mkdirSync(path$1.dirname(destination), { recursive: true });
5216
+ fs$1.copyFileSync(source, destination);
5217
+ }
5218
+ }
5219
+ }
5220
+ const RELATIVE_IMPORT_RE = /(?:\bfrom|\bimport\s*(?:\(\s*)?|\bexport\s*\*\s*from)\s*["'`](\.\.?\/[^"'`]+)["'`]/g;
5221
+ function collectEntryOutputFiles(bundle, entryFileName) {
5222
+ const files = /* @__PURE__ */ new Set();
5223
+ const visit = (fileName) => {
5224
+ if (files.has(fileName)) return;
5225
+ const file = bundle[fileName];
5226
+ if (!file) return;
5227
+ files.add(fileName);
5228
+ const dependencies = new Set([
5229
+ ...file.imports || [],
5230
+ ...file.dynamicImports || [],
5231
+ ...file.implicitlyLoadedBefore || [],
5232
+ ...file.referencedFiles || []
5233
+ ]);
5234
+ const source = typeof file.code === "string" ? file.code : typeof file.source === "string" ? file.source : "";
5235
+ if (source) {
5236
+ const directory = path$1.posix.dirname(fileName);
5237
+ for (const match of source.matchAll(RELATIVE_IMPORT_RE)) dependencies.add(path$1.posix.normalize(path$1.posix.join(directory, match[1])));
5238
+ }
5239
+ for (const dependency of dependencies) visit(dependency);
5240
+ };
5241
+ visit(entryFileName);
5242
+ return files;
5243
+ }
5244
+ function isWithinDirectory(filePath, directory) {
5245
+ const relative = path$1.relative(directory, filePath);
5246
+ return relative !== "" && !relative.startsWith(`..${path$1.sep}`) && relative !== "..";
5049
5247
  }
5050
5248
  //#endregion
5051
5249
  //#region src/plugins/pluginVarRemoteEntry.ts
@@ -5367,14 +5565,32 @@ function createEarlyVirtualModulesPlugin(options) {
5367
5565
  optimizeDeps.rolldownOptions.plugins ??= [];
5368
5566
  optimizeDeps.rolldownOptions.plugins.push({
5369
5567
  name: "module-federation:optimize-shared-resolver",
5568
+ load(id) {
5569
+ if (id !== "module-federation:optimized-require-react") return;
5570
+ const optimizedLoadSharePath = toViteOptimizedDepVirtualId(getLoadShareModulePath("react", isRolldown));
5571
+ const source = JSON.stringify(optimizedLoadSharePath);
5572
+ return "import * as __mfShared from " + source + ";\nexport * from " + source + ";\nexport default __mfShared.default ?? __mfShared;";
5573
+ },
5370
5574
  resolveId(source, importer, options) {
5371
- if (options?.kind?.startsWith("require")) return;
5575
+ if (createViteEncodedIdPrefixRegExp("virtual:mf:").test(source)) return {
5576
+ id: source,
5577
+ external: true
5578
+ };
5372
5579
  if (isSharedResolverInternalImporter(importer)) return;
5373
- if (isCommonJsImporter(importer)) return;
5374
5580
  const key = findSharedKey(source, shared);
5375
5581
  if (!key) return;
5376
5582
  if (source.endsWith(".css")) return;
5377
5583
  const shareItem = shared[key];
5584
+ const isReactSingleton = source === "react" && key === "react" && shareItem.shareConfig?.singleton === true;
5585
+ const isReactRequire = options?.kind?.startsWith("require") && isReactSingleton;
5586
+ if (options?.kind?.startsWith("require") && !isReactSingleton) return;
5587
+ if (isCommonJsImporter(importer) && !isReactSingleton) return;
5588
+ if (isReactRequire) {
5589
+ writeLoadShareModule(source, shareItem, _command, isRolldown);
5590
+ if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(source, shareItem);
5591
+ addUsedShares(source);
5592
+ return { id: "module-federation:optimized-require-react" };
5593
+ }
5378
5594
  const loadSharePath = getLoadShareModulePath(source, isRolldown);
5379
5595
  writeLoadShareModule(source, shareItem, _command, isRolldown);
5380
5596
  if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(source, shareItem);
@@ -5455,7 +5671,7 @@ export default __mfShared.default ?? __mfShared;`
5455
5671
  const optimizeDeps = config.optimizeDeps ??= {};
5456
5672
  optimizeDeps.include ??= [];
5457
5673
  optimizeDeps.exclude ??= [];
5458
- const shouldBypassOptimizeDep = isLitShare(key) || key === "react" && hasPackageDependency("react-redux", root);
5674
+ const shouldBypassOptimizeDep = isLitShare(key) || key === "react" && shareItem.shareConfig?.singleton === true;
5459
5675
  if (optimizeDeps.include.includes(key)) optimizeDeps.exclude = optimizeDeps.exclude.filter((dep) => dep !== key);
5460
5676
  else if (shouldBypassOptimizeDep) optimizeDeps.exclude.push(key);
5461
5677
  else optimizeDeps.include.push(key);
@@ -5510,7 +5726,7 @@ export default __mfShared.default ?? __mfShared;`
5510
5726
  const SSR_ONLY_PLUGINS = new Set(["@module-federation/vite/ssrEntryLoader"]);
5511
5727
  function loadPluginDts(options) {
5512
5728
  if (options.dts === false) return [];
5513
- return [import("./pluginDts-CrSsDUnT.js").then((n) => n.n).then(({ default: pluginDts }) => pluginDts(options))];
5729
+ return [import("./pluginDts-CTAHkt4C.js").then((n) => n.n).then(({ default: pluginDts }) => pluginDts(options))];
5514
5730
  }
5515
5731
  function federation(mfUserOptions) {
5516
5732
  if (isTestEnv()) return [];
@@ -5755,7 +5971,9 @@ function federation(mfUserOptions) {
5755
5971
  },
5756
5972
  load(id) {
5757
5973
  if (id.includes("__loadShare__") || id.includes("__loadRemote__")) {
5758
- let code = VirtualModule.findById(id)?.code ?? readFileSync(id, "utf-8");
5974
+ const virtualModule = VirtualModule.findById(id);
5975
+ if (!virtualModule?.code) return null;
5976
+ let code = virtualModule.code;
5759
5977
  const environmentName = this.environment?.name;
5760
5978
  if (environmentName && environmentName !== "client" || !environmentName && isSsrBuild) code = prependWorkspaceSingletonSsrImport(code);
5761
5979
  code = code.replace(/import\s+["'][^"']*__prebuild__[^"']*["']\s*;?/g, "");
@@ -5839,7 +6057,15 @@ function federation(mfUserOptions) {
5839
6057
  options.runtimePlugins.forEach((p) => {
5840
6058
  const pluginPath = typeof p === "string" ? p : p[0];
5841
6059
  if (SSR_ONLY_PLUGINS.has(pluginPath)) return;
5842
- if (pluginPath && !pluginPath.startsWith(".") && !pluginPath.startsWith("/") && !pluginPath.startsWith("\0") && !pluginPath.startsWith("virtual:")) config.optimizeDeps.include.push(pluginPath);
6060
+ if (pluginPath && !pluginPath.startsWith(".") && !pluginPath.startsWith("/") && !pluginPath.startsWith("\0") && !pluginPath.startsWith("virtual:")) {
6061
+ let optimizeDep = pluginPath;
6062
+ if (pluginPath === "@module-federation/dts-plugin/dynamic-remote-type-hints-plugin") try {
6063
+ optimizeDep = normalizePathForImport(resolveImportPath(pluginPath));
6064
+ } catch {
6065
+ optimizeDep = pluginPath;
6066
+ }
6067
+ config.optimizeDeps.include.push(optimizeDep);
6068
+ }
5843
6069
  });
5844
6070
  if (isRolldown) {
5845
6071
  config.build ??= {};