@module-federation/vite 1.21.3 → 1.21.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.
package/lib/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { n as normalizePathForImport, r as rebaseImport } from "./buildPaths-BkaQHrd2.js";
2
- import { a as getPackageDetectionCwd, c as getSharedCacheDescriptor, d as packageNameDecode, f as packageNameEncode, g as createModuleFederationError, h as sharedCacheHelperCode, i as getIsRolldown, l as hasPackageDependency, m as setPackageDetectionCwd, n as getInstalledPackageEntry, o as getPackageName, p as resolveImportPath, r as getInstalledPackageJson, s as getPackageNameFromNodeModulePath, u as isNuxtProjectRoot, v as mfWarn } from "./dtsConstants-CScOzmdO.js";
3
- import { a as getCommonSharedSubpaths, c as isNodeModulePath, d as normalizeNodeModulePath, f as resolvePublicPath, i as getCommonSharedSubpathFromNodeModulePath, l as isNuxtClientBase, n as filterId, o as getMatchingNodeModuleSubpath, r as getBasePath$1, s as isAssetLikeImport, t as ensureTrailingSlash, u as isViteOptimizableEntry } from "./pathNormalization-CHct3UwV.js";
2
+ import { a as getPackageDetectionCwd, c as getSharedCacheDescriptor, d as packageNameDecode, f as packageNameEncode, g as createModuleFederationError, h as sharedCacheHelperCode, i as getIsRolldown, l as hasPackageDependency, m as setPackageDetectionCwd, n as getInstalledPackageEntry, o as getPackageName, p as resolveImportPath, r as getInstalledPackageJson, s as getPackageNameFromNodeModulePath, u as isNuxtProjectRoot, v as mfWarn } from "./dtsConstants-BsaLBaaK.js";
3
+ import { a as filterId, c as getCommonSharedSubpaths, d as isNodeModulePath, f as isNuxtClientBase, h as resolvePublicPath, i as ensureTrailingSlash, l as getMatchingNodeModuleSubpath, m as normalizeNodeModulePath, n as invalidateSharedKeyMatcher, o as getBasePath$1, p as isViteOptimizableEntry, r as matchesSharedSource, s as getCommonSharedSubpathFromNodeModulePath, t as findSharedKey, u as isAssetLikeImport } from "./sharedKeyMatcher-DiUzRVH1.js";
4
4
  import { createRequire } from "node:module";
5
5
  import * as fs$2 from "fs";
6
- import { existsSync, readFileSync, realpathSync, statSync, writeFileSync } from "fs";
7
- import { createRequire as createRequire$1 } from "module";
6
+ import { existsSync, readFileSync, readdirSync, realpathSync, statSync, writeFileSync } from "fs";
7
+ import { createRequire as createRequire$1, isBuiltin } from "module";
8
8
  import * as path$1 from "node:path";
9
9
  import path, { basename } from "node:path";
10
10
  import { fileURLToPath, pathToFileURL } from "url";
@@ -13,6 +13,7 @@ import { createHash } from "node:crypto";
13
13
  import * as fs$1 from "node:fs";
14
14
  import { existsSync as existsSync$1, readFileSync as readFileSync$1 } from "node:fs";
15
15
  import { pathToFileURL as pathToFileURL$1 } from "node:url";
16
+ import { isIPv6 } from "node:net";
16
17
  //#region src/utils/bundleHelpers.ts
17
18
  function isOutputChunk$1(chunk) {
18
19
  return chunk.type === "chunk";
@@ -639,7 +640,8 @@ function rewriteEntryScripts(html, createProxySrc) {
639
640
  }
640
641
  function injectEntryScript(html, initSrc) {
641
642
  const src = sanitizeDevEntryPath(initSrc);
642
- return html.replace("<head>", `<head><script type="module" src=${JSON.stringify(src)}><\/script>`);
643
+ const script = `<script type="module" src=${JSON.stringify(src)}><\/script>`;
644
+ return html.replace(/<head\b[^>]*>/i, (openTag) => `${openTag}${script}`);
643
645
  }
644
646
  //#endregion
645
647
  //#region src/utils/normalizeModuleFederationOptions.ts
@@ -928,7 +930,7 @@ function normalizeModuleFederationOptions(options) {
928
930
  injectTreeShakingUsedExports: options.injectTreeShakingUsedExports,
929
931
  treeShakingSharedPlugins: options.treeShakingSharedPlugins,
930
932
  treeShakingSharedExcludePlugins: options.treeShakingSharedExcludePlugins,
931
- moduleParseTimeout: options.moduleParseTimeout || 10,
933
+ moduleParseTimeout: options.moduleParseTimeout ?? 10,
932
934
  moduleParseIdleTimeout: options.moduleParseIdleTimeout,
933
935
  varFilename: options.varFilename,
934
936
  target: options.target,
@@ -1090,7 +1092,7 @@ function serializeRuntimeOptions(options) {
1090
1092
  if (type === "number" || type === "boolean") return String(val);
1091
1093
  if (type === "undefined") return "undefined";
1092
1094
  if (type === "symbol") return `Symbol(${toSafeJsLiteral(val.description ?? "")})`;
1093
- if (type === "function") return val.toString();
1095
+ if (type === "function") return functionToExpression(val);
1094
1096
  if (val instanceof Date) return `new Date(${toSafeJsLiteral(val.toISOString())})`;
1095
1097
  if (val instanceof RegExp) return `new RegExp(${toSafeJsLiteral(val.source)}, ${toSafeJsLiteral(val.flags)})`;
1096
1098
  if (type === "object") {
@@ -1113,9 +1115,49 @@ function serializeRuntimeOptions(options) {
1113
1115
  for (const key in options) if (Object.prototype.hasOwnProperty.call(options, key)) topLevelProps.push(`${toSafeJsLiteral(key)}: ${valueToCode(options[key])}`);
1114
1116
  return `{${topLevelProps.join(", ")}}`;
1115
1117
  }
1118
+ const NATIVE_FUNCTION_SOURCE = /\{\s*\[native code\]\s*\}\s*$/;
1119
+ /**
1120
+ * Turns `Function#toString()` output into a JS expression that is valid as an
1121
+ * object-literal value.
1122
+ *
1123
+ * Method shorthand (`onError() { … }`) is not a valid expression after a `:`,
1124
+ * so it is rewritten as a function expression. Native functions have no
1125
+ * reconstructable source (`function parse() { [native code] }`) and serialize
1126
+ * as `undefined` so the generated object stays loadable.
1127
+ */
1128
+ function functionToExpression(fn) {
1129
+ let source;
1130
+ try {
1131
+ source = Function.prototype.toString.call(fn).trim();
1132
+ } catch {
1133
+ return "undefined";
1134
+ }
1135
+ if (NATIVE_FUNCTION_SOURCE.test(source) || /^(async\s+)?(?:get|set)\s+/.test(source)) return "undefined";
1136
+ if (/^(async\s+)?function\b/.test(source) || /^(async\s*)?\(/.test(source) || /^class\b/.test(source) || /^(async\s+)?[$_\p{ID_Start}][$\p{ID_Continue}]*\s*=>/u.test(source)) return isParsableExpression(source) ? source : "undefined";
1137
+ for (const [pattern, prefix] of [
1138
+ [/^async\s*\*\s*[$_\p{ID_Start}][$\p{ID_Continue}]*\s*(\([\s\S]*)$/u, "async function* "],
1139
+ [/^\*\s*[$_\p{ID_Start}][$\p{ID_Continue}]*\s*(\([\s\S]*)$/u, "function* "],
1140
+ [/^async\s+[$_\p{ID_Start}][$\p{ID_Continue}]*\s*(\([\s\S]*)$/u, "async function "],
1141
+ [/^[$_\p{ID_Start}][$\p{ID_Continue}]*\s*(\([\s\S]*)$/u, "function "]
1142
+ ]) {
1143
+ const match = source.match(pattern);
1144
+ if (!match) continue;
1145
+ const expression = `${prefix}${match[1]}`;
1146
+ return isParsableExpression(expression) ? expression : "undefined";
1147
+ }
1148
+ return "undefined";
1149
+ }
1150
+ function isParsableExpression(source) {
1151
+ try {
1152
+ new Function(`return (${source});`);
1153
+ return true;
1154
+ } catch {
1155
+ return false;
1156
+ }
1157
+ }
1116
1158
  //#endregion
1117
1159
  //#region src/utils/reactIsland.ts
1118
- const SOURCE_EXTENSIONS = [
1160
+ const SOURCE_EXTENSIONS$1 = [
1119
1161
  ".tsx",
1120
1162
  ".jsx",
1121
1163
  ".ts",
@@ -1134,8 +1176,8 @@ function resolveSourceFile(importPath, root) {
1134
1176
  const candidate = path$1.isAbsolute(cleanImport) ? cleanImport : path$1.resolve(root, cleanImport);
1135
1177
  return [
1136
1178
  candidate,
1137
- ...SOURCE_EXTENSIONS.map((extension) => `${candidate}${extension}`),
1138
- ...SOURCE_EXTENSIONS.map((extension) => path$1.join(candidate, `index${extension}`))
1179
+ ...SOURCE_EXTENSIONS$1.map((extension) => `${candidate}${extension}`),
1180
+ ...SOURCE_EXTENSIONS$1.map((extension) => path$1.join(candidate, `index${extension}`))
1139
1181
  ].find((filePath) => {
1140
1182
  try {
1141
1183
  return fs$1.statSync(filePath).isFile();
@@ -1574,6 +1616,13 @@ function getRuntimeRemoteAlias(alias, options) {
1574
1616
  if (!options) return alias;
1575
1617
  return `${getFederationScopeKey(options)}__${alias}`;
1576
1618
  }
1619
+ function getSsrRuntimeRemotes(remotes, options) {
1620
+ return Object.entries(remotes).map(([name, item]) => ({
1621
+ name: getRuntimeRemoteAlias(name, options),
1622
+ entry: item.entry,
1623
+ type: item.type ?? "module"
1624
+ }));
1625
+ }
1577
1626
  function getRuntimeInitGlobalKey(ownerImportId) {
1578
1627
  return `__mf_init__${ownerImportId ?? virtualRuntimeInitStatus.getImportId()}__`;
1579
1628
  }
@@ -2044,6 +2093,7 @@ function hasLikelyTypeArgumentFollower(source, end, codePositions, followsNamedE
2044
2093
  let next = end + 1;
2045
2094
  while (next < source.length && (!codePositions[next] || /\s/.test(source[next]))) next++;
2046
2095
  if (next >= source.length || /[([.!?=;,)\]}:|&]/.test(source[next])) return true;
2096
+ if (source.slice(end + 1, next).includes("\n")) return true;
2047
2097
  const followingToken = source.slice(next).match(/^[$_\p{ID_Start}][$_\u200C\u200D\p{ID_Continue}]*/u)?.[0];
2048
2098
  return followingToken === "as" || followingToken === "satisfies" || !followsNamedExpression && followingToken !== void 0;
2049
2099
  }
@@ -2412,6 +2462,11 @@ function getAdditionalTopLevelDeclaratorNames(source, start, codePositions) {
2412
2462
  const tokenStart = index;
2413
2463
  while (/[$_\u200C\u200D\p{ID_Continue}]/u.test(source[index + 1] || "")) index++;
2414
2464
  const token = source.slice(tokenStart, index + 1);
2465
+ if (depth === 0 && templateFrames.length === 0 && token === "export") {
2466
+ let previous = tokenStart - 1;
2467
+ while (/\s/.test(source[previous] || "")) previous--;
2468
+ if (source[previous] !== "." && /^\s+(?:(?:async\s+)?function\b|(?:abstract\s+)?class\b|const\b|let\b|var\b|enum\b|namespace\b|module\b|interface\b|type\b|declare\b|default\b|\{|\*)/.test(source.slice(index + 1))) return names;
2469
+ }
2415
2470
  canStartRegex = /^(?:await|case|delete|in|instanceof|new|return|throw|typeof|void|yield)$/.test(token);
2416
2471
  continue;
2417
2472
  }
@@ -2597,8 +2652,14 @@ function getNamedExportsViaRegex(source, filePath, visited, scanState = { comple
2597
2652
  while (previousCodeIndex >= 0 && (/\s/.test(source[previousCodeIndex]) || !codePositions[previousCodeIndex])) previousCodeIndex--;
2598
2653
  if (source[previousCodeIndex] === ".") continue;
2599
2654
  let nextCodeIndex = match.index + match[0].length;
2600
- while (/\s/.test(source[nextCodeIndex] || "")) nextCodeIndex++;
2655
+ while (nextCodeIndex < source.length && (/\s/.test(source[nextCodeIndex]) || !codePositions[nextCodeIndex])) nextCodeIndex++;
2601
2656
  if (source[nextCodeIndex] === "(") continue;
2657
+ let memberIndex = nextCodeIndex;
2658
+ if (source[memberIndex] === "?") {
2659
+ memberIndex++;
2660
+ while (memberIndex < source.length && (/\s/.test(source[memberIndex]) || !codePositions[memberIndex])) memberIndex++;
2661
+ }
2662
+ if (source[memberIndex] === ":") continue;
2602
2663
  scanState.complete = false;
2603
2664
  break;
2604
2665
  }
@@ -2760,23 +2821,25 @@ function getDependencyNames(packageJson) {
2760
2821
  }
2761
2822
  return Array.from(names);
2762
2823
  }
2763
- function isSharedSingletonConsumedByPeer(pkg, options = getNormalizeModuleFederationOptions()) {
2824
+ function isSharedSingletonConsumedByPeer(pkg, options = getNormalizeModuleFederationOptions(), requireFederationRuntimeDependency = false) {
2764
2825
  const shared = options?.shared || {};
2765
- if (Object.entries(shared).some(([key, item]) => key !== pkg && key.startsWith(`${pkg}/`) && item.shareConfig.singleton === true)) return true;
2826
+ if (!requireFederationRuntimeDependency && Object.entries(shared).some(([key, item]) => key !== pkg && key.startsWith(`${pkg}/`) && item.shareConfig.singleton === true)) return true;
2766
2827
  const sharedKeyByPackageName = /* @__PURE__ */ new Map();
2767
2828
  Object.entries(shared).filter(([, item]) => item.shareConfig.singleton === true).forEach(([key]) => {
2768
2829
  const packageName = getPackageName(key);
2769
2830
  if (!sharedKeyByPackageName.get(packageName) || key === packageName) sharedKeyByPackageName.set(packageName, key);
2770
2831
  });
2771
- const reachesPkg = (current, seen) => {
2772
- const packageJson = getSharedDependencyGraphPackageJson(current);
2773
- for (const dependency of getDependencyNames(packageJson)) {
2832
+ const reachesPkg = (current, seen, hasFederationRuntimeDependency = false) => {
2833
+ const dependencies = getDependencyNames(getSharedDependencyGraphPackageJson(current));
2834
+ const usesFederationRuntime = dependencies.some((dependency) => dependency === "@module-federation/enhanced" || dependency === "@module-federation/runtime" || dependency === "@module-federation/runtime-core");
2835
+ const runtimeIsReachable = hasFederationRuntimeDependency || usesFederationRuntime;
2836
+ for (const dependency of dependencies) {
2774
2837
  const sharedDependency = sharedKeyByPackageName.get(dependency);
2775
2838
  if (!sharedDependency) continue;
2776
- if (sharedDependency === pkg) return true;
2839
+ if (sharedDependency === pkg) return !requireFederationRuntimeDependency || runtimeIsReachable;
2777
2840
  if (seen.has(sharedDependency)) continue;
2778
2841
  seen.add(sharedDependency);
2779
- if (reachesPkg(sharedDependency, seen)) return true;
2842
+ if (reachesPkg(sharedDependency, seen, runtimeIsReachable)) return true;
2780
2843
  }
2781
2844
  return false;
2782
2845
  };
@@ -3107,6 +3170,12 @@ function findCurrentLoadShareForStaleOwnerId(id, shared, findSharedKey, options)
3107
3170
  function getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer) {
3108
3171
  return treeShakingConsumer ? `__mfReadTreeShakingSharedSelection(__mfModuleCache.share, ${cacheDescriptor}, ${JSON.stringify(treeShakingConsumer)})` : `__mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor})`;
3109
3172
  }
3173
+ /**
3174
+ * Eager workspace singleton wrapper: reads the shared cache synchronously and falls back to the local
3175
+ * namespace. Inside the fallback's own evaluation cycle that namespace is not initialized yet (undefined in
3176
+ * a merged chunk, TDZ bindings otherwise), so the exports stay unassigned until the deferred cache write
3177
+ * re-applies them; a host-provided copy re-applies them through the cache subscription as before.
3178
+ */
3110
3179
  function generateEagerWorkspaceSingletonExports(namedExports, importSource, cacheDescriptor, cacheOwner, treeShakingConsumer, mutableExports = []) {
3111
3180
  const copiedExports = namedExports.filter((name) => !mutableExports.includes(name));
3112
3181
  const namedExportVars = copiedExports.map((_name, i) => `__mf_${i}`);
@@ -3118,8 +3187,10 @@ function generateEagerWorkspaceSingletonExports(namedExports, importSource, cach
3118
3187
  let exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
3119
3188
  if (exportModule === undefined) {
3120
3189
  Promise.resolve().then(() => {
3121
- if (__mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor}) === undefined) {
3122
- __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, __mfNormalizeShareModule(__mfLocalShare), ${cacheOwner});
3190
+ if (__mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor}) !== undefined) return;
3191
+ const localShare = __mfInitializedLocalShare(__mfLocalShare);
3192
+ if (localShare !== undefined) {
3193
+ __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, localShare, ${cacheOwner});
3123
3194
  }
3124
3195
  });
3125
3196
  exportModule = __mfLocalShare;
@@ -3128,8 +3199,16 @@ function generateEagerWorkspaceSingletonExports(namedExports, importSource, cach
3128
3199
  const __mfApplyEagerShareExports = (mod) => {
3129
3200
  ${assignments}
3130
3201
  };
3202
+ const __mfApplyEagerShareExportsWhenReady = (mod) => {
3203
+ if (mod === undefined) return;
3204
+ try {
3205
+ __mfApplyEagerShareExports(mod);
3206
+ } catch (error) {
3207
+ if (!(error instanceof ReferenceError)) throw error;
3208
+ }
3209
+ };
3131
3210
  __mfSubscribeSharedCache(__mfModuleCache.share, ${cacheDescriptor}, __mfApplyEagerShareExports);
3132
- __mfApplyEagerShareExports(exportModule);
3211
+ __mfApplyEagerShareExportsWhenReady(exportModule);
3133
3212
  export { __mf_default as default };${namedExportLine}${mutableExportLine}`;
3134
3213
  }
3135
3214
  function generateLazyWorkspaceSingletonExports(namedExports, importSource, cacheDescriptor, cacheOwner, treeShakingConsumer, serveLocalFallback = false, mutableExports = []) {
@@ -3237,6 +3316,15 @@ const normalizeLocalShareModuleCode = `const __mfNormalizeShareModule = (mod) =>
3237
3316
  ? Object.assign({}, normalized)
3238
3317
  : normalized;
3239
3318
  };`;
3319
+ const initializedLocalShareModuleCode = `const __mfInitializedLocalShare = (mod) => {
3320
+ if (mod === undefined) return undefined;
3321
+ try {
3322
+ return __mfNormalizeShareModule(mod);
3323
+ } catch (error) {
3324
+ if (error instanceof ReferenceError) return undefined;
3325
+ throw error;
3326
+ }
3327
+ };`;
3240
3328
  function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exportConditions, importFalseExportUsage) {
3241
3329
  const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
3242
3330
  const { loadShareCacheMap } = getSharedVirtualModuleState(options);
@@ -3284,7 +3372,7 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3284
3372
  const hasCompleteExportCoverage = detectedNamedExports !== void 0;
3285
3373
  const isWorkspaceSingleton = isWorkspacePackage && shareItem.shareConfig.singleton === true;
3286
3374
  const isDefaultShareScope = shareItem.scope === void 0 || shareItem.scope === "default" || Array.isArray(shareItem.scope) && shareItem.scope[0] === "default";
3287
- const usesDeferredSingletonFallback = hasCompleteExportCoverage && shareItem.shareConfig.eager !== true && (isWorkspacePackage || command !== "build" && isRemoteOnlyContainer(resolvedOptions) && shareItem.shareConfig.singleton === true || command === "build" && isRemoteOnlyContainer(resolvedOptions) && (shareItem.shareConfig.singleton === true || isDefaultShareScope));
3375
+ const usesDeferredSingletonFallback = hasCompleteExportCoverage && shareItem.shareConfig.eager !== true && (isWorkspacePackage || command !== "build" && isRemoteOnlyContainer(resolvedOptions) && shareItem.shareConfig.singleton === true || command === "build" && isRemoteOnlyContainer(resolvedOptions) && (shareItem.shareConfig.singleton === true || isDefaultShareScope) && !isSharedSingletonConsumedByPeer(pkg, resolvedOptions, true));
3288
3376
  const servesRemoteSingletonFallback = command !== "build" && isRemoteOnlyContainer(resolvedOptions) && shareItem.shareConfig.singleton === true;
3289
3377
  const isConsumedByPeerSingleton = isSharedSingletonConsumedByPeer(pkg, resolvedOptions);
3290
3378
  const usesEntryInjectedRemoteFallback = hasCompleteExportCoverage && !isWorkspaceSingleton && isRemoteOnlyContainer(resolvedOptions) && shareItem.shareConfig.singleton === true && resolvedOptions.hostInitInjectLocation === "entry" && (command === "build" || isConsumedByPeerSingleton);
@@ -3370,12 +3458,13 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3370
3458
  }
3371
3459
  const prebuildImportLine = usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback ? "" : usesDeferredSingletonFallback || usesDeferredTreeShakingFallback ? !servesRemoteSingletonFallback && usesDeferredSingletonFallback && command !== "build" && (isWorkspaceSingleton || isWorkspacePackage) ? `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(lazyLocalFallbackSource)};` : "" : `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(detectedNamedExports === void 0 ? coherentLocalSource : skipServePrebuildWarmup ? devImportSource : sharedImportSource)};`;
3372
3460
  const devDynamicImportLine = isWorkspacePackage ? "" : usesDeferredSingletonFallback || usesDeferredTreeShakingFallback ? "" : command !== "build" && !skipServePrebuildWarmup ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
3373
- const moduleBody = usesDeferredSingletonFallback || usesDeferredTreeShakingFallback ? `
3461
+ const moduleBody = usesDeferredSingletonFallback || usesDeferredTreeShakingFallback || usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback ? `
3374
3462
  ${prebuildImportLine}
3375
3463
  ${devDynamicImportLine}
3376
3464
  ${importLine}
3377
3465
  ${sharedCacheHelperCode}
3378
3466
  ${normalizeLocalShareModuleCode}
3467
+ ${initializedLocalShareModuleCode}
3379
3468
  ${exportLine}
3380
3469
  ` : `
3381
3470
  ${prebuildImportLine}
@@ -3477,6 +3566,7 @@ function generateLocalSharedImportMap(options) {
3477
3566
  if (!shareItem?.shareConfig.eager || shareItem.shareConfig.import === false) return "";
3478
3567
  return `import * as __mfEagerShare_${index} from ${toSafeJsLiteral(getLocalSharedPackagePath(pkg, shareItem, options))};`;
3479
3568
  }).filter(Boolean).join("\n")}
3569
+ ${normalizeRuntimeShareCode}
3480
3570
  const importMap = {
3481
3571
  ${orderedShares.map((pkg, index) => {
3482
3572
  const shareItem = getNormalizeShareItem(pkg, resolvedOptions);
@@ -3521,7 +3611,7 @@ function generateLocalSharedImportMap(options) {
3521
3611
  const res = await pkgDynamicImport()
3522
3612
  const exportModule = ${toSafeJsLiteral(useDirectReactImport)} && ${toSafeJsLiteral(key)} === "react"
3523
3613
  ? (res?.default ?? res)
3524
- : {...res}
3614
+ : __mfNormalizeRuntimeShare({...res})
3525
3615
  // All npm packages pre-built by vite will be converted to esm
3526
3616
  if (exportModule.__esModule !== true) {
3527
3617
  Object.defineProperty(exportModule, "__esModule", {
@@ -3637,9 +3727,8 @@ function getMaterializedShares(options) {
3637
3727
  return priority(a) - priority(b) || a.localeCompare(b);
3638
3728
  }));
3639
3729
  }
3640
- function getShareBatches(options, materializedOnly = true) {
3641
- const ordered = materializedOnly ? getMaterializedShares(options) : getOrderedUsedShares(options);
3642
- const levels = /* @__PURE__ */ new Map();
3730
+ /** Shared keys a share's package.json depends on (roots stand in for their subpaths, subpaths for their root), keyed by share. */
3731
+ function getSharePrerequisites(ordered) {
3643
3732
  const roots = /* @__PURE__ */ new Map();
3644
3733
  const subpaths = /* @__PURE__ */ new Map();
3645
3734
  for (const pkg of ordered) {
@@ -3647,6 +3736,7 @@ function getShareBatches(options, materializedOnly = true) {
3647
3736
  if (pkg === packageName) roots.set(packageName, pkg);
3648
3737
  else subpaths.set(packageName, [...subpaths.get(packageName) ?? [], pkg]);
3649
3738
  }
3739
+ const prerequisitesByShare = /* @__PURE__ */ new Map();
3650
3740
  for (const pkg of ordered) {
3651
3741
  const packageName = getPackageName(pkg);
3652
3742
  const packageJson = getInstalledPackageJson(pkg)?.packageJson ?? (pkg !== packageName ? getInstalledPackageJson(packageName)?.packageJson : void 0);
@@ -3660,8 +3750,15 @@ function getShareBatches(options, materializedOnly = true) {
3660
3750
  const root = roots.get(packageName);
3661
3751
  if (root) prerequisites.push(root);
3662
3752
  } else if (pkg === packageName && packageName !== "react" && packageName !== "react-dom") prerequisites.push(...subpaths.get(packageName) ?? []);
3663
- levels.set(pkg, prerequisites.reduce((level, dependency) => Math.max(level, (levels.get(dependency) ?? 0) + 1), 0));
3753
+ prerequisitesByShare.set(pkg, prerequisites);
3664
3754
  }
3755
+ return prerequisitesByShare;
3756
+ }
3757
+ function getShareBatches(options, materializedOnly = true) {
3758
+ const ordered = materializedOnly ? getMaterializedShares(options) : getOrderedUsedShares(options);
3759
+ const prerequisitesByShare = getSharePrerequisites(ordered);
3760
+ const levels = /* @__PURE__ */ new Map();
3761
+ for (const pkg of ordered) levels.set(pkg, (prerequisitesByShare.get(pkg) ?? []).reduce((level, dependency) => Math.max(level, (levels.get(dependency) ?? 0) + 1), 0));
3665
3762
  const batches = [];
3666
3763
  for (const pkg of ordered) (batches[levels.get(pkg) ?? 0] ??= []).push(pkg);
3667
3764
  return batches.filter(Boolean);
@@ -3903,9 +4000,14 @@ const externalSharedProviderSelectionHelperCode = `const __mfSelectExternalShare
3903
4000
  };`;
3904
4001
  function generateRuntimeSharedCacheSeedCode(shareStrategy, options) {
3905
4002
  const seedBatches = getShareBatches(options, false);
4003
+ const seedOrder = seedBatches.flat();
4004
+ const seedIndex = new Map(seedOrder.map((pkg, index) => [pkg, index]));
4005
+ const seedPrerequisites = Object.fromEntries(Array.from(getSharePrerequisites(seedOrder)).filter(([, prerequisites]) => prerequisites.length > 0).map(([pkg, prerequisites]) => [seedIndex.get(pkg), prerequisites.map((prerequisite) => seedIndex.get(prerequisite))]));
3906
4006
  return `
3907
- const __mfSeedOrder = ${toSafeJsLiteral(seedBatches.flat())};
4007
+ const __mfSeedOrder = ${toSafeJsLiteral(seedOrder)};
3908
4008
  const __mfSeedBatches = ${toSafeJsLiteral(seedBatches)};
4009
+ const __mfSeedIndex = new Map(__mfSeedOrder.map((pkg, index) => [pkg, index]));
4010
+ const __mfSeedPrerequisites = ${toSafeJsLiteral(seedPrerequisites)};
3909
4011
  // A share is normally skipped here until the dev scanner has observed a real
3910
4012
  // import and set materialize. An import:false share has no local fallback
3911
4013
  // though, so on a cold request (materialize not set yet) it must still be
@@ -4012,15 +4114,30 @@ function generateRuntimeSharedCacheSeedCode(shareStrategy, options) {
4012
4114
  ${toSafeJsLiteral(shareStrategy)}
4013
4115
  ));
4014
4116
  };
4015
- const __mfFirstRuntimeSeedBarrierIndex = __mfSeedKeys.findIndex(
4016
- __mfNeedsPreInitSeedBarrier
4117
+ const __mfExpandBlockedSeedKeys = (blocked) => {
4118
+ let changed = true;
4119
+ while (changed) {
4120
+ changed = false;
4121
+ for (const pkg of __mfSeedKeys) {
4122
+ const seedIndex = __mfSeedIndex.get(pkg);
4123
+ if (blocked.has(seedIndex)) continue;
4124
+ if ((__mfSeedPrerequisites[seedIndex] || []).some((dependency) => blocked.has(dependency))) {
4125
+ blocked.add(seedIndex);
4126
+ changed = true;
4127
+ }
4128
+ }
4129
+ }
4130
+ return blocked;
4131
+ };
4132
+ const __mfPreInitBlockedSeedKeys = __mfExpandBlockedSeedKeys(new Set(
4133
+ __mfSeedKeys.filter(__mfNeedsPreInitSeedBarrier).map((pkg) => __mfSeedIndex.get(pkg))
4134
+ ));
4135
+ const __mfImmediateSeedKeys = __mfSeedKeys.filter(
4136
+ (pkg) => !__mfPreInitBlockedSeedKeys.has(__mfSeedIndex.get(pkg))
4137
+ );
4138
+ var __mfDeferredSeedKeys = __mfSeedKeys.filter(
4139
+ (pkg) => __mfPreInitBlockedSeedKeys.has(__mfSeedIndex.get(pkg))
4017
4140
  );
4018
- const __mfImmediateSeedKeys = __mfFirstRuntimeSeedBarrierIndex === -1
4019
- ? __mfSeedKeys
4020
- : __mfSeedKeys.slice(0, __mfFirstRuntimeSeedBarrierIndex);
4021
- var __mfDeferredSeedKeys = __mfFirstRuntimeSeedBarrierIndex === -1
4022
- ? []
4023
- : __mfSeedKeys.slice(__mfFirstRuntimeSeedBarrierIndex);
4024
4141
  await __mfSeedLocalShared(__mfImmediateSeedKeys);`;
4025
4142
  }
4026
4143
  function getBrowserImportPath(importPath) {
@@ -4770,6 +4887,8 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
4770
4887
  const providerEntry = __mfFindSharedProviderEntry(versionMap, provider);
4771
4888
  if (!providerEntry) return;
4772
4889
  if (usedShare.shareConfig?.import === false && __mfMatchesSharedProvider(provider, usedShare)) return;
4890
+ // Another container's consume-only stub has nothing to bridge to: its get() throws by construction.
4891
+ if (provider?.shareConfig?.import === false) return;
4773
4892
  const { version } = providerEntry;
4774
4893
  if (!singleton && version !== usedShare.version) return;
4775
4894
  if (
@@ -4884,6 +5003,8 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
4884
5003
  };
4885
5004
  if (usedShare.canLiveRebind === false) return;
4886
5005
  if (usedShare.shareConfig?.import === false && __mfMatchesSharedProvider(provider, usedShare)) return;
5006
+ // Another container's consume-only stub has nothing to bridge to: its get() throws by construction.
5007
+ if (provider?.shareConfig?.import === false) return;
4887
5008
  // Preserve a singleton already selected by another container. The bridge may
4888
5009
  // only replace the provisional local fallback seeded by this container.
4889
5010
  if (cachedShare !== undefined && cachedShareOwner !== mfName) return;
@@ -5105,11 +5226,13 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
5105
5226
  }
5106
5227
  };
5107
5228
  // Resolve runtime-only dependencies and seed local fallbacks in dependency
5108
- // order. Stop at an unresolved provider so its consumers cannot capture an
5109
- // undefined or provisional singleton.
5229
+ // order. An unresolved provider blocks its consumers, which would otherwise
5230
+ // capture an undefined or provisional singleton; unrelated shares still seed.
5110
5231
  const __mfReadyDeferredSeedKeys = [];
5232
+ const __mfBlockedSeedKeys = new Set();
5111
5233
  for (const pkg of __mfDeferredSeedKeys) {
5112
5234
  const share = usedShared[pkg];
5235
+ const seedIndex = __mfSeedIndex.get(pkg);
5113
5236
  if (__mfIsRuntimeOnlySharePending(pkg)) {
5114
5237
  try {
5115
5238
  if (share.treeShaking) {
@@ -5118,18 +5241,22 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
5118
5241
  await __mfResolveImportFalseShared(pkg, share);
5119
5242
  }
5120
5243
  } catch (err) {
5121
- // A rejected provider is an unresolved provider: stop here as the comment above
5122
- // prescribes, instead of escalating to a container-wide init() failure.
5244
+ // A rejected provider is an unresolved provider: block its consumers as the
5245
+ // comment above prescribes, instead of escalating to a container-wide init() failure.
5123
5246
  console.error(
5124
5247
  \`[Module Federation] Failed to resolve runtime-only shared module "\${pkg}"\`,
5125
5248
  err
5126
5249
  );
5127
- break;
5128
5250
  }
5129
5251
  }
5130
- if (__mfIsRuntimeOnlySharePending(pkg)) break;
5131
- __mfReadyDeferredSeedKeys.push(pkg);
5252
+ if (__mfIsRuntimeOnlySharePending(pkg)) {
5253
+ __mfBlockedSeedKeys.add(seedIndex);
5254
+ }
5132
5255
  }
5256
+ __mfExpandBlockedSeedKeys(__mfBlockedSeedKeys);
5257
+ __mfReadyDeferredSeedKeys.push(...__mfDeferredSeedKeys.filter(
5258
+ (pkg) => !__mfBlockedSeedKeys.has(__mfSeedIndex.get(pkg))
5259
+ ));
5133
5260
  await __mfSeedLocalShared(__mfReadyDeferredSeedKeys);
5134
5261
  initResolve(initRes)
5135
5262
  return initRes
@@ -5275,6 +5402,71 @@ function getHostAutoInitPath(options) {
5275
5402
  function isOwnedHostAutoInitId(id, options) {
5276
5403
  return VirtualModule.findById(id) === getHostAutoInitState(options).module;
5277
5404
  }
5405
+ /**
5406
+ * Build-time list of the loadShare wrappers this container bundles a fallback for, plus a function the host
5407
+ * bootstrap calls after the remote preloads: a share still unseeded then (behind an unresolved runtime-only
5408
+ * share in init()) has a deferred wrapper that only registers its pending load once evaluated. Importing it
5409
+ * here puts that load in front of the bootstrap's pendingShareLoads barrier instead of inside the entry's own
5410
+ * import graph, where module-scope reads would see it undefined. Kept out of hostInit so that chunk stays
5411
+ * free of wrapper references.
5412
+ */
5413
+ const PENDING_SHARES_TAG = "__P_S__";
5414
+ const legacyPendingSharesState = {
5415
+ module: new VirtualModule("pendingShares", PENDING_SHARES_TAG),
5416
+ command: "build"
5417
+ };
5418
+ const pendingSharesStates = /* @__PURE__ */ new WeakMap();
5419
+ function getPendingSharesState(options) {
5420
+ if (!options) return legacyPendingSharesState;
5421
+ let state = pendingSharesStates.get(options);
5422
+ if (!state) {
5423
+ state = {
5424
+ module: new VirtualModule("pendingShares", PENDING_SHARES_TAG, "", getLocalOwnerKey(options)),
5425
+ command: "build"
5426
+ };
5427
+ pendingSharesStates.set(options, state);
5428
+ }
5429
+ return state;
5430
+ }
5431
+ function generatePendingSharesCode(command = "build", options) {
5432
+ const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
5433
+ const pendingShareImports = command === "build" ? getMaterializedShares(options).filter((pkg) => {
5434
+ const shareItem = resolvedOptions.shared?.[pkg];
5435
+ return Boolean(shareItem) && !pkg.endsWith("/") && shareItem.shareConfig.import !== false && !shareItem.shareConfig.treeShaking;
5436
+ }).map((pkg) => `[${toSafeJsLiteral(pkg)}, () => import(${toSafeJsLiteral(getLoadShareModulePath(pkg, false, options))})]`) : [];
5437
+ return `
5438
+ ${getRuntimeModuleCacheBootstrapCode()}
5439
+ ${sharedCacheHelperCode}
5440
+ const __mfPendingShareImports = [${pendingShareImports.join(", ")}];
5441
+ export async function preloadPendingShares() {
5442
+ if (__mfPendingShareImports.length === 0) return;
5443
+ const {usedShared} = await import("${getLocalSharedImportMapPath(options)}");
5444
+ await Promise.all(__mfPendingShareImports.map(async ([pkg, load]) => {
5445
+ const share = usedShared[pkg];
5446
+ if (!share || share.materialize === false || share.treeShaking || share.shareConfig?.import === false) return;
5447
+ const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, share.shareConfig?.singleton, share.version, share.scope);
5448
+ if (__mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined) return;
5449
+ await load().catch((err) => console.warn("[module-federation] shared preload failed:", pkg, err));
5450
+ }));
5451
+ }
5452
+ `;
5453
+ }
5454
+ function writePendingShares(command = "build", options) {
5455
+ const state = getPendingSharesState(options);
5456
+ state.command = command;
5457
+ state.module.writeSync(generatePendingSharesCode(command, options), true);
5458
+ }
5459
+ function refreshPendingShares(options) {
5460
+ try {
5461
+ writePendingShares(getPendingSharesState(options).command, options);
5462
+ } catch {}
5463
+ }
5464
+ function getPendingSharesPath(options) {
5465
+ return getPendingSharesState(options).module.getImportId();
5466
+ }
5467
+ function isOwnedPendingSharesId(id, options) {
5468
+ return VirtualModule.findById(id) === getPendingSharesState(options).module;
5469
+ }
5278
5470
  //#endregion
5279
5471
  //#region src/virtualModules/virtualRemotes.ts
5280
5472
  const cacheRemoteMap = /* @__PURE__ */ new WeakMap();
@@ -5568,11 +5760,7 @@ function generateRemotes(id, command, enableSsrInit = false, consumer = "unified
5568
5760
  const remoteRegistration = getRemoteRegistration(id, resolvedOptions.remotes, options);
5569
5761
  const registerRemoteCode = isLoadedFirst && remoteRegistration ? `runtime.registerRemotes([${JSON.stringify(remoteRegistration)}]);` : "";
5570
5762
  const hostAutoInitPath = getHostAutoInitPath(options);
5571
- const ssrRemotes = Object.entries(resolvedOptions.remotes).map(([name, item]) => ({
5572
- name: getRuntimeRemoteAlias(name, options),
5573
- entry: item.entry,
5574
- type: item.type ?? "module"
5575
- }));
5763
+ const ssrRemotes = getSsrRuntimeRemotes(resolvedOptions.remotes, options);
5576
5764
  const browserHostInitCode = `import(${JSON.stringify(hostAutoInitPath)})
5577
5765
  .then((mod) => mod.hostInitPromise)
5578
5766
  .then(initResolve, initReject);`;
@@ -5798,6 +5986,7 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
5798
5986
  let htmlFilePath;
5799
5987
  let _command;
5800
5988
  let emitFileId;
5989
+ let pendingSharesEmitId;
5801
5990
  let viteConfig;
5802
5991
  let skipHtmlDevFallback = forceClientInjected ?? false;
5803
5992
  let clientInjected = false;
@@ -5941,12 +6130,15 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
5941
6130
  if (__mfReactServerModuleCache?.pendingShareLoads) {
5942
6131
  await Promise.all(__mfReactServerModuleCache.pendingShareLoads);
5943
6132
  }`;
6133
+ const pendingSharesBlock = waitsForInit && (_command === "build" || viteConfig?.command === "build") ? `
6134
+ const __mfPendingShares = await ${importExpression(options?.pendingSharesSrc ?? getPendingSharesPath(federationOptions))}.catch(() => undefined);
6135
+ if (__mfPendingShares && typeof __mfPendingShares.preloadPendingShares === "function") await __mfPendingShares.preloadPendingShares();` : "";
5944
6136
  const importCode = `
5945
6137
  (async () => {
5946
6138
  const __mfHostInit = await ${importExpression(initSrc)};
5947
6139
  await __mfHostInit.__tla;
5948
6140
  const { initHost } = __mfHostInit;
5949
- ${preloadBlock}${sharedPreloadBlock}${pendingShareLoadsAwait}
6141
+ ${preloadBlock}${pendingSharesBlock}${sharedPreloadBlock}${pendingShareLoadsAwait}
5950
6142
  })().then(() => ${entryImportExpression});
5951
6143
  `;
5952
6144
  return [
@@ -5957,8 +6149,8 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
5957
6149
  importCode
5958
6150
  ].join("\n");
5959
6151
  }
5960
- function getSystemBootstrapSource(initSrc, entrySrc) {
5961
- return getBootstrapSource(initSrc, entrySrc, true);
6152
+ function getSystemBootstrapSource(initSrc, entrySrc, pendingSharesSrc) {
6153
+ return getBootstrapSource(initSrc, entrySrc, true, { pendingSharesSrc });
5962
6154
  }
5963
6155
  function injectHtml() {
5964
6156
  return inject === "html" && (htmlFilePath || hasPackageDependency("@sveltejs/kit"));
@@ -6150,6 +6342,12 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
6150
6342
  };
6151
6343
  if (!hasHash) emitFileOptions.fileName = fileName;
6152
6344
  emitFileId = this.emitFile(emitFileOptions);
6345
+ if (waitsForInit) pendingSharesEmitId = this.emitFile({
6346
+ name: "pendingShares",
6347
+ type: "chunk",
6348
+ id: getPendingSharesPath(federationOptions),
6349
+ preserveSignature: "strict"
6350
+ });
6153
6351
  if (htmlFilePath) addHtmlScriptEntries(htmlFilePath);
6154
6352
  },
6155
6353
  generateBundle(_options, bundle) {
@@ -6164,6 +6362,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
6164
6362
  if (htmlFileNames.length === 0) return;
6165
6363
  const file = this.getFileName(emitFileId);
6166
6364
  emittedFileName = file;
6365
+ const pendingSharesFile = pendingSharesEmitId ? this.getFileName(pendingSharesEmitId) : void 0;
6167
6366
  const lastSlash = file.lastIndexOf("/");
6168
6367
  bootstrapDir = lastSlash !== -1 ? file.slice(0, lastSlash + 1) : "";
6169
6368
  const resolvePath = (builtFileName, htmlFileName) => {
@@ -6199,7 +6398,10 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
6199
6398
  rewritten = true;
6200
6399
  const strippedInit = stripBase(initPath);
6201
6400
  const strippedEntry = stripBase(entrySrc);
6202
- const bootstrapSource = getSystemBootstrapSource(bootstrapDir ? rebaseImport(strippedInit, bootstrapDir) : initPath, bootstrapDir ? rebaseImport(strippedEntry, bootstrapDir) : entrySrc);
6401
+ const rebasedInitPath = bootstrapDir ? rebaseImport(strippedInit, bootstrapDir) : initPath;
6402
+ const rebasedEntrySrc = bootstrapDir ? rebaseImport(strippedEntry, bootstrapDir) : entrySrc;
6403
+ const pendingSharesPath = pendingSharesFile ? resolvePath(pendingSharesFile, fileName) : void 0;
6404
+ const bootstrapSource = getSystemBootstrapSource(rebasedInitPath, rebasedEntrySrc, pendingSharesPath && bootstrapDir ? rebaseImport(stripBase(pendingSharesPath), bootstrapDir) : pendingSharesPath);
6203
6405
  const bootstrapHash = createHash("sha256").update(bootstrapSource).digest("hex").slice(0, 8);
6204
6406
  const bootstrapFileName = `${bootstrapDir}mf-entry-bootstrap-${bootstrapIndex++}-${bootstrapHash}.js`;
6205
6407
  const bootstrapRef = this.emitFile({
@@ -6296,7 +6498,12 @@ function checkAliasConflicts(options) {
6296
6498
  const matchesSharedKey = (aliasEntry, sharedKey) => {
6297
6499
  const findPattern = aliasEntry.find;
6298
6500
  if (typeof findPattern === "string") return findPattern === sharedKey || sharedKey.startsWith(findPattern + "/");
6299
- if (findPattern instanceof RegExp) return findPattern.test(sharedKey);
6501
+ if (findPattern instanceof RegExp) {
6502
+ findPattern.lastIndex = 0;
6503
+ const matched = findPattern.test(sharedKey);
6504
+ findPattern.lastIndex = 0;
6505
+ return matched;
6506
+ }
6300
6507
  return false;
6301
6508
  };
6302
6509
  for (const sharedKey of sharedKeys) for (const aliasEntry of userAliases) {
@@ -6487,6 +6694,21 @@ const vueAdapter = {
6487
6694
  } }
6488
6695
  };
6489
6696
  //#endregion
6697
+ //#region src/utils/devServerHost.ts
6698
+ const UNSPECIFIED_HOSTS = /* @__PURE__ */ new Set(["0.0.0.0", "::"]);
6699
+ /**
6700
+ * Hostname for client-facing HTTP/WS origins built from Vite `server.host`.
6701
+ *
6702
+ * Unspecified bind addresses (`0.0.0.0`, `::`) map to `localhost`, matching
6703
+ * Vite's own printed local URL. IPv6 addresses are wrapped in brackets so
6704
+ * `http://[::1]:5173` / `ws://[::1]:5173` parse as valid URLs.
6705
+ */
6706
+ function formatDevServerHostForOrigin(host) {
6707
+ if (typeof host !== "string" || UNSPECIFIED_HOSTS.has(host)) return "localhost";
6708
+ if (host.startsWith("[") && host.endsWith("]")) return host;
6709
+ return isIPv6(host) ? `[${host}]` : host;
6710
+ }
6711
+ //#endregion
6490
6712
  //#region src/plugins/hmr/fullReload.ts
6491
6713
  const REMOTE_HMR_ENDPOINT = "__mf_hmr";
6492
6714
  const REMOTE_HMR_EVENT = "mf:remote-update";
@@ -6512,10 +6734,10 @@ function getHmrWsPath(base, hmrPath) {
6512
6734
  }
6513
6735
  function getRemoteHmrWsUrl(server) {
6514
6736
  const hmr = server.config.server.hmr;
6515
- return `${hmr && typeof hmr === "object" && hmr.protocol ? hmr.protocol : server.config.server.https ? "wss" : "ws"}://${hmr && typeof hmr === "object" && hmr.host ? hmr.host : typeof server.config.server.host === "string" && server.config.server.host !== "0.0.0.0" ? server.config.server.host : "localhost"}:${hmr && typeof hmr === "object" && (hmr.clientPort || hmr.port) ? hmr.clientPort || hmr.port : server.config.server.port}${getHmrWsPath(server.config.base, hmr && typeof hmr === "object" ? hmr.path : "")}?token=${server.config.webSocketToken}`;
6737
+ return `${hmr && typeof hmr === "object" && hmr.protocol ? hmr.protocol : server.config.server.https ? "wss" : "ws"}://${formatDevServerHostForOrigin(hmr && typeof hmr === "object" && hmr.host ? hmr.host : server.config.server.host)}:${hmr && typeof hmr === "object" && (hmr.clientPort || hmr.port) ? hmr.clientPort || hmr.port : server.config.server.port}${getHmrWsPath(server.config.base, hmr && typeof hmr === "object" ? hmr.path : "")}?token=${server.config.webSocketToken}`;
6516
6738
  }
6517
6739
  function getLocalFallbackOrigin(server) {
6518
- return `${server.config.server.https ? "https" : "http"}://${typeof server.config.server.host === "string" && server.config.server.host !== "0.0.0.0" && server.config.server.host !== "::" ? server.config.server.host : "localhost"}:${server.config.server.port || 5173}`;
6740
+ return `${server.config.server.https ? "https" : "http"}://${formatDevServerHostForOrigin(server.config.server.host)}:${server.config.server.port || 5173}`;
6519
6741
  }
6520
6742
  function getRemoteHmrEndpoint(remoteEntry, server) {
6521
6743
  try {
@@ -7013,11 +7235,7 @@ function pluginExternalRuntimeCore() {
7013
7235
  function initVirtualModules(command, remoteEntryId, enableSsrInit = false, options) {
7014
7236
  writeLocalSharedImportMap(options);
7015
7237
  writeHostAutoInit(remoteEntryId, command, options);
7016
- writeRuntimeInitStatus(command, enableSsrInit, getHostAutoInitPath(options), options, options ? Object.entries(options.remotes).map(([name, item]) => ({
7017
- name,
7018
- entry: item.entry,
7019
- type: item.type ?? "module"
7020
- })) : void 0);
7238
+ writeRuntimeInitStatus(command, enableSsrInit, getHostAutoInitPath(options), options, options ? getSsrRuntimeRemotes(options.remotes, options) : void 0);
7021
7239
  }
7022
7240
  //#endregion
7023
7241
  //#region src/utils/cssModuleHelpers.ts
@@ -7240,15 +7458,22 @@ const REMOTE_ENTRY_SSR_ID = "virtual:mf-REMOTE_ENTRY_SSR_ID";
7240
7458
  function getRemoteEntrySSRId(options) {
7241
7459
  return `${REMOTE_ENTRY_SSR_ID}:${getVirtualModuleScopeKey(options)}`;
7242
7460
  }
7461
+ function stripSsrFilenameHashPlaceholder(filename) {
7462
+ if (!filename.includes("[hash")) return filename;
7463
+ filename = filename.replace(/(?:[._-]?\[hash(?::\d+)?\])/g, "");
7464
+ if (!/\.[^.]+$/.test(filename)) filename = `${filename}.js`;
7465
+ return filename;
7466
+ }
7243
7467
  function getSsrRemoteEntryFileName(browserFilename) {
7244
- let filename = browserFilename;
7245
- if (filename.includes("[hash")) {
7246
- filename = filename.replace(/(?:[._-]?\[hash(?::\d+)?\])/g, "");
7247
- if (!/\.[^.]+$/.test(filename)) filename = `${filename}.js`;
7248
- }
7468
+ const filename = stripSsrFilenameHashPlaceholder(browserFilename);
7249
7469
  const ext = filename.match(/\.[^.]+$/)?.[0] || ".js";
7250
7470
  return `${filename.slice(0, filename.length - ext.length)}.ssr${ext}`;
7251
7471
  }
7472
+ function getSsrExposesFileName(browserFilename) {
7473
+ const filename = stripSsrFilenameHashPlaceholder(browserFilename);
7474
+ const ext = filename.match(/\.[^.]+$/)?.[0];
7475
+ return `${ext ? filename.slice(0, filename.length - ext.length) : filename}.exposes.js`;
7476
+ }
7252
7477
  /** Singleton map for SSR loadShare: expand `pkg/` via usedShares; never serialize the prefix. */
7253
7478
  function getSsrSharedSingletons(options) {
7254
7479
  const used = getUsedShares(options);
@@ -8138,7 +8363,7 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
8138
8363
  }
8139
8364
  if (isHostAutoInitId(id)) {
8140
8365
  if (_command === "serve") {
8141
- const host = typeof viteConfig.server?.host === "string" && viteConfig.server.host !== "0.0.0.0" ? viteConfig.server.host : "localhost";
8366
+ const host = formatDevServerHostForOrigin(viteConfig.server?.host);
8142
8367
  const resolvedPublicPath = resolvePublicPath(options, viteConfig.base, originalConfigBase);
8143
8368
  const devPublicPath = resolvedPublicPath === "auto" ? "/" : resolvedPublicPath;
8144
8369
  const remoteEntryFileName = resolveDevHashEntryFileName(options.filename);
@@ -8340,54 +8565,6 @@ function isBuildConfigImporter(importer) {
8340
8565
  if (!importer) return false;
8341
8566
  return /(^|\/)(?:nuxt|vite|vitest|webpack|rollup|rspack)\.config\.[cm]?[jt]sx?$/.test(importer.replace(/\\/g, "/"));
8342
8567
  }
8343
- function matchesSharedSource(source, key) {
8344
- const keyBase = key.endsWith("/") ? key.slice(0, -1) : key;
8345
- if (keyBase === "vue" && (source === "vue/dist/vue.esm-bundler.js" || source === "vue/dist/vue.runtime.esm-bundler.js")) return true;
8346
- if (key.endsWith("/")) return source === keyBase || source.startsWith(`${keyBase}/`);
8347
- if (getCommonSharedSubpaths(keyBase).includes(source)) return true;
8348
- return source === keyBase;
8349
- }
8350
- function findSharedKey(source, shared) {
8351
- return getSharedKeyMatcher(shared).find(source);
8352
- }
8353
- const emptySharedKeyMatcher = { find: () => void 0 };
8354
- const sharedKeyMatcherCache = /* @__PURE__ */ new WeakMap();
8355
- function getSharedKeyMatcher(shared) {
8356
- if (!shared) return emptySharedKeyMatcher;
8357
- const cached = sharedKeyMatcherCache.get(shared);
8358
- if (cached) return cached;
8359
- const keys = Object.keys(shared);
8360
- const exactKeys = new Set(keys);
8361
- const commonSubpathKeys = /* @__PURE__ */ new Map();
8362
- const wildcardKeys = [];
8363
- let vueKey;
8364
- for (const key of keys) {
8365
- const keyBase = key.endsWith("/") ? key.slice(0, -1) : key;
8366
- const shareItem = shared[key];
8367
- if (!vueKey && keyBase === "vue") vueKey = key;
8368
- if (key.endsWith("/")) wildcardKeys.push({
8369
- key,
8370
- base: keyBase
8371
- });
8372
- if (shareItem.shareConfig?.import !== false) {
8373
- for (const subpath of getCommonSharedSubpaths(keyBase)) if (!commonSubpathKeys.has(subpath)) commonSubpathKeys.set(subpath, key);
8374
- }
8375
- }
8376
- const sourceCache = /* @__PURE__ */ new Map();
8377
- const matcher = { find(source) {
8378
- if (sourceCache.has(source)) return sourceCache.get(source);
8379
- let result = exactKeys.has(source) ? source : void 0;
8380
- if (!result && vueKey) {
8381
- if (source === "vue/dist/vue.esm-bundler.js" || source === "vue/dist/vue.runtime.esm-bundler.js") result = vueKey;
8382
- }
8383
- if (!result) result = commonSubpathKeys.get(source);
8384
- if (!result) result = wildcardKeys.find(({ base }) => source === base || source.startsWith(`${base}/`))?.key;
8385
- sourceCache.set(source, result);
8386
- return result;
8387
- } };
8388
- sharedKeyMatcherCache.set(shared, matcher);
8389
- return matcher;
8390
- }
8391
8568
  function findSharedKeyForSource(source, shared) {
8392
8569
  const key = findSharedKey(source, shared);
8393
8570
  if (key) return key;
@@ -8433,12 +8610,109 @@ function excludeSharedSubDependencies(shared) {
8433
8610
  delete shared[depKey];
8434
8611
  sharedKeys.delete(depKey);
8435
8612
  sharedKeyByBase.delete(dep);
8436
- sharedKeyMatcherCache.delete(shared);
8613
+ invalidateSharedKeyMatcher(shared);
8437
8614
  }
8438
8615
  }
8439
8616
  }
8440
8617
  }
8441
8618
  const sharedDependencyCache = /* @__PURE__ */ new Map();
8619
+ const sharedPackageDirectoryCache = /* @__PURE__ */ new WeakMap();
8620
+ function getSharedPackageFromFile(importer, shared, cwd = getPackageDetectionCwd()) {
8621
+ if (!importer) return;
8622
+ const nodeModulePackage = getPackageNameFromNodeModulePath(importer);
8623
+ if (nodeModulePackage) return nodeModulePackage;
8624
+ let cached = sharedPackageDirectoryCache.get(shared);
8625
+ if (!cached || cached.cwd !== cwd) {
8626
+ const entries = /* @__PURE__ */ new Map();
8627
+ for (const key of Object.keys(shared)) {
8628
+ const packageName = getPackageName(key);
8629
+ const entry = getInstalledPackageEntry(packageName, { cwd });
8630
+ if (entry && !isNodeModulePath(entry)) entries.set(path$1.dirname(normalizePathForImport(entry)), packageName);
8631
+ }
8632
+ cached = {
8633
+ cwd,
8634
+ entries
8635
+ };
8636
+ sharedPackageDirectoryCache.set(shared, cached);
8637
+ }
8638
+ const normalizedImporter = normalizePathForImport(importer);
8639
+ return [...cached.entries].find(([dir]) => normalizedImporter === dir || normalizedImporter.startsWith(`${dir}/`))?.[1] ?? getWorkspacePackageNameFromFile(normalizedImporter);
8640
+ }
8641
+ const workspacePackageNameCache = /* @__PURE__ */ new Map();
8642
+ /** Name from the nearest `package.json` above `file`, for files outside `node_modules`. */
8643
+ function getWorkspacePackageNameFromFile(file) {
8644
+ const filePath = file.split("?")[0];
8645
+ if (!path$1.isAbsolute(filePath) || isNodeModulePath(filePath)) return;
8646
+ const visited = [];
8647
+ let dir = path$1.dirname(filePath);
8648
+ let name;
8649
+ while (true) {
8650
+ if (workspacePackageNameCache.has(dir)) {
8651
+ name = workspacePackageNameCache.get(dir);
8652
+ break;
8653
+ }
8654
+ visited.push(dir);
8655
+ const manifestPath = path$1.join(dir, "package.json");
8656
+ if (existsSync(manifestPath)) {
8657
+ try {
8658
+ const manifestName = JSON.parse(readFileSync(manifestPath, "utf-8")).name;
8659
+ if (typeof manifestName !== "string") {
8660
+ const parent = path$1.dirname(dir);
8661
+ if (parent === dir) break;
8662
+ dir = parent;
8663
+ continue;
8664
+ }
8665
+ name = manifestName;
8666
+ } catch {
8667
+ name = void 0;
8668
+ }
8669
+ break;
8670
+ }
8671
+ const parent = path$1.dirname(dir);
8672
+ if (parent === dir) break;
8673
+ dir = parent;
8674
+ }
8675
+ for (const visitedDir of visited) workspacePackageNameCache.set(visitedDir, name);
8676
+ return name;
8677
+ }
8678
+ const dependencyManifestCache = /* @__PURE__ */ new Map();
8679
+ /**
8680
+ * The manifest of `dep` as seen from `fromDir`: a plain `node_modules` walk-up first, because the
8681
+ * cycle walk below visits every package in the tree and `getInstalledPackageJson`'s resolver is
8682
+ * far too expensive for that many lookups; it stays the fallback for layouts the walk-up misses.
8683
+ */
8684
+ function getDependencyManifest(dep, fromDir) {
8685
+ const cacheKey = `${fromDir}\0${dep}`;
8686
+ if (dependencyManifestCache.has(cacheKey)) return dependencyManifestCache.get(cacheKey);
8687
+ let found;
8688
+ let currentDir = fromDir;
8689
+ while (true) {
8690
+ const packageJsonPath = path$1.join(currentDir, "node_modules", dep, "package.json");
8691
+ if (existsSync(packageJsonPath)) {
8692
+ try {
8693
+ let dir = path$1.dirname(packageJsonPath);
8694
+ try {
8695
+ dir = realpathSync(dir);
8696
+ } catch {}
8697
+ found = {
8698
+ path: packageJsonPath,
8699
+ dir,
8700
+ packageJson: JSON.parse(readFileSync(packageJsonPath, "utf-8"))
8701
+ };
8702
+ } catch {}
8703
+ break;
8704
+ }
8705
+ const parentDir = path$1.dirname(currentDir);
8706
+ if (parentDir === currentDir) break;
8707
+ currentDir = parentDir;
8708
+ }
8709
+ found ??= getInstalledPackageJson(dep, {
8710
+ cwd: fromDir,
8711
+ packageName: dep
8712
+ });
8713
+ dependencyManifestCache.set(cacheKey, found);
8714
+ return found;
8715
+ }
8442
8716
  /** Whether `dependency` is reachable through the shared package's manifest dependencies. */
8443
8717
  function isSharedPackageDependency(sharedKey, dependency) {
8444
8718
  const sharedPackage = getPackageName(sharedKey);
@@ -8447,8 +8721,9 @@ function isSharedPackageDependency(sharedKey, dependency) {
8447
8721
  reachable = /* @__PURE__ */ new Set();
8448
8722
  const visited = /* @__PURE__ */ new Set();
8449
8723
  const queue = [getInstalledPackageJson(sharedPackage, { packageName: sharedPackage })];
8450
- for (let installed = queue.shift(); installed; installed = queue.shift()) {
8451
- if (visited.has(installed.dir)) continue;
8724
+ while (queue.length) {
8725
+ const installed = queue.shift();
8726
+ if (!installed || visited.has(installed.dir)) continue;
8452
8727
  visited.add(installed.dir);
8453
8728
  const manifest = installed.packageJson;
8454
8729
  for (const dep of Object.keys({
@@ -8457,16 +8732,145 @@ function isSharedPackageDependency(sharedKey, dependency) {
8457
8732
  ...manifest.optionalDependencies
8458
8733
  })) {
8459
8734
  reachable.add(dep);
8460
- queue.push(getInstalledPackageJson(dep, {
8461
- cwd: installed.dir,
8462
- packageName: dep
8463
- }));
8735
+ queue.push(getDependencyManifest(dep, installed.dir));
8464
8736
  }
8465
8737
  }
8466
8738
  sharedDependencyCache.set(sharedPackage, reachable);
8467
8739
  }
8468
8740
  return reachable.has(dependency);
8469
8741
  }
8742
+ const sharedRuntimeDependencyCache = /* @__PURE__ */ new Map();
8743
+ const SOURCE_FILE_RE = /\.(?:[cm]?js|[cm]?ts|jsx|tsx)$/;
8744
+ const NON_RUNTIME_SOURCE_RE = /(?:\.d\.[cm]?ts|\.(?:test|spec|stories)\.[cm]?[jt]sx?)$/;
8745
+ const NON_RUNTIME_DIRS = /* @__PURE__ */ new Set([
8746
+ "node_modules",
8747
+ "__tests__",
8748
+ "dist",
8749
+ "build"
8750
+ ]);
8751
+ /** Bundled artifacts of a published package never import workspace packages; skip them instead of scanning megabytes. */
8752
+ const MAX_SCANNED_SOURCE_BYTES = 256 * 1024;
8753
+ const BARE_PACKAGE_SPECIFIER_RE = /^(?:@[^\s'"`()\/]+\/)?[^\s'"`()\/.@][^\s'"`()\/]*(?:\/[^\s'"`()]*)?$/;
8754
+ /** Module specifiers evaluated by a source file. */
8755
+ function getRuntimeModuleSpecifiers(code) {
8756
+ return findModuleImportDescriptors(code).filter(({ typeOnly }) => !typeOnly).map(({ source }) => source);
8757
+ }
8758
+ /** Bare specifiers a source file imports at runtime. */
8759
+ function getRuntimeImportSpecifiers(code) {
8760
+ return getRuntimeModuleSpecifiers(code).filter((specifier) => BARE_PACKAGE_SPECIFIER_RE.test(specifier) && !isBuiltin(specifier));
8761
+ }
8762
+ function collectAllRuntimeImports(dir, into) {
8763
+ let entries;
8764
+ try {
8765
+ entries = readdirSync(dir, { withFileTypes: true });
8766
+ } catch {
8767
+ return;
8768
+ }
8769
+ for (const entry of entries) {
8770
+ if (entry.isDirectory()) {
8771
+ if (!NON_RUNTIME_DIRS.has(entry.name)) collectAllRuntimeImports(path$1.join(dir, entry.name), into);
8772
+ continue;
8773
+ }
8774
+ if (!SOURCE_FILE_RE.test(entry.name) || NON_RUNTIME_SOURCE_RE.test(entry.name)) continue;
8775
+ const file = path$1.join(dir, entry.name);
8776
+ let code;
8777
+ try {
8778
+ if (statSync(file).size > MAX_SCANNED_SOURCE_BYTES) continue;
8779
+ code = readFileSync(file, "utf-8");
8780
+ } catch {
8781
+ continue;
8782
+ }
8783
+ for (const specifier of getRuntimeImportSpecifiers(code)) into.add(specifier);
8784
+ }
8785
+ }
8786
+ const SOURCE_EXTENSIONS = [
8787
+ "",
8788
+ ".js",
8789
+ ".mjs",
8790
+ ".cjs",
8791
+ ".ts",
8792
+ ".mts",
8793
+ ".cts",
8794
+ ".jsx",
8795
+ ".tsx"
8796
+ ];
8797
+ function resolveLocalRuntimeImport(importer, specifier) {
8798
+ if (!specifier.startsWith(".")) return;
8799
+ const resolved = path$1.resolve(path$1.dirname(importer), specifier);
8800
+ return SOURCE_EXTENSIONS.flatMap((extension) => [`${resolved}${extension}`, path$1.join(resolved, `index${extension}`)]).find((candidate) => existsSync(candidate));
8801
+ }
8802
+ function collectReachableRuntimeImports(entry, dir, into) {
8803
+ const visited = /* @__PURE__ */ new Set();
8804
+ const queue = [entry];
8805
+ let scanned = false;
8806
+ while (queue.length) {
8807
+ const file = queue.shift();
8808
+ const relative = path$1.relative(dir, file);
8809
+ if (relative.startsWith("..") || path$1.isAbsolute(relative) || visited.has(file)) continue;
8810
+ visited.add(file);
8811
+ let code;
8812
+ try {
8813
+ if (statSync(file).size > MAX_SCANNED_SOURCE_BYTES) continue;
8814
+ code = readFileSync(file, "utf-8");
8815
+ scanned = true;
8816
+ } catch {
8817
+ continue;
8818
+ }
8819
+ for (const specifier of getRuntimeModuleSpecifiers(code)) {
8820
+ if (BARE_PACKAGE_SPECIFIER_RE.test(specifier) && !isBuiltin(specifier)) {
8821
+ into.add(specifier);
8822
+ continue;
8823
+ }
8824
+ const local = resolveLocalRuntimeImport(file, specifier);
8825
+ if (local) queue.push(local);
8826
+ }
8827
+ }
8828
+ return scanned;
8829
+ }
8830
+ /**
8831
+ * Whether `dependency` is reachable from the shared package through the imports its source files
8832
+ * (and those of the workspace packages they pull in) actually evaluate. Unlike the manifest walk
8833
+ * above this ignores `import type` edges and stops at `node_modules` boundaries, so it approximates
8834
+ * the fallback's evaluation graph rather than the package's declared closure — in a monorepo the
8835
+ * latter covers far more than the module graph ever does.
8836
+ */
8837
+ function isSharedPackageRuntimeDependency(sharedKey, dependency) {
8838
+ const sharedPackage = getPackageName(sharedKey);
8839
+ let reachable = sharedRuntimeDependencyCache.get(sharedKey);
8840
+ if (!reachable) {
8841
+ reachable = /* @__PURE__ */ new Set();
8842
+ const visited = /* @__PURE__ */ new Set();
8843
+ const queue = [{
8844
+ request: sharedKey,
8845
+ installed: getInstalledPackageJson(sharedPackage, { packageName: sharedPackage })
8846
+ }];
8847
+ while (queue.length) {
8848
+ const { request, installed } = queue.shift();
8849
+ if (!installed) continue;
8850
+ const visitKey = `${installed.dir}\0${request}`;
8851
+ if (visited.has(visitKey)) continue;
8852
+ visited.add(visitKey);
8853
+ const specifiers = /* @__PURE__ */ new Set();
8854
+ const entry = getInstalledPackageEntry(request, {
8855
+ cwd: installed.dir,
8856
+ packageName: getPackageName(request)
8857
+ });
8858
+ if (!entry || !collectReachableRuntimeImports(entry, installed.dir, specifiers)) collectAllRuntimeImports(installed.dir, specifiers);
8859
+ for (const specifier of specifiers) {
8860
+ const dep = getPackageName(specifier);
8861
+ if (dep === sharedPackage) continue;
8862
+ reachable.add(dep);
8863
+ const manifest = getDependencyManifest(dep, installed.dir);
8864
+ if (manifest && !isNodeModulePath(manifest.dir)) queue.push({
8865
+ request: specifier,
8866
+ installed: manifest
8867
+ });
8868
+ }
8869
+ }
8870
+ sharedRuntimeDependencyCache.set(sharedKey, reachable);
8871
+ }
8872
+ return reachable.has(dependency);
8873
+ }
8470
8874
  function proxySharedModule(options) {
8471
8875
  const { shared = {}, federationOptions, getParsePromise = () => Promise.resolve() } = options;
8472
8876
  let _config;
@@ -8549,6 +8953,9 @@ function proxySharedModule(options) {
8549
8953
  resetTreeShakingExports(federationOptions);
8550
8954
  emittedTreeShakingProviders.clear();
8551
8955
  sharedDependencyCache.clear();
8956
+ dependencyManifestCache.clear();
8957
+ sharedRuntimeDependencyCache.clear();
8958
+ workspacePackageNameCache.clear();
8552
8959
  const isVinext = hasPackageDependency("vinext");
8553
8960
  const isAstro = hasPackageDependency("astro");
8554
8961
  const isRolldown = getIsRolldown(this);
@@ -8637,9 +9044,11 @@ function proxySharedModule(options) {
8637
9044
  }
8638
9045
  const key = findSharedKeyForSource(source, shared);
8639
9046
  if (!key) return;
8640
- const importerPackage = importer ? getPackageNameFromNodeModulePath(importer) : void 0;
9047
+ const importerPackage = getSharedPackageFromFile(importer, shared);
8641
9048
  if (importerPackage === getPackageName(key)) return;
8642
- if (importerPackage && isSharedPackageDependency(key, importerPackage)) return;
9049
+ if (importerPackage) {
9050
+ if (!isNodeModulePath(importer) && !Object.keys(shared).some((sharedKey) => getPackageName(sharedKey) === importerPackage) ? isSharedPackageRuntimeDependency(key, importerPackage) : isSharedPackageDependency(key, importerPackage)) return;
9051
+ }
8643
9052
  if (useDirectReactImport && key === "react") return;
8644
9053
  if (isAssetLikeImport(source)) return;
8645
9054
  if (isBuildConfigImporter(importer)) return;
@@ -9105,6 +9514,7 @@ function pluginSSRRemoteEntry(options) {
9105
9514
  const virtualExposesSSRId = getVirtualExposesSSRId(options);
9106
9515
  let cachedSsrRemoteEntrySource;
9107
9516
  const ssrOutputFilename = getSsrRemoteEntryFileName(options.filename);
9517
+ const ssrExposesFileName = getSsrExposesFileName(options.filename);
9108
9518
  let ssrOutputFiles = /* @__PURE__ */ new Set();
9109
9519
  let ssrOutputDir = "";
9110
9520
  let clientOutputDir = "";
@@ -9232,13 +9642,13 @@ function pluginSSRRemoteEntry(options) {
9232
9642
  });
9233
9643
  const ssrPath = `${base}/${ssrEntryFileName}`;
9234
9644
  server.middlewares.use(ssrPath, (_req, res) => {
9235
- const exposesUrl = `${base}/${options.filename.replace(/\.[^.]+$/, "")}.exposes.js`;
9645
+ const exposesUrl = `${base}/${ssrExposesFileName}`;
9236
9646
  const code = getSsrRemoteEntrySource().replace(JSON.stringify(virtualExposesSSRId), JSON.stringify(exposesUrl));
9237
9647
  res.setHeader("Content-Type", "application/javascript");
9238
9648
  res.setHeader("Access-Control-Allow-Origin", "*");
9239
9649
  res.end(code);
9240
9650
  });
9241
- const exposesPath = `${base}/${options.filename.replace(/\.[^.]+$/, "")}.exposes.js`;
9651
+ const exposesPath = `${base}/${ssrExposesFileName}`;
9242
9652
  server.middlewares.use(exposesPath, (_req, res) => {
9243
9653
  res.setHeader("Content-Type", "application/javascript");
9244
9654
  res.setHeader("Access-Control-Allow-Origin", "*");
@@ -9249,7 +9659,7 @@ function pluginSSRRemoteEntry(options) {
9249
9659
  if (id === remoteEntrySSRId || id.startsWith(remoteEntrySSRId)) return id;
9250
9660
  if (id === virtualExposesSSRId || id.startsWith(virtualExposesSSRId)) return id;
9251
9661
  if (id === `/__mf_ssr__/${getSsrRemoteEntryFileName(options.filename)}`) return remoteEntrySSRId;
9252
- if (id === `/__mf_ssr__/${options.filename.replace(/\.[^.]+$/, "")}.exposes.js`) return virtualExposesSSRId;
9662
+ if (id === `/__mf_ssr__/${ssrExposesFileName}`) return virtualExposesSSRId;
9253
9663
  },
9254
9664
  load(id) {
9255
9665
  if (id === remoteEntrySSRId || id.startsWith(remoteEntrySSRId)) return getSsrRemoteEntrySource();
@@ -9783,6 +10193,22 @@ function isFile(candidate) {
9783
10193
  function isReactRouterBuildClientRouteInput(entry) {
9784
10194
  return /[?&]__react-router-build-client-route(?:[=&]|$)/.test(entry);
9785
10195
  }
10196
+ /**
10197
+ * Files whose JSX the compiler rewrites to an automatic-runtime import.
10198
+ * Vite only applies the JSX transform to these extensions by default.
10199
+ */
10200
+ const JSX_SOURCE_EXTENSIONS = [".jsx", ".tsx"];
10201
+ function getAutomaticJsxRuntime(config) {
10202
+ for (const candidate of [config.oxc, config.esbuild]) {
10203
+ if (!candidate || typeof candidate !== "object") continue;
10204
+ const transform = candidate;
10205
+ const jsx = transform.jsx;
10206
+ const runtime = typeof jsx === "object" ? jsx.runtime : jsx;
10207
+ if (runtime && runtime !== "automatic") return void 0;
10208
+ if (runtime !== "automatic") continue;
10209
+ return `${(typeof jsx === "object" ? jsx.importSource : void 0) ?? transform.jsxImportSource ?? "react"}/${(typeof jsx === "object" ? jsx.development : void 0) ?? transform.jsxDev ?? true ? "jsx-dev-runtime" : "jsx-runtime"}`;
10210
+ }
10211
+ }
9786
10212
  function registerEntryImports(options, projectRoot, recordShared = true, entryFiles = []) {
9787
10213
  const sourceExtensions = [
9788
10214
  ".mjs",
@@ -9797,6 +10223,7 @@ function registerEntryImports(options, projectRoot, recordShared = true, entryFi
9797
10223
  const root = path$1.resolve(projectRoot);
9798
10224
  const pending = [];
9799
10225
  const visited = /* @__PURE__ */ new Map();
10226
+ let hasJsxSource = false;
9800
10227
  const enqueue = (request, importer = path$1.join(root, "index.html"), preloadRemotes = false) => {
9801
10228
  const cleanRequest = request.replace(/[?#].*$/, "");
9802
10229
  if (!cleanRequest.startsWith(".") && !cleanRequest.startsWith("/") && !path$1.isAbsolute(cleanRequest)) return;
@@ -9829,6 +10256,7 @@ function registerEntryImports(options, projectRoot, recordShared = true, entryFi
9829
10256
  if (visited.get(file) || visited.has(file) && !preloadRemotes) continue;
9830
10257
  visited.set(file, preloadRemotes);
9831
10258
  const code = getScannableModuleSource(file, readFileSync(file, "utf8"));
10259
+ if (JSX_SOURCE_EXTENSIONS.some((extension) => file.endsWith(extension))) hasJsxSource = true;
9832
10260
  for (const { source: request, kind, typeOnly } of findModuleImportDescriptors(code)) {
9833
10261
  const isStatic = kind === "static" && !typeOnly;
9834
10262
  const remoteKey = preloadRemotes && isStatic && request ? Object.keys(options.remotes).find((name) => request === name || request.startsWith(`${name}/`)) : void 0;
@@ -9841,6 +10269,14 @@ function registerEntryImports(options, projectRoot, recordShared = true, entryFi
9841
10269
  else if (request && !typeOnly) enqueue(request, file, preloadRemotes && isStatic);
9842
10270
  }
9843
10271
  }
10272
+ return hasJsxSource;
10273
+ }
10274
+ function materializeAutomaticJsxRuntime(options, runtime) {
10275
+ if (!findSharedKey(runtime, options.shared)) return false;
10276
+ addUsedShares(runtime, options);
10277
+ const packageName = getPackageName(runtime);
10278
+ if (packageName !== runtime && findSharedKey(packageName, options.shared)) addUsedShares(packageName, options);
10279
+ return true;
9844
10280
  }
9845
10281
  /**
9846
10282
  * Plugin that runs FIRST to register generated virtual modules in the config hook.
@@ -9850,6 +10286,7 @@ function registerEntryImports(options, projectRoot, recordShared = true, entryFi
9850
10286
  function createEarlyVirtualModulesPlugin(options) {
9851
10287
  const { shared, remotes } = options;
9852
10288
  const isLitShare = (pkg) => pkg === "lit" || pkg.startsWith("lit/");
10289
+ let hasClientJsxSource = false;
9853
10290
  return {
9854
10291
  name: "vite:module-federation-early-init",
9855
10292
  enforce: "pre",
@@ -9872,7 +10309,10 @@ function createEarlyVirtualModulesPlugin(options) {
9872
10309
  config.optimizeDeps.exclude.push(...Object.keys(remotes || {}));
9873
10310
  }
9874
10311
  }
9875
- if (!config.build?.ssr && (Object.keys(shared ?? {}).length > 0 || Object.keys(remotes ?? {}).length > 0)) registerEntryImports(options, root, _command === "serve", resolvedConfiguredEntryFiles);
10312
+ if (!config.build?.ssr && (Object.keys(shared ?? {}).length > 0 || Object.keys(remotes ?? {}).length > 0)) {
10313
+ const hasJsxSource = registerEntryImports(options, root, _command === "serve", resolvedConfiguredEntryFiles);
10314
+ if (_command === "serve") hasClientJsxSource = hasJsxSource;
10315
+ }
9876
10316
  if (shared && Object.keys(shared).length > 0) {
9877
10317
  if (_command === "serve") {
9878
10318
  excludeSharedSubDependencies(shared);
@@ -9900,6 +10340,8 @@ function createEarlyVirtualModulesPlugin(options) {
9900
10340
  if (isSharedResolverInternalImporter(importer)) return;
9901
10341
  const key = findSharedKey(source, shared);
9902
10342
  if (!key) return;
10343
+ const importerPackage = getSharedPackageFromFile(importer, shared, root);
10344
+ if (!isReactDomSelfReference(source, importer) && (importerPackage === getPackageName(key) || importerPackage && isSharedPackageDependency(key, importerPackage))) return;
9903
10345
  if (isAssetLikeImport(source)) return;
9904
10346
  const shareItem = shared[key];
9905
10347
  const isReactSingleton = source === "react" && key === "react" && shareItem.shareConfig?.singleton === true;
@@ -9938,7 +10380,9 @@ function createEarlyVirtualModulesPlugin(options) {
9938
10380
  if (isSharedResolverInternalImporter(args.importer)) return;
9939
10381
  const key = findSharedKey(args.path, shared);
9940
10382
  if (!key || isAssetLikeImport(args.path)) return;
9941
- if (getPackageNameFromNodeModulePath(args.importer) === getPackageName(args.path) && !isReactDomSelfReference(args.path, args.importer)) return;
10383
+ const importerPackage = getSharedPackageFromFile(args.importer, shared, root);
10384
+ if (importerPackage === getPackageName(args.path) && !isReactDomSelfReference(args.path, args.importer)) return;
10385
+ if (importerPackage && isSharedPackageDependency(key, importerPackage)) return;
9942
10386
  addUsedShares(args.path, options);
9943
10387
  if (args.kind === "import-statement" || args.kind === "dynamic-import") {
9944
10388
  const shareItem = shared[key];
@@ -10038,6 +10482,10 @@ export default __mfShared.default ?? __mfShared;`
10038
10482
  }
10039
10483
  },
10040
10484
  configResolved(config) {
10485
+ if (hasClientJsxSource) {
10486
+ const automaticJsxRuntime = getAutomaticJsxRuntime(config);
10487
+ if (automaticJsxRuntime && materializeAutomaticJsxRuntime(options, automaticJsxRuntime)) writeLocalSharedImportMap(options);
10488
+ }
10041
10489
  const viteMajor = parseInt(version, 10);
10042
10490
  const hasRemotes = Object.keys(options.remotes).length > 0;
10043
10491
  if (!getSsrCapabilities(viteMajor, config.command, hasRemotes).injectSsrEntryLoader) return;
@@ -10083,7 +10531,7 @@ function applyBuildTimeRuntimeDefines(define, options, { target, isAstro, defaul
10083
10531
  }
10084
10532
  function loadPluginDts(options) {
10085
10533
  if (options.dts === false) return [];
10086
- return [import("./pluginDts-C2bUY8h9.js").then(({ default: pluginDts }) => pluginDts(options))];
10534
+ return [import("./pluginDts-BhONN9dR.js").then(({ default: pluginDts }) => pluginDts(options))];
10087
10535
  }
10088
10536
  const INJECT_EXTERNAL_RUNTIME_CORE_PLUGIN = "@module-federation/vite/injectExternalRuntimeCorePlugin";
10089
10537
  function isInjectExternalRuntimeCorePlugin(specifier) {
@@ -10124,7 +10572,7 @@ function federation(mfUserOptions) {
10124
10572
  const virtualExposesId = getVirtualExposesId(options);
10125
10573
  const moduleParseController = createModuleParseController();
10126
10574
  const moduleParsePlugins = pluginModuleParseEnd_default((id) => {
10127
- return id.includes(getHostAutoInitPath(options)) || id.includes(remoteEntryId) || id.includes(virtualExposesId) || id.includes("virtual:mf-localSharedImportMap") || id.includes("__loadShare__") || id.includes("__prebuild__") || id.includes("__treeShakingProvider__") || id.includes("__mf_tree_shaking_graph__");
10575
+ return id.includes(getHostAutoInitPath(options)) || id.includes(getPendingSharesPath(options)) || id.includes(remoteEntryId) || id.includes(virtualExposesId) || id.includes("virtual:mf-localSharedImportMap") || id.includes("__loadShare__") || id.includes("__prebuild__") || id.includes("__treeShakingProvider__") || id.includes("__mf_tree_shaking_graph__");
10128
10576
  }, {
10129
10577
  moduleParseTimeout: options.moduleParseTimeout,
10130
10578
  moduleParseIdleTimeout: options.moduleParseIdleTimeout,
@@ -10226,6 +10674,7 @@ function federation(mfUserOptions) {
10226
10674
  }
10227
10675
  if (id.includes("__prebuild__") && refreshPreBuildModuleForEnvironment(id, this, loadOptions) === "not-owned") return;
10228
10676
  if (id.includes("__H_A_I__") && isOwnedHostAutoInitId(id, options)) refreshHostAutoInit(options, getLoadHookExportConditions(this, loadOptions));
10677
+ if (id.includes("__P_S__") && isOwnedPendingSharesId(id, options)) refreshPendingShares(options);
10229
10678
  const virtualModule = VirtualModule.findById(id);
10230
10679
  if (!virtualModule) return;
10231
10680
  if (command === "build" && (id.includes("__loadShare__") || id.includes("__loadRemote__"))) return;