@module-federation/vite 1.23.4 → 1.23.6

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 resolvePublicPath, a as matchesSharedSource, c as filterId, d as getNodeModulesSuffix, f as isAssetLikeImport, g as normalizeNodeModulePath, h as isViteOptimizableEntry, i as invalidateSharedKeyMatcher, l as getBasePath$1, m as isNuxtClientBase, n as getSharedRequest, p as isNodeModulePath, r as getSharedRuntimeKey, s as ensureTrailingSlash, t as findSharedKey, u as getCommonSharedSubpaths, v as stripQueryAndHash, y as stripViteFsPrefix } from "./sharedKeyMatcher-Od_nYxJA.js";
2
- import { a as CodeRewriter, c as isAbsoluteUrl, d as resolveHashPlaceholderFileName, i as createCodePositionMap, l as normalizePathForImport, o as createSourceMap, r as mfWarn, t as createModuleFederationError, u as rebaseImport } from "./logger-DOwfTlw5.js";
3
- import { C as isReactCoreShare, S as REACT_DOM_CLIENT_SHARE, _ as resolveModulePath, a as getIsRolldown, b as supportsCodeSplittingGroupDebugName, c as getPackageNameFromNodeModulePath, d as isNuxtProjectRoot, f as isPackageExportAvailable, g as resolveImportPath, h as packageNameEncode, i as getInstalledPackageJson, l as getSharedCacheDescriptor, m as packageNameDecode, n as getDependencyNames, o as getPackageDetectionCwd, p as isPackageInstalled, r as getInstalledPackageEntry, s as getPackageName, u as hasPackageDependency, v as setPackageDetectionCwd, x as REACT_CLIENT_INTERNALS_KEY, y as sharedCacheHelperCode } from "./dtsConstants-DSTzyKSG.js";
1
+ import { a as CodeRewriter, c as isAbsoluteUrl, d as rebaseImport, f as resolveHashPlaceholderFileName, i as createCodePositionMap, l as isHttpUrl, o as createSourceMap, r as mfWarn, t as createModuleFederationError, u as normalizePathForImport } from "./logger-D67aJYOe.js";
2
+ import { _ as removeTrailingSlash, a as matchesSharedSource, b as stripViteFsPrefix, c as filterId, d as getNodeModulesSuffix, f as isAssetLikeImport, g as normalizeNodeModulePath, h as isViteOptimizableEntry, i as invalidateSharedKeyMatcher, l as getBasePath$1, m as isNuxtClientBase, n as getSharedRequest, p as isNodeModulePath, r as getSharedRuntimeKey, s as ensureTrailingSlash, t as findSharedKey, u as getCommonSharedSubpaths, v as resolvePublicPath, x as toRelativeImport, y as stripQueryAndHash } from "./sharedKeyMatcher-C04bVN1q.js";
3
+ import { C as supportsCodeSplittingGroupDebugName, E as isReactCoreShare, S as sharedCacheHelperCode, T as REACT_DOM_CLIENT_SHARE, _ as packageNameDecode, a as getInstalledPackageEntry, b as resolveModulePath, c as getPackageDetectionCwd, d as getPackageNameFromNodeModulePath, f as getSharedCacheDescriptor, g as isPackageInstalled, h as isPackageExportAvailable, i as getDependencyNames, l as getPackageExportSpecifiersForFile, m as isNuxtProjectRoot, n as formatDevServerHostForOrigin, o as getInstalledPackageJson, p as hasPackageDependency, r as watchFileEvents, s as getIsRolldown, u as getPackageName, v as packageNameEncode, w as REACT_CLIENT_INTERNALS_KEY, x as setPackageDetectionCwd, y as resolveImportPath } from "./dtsConstants-CDuC8Bb7.js";
4
4
  import { createRequire } from "node:module";
5
5
  import * as fs$2 from "fs";
6
6
  import { existsSync, readFileSync, readdirSync, realpathSync, statSync, writeFileSync } from "fs";
@@ -14,7 +14,6 @@ import { createHash } from "node:crypto";
14
14
  import * as fs$1 from "node:fs";
15
15
  import { existsSync as existsSync$1, readFileSync as readFileSync$1 } from "node:fs";
16
16
  import { pathToFileURL as pathToFileURL$1 } from "node:url";
17
- import { isIPv6 } from "node:net";
18
17
  import { inferAutoPublicPath } from "@module-federation/sdk";
19
18
  import { readFile } from "node:fs/promises";
20
19
  //#region src/utils/regexEscape.ts
@@ -259,8 +258,8 @@ function getPluginEnvironmentName(ctx) {
259
258
  /**
260
259
  * Classify a plugin hook context's Vite environment. Environment names are
261
260
  * user-defined, so Vite's `config.consumer` is the semantic role; fall back to
262
- * the name only when it is missing (Vite 5–7). Returns `undefined` when the hook
263
- * has no environment context at all.
261
+ * the name only when it is missing. Returns `undefined` when the hook has no
262
+ * environment context at all (Vite 5).
264
263
  */
265
264
  function resolveEnvironmentConsumerTarget(ctx) {
266
265
  if (ctx == null || typeof ctx !== "object") return void 0;
@@ -271,7 +270,7 @@ function resolveEnvironmentConsumerTarget(ctx) {
271
270
  const envName = getPluginEnvironmentName(ctx);
272
271
  return !envName || envName === "client" ? "client" : "server";
273
272
  }
274
- /** Vite 5–7 hooks have no environment context and keep their client build behavior. */
273
+ /** Hooks without an environment context (Vite 5) keep their client build behavior. */
275
274
  function isClientEnvironment(ctx) {
276
275
  return resolveEnvironmentConsumerTarget(ctx) !== "server";
277
276
  }
@@ -721,6 +720,11 @@ function normalizeLibrary(library) {
721
720
  if (!library) return void 0;
722
721
  return library;
723
722
  }
723
+ /** An explicit `manifest.disableAssetsAnalyze` wins; otherwise `fallback` applies. */
724
+ function resolveDisableAssetsAnalyze(manifest, fallback) {
725
+ if (typeof manifest === "object" && manifest !== null && Object.hasOwn(manifest, "disableAssetsAnalyze")) return manifest.disableAssetsAnalyze === true;
726
+ return fallback;
727
+ }
724
728
  function normalizeManifest(manifest) {
725
729
  if (manifest === void 0) return;
726
730
  if (typeof manifest === "boolean") return manifest;
@@ -977,6 +981,16 @@ function getSsrCapabilities(viteMajor, command, hasRemotes, isSsr = false) {
977
981
  };
978
982
  }
979
983
  //#endregion
984
+ //#region src/utils/runtimePluginSpecifier.ts
985
+ function getRuntimePluginSpecifier(plugin) {
986
+ return typeof plugin === "string" ? plugin : plugin[0];
987
+ }
988
+ /** Drop SSR-only plugins from a client graph; a server graph keeps them all. */
989
+ function filterRuntimePluginsForTarget(runtimePlugins, ssrOnlySpecifiers, isServer) {
990
+ if (isServer) return [...runtimePlugins];
991
+ return runtimePlugins.filter((plugin) => !ssrOnlySpecifiers.has(getRuntimePluginSpecifier(plugin)));
992
+ }
993
+ //#endregion
980
994
  //#region src/utils/serializeRuntimeOptions.ts
981
995
  const UNSAFE_JS_CHAR_MAP = {
982
996
  "<": "\\u003C",
@@ -1074,16 +1088,6 @@ function isParsableExpression(source) {
1074
1088
  }
1075
1089
  }
1076
1090
  //#endregion
1077
- //#region src/utils/runtimePluginSpecifier.ts
1078
- function getRuntimePluginSpecifier(plugin) {
1079
- return typeof plugin === "string" ? plugin : plugin[0];
1080
- }
1081
- /** Drop SSR-only plugins from a client graph; a server graph keeps them all. */
1082
- function filterRuntimePluginsForTarget(runtimePlugins, ssrOnlySpecifiers, isServer) {
1083
- if (isServer) return [...runtimePlugins];
1084
- return runtimePlugins.filter((plugin) => !ssrOnlySpecifiers.has(getRuntimePluginSpecifier(plugin)));
1085
- }
1086
- //#endregion
1087
1091
  //#region src/utils/importAnalysis.ts
1088
1092
  const analysisByBuild = /* @__PURE__ */ new WeakMap();
1089
1093
  /**
@@ -1233,7 +1237,62 @@ function collectReExport(node, source, record, requireAllExports) {
1233
1237
  }
1234
1238
  record(names, source);
1235
1239
  }
1240
+ const NEEDS_AST_RE = /\brequire\s*(?:\?\.\s*)?(?:\(|\/[*/])|\bexport(?:\s|\/\*[^*]*\*+(?:[^/*][^*]*\*+)*\/|\/\/[^\n]*\n)*\{(?:\s|\/\*[^*]*\*+(?:[^/*][^*]*\*+)*\/|\/\/[^\n]*\n)*\}/;
1241
+ /**
1242
+ * Vite 8 parses with oxc, whose module record lists static imports, re-exports
1243
+ * and dynamic imports without materializing the AST. Same result as the AST
1244
+ * walk below; `undefined` when this input needs the AST.
1245
+ */
1246
+ function analyzeImportsFromModuleRecord(code) {
1247
+ const parseSync = vite.parseSync;
1248
+ if (typeof parseSync !== "function" || NEEDS_AST_RE.test(code)) return void 0;
1249
+ const result = parseSync("file.js", code, {
1250
+ lang: "js",
1251
+ preserveParens: false
1252
+ });
1253
+ if (result.errors.length > 0) return null;
1254
+ const { staticImports, staticExports, dynamicImports } = result.module;
1255
+ const found = [];
1256
+ const isStringName = (name) => name.start !== null && (code[name.start] === "\"" || code[name.start] === "'");
1257
+ const add = (start, source, names) => found.push({
1258
+ start,
1259
+ usage: {
1260
+ source,
1261
+ usedExports: names
1262
+ }
1263
+ });
1264
+ for (const declaration of staticImports) {
1265
+ const source = declaration.moduleRequest.value;
1266
+ let names = declaration.entries.length === 0 ? null : [];
1267
+ for (const { importName } of declaration.entries) if (importName.kind === "Default") names?.push("default");
1268
+ else if (importName.kind === "Name" && importName.name && !isStringName(importName)) names?.push(importName.name);
1269
+ else names = null;
1270
+ add(declaration.start, source, names);
1271
+ }
1272
+ const importStarts = new Set(staticImports.map((declaration) => declaration.start));
1273
+ for (const declaration of staticExports) {
1274
+ const request = declaration.entries[0]?.moduleRequest;
1275
+ if (!request || importStarts.has(declaration.start)) continue;
1276
+ const source = request.value;
1277
+ let names = [];
1278
+ for (const { importName } of declaration.entries) if (importName.kind === "Name" && importName.name && !isStringName(importName)) names?.push(importName.name);
1279
+ else names = null;
1280
+ add(declaration.start, source, names);
1281
+ }
1282
+ const dynamicStarts = /* @__PURE__ */ new Set();
1283
+ for (const { start, moduleRequest } of dynamicImports) {
1284
+ if (dynamicStarts.has(start)) continue;
1285
+ dynamicStarts.add(start);
1286
+ const text = code.slice(moduleRequest.start, moduleRequest.end);
1287
+ const quote = text[0];
1288
+ if (text.length >= 2 && (quote === "\"" || quote === "'" || quote === "`") && text.at(-1) === quote && !text.includes("\\") && !text.slice(1, -1).includes(quote) && !(quote === "`" && text.includes("${"))) add(start, text.slice(1, -1), null);
1289
+ else if (text.includes("\\")) return;
1290
+ }
1291
+ return found.sort((a, b) => a.start - b.start).map(({ usage }) => usage);
1292
+ }
1236
1293
  function analyzeImports(code) {
1294
+ const fromModuleRecord = analyzeImportsFromModuleRecord(code);
1295
+ if (fromModuleRecord !== void 0) return fromModuleRecord;
1237
1296
  let ast;
1238
1297
  try {
1239
1298
  ast = vite.parseAst(code);
@@ -1299,13 +1358,8 @@ function analyzeImports(code) {
1299
1358
  function shouldAnalyzeSharedExports(shareItem) {
1300
1359
  return !!(shareItem && (shareItem.shareConfig.treeShaking || shareItem.shareConfig.import === false));
1301
1360
  }
1302
- const legacyTreeShakingState = {
1303
- inferredUsage: /* @__PURE__ */ new Map(),
1304
- buildMode: false
1305
- };
1306
1361
  const treeShakingStates = /* @__PURE__ */ new WeakMap();
1307
1362
  function getTreeShakingState(options) {
1308
- if (!options) return legacyTreeShakingState;
1309
1363
  let state = treeShakingStates.get(options);
1310
1364
  if (!state) {
1311
1365
  state = {
@@ -1358,7 +1412,7 @@ function getExportRecords(sharedKey, request, options) {
1358
1412
  inferredUsage.forEach((byRequest, configuredKey) => {
1359
1413
  const wildcard = byRequest.get("*");
1360
1414
  const exact = byRequest.get(request);
1361
- const configuredRequest = getSharedRequest(configuredKey, options?.shared?.[configuredKey]);
1415
+ const configuredRequest = getSharedRequest(configuredKey, options.shared?.[configuredKey]);
1362
1416
  const keyBase = configuredRequest.endsWith("/") ? configuredRequest.slice(0, -1) : configuredRequest;
1363
1417
  const requestMatchesConfiguredKey = request === keyBase || request.startsWith(`${keyBase}/`);
1364
1418
  if (wildcard && requestMatchesConfiguredKey) records.push(wildcard);
@@ -1772,7 +1826,10 @@ function generateExposes(options, remoteDependencyMap = {}, command = "build", r
1772
1826
  link.rel = "stylesheet";
1773
1827
  link.href = href;
1774
1828
  link.onload = () => resolve();
1775
- link.onerror = () => reject(new Error(\`[Module Federation] Failed to load CSS asset: \${href}\`));
1829
+ link.onerror = () => {
1830
+ injectedCssHrefs.delete(href);
1831
+ reject(new Error(\`[Module Federation] Failed to load CSS asset: \${href}\`));
1832
+ };
1776
1833
  document.head.appendChild(link);
1777
1834
  });
1778
1835
  })
@@ -2034,24 +2091,6 @@ ${exportStatement}
2034
2091
  `);
2035
2092
  }
2036
2093
  //#endregion
2037
- //#region src/plugins/pluginReactMixedModeGuard.ts
2038
- function createReactMixedModeRuntimeGuard() {
2039
- return `const __mfReactInternals = mod[${JSON.stringify(REACT_CLIENT_INTERNALS_KEY)}];
2040
- if (__mfReactInternals && "A" in __mfReactInternals) {
2041
- let __mfReactDispatcher = __mfReactInternals.A;
2042
- Object.defineProperty(__mfReactInternals, "A", {
2043
- configurable: true,
2044
- enumerable: true,
2045
- get: () => __mfReactDispatcher,
2046
- set: (next) => {
2047
- if (next && typeof next.getOwner !== "function") next.getOwner = () => null;
2048
- __mfReactDispatcher = next;
2049
- },
2050
- });
2051
- __mfReactInternals.A = __mfReactDispatcher;
2052
- }`;
2053
- }
2054
- //#endregion
2055
2094
  //#region src/utils/typeArgumentScanner.ts
2056
2095
  function getTypeArgumentStartContext(source, start) {
2057
2096
  let previous = start - 1;
@@ -2220,6 +2259,9 @@ function escapeGeneratedStringLiteral(value) {
2220
2259
  }
2221
2260
  });
2222
2261
  }
2262
+ function getDefaultOrNamespaceExpression(namespace) {
2263
+ return `Reflect.get(${namespace}, "default") ?? ${namespace}`;
2264
+ }
2223
2265
  function getSharedCacheDescriptorLiteral(pkg, shareItem) {
2224
2266
  return JSON.stringify(getSharedCacheDescriptor(pkg, shareItem));
2225
2267
  }
@@ -2281,8 +2323,37 @@ function hasCodeMatch(source, regex, codePositions) {
2281
2323
  while ((match = regex.exec(source)) !== null) if (codePositions[match.index]) return true;
2282
2324
  return false;
2283
2325
  }
2326
+ /**
2327
+ * True when the file contains a top-level static `import`/`export` declaration.
2328
+ * Local identifiers named `module` or `exports` (webpack/rspack helpers,
2329
+ * function parameters, etc.) must not override that module format.
2330
+ */
2331
+ function hasEsmModuleSyntax(source, codePositions) {
2332
+ const keywordRegex = /(?<![$\w])(?:import|export)\b/g;
2333
+ let match;
2334
+ let braceDepth = 0;
2335
+ let braceScanIndex = 0;
2336
+ while ((match = keywordRegex.exec(source)) !== null) {
2337
+ for (; braceScanIndex < match.index; braceScanIndex++) {
2338
+ if (!codePositions[braceScanIndex]) continue;
2339
+ if (source[braceScanIndex] === "{") braceDepth++;
2340
+ else if (source[braceScanIndex] === "}") braceDepth--;
2341
+ }
2342
+ if (!codePositions[match.index]) continue;
2343
+ if (braceDepth !== 0) continue;
2344
+ let previousCodeIndex = match.index - 1;
2345
+ while (previousCodeIndex >= 0 && (/\s/.test(source[previousCodeIndex]) || !codePositions[previousCodeIndex])) previousCodeIndex--;
2346
+ if (source[previousCodeIndex] === ".") continue;
2347
+ let nextCodeIndex = match.index + match[0].length;
2348
+ while (nextCodeIndex < source.length && (/\s/.test(source[nextCodeIndex]) || !codePositions[nextCodeIndex])) nextCodeIndex++;
2349
+ if (source[nextCodeIndex] === "(") continue;
2350
+ return true;
2351
+ }
2352
+ return false;
2353
+ }
2284
2354
  function hasCommonJsExports(source) {
2285
2355
  const codePositions = createCodePositionMap(source);
2356
+ if (hasEsmModuleSyntax(source, codePositions)) return false;
2286
2357
  if (hasCodeMatch(source, /\bmodule\s*(?:\.exports|\[\s*['"]exports['"]\s*\])/g, codePositions)) return true;
2287
2358
  const exportsRegex = /\bexports\s*(?:\.|\[|[,)]|=(?!=|>))/g;
2288
2359
  let match;
@@ -2455,160 +2526,59 @@ function resolveReExportModule(filePath, specifier, exportConditions) {
2455
2526
  return;
2456
2527
  }
2457
2528
  }
2458
- /** Marks a template-literal frame whose text (not its interpolation) is being scanned. */
2459
- const TEMPLATE_TEXT = Symbol("templateText");
2460
2529
  function getAdditionalTopLevelDeclaratorNames(source, start, codePositions) {
2461
2530
  const names = [];
2462
2531
  let depth = 0;
2463
- let quote;
2464
- let escaped = false;
2465
- let canStartRegex = true;
2466
- const templateFrames = [];
2467
- const inTemplateText = () => templateFrames[templateFrames.length - 1] === TEMPLATE_TEXT;
2468
2532
  for (let index = start; index < source.length; index++) {
2469
2533
  const char = source[index];
2470
- if (inTemplateText()) {
2471
- if (escaped) escaped = false;
2472
- else if (char === "\\") escaped = true;
2473
- else if (char === "$" && source[index + 1] === "{") {
2474
- templateFrames.push(depth);
2475
- index++;
2476
- canStartRegex = true;
2477
- } else if (char === "`") {
2478
- templateFrames.pop();
2479
- canStartRegex = false;
2480
- }
2481
- continue;
2482
- }
2483
- if (quote) {
2484
- if (escaped) escaped = false;
2485
- else if (char === "\\") escaped = true;
2486
- else if (char === quote) quote = void 0;
2487
- continue;
2488
- }
2489
- if (char === "`") {
2490
- templateFrames.push(TEMPLATE_TEXT);
2491
- canStartRegex = false;
2492
- continue;
2493
- }
2494
- if (char === "\"" || char === "'") {
2495
- quote = char;
2496
- canStartRegex = false;
2497
- continue;
2498
- }
2534
+ if (!codePositions[index]) continue;
2499
2535
  if (char === "<" && source[index + 1] === "/") {
2500
2536
  const jsxClosingTag = source.slice(index).match(/^<\/\s*(?:[$_\p{ID_Start}][$_\u200C\u200D\p{ID_Continue}.:-]*\s*)?>/u);
2501
2537
  if (jsxClosingTag) {
2502
2538
  index += jsxClosingTag[0].length - 1;
2503
- canStartRegex = false;
2504
2539
  continue;
2505
2540
  }
2506
2541
  }
2507
- if (char === "/" && source[index + 1] === "/") {
2508
- index = source.indexOf("\n", index + 2);
2509
- if (index === -1) return names;
2510
- continue;
2511
- }
2512
- if (char === "/" && source[index + 1] === "*") {
2513
- const commentEnd = source.indexOf("*/", index + 2);
2514
- if (commentEnd === -1) return void 0;
2515
- index = commentEnd + 1;
2516
- continue;
2517
- }
2518
- if (char === "/" && canStartRegex) {
2519
- let regexEscaped = false;
2520
- let inCharacterClass = false;
2521
- let closed = false;
2522
- for (index++; index < source.length; index++) {
2523
- const regexChar = source[index];
2524
- if (regexEscaped) {
2525
- regexEscaped = false;
2526
- continue;
2527
- }
2528
- if (regexChar === "\\") {
2529
- regexEscaped = true;
2530
- continue;
2531
- }
2532
- if (regexChar === "[") {
2533
- inCharacterClass = true;
2534
- continue;
2535
- }
2536
- if (regexChar === "]" && inCharacterClass) {
2537
- inCharacterClass = false;
2538
- continue;
2539
- }
2540
- if (regexChar === "/" && !inCharacterClass) {
2541
- closed = true;
2542
- while (/[$_\p{ID_Continue}]/u.test(source[index + 1] || "")) index++;
2543
- break;
2544
- }
2545
- if (regexChar === "\n" || regexChar === "\r") return void 0;
2546
- }
2547
- if (!closed) return void 0;
2548
- canStartRegex = false;
2549
- continue;
2550
- }
2551
- if (char === "/") {
2552
- canStartRegex = true;
2553
- continue;
2554
- }
2555
2542
  if (/[$_\p{ID_Start}]/u.test(char)) {
2556
2543
  const tokenStart = index;
2557
2544
  while (/[$_\u200C\u200D\p{ID_Continue}]/u.test(source[index + 1] || "")) index++;
2558
2545
  const token = source.slice(tokenStart, index + 1);
2559
- if (depth === 0 && templateFrames.length === 0 && token === "export") {
2546
+ if (depth === 0 && token === "export") {
2560
2547
  let previous = tokenStart - 1;
2561
2548
  while (/\s/.test(source[previous] || "")) previous--;
2562
2549
  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;
2563
2550
  }
2564
- canStartRegex = /^(?:await|case|delete|in|instanceof|new|return|throw|typeof|void|yield)$/.test(token);
2565
2551
  continue;
2566
2552
  }
2567
2553
  if (/\d/.test(char)) {
2568
2554
  while (/[\w.]/.test(source[index + 1] || "")) index++;
2569
- canStartRegex = false;
2570
- continue;
2571
- }
2572
- if ((char === "+" || char === "-") && source[index + 1] === char) {
2573
- index++;
2574
2555
  continue;
2575
2556
  }
2576
- if (char === "!" && source[index + 1] !== "=") continue;
2577
2557
  if (char === "<") {
2578
2558
  const typeArgumentEnd = findLikelyTypeArgumentEnd(source, index, codePositions);
2579
2559
  if (typeArgumentEnd !== void 0) {
2580
2560
  index = typeArgumentEnd;
2581
- canStartRegex = false;
2582
2561
  continue;
2583
2562
  }
2584
2563
  }
2585
2564
  if (char === "(" || char === "[" || char === "{") {
2586
2565
  depth++;
2587
- canStartRegex = true;
2588
2566
  continue;
2589
2567
  }
2590
2568
  if (char === ")" || char === "]" || char === "}") {
2591
- if (char === "}" && templateFrames.length > 0 && templateFrames[templateFrames.length - 1] === depth) {
2592
- templateFrames.pop();
2593
- canStartRegex = false;
2594
- continue;
2595
- }
2596
2569
  depth = Math.max(0, depth - 1);
2597
- canStartRegex = false;
2598
2570
  continue;
2599
2571
  }
2600
- if (templateFrames.length === 0 && depth === 0 && char === ",") {
2572
+ if (depth === 0 && char === ",") {
2601
2573
  let bindingStart = index + 1;
2602
2574
  while (/\s/.test(source[bindingStart] || "")) bindingStart++;
2603
2575
  const binding = source.slice(bindingStart).match(new RegExp(`^(${JS_IDENTIFIER_PATTERN})`, "u"));
2604
2576
  if (!binding || !isValidEsmExportName(binding[1])) return void 0;
2605
2577
  names.push(binding[1]);
2606
2578
  index = bindingStart + binding[1].length - 1;
2607
- canStartRegex = false;
2608
2579
  continue;
2609
2580
  }
2610
- if (templateFrames.length === 0 && depth === 0 && char === ";") return names;
2611
- if (!/\s/.test(char)) canStartRegex = char !== ".";
2581
+ if (depth === 0 && char === ";") return names;
2612
2582
  }
2613
2583
  return names;
2614
2584
  }
@@ -2895,7 +2865,15 @@ function getWorkspacePackageJson(pkg) {
2895
2865
  fromResolvedEntry: resolved
2896
2866
  })?.packageJson;
2897
2867
  }
2868
+ const sharedDependencyGraphPackageJsonCache = /* @__PURE__ */ new Map();
2898
2869
  function getSharedDependencyGraphPackageJson(pkg) {
2870
+ const cacheKey = `${getPackageDetectionCwd()}\0${pkg}`;
2871
+ if (sharedDependencyGraphPackageJsonCache.has(cacheKey)) return sharedDependencyGraphPackageJsonCache.get(cacheKey);
2872
+ const packageJson = resolveSharedDependencyGraphPackageJson(pkg);
2873
+ sharedDependencyGraphPackageJsonCache.set(cacheKey, packageJson);
2874
+ return packageJson;
2875
+ }
2876
+ function resolveSharedDependencyGraphPackageJson(pkg) {
2899
2877
  const installedPackageJson = getInstalledPackageJson(pkg, { packageName: getPackageName(pkg) })?.packageJson;
2900
2878
  if (installedPackageJson) return installedPackageJson;
2901
2879
  try {
@@ -2904,7 +2882,16 @@ function getSharedDependencyGraphPackageJson(pkg) {
2904
2882
  } catch {}
2905
2883
  return getWorkspacePackageJson(pkg);
2906
2884
  }
2885
+ const sharedSingletonConsumedByPeerCache = /* @__PURE__ */ new WeakMap();
2907
2886
  function isSharedSingletonConsumedByPeer(pkg, options = getNormalizeModuleFederationOptions(), requireFederationRuntimeDependency = false) {
2887
+ if (!options) return computeSharedSingletonConsumedByPeer(pkg, options, requireFederationRuntimeDependency);
2888
+ let cache = sharedSingletonConsumedByPeerCache.get(options);
2889
+ if (!cache) sharedSingletonConsumedByPeerCache.set(options, cache = /* @__PURE__ */ new Map());
2890
+ const cacheKey = `${getPackageDetectionCwd()}\0${pkg}\0${requireFederationRuntimeDependency}`;
2891
+ if (!cache.has(cacheKey)) cache.set(cacheKey, computeSharedSingletonConsumedByPeer(pkg, options, requireFederationRuntimeDependency));
2892
+ return cache.get(cacheKey);
2893
+ }
2894
+ function computeSharedSingletonConsumedByPeer(pkg, options, requireFederationRuntimeDependency) {
2908
2895
  const shared = options?.shared || {};
2909
2896
  if (!requireFederationRuntimeDependency && Object.entries(shared).some(([key, item]) => key !== pkg && key.startsWith(`${pkg}/`) && item.shareConfig.singleton === true)) return true;
2910
2897
  const sharedKeyByPackageName = /* @__PURE__ */ new Map();
@@ -2984,24 +2971,9 @@ function resolveConcreteSharedImportSource(pkg, projectRoot) {
2984
2971
  }
2985
2972
  const TREE_SHAKING_PROVIDER_TAG = "__treeShakingProvider__";
2986
2973
  const TREE_SHAKING_GRAPH_QUERY = "__mf_tree_shaking_graph__";
2987
- const legacySharedVirtualModuleState = {
2988
- preBuildCacheMap: {},
2989
- preBuildShareItemMap: {},
2990
- treeShakingProviderCacheMap: {},
2991
- materializedTreeShakingProviders: /* @__PURE__ */ new Set(),
2992
- loadShareCacheMap: {},
2993
- warnedMissingImportFalse: /* @__PURE__ */ new Set(),
2994
- coalescableLoadShares: /* @__PURE__ */ new Set()
2995
- };
2996
2974
  const sharedVirtualModuleStates = /* @__PURE__ */ new WeakMap();
2997
2975
  const sharedVirtualModuleStatesByOwner = /* @__PURE__ */ new Map();
2998
2976
  function getSharedVirtualModuleState(options) {
2999
- if (!options) try {
3000
- const currentOptions = getNormalizeModuleFederationOptions();
3001
- return sharedVirtualModuleStates.get(currentOptions) ?? legacySharedVirtualModuleState;
3002
- } catch {
3003
- return legacySharedVirtualModuleState;
3004
- }
3005
2977
  let state = sharedVirtualModuleStates.get(options);
3006
2978
  if (!state) {
3007
2979
  state = {
@@ -3061,8 +3033,7 @@ function getConcreteTreeShakingExportUsage(pkg, shareItem, options) {
3061
3033
  return getTreeShakingExportUsage(pkg, shareItem, shareItem?.name, options);
3062
3034
  }
3063
3035
  function getTreeShakingSharedProviderName(pkg, options) {
3064
- const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
3065
- return `${getSharedVirtualModuleState(options).ownerKey ?? resolvedOptions.internalName ?? resolvedOptions.name}__tree_shaking__${packageNameEncode(pkg)}`;
3036
+ return `${getSharedVirtualModuleState(options).ownerKey ?? options.internalName ?? options.name}__tree_shaking__${packageNameEncode(pkg)}`;
3066
3037
  }
3067
3038
  function getTreeShakingSharedProviderImportId(pkg, options) {
3068
3039
  const { treeShakingProviderCacheMap } = getSharedVirtualModuleState(options);
@@ -3120,7 +3091,6 @@ export default { get, init };
3120
3091
  materializedTreeShakingProviders.add(pkg);
3121
3092
  }
3122
3093
  function writePreBuildLibPath(pkg, shareItem, options, exportConditions) {
3123
- const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
3124
3094
  const { preBuildCacheMap, preBuildShareItemMap } = getSharedVirtualModuleState(options);
3125
3095
  if (!preBuildCacheMap[pkg]) preBuildCacheMap[pkg] = createScopedSharedVirtualModule(pkg, PREBUILD_TAG, options);
3126
3096
  preBuildShareItemMap[pkg] = shareItem;
@@ -3149,9 +3119,8 @@ function writePreBuildLibPath(pkg, shareItem, options, exportConditions) {
3149
3119
  }
3150
3120
  if (pkg === "react/jsx-dev-runtime") {
3151
3121
  preBuildCacheMap[pkg].writeSync(`
3152
- import __mfPrebuildDefault from ${escapeGeneratedStringLiteral(importSource)};
3153
3122
  import * as __mfPrebuildNamespace from ${escapeGeneratedStringLiteral(importSource)};
3154
- const __mfPrebuildExports = __mfPrebuildDefault ?? __mfPrebuildNamespace;
3123
+ const __mfPrebuildExports = ${getDefaultOrNamespaceExpression("__mfPrebuildNamespace")};
3155
3124
  export const Fragment = __mfPrebuildExports.Fragment;
3156
3125
  export const jsxDEV = __mfPrebuildExports.jsxDEV;
3157
3126
  export default __mfPrebuildExports;
@@ -3160,9 +3129,8 @@ function writePreBuildLibPath(pkg, shareItem, options, exportConditions) {
3160
3129
  }
3161
3130
  if (pkg === "react/jsx-runtime") {
3162
3131
  preBuildCacheMap[pkg].writeSync(`
3163
- import __mfPrebuildDefault from ${escapeGeneratedStringLiteral(importSource)};
3164
3132
  import * as __mfPrebuildNamespace from ${escapeGeneratedStringLiteral(importSource)};
3165
- const __mfPrebuildExports = __mfPrebuildDefault ?? __mfPrebuildNamespace;
3133
+ const __mfPrebuildExports = ${getDefaultOrNamespaceExpression("__mfPrebuildNamespace")};
3166
3134
  export const Fragment = __mfPrebuildExports.Fragment;
3167
3135
  export const jsx = __mfPrebuildExports.jsx;
3168
3136
  export const jsxs = __mfPrebuildExports.jsxs;
@@ -3172,7 +3140,7 @@ function writePreBuildLibPath(pkg, shareItem, options, exportConditions) {
3172
3140
  }
3173
3141
  const namedExports = getSharedNamedExports(pkg, shareItem, exportConditions) ?? [];
3174
3142
  if (namedExports.length > 0) {
3175
- const mutableExports = new Set(isLocalOnlyContainer(resolvedOptions) ? getSharedMutableExports(pkg, shareItem, exportConditions) : []);
3143
+ const mutableExports = new Set(isLocalOnlyContainer(options) ? getSharedMutableExports(pkg, shareItem, exportConditions) : []);
3176
3144
  const copiedExports = namedExports.filter((name) => !mutableExports.has(name));
3177
3145
  const liveExports = namedExports.filter((name) => mutableExports.has(name));
3178
3146
  const namedExportVars = copiedExports.map((_name, i) => `__mf_${i}`);
@@ -3185,26 +3153,23 @@ function writePreBuildLibPath(pkg, shareItem, options, exportConditions) {
3185
3153
  ${declarations}
3186
3154
  ${namedExportLine}
3187
3155
  ${liveExportLine}
3188
- export default Reflect.get(__mfPrebuildNamespace, "default") ?? __mfPrebuildNamespace;
3156
+ export default ${getDefaultOrNamespaceExpression("__mfPrebuildNamespace")};
3189
3157
  `, true);
3190
3158
  return;
3191
3159
  }
3192
3160
  preBuildCacheMap[pkg].writeSync(`
3193
3161
  import * as __mfPrebuildExports from ${escapeGeneratedStringLiteral(importSource)};
3194
3162
  export * from ${escapeGeneratedStringLiteral(importSource)};
3195
- // Reflect access avoids bundler warnings for ESM packages without a
3196
- // default export (for example antd/es/index.js), while preserving the
3197
- // namespace fallback for packages that do provide one.
3198
- export default Reflect.get(__mfPrebuildExports, "default") ?? __mfPrebuildExports;
3163
+ export default ${getDefaultOrNamespaceExpression("__mfPrebuildExports")};
3199
3164
  `, true);
3200
3165
  }
3201
3166
  /** Re-render already materialized wrappers after import analysis discovers exports. */
3202
- function refreshTreeShakingModules(options, command = "build", isRolldown = false, exportConditions) {
3167
+ function refreshTreeShakingModules(options, command = "build", exportConditions) {
3203
3168
  const { preBuildShareItemMap } = getSharedVirtualModuleState(options);
3204
3169
  for (const [pkg, shareItem] of Object.entries(preBuildShareItemMap)) {
3205
3170
  if (!shareItem?.shareConfig.treeShaking) continue;
3206
3171
  writePreBuildLibPath(pkg, shareItem, options, exportConditions);
3207
- writeLoadShareModule(pkg, shareItem, command, isRolldown, options, exportConditions);
3172
+ writeLoadShareModule(pkg, shareItem, command, options, exportConditions);
3208
3173
  }
3209
3174
  }
3210
3175
  function getPreBuildLibImportId(pkg, options) {
@@ -3218,16 +3183,11 @@ function getPreBuildShareItem(pkg, options) {
3218
3183
  function getSharedImportSource(pkg, shareItem, options) {
3219
3184
  return getConcreteSharedImportSource(pkg, shareItem) || getPreBuildLibImportId(pkg, options);
3220
3185
  }
3221
- function getLoadShareImportId(pkg, _isRolldown, options) {
3186
+ function getLoadShareModulePath(pkg, options) {
3222
3187
  const { loadShareCacheMap } = getSharedVirtualModuleState(options);
3223
3188
  if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = createScopedSharedVirtualModule(pkg, LOAD_SHARE_TAG, options);
3224
3189
  return loadShareCacheMap[pkg].getImportId();
3225
3190
  }
3226
- function getLoadShareModulePath(pkg, isRolldown, options) {
3227
- const { loadShareCacheMap } = getSharedVirtualModuleState(options);
3228
- if (!loadShareCacheMap[pkg]) getLoadShareImportId(pkg, isRolldown, options);
3229
- return loadShareCacheMap[pkg].getImportId();
3230
- }
3231
3191
  function getCachedSharedVirtualPkg(id, tag) {
3232
3192
  if (!id.includes(tag)) return;
3233
3193
  const normalized = normalizeVirtualModuleId(id);
@@ -3251,7 +3211,7 @@ function materializeCachedLoadShareModule(options) {
3251
3211
  const key = options.findSharedKey(pkg, options.shared);
3252
3212
  if (!key) return;
3253
3213
  const shareItem = options.shared[key];
3254
- writeLoadShareModule(pkg, shareItem, options.command, options.isRolldown, options.federationOptions);
3214
+ writeLoadShareModule(pkg, shareItem, options.command, options.federationOptions);
3255
3215
  if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(pkg, shareItem, options.federationOptions);
3256
3216
  options.addUsedShares(pkg);
3257
3217
  options.writeLocalSharedImportMap();
@@ -3356,6 +3316,7 @@ function generateLazyWorkspaceSingletonExports(edges, namedExports, importSource
3356
3316
  const trackPendingLoad = `__mfTrackPendingShareLoad(${deferredEntryFallback ? deferredEntryLoad : deferredInitLoad});`;
3357
3317
  return `${declarations}
3358
3318
  const __mfApplyLazyShareExports = (mod) => {
3319
+ exportModule = mod;
3359
3320
  ${assignments}
3360
3321
  };
3361
3322
  __mfSubscribeSharedCache(__mfModuleCache.share, ${cacheDescriptor}, __mfApplyLazyShareExports);
@@ -3369,7 +3330,7 @@ function generateLazyWorkspaceSingletonExports(edges, namedExports, importSource
3369
3330
  } else {
3370
3331
  __mfApplyLazyShareExports(exportModule);
3371
3332
  }
3372
- export { __mf_default as default };${namedExportLine}${mutableExportLine}`;
3333
+ export { __mf_default as default, exportModule as __moduleExports };${namedExportLine}${mutableExportLine}`;
3373
3334
  }
3374
3335
  const WORKSPACE_SINGLETON_SSR_LOCAL_SHARE = "__mfNormalizeShareModule(__mfLocalShare)";
3375
3336
  function prependWorkspaceSingletonSsrImport(code) {
@@ -3495,23 +3456,37 @@ function markLoadShareWrapperNotCoalescable(pkg, options, id) {
3495
3456
  function isCoalescableLoadShareWrapper(pkg, options, id) {
3496
3457
  return getSharedVirtualModuleStateForId(id, options).coalescableLoadShares.has(pkg);
3497
3458
  }
3498
- function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exportConditions, importFalseExportUsage) {
3499
- const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
3459
+ /** Keeps runtime-shared React dispatchers usable when a mixed-mode remote swaps them in. */
3460
+ const REACT_MIXED_MODE_GUARD = `const __mfReactInternals = mod[${JSON.stringify(REACT_CLIENT_INTERNALS_KEY)}];
3461
+ if (__mfReactInternals && "A" in __mfReactInternals) {
3462
+ let __mfReactDispatcher = __mfReactInternals.A;
3463
+ Object.defineProperty(__mfReactInternals, "A", {
3464
+ configurable: true,
3465
+ enumerable: true,
3466
+ get: () => __mfReactDispatcher,
3467
+ set: (next) => {
3468
+ if (next && typeof next.getOwner !== "function") next.getOwner = () => null;
3469
+ __mfReactDispatcher = next;
3470
+ },
3471
+ });
3472
+ __mfReactInternals.A = __mfReactDispatcher;
3473
+ }`;
3474
+ function writeLoadShareModule(pkg, shareItem, command, options, exportConditions, importFalseExportUsage) {
3500
3475
  const { loadShareCacheMap, coalescableLoadShares } = getSharedVirtualModuleState(options);
3501
3476
  const edges = createLocalPayloadEdges();
3502
3477
  if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = createScopedSharedVirtualModule(pkg, LOAD_SHARE_TAG, options);
3503
3478
  let importLine = getRuntimeModuleCacheBootstrapCode(exportConditions);
3504
3479
  const cacheDescriptor = getSharedCacheDescriptorLiteral(pkg, shareItem);
3505
- const cacheOwner = JSON.stringify(resolvedOptions.name);
3506
- const runtimeInitOwnerImportId = options ? getRuntimeInitStatusImportId(options) : void 0;
3507
- const treeShakingConsumer = command === "build" && shareItem.shareConfig.treeShaking ? resolvedOptions.name : void 0;
3480
+ const cacheOwner = JSON.stringify(options.name);
3481
+ const runtimeInitOwnerImportId = getRuntimeInitStatusImportId(options);
3482
+ const treeShakingConsumer = command === "build" && shareItem.shareConfig.treeShaking ? options.name : void 0;
3508
3483
  if (shareItem.shareConfig.import === false) {
3509
3484
  const detectedNamedExports = getPackageNamedExports(pkg, exportConditions);
3510
3485
  const namedExports = selectImportFalseNamedExports(detectedNamedExports, importFalseExportUsage);
3511
3486
  let exportLine;
3512
3487
  if (namedExports.length > 0) exportLine = generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor, treeShakingConsumer);
3513
3488
  else {
3514
- const { warnedMissingImportFalse } = getSharedVirtualModuleState(resolvedOptions);
3489
+ const { warnedMissingImportFalse } = getSharedVirtualModuleState(options);
3515
3490
  if (detectedNamedExports === void 0 && !shareItem.shareConfig.suppressMissingImportWarning && !warnedMissingImportFalse.has(pkg)) {
3516
3491
  warnedMissingImportFalse.add(pkg);
3517
3492
  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.`);
@@ -3537,20 +3512,22 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3537
3512
  const skipServePrebuildWarmup = command !== "build" && (pkg === "lit" || pkg.startsWith("lit/"));
3538
3513
  const detectedNamedExports = getSharedNamedExports(pkg, shareItem, exportConditions);
3539
3514
  const namedExports = detectedNamedExports ?? [];
3540
- const mutableExports = new Set(isLocalOnlyContainer(resolvedOptions) ? getSharedMutableExports(pkg, shareItem, exportConditions) : []);
3515
+ const mutableExports = new Set(isLocalOnlyContainer(options) ? getSharedMutableExports(pkg, shareItem, exportConditions) : []);
3541
3516
  const copiedNamedExports = namedExports.filter((name) => !mutableExports.has(name));
3542
3517
  const liveNamedExports = namedExports.filter((name) => mutableExports.has(name));
3543
3518
  const liveNamedExportLine = edges.reExportNames(liveNamedExports, sharedImportSource);
3544
3519
  const hasCompleteExportCoverage = detectedNamedExports !== void 0;
3545
- const isWorkspaceSingleton = isWorkspacePackage && shareItem.shareConfig.singleton === true;
3546
- const usesDeferredSingletonFallback = hasCompleteExportCoverage && shareItem.shareConfig.eager !== true && (isWorkspacePackage || command !== "build" && isRemoteOnlyContainer(resolvedOptions) && shareItem.shareConfig.singleton === true || command === "build" && isRemoteContainer(resolvedOptions) && !isSharedSingletonConsumedByPeer(pkg, resolvedOptions, true));
3547
- const servesRemoteSingletonFallback = command !== "build" && isRemoteOnlyContainer(resolvedOptions) && shareItem.shareConfig.singleton === true;
3548
- const isConsumedByPeerSingleton = isSharedSingletonConsumedByPeer(pkg, resolvedOptions);
3549
- const usesEntryInjectedRemoteFallback = hasCompleteExportCoverage && !isWorkspaceSingleton && isRemoteContainer(resolvedOptions) && shareItem.shareConfig.singleton === true && resolvedOptions.hostInitInjectLocation === "entry" && (command === "build" || isConsumedByPeerSingleton);
3550
- const usesDeferredEntryInjectedSingletonFallback = usesEntryInjectedRemoteFallback && !isReactCoreShare(pkg) && (pkg === "react-dom/client" || shareItem.shareConfig.eager !== true && !isSharedSingletonConsumedByPeer(pkg, resolvedOptions, true));
3520
+ const isSingleton = shareItem.shareConfig.singleton === true;
3521
+ const isWorkspaceSingleton = isWorkspacePackage && isSingleton;
3522
+ const usesDeferredSingletonFallback = hasCompleteExportCoverage && shareItem.shareConfig.eager !== true && (isWorkspacePackage || command !== "build" && isRemoteOnlyContainer(options) && isSingleton || command === "build" && isRemoteContainer(options) && !isSharedSingletonConsumedByPeer(pkg, options, true));
3523
+ const servesRemoteSingletonFallback = command !== "build" && isRemoteOnlyContainer(options) && isSingleton;
3524
+ const isConsumedByPeerSingleton = isSharedSingletonConsumedByPeer(pkg, options);
3525
+ const usesEntryInjectedRemoteFallback = hasCompleteExportCoverage && !isWorkspaceSingleton && isRemoteContainer(options) && isSingleton && options.hostInitInjectLocation === "entry" && (command === "build" || isConsumedByPeerSingleton);
3526
+ const usesDeferredEntryInjectedSingletonFallback = usesEntryInjectedRemoteFallback && !isReactCoreShare(pkg) && (pkg === "react-dom/client" || shareItem.shareConfig.eager !== true && !isSharedSingletonConsumedByPeer(pkg, options, true));
3551
3527
  const usesEagerWorkspaceFallback = hasCompleteExportCoverage && isWorkspaceSingleton && !servesRemoteSingletonFallback && (isConsumedByPeerSingleton || shareItem.shareConfig.eager === true);
3552
3528
  const usesDeferredTreeShakingFallback = hasCompleteExportCoverage && Boolean(treeShakingConsumer);
3553
- const reactMixedModeGuard = pkg === "react" ? createReactMixedModeRuntimeGuard() : "";
3529
+ const rebindsSharedExports = isSingleton || options.shareStrategy === "version-first";
3530
+ const reactMixedModeGuard = pkg === "react" && isSingleton ? REACT_MIXED_MODE_GUARD : "";
3554
3531
  let exportLine;
3555
3532
  let initBlock = "";
3556
3533
  if (usesDeferredTreeShakingFallback) {
@@ -3575,7 +3552,7 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3575
3552
  ${edges.reExportAll(coherentLocalSource)}`;
3576
3553
  initBlock = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
3577
3554
  __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});`;
3578
- } else if (namedExports.length > 0 && shareItem.shareConfig.singleton === true) {
3555
+ } else if (namedExports.length > 0 && rebindsSharedExports) {
3579
3556
  const namedExportVars = copiedNamedExports.map((_name, i) => `__mf_${i}`);
3580
3557
  exportLine = `${["let __mfDefaultExport;", ...namedExportVars.map((name) => `let ${name};`)].join("\n ")}
3581
3558
  const __mfApplySharedExports = (mod) => {
@@ -3614,7 +3591,7 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3614
3591
  ${liveNamedExportLine}`;
3615
3592
  initBlock = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
3616
3593
  __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});`;
3617
- } else if (shareItem.shareConfig.singleton === true) {
3594
+ } else if (rebindsSharedExports) {
3618
3595
  exportLine = `let __mfDefaultExport;
3619
3596
  const __mfApplySharedDefaultExport = (mod) => {
3620
3597
  ${reactMixedModeGuard}
@@ -3634,7 +3611,7 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3634
3611
  const staticLocalShareSource = detectedNamedExports === void 0 ? coherentLocalSource : skipServePrebuildWarmup ? devImportSource : sharedImportSource;
3635
3612
  const prebuildImportLine = usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback ? "" : usesDeferredSingletonFallback || usesDeferredTreeShakingFallback ? !servesRemoteSingletonFallback && usesDeferredSingletonFallback && command !== "build" && (isWorkspaceSingleton || isWorkspacePackage) ? edges.importNamespace(lazyLocalFallbackSource) : "" : edges.importNamespace(staticLocalShareSource);
3636
3613
  const devDynamicImportLine = isWorkspacePackage ? "" : usesDeferredSingletonFallback || usesDeferredTreeShakingFallback || usesDeferredEntryInjectedSingletonFallback ? "" : command !== "build" && !skipServePrebuildWarmup ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
3637
- const cacheHelpers = recordCoalescability(pkg, edges.none, command, shareItem.shareConfig, coalescableLoadShares) ? getSharedCacheHelpersImportCode(resolvedOptions) : sharedCacheHelperCode;
3614
+ const cacheHelpers = recordCoalescability(pkg, edges.none, command, shareItem.shareConfig, coalescableLoadShares) ? getSharedCacheHelpersImportCode(options) : sharedCacheHelperCode;
3638
3615
  const moduleBody = usesDeferredSingletonFallback || usesDeferredTreeShakingFallback || usesDeferredEntryInjectedSingletonFallback || usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback ? `
3639
3616
  ${usesDeferredEntryInjectedSingletonFallback ? "" : prebuildImportLine}
3640
3617
  ${devDynamicImportLine}
@@ -3659,10 +3636,9 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3659
3636
  }
3660
3637
  //#endregion
3661
3638
  //#region src/virtualModules/virtualRemoteEntry.ts
3662
- let usedShares = /* @__PURE__ */ new Set();
3663
3639
  const usedSharesByOptions = /* @__PURE__ */ new WeakMap();
3664
3640
  const materializedSharesByOptions = /* @__PURE__ */ new WeakMap();
3665
- function getScopedUsedShares(options) {
3641
+ function getUsedShares(options) {
3666
3642
  let scoped = usedSharesByOptions.get(options);
3667
3643
  if (!scoped) {
3668
3644
  scoped = /* @__PURE__ */ new Set();
@@ -3670,25 +3646,17 @@ function getScopedUsedShares(options) {
3670
3646
  }
3671
3647
  return scoped;
3672
3648
  }
3673
- function getUsedShares(options) {
3674
- if (options) return getScopedUsedShares(options);
3675
- return usedShares;
3676
- }
3677
3649
  function addUsedShares(pkg, options) {
3678
- usedShares.add(pkg);
3679
- if (options) getScopedUsedShares(options).add(pkg);
3680
- if (options) {
3681
- let scoped = materializedSharesByOptions.get(options);
3682
- if (!scoped) {
3683
- scoped = /* @__PURE__ */ new Set();
3684
- materializedSharesByOptions.set(options, scoped);
3685
- }
3686
- scoped.add(pkg);
3650
+ getUsedShares(options).add(pkg);
3651
+ let scoped = materializedSharesByOptions.get(options);
3652
+ if (!scoped) {
3653
+ scoped = /* @__PURE__ */ new Set();
3654
+ materializedSharesByOptions.set(options, scoped);
3687
3655
  }
3656
+ scoped.add(pkg);
3688
3657
  }
3689
3658
  function addConfiguredShare(pkg, options) {
3690
- usedShares.add(pkg);
3691
- if (options) getScopedUsedShares(options).add(pkg);
3659
+ getUsedShares(options).add(pkg);
3692
3660
  }
3693
3661
  const LOCAL_SHARED_IMPORT_MAP_ID = "virtual:mf-localSharedImportMap";
3694
3662
  const LAZY_CONSUME_ONLY_SHARES_PLACEHOLDER = "__MF_LAZY_CONSUME_ONLY_SHARES__";
@@ -3710,15 +3678,13 @@ function getLocalSharedImportMapPath(options) {
3710
3678
  function getResolvedLocalSharedImportMapId(options) {
3711
3679
  return `\0${getLocalSharedImportMapPath(options)}`;
3712
3680
  }
3713
- let invalidateLocalSharedImportMap;
3714
3681
  const localSharedImportMapInvalidators = /* @__PURE__ */ new WeakMap();
3715
3682
  function setLocalSharedImportMapInvalidator(invalidator, options) {
3716
- if (!options) invalidateLocalSharedImportMap = invalidator;
3717
- else if (invalidator) localSharedImportMapInvalidators.set(options, invalidator);
3683
+ if (invalidator) localSharedImportMapInvalidators.set(options, invalidator);
3718
3684
  else localSharedImportMapInvalidators.delete(options);
3719
3685
  }
3720
3686
  function writeLocalSharedImportMap(options) {
3721
- (options ? localSharedImportMapInvalidators.get(options) : invalidateLocalSharedImportMap)?.();
3687
+ localSharedImportMapInvalidators.get(options)?.();
3722
3688
  }
3723
3689
  function shouldUseDirectReactImport() {
3724
3690
  const isVinext = hasPackageDependency("vinext");
@@ -3739,15 +3705,15 @@ function getDirectSharedCacheSeedImportPath(pkg, shareItem) {
3739
3705
  function generateLocalSharedImportMap(options) {
3740
3706
  const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
3741
3707
  const useDirectReactImport = shouldUseDirectReactImport();
3742
- const orderedShares = getOrderedUsedShares(options);
3743
- const sharesToMaterialize = new Set(getMaterializedShares(options));
3708
+ const orderedShares = getOrderedUsedShares(resolvedOptions);
3709
+ const sharesToMaterialize = new Set(getMaterializedShares(resolvedOptions));
3744
3710
  const hasConsumeOnlyShare = orderedShares.some((pkg) => getNormalizeShareItem(pkg, resolvedOptions)?.shareConfig.import === false);
3745
3711
  return `
3746
3712
  import {loadShare} from "@module-federation/runtime";
3747
3713
  ${orderedShares.map((pkg, index) => {
3748
3714
  const shareItem = getNormalizeShareItem(pkg, resolvedOptions);
3749
3715
  if (!shareItem || !shareItem.shareConfig.eager || shareItem.shareConfig.import === false) return "";
3750
- return `import * as __mfEagerShare_${index} from ${toSafeJsLiteral(getLocalSharedPackagePath(pkg, shareItem, options))};`;
3716
+ return `import * as __mfEagerShare_${index} from ${toSafeJsLiteral(getLocalSharedPackagePath(pkg, shareItem, resolvedOptions))};`;
3751
3717
  }).filter(Boolean).join("\n")}
3752
3718
  ${normalizeRuntimeShareCode}
3753
3719
  const __mfGetCachedReactFamily = (keys, reactKeys, localVersion, requiredExport) => {
@@ -3769,7 +3735,24 @@ function generateLocalSharedImportMap(options) {
3769
3735
  // A host seed from an older React family is not coherent with the newer cached react
3770
3736
  const cachedVersion = cached?.version ?? cached?.default?.version;
3771
3737
  if (cachedVersion !== undefined && isOlder(cachedVersion)) continue;
3772
- if (!requiredExport || typeof cached?.[requiredExport] === 'function' || typeof cached?.default?.[requiredExport] === 'function') return cached;
3738
+ if (!requiredExport || typeof cached?.[requiredExport] === 'function' || typeof cached?.default?.[requiredExport] === 'function') {
3739
+ const dom = typeof cached?.[requiredExport] === 'function' ? cached : cached?.default;
3740
+ const internals = dom?.__SECRET_INTERNALS_DO_NOT_USE_OR_YOU_WILL_BE_FIRED;
3741
+ if (!requiredExport || key.endsWith('/client') || !internals) return cached;
3742
+ // React 18 root: mirror react-dom/client.js, or createRoot warns it was imported from "react-dom"
3743
+ const client = {};
3744
+ for (const name of ['createRoot', 'hydrateRoot']) {
3745
+ client[name] = (...args) => {
3746
+ internals.usingClientEntryPoint = true;
3747
+ try {
3748
+ return dom[name](...args);
3749
+ } finally {
3750
+ internals.usingClientEntryPoint = false;
3751
+ }
3752
+ };
3753
+ }
3754
+ return { ...client, default: client };
3755
+ }
3773
3756
  }
3774
3757
  return undefined;
3775
3758
  };
@@ -3803,7 +3786,7 @@ function generateLocalSharedImportMap(options) {
3803
3786
  return `
3804
3787
  ${toSafeJsLiteral(pkg)}: async () => {
3805
3788
  ${shareItem?.shareConfig.eager ? `let pkg = __mfEagerShare_${index};
3806
- return pkg;` : `let pkg = await import(${toSafeJsLiteral(getLocalSharedPackagePath(pkg, shareItem, options))});
3789
+ return pkg;` : `let pkg = await import(${toSafeJsLiteral(getLocalSharedPackagePath(pkg, shareItem, resolvedOptions))});
3807
3790
  return pkg;`}
3808
3791
  }
3809
3792
  `;
@@ -3827,11 +3810,11 @@ function generateLocalSharedImportMap(options) {
3827
3810
  const treeShakingConfig = canLiveRebind ? shareItem.shareConfig.treeShaking : void 0;
3828
3811
  if (shareItem.shareConfig.import === false && !treeShakingConfig) return `
3829
3812
  ${toSafeJsLiteral(key)}: __mfConsumeOnly(${toSafeJsLiteral(key)}, ${toSafeJsLiteral(shareItem.version)}, ${toSafeJsLiteral(shareItem.scope)}, ${sharesToMaterialize.has(key)}, {singleton: ${shareItem.shareConfig.singleton}, requiredVersion: ${toSafeJsLiteral(shareItem.shareConfig.requiredVersion)}, strictVersion: ${shareItem.shareConfig.strictVersion}, eager: ${Boolean(shareItem.shareConfig.eager)}, ${shareItem.shareConfig.request !== void 0 ? `request: ${toSafeJsLiteral(shareItem.shareConfig.request)},` : ""} ${shareItem.shareConfig.shareKey !== void 0 ? `shareKey: ${toSafeJsLiteral(shareItem.shareConfig.shareKey)},` : ""}})`;
3830
- const treeShakingUsage = treeShakingConfig ? getTreeShakingExportUsage(key, shareItem, shareItem.name, options) : void 0;
3813
+ const treeShakingUsage = treeShakingConfig ? getTreeShakingExportUsage(key, shareItem, shareItem.name, resolvedOptions) : void 0;
3831
3814
  const treeShakingProviderExports = treeShakingUsage?.kind === "exports" ? treeShakingUsage.usedExports : [];
3832
3815
  const treeShakingUsedExports = resolvedOptions.injectTreeShakingUsedExports === false ? treeShakingConfig?.usedExports || [] : treeShakingProviderExports;
3833
3816
  const disableRuntimeInference = treeShakingConfig?.mode === "runtime-infer" && resolvedOptions.injectTreeShakingUsedExports === false;
3834
- const treeShakingProviderImportId = treeShakingConfig && !disableRuntimeInference && hasTreeShakingSharedProvider(key, shareItem, options) ? getTreeShakingSharedProviderImportId(key, options) : void 0;
3817
+ const treeShakingProviderImportId = treeShakingConfig && !disableRuntimeInference && hasTreeShakingSharedProvider(key, shareItem, resolvedOptions) ? getTreeShakingSharedProviderImportId(key, resolvedOptions) : void 0;
3835
3818
  const treeShakingStatus = treeShakingUsage?.kind === "full" || disableRuntimeInference || treeShakingConfig?.mode === "runtime-infer" && !treeShakingProviderImportId && shareItem.shareConfig.import !== false ? 0 : 1;
3836
3819
  return `
3837
3820
  ${toSafeJsLiteral(key)}: {
@@ -3916,7 +3899,7 @@ function generateLocalSharedImportMap(options) {
3916
3899
  `;
3917
3900
  }).filter((x) => x !== null).join(",")}
3918
3901
  }
3919
- const usedRemotes = [${Object.keys(getUsedRemotesMap(options)).map((key) => {
3902
+ const usedRemotes = [${Object.keys(getUsedRemotesMap(resolvedOptions)).map((key) => {
3920
3903
  const remote = resolvedOptions.remotes[key];
3921
3904
  if (!remote) return null;
3922
3905
  return `
@@ -3949,30 +3932,27 @@ function expandSharedPrefixKey(prefixKey, used) {
3949
3932
  return [...expanded];
3950
3933
  }
3951
3934
  function getOrderedUsedShares(options) {
3952
- const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
3953
3935
  const used = getUsedShares(options);
3954
3936
  const shares = /* @__PURE__ */ new Set();
3955
3937
  const addShare = (pkg) => {
3956
- const shareItem = getNormalizeShareItem(pkg, resolvedOptions);
3938
+ const shareItem = getNormalizeShareItem(pkg, options);
3957
3939
  shares.add(shareItem ? getCanonicalSharedKey(pkg, shareItem) : pkg);
3958
3940
  };
3959
3941
  used.forEach(addShare);
3960
- Object.keys(resolvedOptions.shared ?? {}).forEach((pkg) => {
3961
- const share = resolvedOptions.shared?.[pkg];
3942
+ Object.keys(options.shared ?? {}).forEach((pkg) => {
3943
+ const share = options.shared?.[pkg];
3962
3944
  if (share && !getSharedRequest(pkg, share).endsWith("/")) addShare(pkg);
3963
3945
  });
3964
- for (const [pkg, share] of Object.entries(resolvedOptions.shared ?? {})) if (share.shareConfig?.eager && getSharedRequest(pkg, share).endsWith("/")) for (const concrete of expandSharedPrefixKey(getSharedRequest(pkg, share), used)) addShare(concrete);
3946
+ for (const [pkg, share] of Object.entries(options.shared ?? {})) if (share.shareConfig?.eager && getSharedRequest(pkg, share).endsWith("/")) for (const concrete of expandSharedPrefixKey(getSharedRequest(pkg, share), used)) addShare(concrete);
3965
3947
  return orderSharedDependenciesFirst(Array.from(shares).sort((a, b) => {
3966
3948
  const priority = (pkg) => pkg === "react" ? 0 : pkg === "react-dom" ? 1 : pkg.startsWith("react/") ? 2 : 3;
3967
3949
  return priority(a) - priority(b) || a.localeCompare(b);
3968
3950
  }));
3969
3951
  }
3970
3952
  function getMaterializedShares(options) {
3971
- const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
3972
- const scopedRegistrations = options ? usedSharesByOptions.get(options) : void 0;
3973
- const shares = new Set(options && scopedRegistrations?.size ? materializedSharesByOptions.get(options) ?? [] : usedShares);
3974
- const usedForEager = options ? usedSharesByOptions.get(options) ?? [] : usedShares;
3975
- for (const [pkg, share] of Object.entries(resolvedOptions.shared ?? {})) {
3953
+ const shares = new Set(materializedSharesByOptions.get(options));
3954
+ const usedForEager = usedSharesByOptions.get(options) ?? [];
3955
+ for (const [pkg, share] of Object.entries(options.shared ?? {})) {
3976
3956
  if (!share.shareConfig?.eager) continue;
3977
3957
  const request = getSharedRequest(pkg, share);
3978
3958
  if (request.endsWith("/")) for (const concrete of expandSharedPrefixKey(request, usedForEager)) shares.add(concrete);
@@ -3986,17 +3966,18 @@ function getMaterializedShares(options) {
3986
3966
  const pending = [...shares];
3987
3967
  while (pending.length) {
3988
3968
  const pkg = pending.pop();
3989
- const share = getNormalizeShareItem(pkg, resolvedOptions);
3969
+ const share = getNormalizeShareItem(pkg, options);
3990
3970
  const packageName = getPackageName(pkg);
3991
3971
  const packageJson = getInstalledPackageJson(pkg)?.packageJson ?? (pkg !== packageName ? getInstalledPackageJson(packageName)?.packageJson : void 0);
3992
3972
  const dependencies = {
3993
3973
  ...packageJson?.dependencies || {},
3994
3974
  ...packageJson?.peerDependencies || {},
3995
- ...packageJson?.optionalDependencies || {}
3975
+ ...packageJson?.optionalDependencies || {},
3976
+ ...packageJson?.peerDependenciesMeta || {}
3996
3977
  };
3997
3978
  for (const dependency of Object.keys(dependencies)) {
3998
3979
  const sharedDependency = configured.get(dependency);
3999
- const dependencyShare = sharedDependency ? getNormalizeShareItem(sharedDependency, resolvedOptions) : void 0;
3980
+ const dependencyShare = sharedDependency ? getNormalizeShareItem(sharedDependency, options) : void 0;
4000
3981
  if (sharedDependency && !shares.has(sharedDependency) && dependencyShare?.scope === share?.scope) {
4001
3982
  shares.add(sharedDependency);
4002
3983
  pending.push(sharedDependency);
@@ -4008,7 +3989,7 @@ function getMaterializedShares(options) {
4008
3989
  return priority(a) - priority(b) || a.localeCompare(b);
4009
3990
  });
4010
3991
  return orderSharedDependenciesFirst([...new Set(sorted.map((pkg) => {
4011
- const shareItem = getNormalizeShareItem(pkg, resolvedOptions);
3992
+ const shareItem = getNormalizeShareItem(pkg, options);
4012
3993
  return shareItem ? getCanonicalSharedKey(pkg, shareItem) : pkg;
4013
3994
  }))]);
4014
3995
  }
@@ -4028,7 +4009,8 @@ function getSharePrerequisites(ordered) {
4028
4009
  const dependencies = {
4029
4010
  ...packageJson?.dependencies || {},
4030
4011
  ...packageJson?.peerDependencies || {},
4031
- ...packageJson?.optionalDependencies || {}
4012
+ ...packageJson?.optionalDependencies || {},
4013
+ ...packageJson?.peerDependenciesMeta || {}
4032
4014
  };
4033
4015
  const prerequisites = Object.keys(dependencies).map((dependency) => roots.get(dependency)).filter((dependency) => Boolean(dependency));
4034
4016
  if (pkg !== packageName && (packageName === "react" || packageName === "react-dom")) {
@@ -4072,7 +4054,8 @@ function orderSharedDependenciesFirst(sharedPackages) {
4072
4054
  const dependencies = {
4073
4055
  ...packageJson?.dependencies || {},
4074
4056
  ...packageJson?.peerDependencies || {},
4075
- ...packageJson?.optionalDependencies || {}
4057
+ ...packageJson?.optionalDependencies || {},
4058
+ ...packageJson?.peerDependenciesMeta || {}
4076
4059
  };
4077
4060
  Object.keys(dependencies).forEach((dependency) => {
4078
4061
  const sharedDependency = sharedKeyByPackageName.get(dependency);
@@ -4312,21 +4295,33 @@ const externalSharedProviderSelectionHelperCode = `const __mfSelectExternalShare
4312
4295
  /**
4313
4296
  * A consume-only stub never outranks a provider: when registering this container's
4314
4297
  * `import: false` share replaces an unloaded provider of the same version (#1311),
4315
- * the `afterRegisterShare` hook restores the provider. Registered once per instance.
4298
+ * the `afterRegisterShare` hook restores the provider, and a provider kept out by an
4299
+ * unloaded stub takes its slot. Registered once per instance.
4316
4300
  */
4317
4301
  function generateKeepProvidersOverStubsCode(runtimeVar) {
4318
4302
  return `if (!${runtimeVar}.__mfKeepAdoptedProviders) {
4319
4303
  ${runtimeVar}.__mfKeepAdoptedProviders = true;
4320
4304
  ${runtimeVar}.sharedHandler?.hooks?.lifecycle?.afterRegisterShare?.on?.((args) => {
4321
4305
  const { shared, previousShared, registeredShared } = args || {};
4306
+ const versions = ${runtimeVar}.shareScopeMap?.[args.scope]?.[args.pkgName];
4307
+ if (!shared || !versions) return;
4308
+ // The reverse: a stub already in the slot (e.g. a loaded-first parent's) keeps a provider
4309
+ // out, and a webpack consumer reading the scope then falls back to its own copy.
4310
+ if (shared.shareConfig?.import !== false) {
4311
+ if (
4312
+ registeredShared !== shared &&
4313
+ registeredShared?.shareConfig?.import === false &&
4314
+ !registeredShared.loaded &&
4315
+ versions[shared.version] === registeredShared
4316
+ ) versions[shared.version] = shared;
4317
+ return;
4318
+ }
4322
4319
  if (
4323
- shared?.shareConfig?.import !== false ||
4324
4320
  registeredShared !== shared ||
4325
4321
  !previousShared ||
4326
4322
  previousShared.shareConfig?.import === false
4327
4323
  ) return;
4328
- const versions = ${runtimeVar}.shareScopeMap?.[args.scope]?.[args.pkgName];
4329
- if (versions && versions[shared.version] === shared) versions[shared.version] = previousShared;
4324
+ if (versions[shared.version] === shared) versions[shared.version] = previousShared;
4330
4325
  });
4331
4326
  }`;
4332
4327
  }
@@ -4408,6 +4403,19 @@ function generateRuntimeSharedCacheSeedCode(shareStrategy, options, command = "b
4408
4403
  );
4409
4404
  return;
4410
4405
  }
4406
+ // A Vite container seeds its own copy into the module cache before the Runtime
4407
+ // marks its provider loaded. A non-singleton is cached under its version, so
4408
+ // look the selected provider's copy up under that version, not this share's.
4409
+ if (!share.shareConfig?.singleton && typeof externalProvider.version === 'string') {
4410
+ const externalCached = __mfReadSharedCache(
4411
+ __mfModuleCache.share,
4412
+ __mfGetSharedCacheDescriptor(pkg, false, externalProvider.version, share.scope)
4413
+ );
4414
+ if (externalCached !== undefined) {
4415
+ __mfWriteSharedCache(__mfModuleCache.share, cacheDescriptor, externalCached, externalProvider.from);
4416
+ return;
4417
+ }
4418
+ }
4411
4419
  // Leave an unloaded webpack provider to the late bridge, which only takes a
4412
4420
  // non-singleton of this share's own version; any other version seeds locally.
4413
4421
  if (
@@ -4510,17 +4518,16 @@ function generateRuntimeSharedCacheSeedCode(shareStrategy, options, command = "b
4510
4518
  var __mfDeferredSeedKeys = __mfSeedKeys.filter(
4511
4519
  (pkg) => __mfPreInitBlockedSeedKeys.has(__mfSeedIndex.get(pkg))
4512
4520
  );
4513
- await __mfSeedLocalShared(__mfImmediateSeedKeys);`;
4521
+ await __mfSeedLocalShared(__mfImmediateSeedKeys).catch(__mfRejectInit);`;
4514
4522
  }
4515
4523
  function getBrowserImportPath(importPath) {
4516
4524
  if (/^(?:[a-zA-Z]:[\\/]|\/)/.test(importPath) && !importPath.startsWith("/@")) return `/@fs/${importPath}`;
4517
4525
  return importPath;
4518
4526
  }
4519
4527
  function getHostAutoInitSharedSeedItems(options) {
4520
- const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
4521
4528
  return getMaterializedShares(options).map((pkg) => ({
4522
4529
  pkg,
4523
- shareItem: getShareItemForPreload(pkg, resolvedOptions)
4530
+ shareItem: getShareItemForPreload(pkg, options)
4524
4531
  })).filter(({ shareItem }) => shareItem?.shareConfig?.import === false).sort((a, b) => {
4525
4532
  const priority = (pkg) => pkg === "vue" ? 0 : pkg === "pinia" ? 1 : 2;
4526
4533
  const aIsLocal = !!getLocalProviderImportPath(a.pkg);
@@ -4531,7 +4538,7 @@ function getHostAutoInitSharedSeedItems(options) {
4531
4538
  function generateHostAutoInitSharedCacheSeedCode(command = "build", options) {
4532
4539
  if (command === "build") return "";
4533
4540
  const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
4534
- return getHostAutoInitSharedSeedItems(options).map(({ pkg, shareItem }) => {
4541
+ return getHostAutoInitSharedSeedItems(resolvedOptions).map(({ pkg, shareItem }) => {
4535
4542
  if (!shareItem) return null;
4536
4543
  return generateSharedCacheSeedItem(pkg, shareItem, getBrowserImportPath(getDirectSharedCacheSeedImportPath(pkg, shareItem)), resolvedOptions);
4537
4544
  }).filter((item) => item !== null).join("\n");
@@ -4761,7 +4768,12 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
4761
4768
  ${runtimeHelperImports.length ? `import {${runtimeHelperImports.join(", ")}} from "@module-federation/runtime/helpers";` : ""}
4762
4769
  ${pluginImportNames.filter((item) => !isSsrOnlyPlugin(item[1])).map((item) => item[1]).join("\n")}
4763
4770
  import __mfExposesMap from "${virtualExposesId}"
4764
- ${command === "build" ? getRuntimeInitResolveBootstrapCode(false, getRuntimeInitStatusImportId(options)) : getRuntimeInitBootstrapCode(false, getRuntimeInitStatusImportId(options), void 0, void 0, exportConditions) + "\n const { initResolve } = globalThis[globalKey];"}
4771
+ ${command === "build" ? getRuntimeInitResolveBootstrapCode(false, getRuntimeInitStatusImportId(options)) + "\n const { initReject } = __mfResolveState;" : getRuntimeInitBootstrapCode(false, getRuntimeInitStatusImportId(options), void 0, void 0, exportConditions) + "\n const { initResolve, initReject } = globalThis[globalKey];"}
4772
+ // A failed seed must settle initPromise, or every pending share load hangs forever.
4773
+ const __mfRejectInit = (err) => {
4774
+ initReject(err);
4775
+ throw err;
4776
+ };
4765
4777
  ${getRuntimeModuleCacheBootstrapCode(exportConditions)}
4766
4778
  const initTokens = {}
4767
4779
  const shareScopeNames = Array.isArray(${toSafeJsLiteral(options.shareScope)}) ? ${toSafeJsLiteral(options.shareScope)} : [${toSafeJsLiteral(options.shareScope)}]
@@ -5655,7 +5667,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
5655
5667
  __mfReadyDeferredSeedKeys.push(...__mfDeferredSeedKeys.filter(
5656
5668
  (pkg) => !__mfBlockedSeedKeys.has(__mfSeedIndex.get(pkg))
5657
5669
  ));
5658
- await __mfSeedLocalShared(__mfReadyDeferredSeedKeys);
5670
+ await __mfSeedLocalShared(__mfReadyDeferredSeedKeys).catch(__mfRejectInit);
5659
5671
  ${command === "build" ? `// A consume-only share reached only through import() is bridged when that import runs
5660
5672
  // (see pluginLazyConsumeOnlyShares), through the same provider selection init() uses.
5661
5673
  const __mfLazyShareLoads = new Map();
@@ -5712,13 +5724,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
5712
5724
  */
5713
5725
  const HOST_AUTO_INIT_TAG = "__H_A_I__";
5714
5726
  const hostAutoInitStates = /* @__PURE__ */ new WeakMap();
5715
- const legacyHostAutoInitState = {
5716
- module: new VirtualModule("hostAutoInit", HOST_AUTO_INIT_TAG),
5717
- remoteEntryId: REMOTE_ENTRY_ID,
5718
- command: "build"
5719
- };
5720
5727
  function getHostAutoInitState(options) {
5721
- if (!options) return legacyHostAutoInitState;
5722
5728
  let state = hostAutoInitStates.get(options);
5723
5729
  if (!state) {
5724
5730
  const ownerKey = getLocalOwnerKey(options);
@@ -5734,7 +5740,7 @@ function getHostAutoInitState(options) {
5734
5740
  function generateHostAutoInitCode(remoteEntryImport, _command = "build", options, exportConditions) {
5735
5741
  const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
5736
5742
  const shouldPreloadShares = resolvedOptions.shareStrategy !== "loaded-first";
5737
- const hostInitShareBatches = toSafeJsLiteral(getShareBatches(options, false));
5743
+ const hostInitShareBatches = toSafeJsLiteral(getShareBatches(resolvedOptions, false));
5738
5744
  const cacheOwner = toSafeJsLiteral(resolvedOptions.name);
5739
5745
  const preferLocalVinextReact = hasPackageDependency("vinext") && (!exportConditions?.includes("browser") || exportConditions.includes("worker"));
5740
5746
  const hasConfiguredShared = hasShared(resolvedOptions);
@@ -5778,6 +5784,15 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build", options
5778
5784
  )
5779
5785
  );
5780
5786
  const __mfHostInitShareBatches = ${hostInitShareBatches};
5787
+ // The baked batches are generated before the build has seen every import, so a
5788
+ // share first used later in the graph, such as react-dom/client, is missing from
5789
+ // them. Negotiate those after the baked batches, once their package roots have
5790
+ // settled (#1503).
5791
+ {
5792
+ const bakedKeys = new Set(__mfHostInitShareBatches.flat());
5793
+ const lateKeys = Object.keys(usedShared).filter((pkg) => !bakedKeys.has(pkg));
5794
+ if (lateKeys.length) __mfHostInitShareBatches.push(lateKeys);
5795
+ }
5781
5796
  ${hostInitSharedProviderHelperCode}
5782
5797
  for (const __mfHostInitShareBatch of __mfHostInitShareBatches) {
5783
5798
  await Promise.all(__mfHostInitShareBatch.map(async (pkg) => {
@@ -5792,9 +5807,10 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build", options
5792
5807
  if (
5793
5808
  __mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined &&
5794
5809
  ${_command === "serve" ? `__mfReadSharedCacheOwner(__mfModuleCache.share, cacheDescriptor) !== undefined &&
5795
- !(share.shareConfig?.singleton && __mfHasAlternativeSharedVersion(pkg, share))` : `(
5796
- (!share.shareConfig?.singleton && __mfReadSharedCacheOwner(__mfModuleCache.share, cacheDescriptor) === ${cacheOwner}) ||
5797
- (share.shareConfig?.singleton && !__mfHasAlternativeSharedVersion(pkg, share))
5810
+ !__mfHasAlternativeSharedVersion(pkg, share)` : `(
5811
+ !__mfHasAlternativeSharedVersion(pkg, share) &&
5812
+ (share.shareConfig?.singleton ||
5813
+ __mfReadSharedCacheOwner(__mfModuleCache.share, cacheDescriptor) === ${cacheOwner})
5798
5814
  )`}
5799
5815
  ) return;
5800
5816
  // An import:false share has nothing to load until a foreign provider
@@ -5884,7 +5900,7 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build", options
5884
5900
  export { initHost, hostInitPromise };
5885
5901
  `;
5886
5902
  }
5887
- function writeHostAutoInit(remoteEntryId = REMOTE_ENTRY_ID, command = "build", options, exportConditions) {
5903
+ function writeHostAutoInit(remoteEntryId = REMOTE_ENTRY_ID, command, options, exportConditions) {
5888
5904
  const state = getHostAutoInitState(options);
5889
5905
  state.remoteEntryId = remoteEntryId;
5890
5906
  state.command = command;
@@ -5912,13 +5928,8 @@ function isOwnedHostAutoInitId(id, options) {
5912
5928
  * free of wrapper references.
5913
5929
  */
5914
5930
  const PENDING_SHARES_TAG = "__P_S__";
5915
- const legacyPendingSharesState = {
5916
- module: new VirtualModule("pendingShares", PENDING_SHARES_TAG),
5917
- command: "build"
5918
- };
5919
5931
  const pendingSharesStates = /* @__PURE__ */ new WeakMap();
5920
5932
  function getPendingSharesState(options) {
5921
- if (!options) return legacyPendingSharesState;
5922
5933
  let state = pendingSharesStates.get(options);
5923
5934
  if (!state) {
5924
5935
  state = {
@@ -5931,14 +5942,14 @@ function getPendingSharesState(options) {
5931
5942
  }
5932
5943
  function generatePendingSharesCode(command = "build", options) {
5933
5944
  const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
5934
- const pendingSharePkgs = command === "build" ? getMaterializedShares(options).filter((pkg) => {
5945
+ const pendingSharePkgs = command === "build" ? getMaterializedShares(resolvedOptions).filter((pkg) => {
5935
5946
  const shareItem = getShareItemForPreload(pkg, resolvedOptions);
5936
5947
  if (!shareItem || pkg.endsWith("/")) return false;
5937
5948
  if (shareItem.shareConfig.eager) return false;
5938
5949
  return shareItem.shareConfig.import !== false && !shareItem.shareConfig.treeShaking;
5939
5950
  }) : [];
5940
5951
  if (command === "build" && shouldPreloadEntryDeferredReactDomClient(resolvedOptions) && !pendingSharePkgs.includes("react-dom/client")) pendingSharePkgs.push(REACT_DOM_CLIENT_SHARE);
5941
- const pendingShareImports = pendingSharePkgs.map((pkg) => `[${toSafeJsLiteral(pkg)}, () => import(${toSafeJsLiteral(getLoadShareModulePath(pkg, false, options))})]`);
5952
+ const pendingShareImports = pendingSharePkgs.map((pkg) => `[${toSafeJsLiteral(pkg)}, () => import(${toSafeJsLiteral(getLoadShareModulePath(pkg, resolvedOptions))})]`);
5942
5953
  return `
5943
5954
  ${getRuntimeModuleCacheBootstrapCode()}
5944
5955
  ${sharedCacheHelperCode}
@@ -5964,7 +5975,7 @@ function generatePendingSharesCode(command = "build", options) {
5964
5975
  }
5965
5976
  `;
5966
5977
  }
5967
- function writePendingShares(command = "build", options) {
5978
+ function writePendingShares(command, options) {
5968
5979
  const state = getPendingSharesState(options);
5969
5980
  state.command = command;
5970
5981
  state.module.writeSync(generatePendingSharesCode(command, options), true);
@@ -6023,20 +6034,11 @@ function refreshRemoteModuleForEnvironment(id, options, exportConditions) {
6023
6034
  virtual.write(generateRemotes(metadata.remote, metadata.command, metadata.enableSsrInit, metadata.consumer, options, exportConditions));
6024
6035
  return true;
6025
6036
  }
6026
- const usedRemotesMap = {};
6027
6037
  const usedRemotesByOptions = /* @__PURE__ */ new WeakMap();
6028
6038
  const dynamicRemotesByOptions = /* @__PURE__ */ new WeakMap();
6029
6039
  const staticRemotesByOptions = /* @__PURE__ */ new WeakMap();
6030
6040
  const preloadRemotesByOptions = /* @__PURE__ */ new WeakMap();
6031
6041
  const EMPTY_STATIC_REMOTES = /* @__PURE__ */ new Set();
6032
- function getScopedUsedRemotesMap(options) {
6033
- let scoped = usedRemotesByOptions.get(options);
6034
- if (!scoped) {
6035
- scoped = {};
6036
- usedRemotesByOptions.set(options, scoped);
6037
- }
6038
- return scoped;
6039
- }
6040
6042
  function recordUsedRemote(map, remoteKey, remoteModule) {
6041
6043
  ensureUsedRemoteKey(map, remoteKey).add(remoteModule);
6042
6044
  }
@@ -6045,16 +6047,18 @@ function ensureUsedRemoteKey(map, remoteKey) {
6045
6047
  return map[remoteKey];
6046
6048
  }
6047
6049
  function ensureUsedRemote(remoteKey, options) {
6048
- ensureUsedRemoteKey(usedRemotesMap, remoteKey);
6049
- if (options) ensureUsedRemoteKey(getScopedUsedRemotesMap(options), remoteKey);
6050
+ ensureUsedRemoteKey(getUsedRemotesMap(options), remoteKey);
6050
6051
  }
6051
6052
  function addUsedRemote(remoteKey, remoteModule, options) {
6052
- recordUsedRemote(usedRemotesMap, remoteKey, remoteModule);
6053
- if (options) recordUsedRemote(getScopedUsedRemotesMap(options), remoteKey, remoteModule);
6053
+ recordUsedRemote(getUsedRemotesMap(options), remoteKey, remoteModule);
6054
6054
  }
6055
6055
  function getUsedRemotesMap(options) {
6056
- if (options) return getScopedUsedRemotesMap(options);
6057
- return usedRemotesMap;
6056
+ let usedRemotes = usedRemotesByOptions.get(options);
6057
+ if (!usedRemotes) {
6058
+ usedRemotes = {};
6059
+ usedRemotesByOptions.set(options, usedRemotes);
6060
+ }
6061
+ return usedRemotes;
6058
6062
  }
6059
6063
  function markDynamicRemote(remote, options) {
6060
6064
  let remotes = dynamicRemotesByOptions.get(options);
@@ -6124,12 +6128,6 @@ function getEagerDeferredClientInit() {
6124
6128
  return `__mfRemotePending = __mfStartRemoteLoad().then(__mfAssignRemoteModule);
6125
6129
  exportModule = __mfCreateDeferredRemoteProxy();`;
6126
6130
  }
6127
- function shouldIncludeDeferredProxy(initMode, consumer, eagerLoadClientRemote, deferRemoteLoad) {
6128
- if (eagerLoadClientRemote && consumer !== "server") return true;
6129
- if (initMode === "eager") return consumer !== "server" && (consumer === "unified" || !eagerLoadClientRemote);
6130
- if (consumer === "client" && eagerLoadClientRemote) return false;
6131
- return deferRemoteLoad || consumer !== "server";
6132
- }
6133
6131
  /** Codegen shared by every remote virtual module (no top-level await). */
6134
6132
  function getRemoteModuleRuntimeHelpers() {
6135
6133
  return `
@@ -6170,12 +6168,16 @@ function getDeferredProxyHelper(remoteCacheKey) {
6170
6168
  function __mfCreateDeferredRemoteProxy() {
6171
6169
  let pendingPromise;
6172
6170
  const ensurePending = () => {
6173
- pendingPromise ||= __mfStartRemoteLoad();
6171
+ if (!pendingPromise) {
6172
+ pendingPromise = __mfStartRemoteLoad();
6173
+ // Property reads can start a load without an awaiter to handle failure.
6174
+ pendingPromise.then(undefined, () => { pendingPromise = undefined; });
6175
+ }
6174
6176
  return pendingPromise;
6175
6177
  };
6176
6178
  const getModule = () => __mfModuleCache.remote[${JSON.stringify(remoteCacheKey)}];
6177
6179
  const proxyTarget = function (...args) {
6178
- pendingPromise ||= __mfStartRemoteLoad();
6180
+ ensurePending();
6179
6181
  const mod = getModule();
6180
6182
  const fn = mod && (mod.default ?? mod);
6181
6183
  if (fn !== undefined && fn !== null) {
@@ -6194,7 +6196,7 @@ function getDeferredProxyHelper(remoteCacheKey) {
6194
6196
  if (mod) {
6195
6197
  return prop in mod ? mod[prop] : mod.default?.[prop];
6196
6198
  }
6197
- pendingPromise ||= __mfStartRemoteLoad();
6199
+ ensurePending();
6198
6200
  if (prop === "default") return proxyTarget;
6199
6201
  throw ensurePending();
6200
6202
  },
@@ -6234,9 +6236,19 @@ function getDeferredProxyHelper(remoteCacheKey) {
6234
6236
  }`;
6235
6237
  }
6236
6238
  function getLazyRemotePendingExport() {
6237
- return `export const __mf_remote_pending = __mfRemotePending ?? {
6239
+ return `function __mfResetFailedRemotePending(pending) {
6240
+ pending.then(undefined, () => {
6241
+ if (__mfRemotePending === pending) __mfRemotePending = undefined;
6242
+ });
6243
+ }
6244
+ if (__mfRemotePending) __mfResetFailedRemotePending(__mfRemotePending);
6245
+ export const __mf_remote_pending = {
6238
6246
  then(onFulfilled, onRejected) {
6239
- return (__mfRemotePending ??= __mfStartRemoteLoad().then(__mfAssignRemoteModule)).then(onFulfilled, onRejected);
6247
+ if (!__mfRemotePending) {
6248
+ __mfRemotePending = __mfStartRemoteLoad().then(__mfAssignRemoteModule);
6249
+ __mfResetFailedRemotePending(__mfRemotePending);
6250
+ }
6251
+ return __mfRemotePending.then(onFulfilled, onRejected);
6240
6252
  },
6241
6253
  };`;
6242
6254
  }
@@ -6296,12 +6308,11 @@ export { __mfDefaultExport as default };`;
6296
6308
  function generateRemotes(id, command, enableSsrInit = false, consumer = "unified", options, exportConditions) {
6297
6309
  const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
6298
6310
  const isLoadedFirst = resolvedOptions.shareStrategy === "loaded-first";
6299
- const initMode = resolveRemoteInitMode(resolvedOptions.shareStrategy, consumer);
6300
- const deferRemoteLoad = shouldDeferRemoteLoad(initMode);
6311
+ const deferRemoteLoad = shouldDeferRemoteLoad(resolveRemoteInitMode(resolvedOptions.shareStrategy, consumer));
6301
6312
  const runtimeRemoteId = getRuntimeRemoteId(id, resolvedOptions.remotes, options);
6302
6313
  const remoteRegistration = getRemoteRegistration(id, resolvedOptions.remotes, options);
6303
6314
  const registerRemoteCode = isLoadedFirst && remoteRegistration ? `runtime.registerRemotes([${JSON.stringify(remoteRegistration)}]);` : "";
6304
- const hostAutoInitPath = getHostAutoInitPath(options);
6315
+ const hostAutoInitPath = getHostAutoInitPath(resolvedOptions);
6305
6316
  const ssrRemotes = getSsrRuntimeRemotes(resolvedOptions.remotes, options);
6306
6317
  const browserHostInitCode = `import(${JSON.stringify(hostAutoInitPath)})
6307
6318
  .then((mod) => mod.hostInitPromise)
@@ -6314,20 +6325,13 @@ function generateRemotes(id, command, enableSsrInit = false, consumer = "unified
6314
6325
  ${command === "serve" && consumer !== "server" ? browserHostInitCode : ""}`;
6315
6326
  const remoteLoadRuntimePromise = command === "build" ? "__mfHostInitPromise()" : "initPromise";
6316
6327
  const remoteCacheKey = `${getRuntimeRemoteCachePrefix(options)}${id}`;
6317
- const remoteLoadFailureHandler = command === "build" ? `.catch((error) => {
6318
- delete __mfModuleCache.remote[pendingKey];
6319
- throw error;
6320
- })` : `.catch((error) => {
6321
- delete __mfModuleCache.remote[pendingKey];
6322
- throw error;
6323
- })`;
6324
6328
  const remoteLoadCode = `
6325
6329
  function __mfStartRemoteLoad() {
6326
6330
  ${`
6327
6331
  const remoteCacheKey = ${JSON.stringify(remoteCacheKey)};
6328
6332
  const pendingKey = "__mf_pending__" + remoteCacheKey;
6329
6333
  if (!__mfModuleCache.remote[pendingKey]) {
6330
- __mfModuleCache.remote[pendingKey] = ${remoteLoadRuntimePromise}
6334
+ const pending = ${remoteLoadRuntimePromise}
6331
6335
  .then((runtime) => {
6332
6336
  ${registerRemoteCode}
6333
6337
  const moduleCacheKey = Symbol.for(${JSON.stringify(MODULE_CACHE_SHARE_SCOPE_KEY)});
@@ -6344,22 +6348,25 @@ function generateRemotes(id, command, enableSsrInit = false, consumer = "unified
6344
6348
  delete __mfModuleCache.remote[pendingKey];
6345
6349
  return mod;
6346
6350
  })
6347
- ${remoteLoadFailureHandler};
6351
+ .catch((error) => {
6352
+ if (__mfModuleCache.remote[pendingKey] === pending) {
6353
+ delete __mfModuleCache.remote[pendingKey];
6354
+ }
6355
+ throw error;
6356
+ });
6357
+ __mfModuleCache.remote[pendingKey] = pending;
6348
6358
  }
6349
6359
  return __mfModuleCache.remote[pendingKey];`}
6350
6360
  }`;
6351
6361
  const realRemoteInit = `__mfRemotePending = __mfStartRemoteLoad().then(__mfAssignRemoteModule);`;
6352
- const deferredClientInit = `exportModule = __mfCreateDeferredRemoteProxy();`;
6353
- const eagerLoadClientRemote = id === remoteRegistration?.alias || shouldEagerLoadClientRemoteInDev(command, enableSsrInit);
6354
- const eagerClientInit = eagerLoadClientRemote ? getEagerDeferredClientInit() : deferredClientInit;
6355
- const loadedFirstClientInit = eagerLoadClientRemote ? getEagerDeferredClientInit() : deferredClientInit;
6362
+ const clientInit = id === remoteRegistration?.alias || shouldEagerLoadClientRemoteInDev(command, enableSsrInit) ? getEagerDeferredClientInit() : `exportModule = __mfCreateDeferredRemoteProxy();`;
6356
6363
  const environmentSplitInit = (clientInit, serverInit) => consumer === "client" ? clientInit : consumer === "server" ? serverInit : `if (${SERVER_ENV_GUARD}) {
6357
6364
  ${serverInit}
6358
6365
  } else {
6359
6366
  ${clientInit}
6360
6367
  }`;
6361
- const initExportModule = initMode === "eager" ? environmentSplitInit(eagerClientInit, realRemoteInit) : environmentSplitInit(loadedFirstClientInit, realRemoteInit);
6362
- const includeProxyHelper = shouldIncludeDeferredProxy(initMode, consumer, eagerLoadClientRemote, deferRemoteLoad);
6368
+ const initExportModule = environmentSplitInit(clientInit, realRemoteInit);
6369
+ const includeProxyHelper = consumer !== "server";
6363
6370
  const deferredProxyCode = getDeferredProxyHelper(remoteCacheKey);
6364
6371
  return `
6365
6372
  ${importLine}
@@ -6380,9 +6387,9 @@ const isPreloadableVirtualMfChunk = (name) => name.includes("virtual_mf") && !na
6380
6387
  const HOST_INIT_PRELOAD_CHUNKS = [
6381
6388
  (name) => name === "hostInit",
6382
6389
  (name) => name === "remoteEntry",
6383
- isPreloadableVirtualMfChunk,
6384
- (name) => name === "index"
6390
+ isPreloadableVirtualMfChunk
6385
6391
  ];
6392
+ const isHostInitPreloadSeed = (chunk) => chunk.isEntry || HOST_INIT_PRELOAD_CHUNKS.some((match) => match(chunk.name));
6386
6393
  const isRemoteWarmupExcluded = (name) => name.includes("__prebuild__") || name.includes("__loadShare__");
6387
6394
  const REMOTE_ENTRY_WARMUP_CHUNKS = [(name) => name === "hostInit", (name) => isPreloadableVirtualMfChunk(name) && !isRemoteWarmupExcluded(name)];
6388
6395
  function getChunksByFileName(bundle) {
@@ -6419,7 +6426,7 @@ function injectHostInitPreloads(html, bundle, resolvePath, externalHrefs = []) {
6419
6426
  hrefs.push(href);
6420
6427
  }
6421
6428
  const chunksByFileName = getChunksByFileName(bundle);
6422
- const seeds = Array.from(chunksByFileName.values()).filter((chunk) => HOST_INIT_PRELOAD_CHUNKS.some((match) => match(chunk.name)));
6429
+ const seeds = Array.from(chunksByFileName.values()).filter(isHostInitPreloadSeed);
6423
6430
  for (const fileName of collectPreloadChunkFiles(chunksByFileName, seeds)) {
6424
6431
  const href = resolvePath(fileName);
6425
6432
  if (existingHrefs.has(href)) continue;
@@ -6514,7 +6521,7 @@ const ROLLDOWN_RUNTIME_GLOBAL = "__rolldown_runtime__";
6514
6521
  * in every chunk and HMR patch it serves.
6515
6522
  */
6516
6523
  function renameBundledDevRuntime(req, res, remoteName) {
6517
- if (!req.url || !stripQueryAndHash(req.url).endsWith(".js")) return;
6524
+ if (!req.url || !/\.m?js$/.test(stripQueryAndHash(req.url))) return;
6518
6525
  const runtimeGlobal = `__mf_rt_${createHash("sha256").update(remoteName).digest("hex").slice(0, 10)}__`;
6519
6526
  const end = res.end;
6520
6527
  res.end = function(chunk, ...args) {
@@ -6531,6 +6538,7 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
6531
6538
  const ENTRY_BOOTSTRAP_QUERY = `?${ENTRY_BOOTSTRAP_PARAM}`;
6532
6539
  const waitsForInit = entryName === "hostInit";
6533
6540
  const getEntryPath = () => typeof entryPath === "function" ? entryPath() : entryPath;
6541
+ const getFederationOptions = () => federationOptions ?? getNormalizeModuleFederationOptions();
6534
6542
  let devEntryPath = "";
6535
6543
  let entryFiles = [];
6536
6544
  let htmlFilePath;
@@ -6550,8 +6558,14 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
6550
6558
  let isBundledDevRemote = false;
6551
6559
  let bundledDevRemoteEntryCode;
6552
6560
  let resolveBundledDevRemoteEntryCode;
6561
+ function isBuildCommand() {
6562
+ return _command === "build" || viteConfig?.command === "build";
6563
+ }
6564
+ function isLoadedFirstClientBuildFor(shareStrategy) {
6565
+ return isBuildCommand() && waitsForInit && !viteConfig?.build?.ssr && shareStrategy === "loaded-first";
6566
+ }
6553
6567
  function skipSvelteKitSsrBuild() {
6554
- return (_command === "build" || viteConfig?.command === "build") && viteConfig?.build?.ssr && hasPackageDependency("@sveltejs/kit");
6568
+ return isBuildCommand() && viteConfig?.build?.ssr && hasPackageDependency("@sveltejs/kit");
6555
6569
  }
6556
6570
  function isSvelteKitServerModule(id) {
6557
6571
  return hasPackageDependency("@sveltejs/kit") && (id.includes(".svelte-kit/generated/") || id.includes("/@sveltejs/kit/src/runtime/server/"));
@@ -6586,10 +6600,6 @@ const __mfCurrentScript = document.currentScript;
6586
6600
  function walkHtmlFiles(dir) {
6587
6601
  return walkFiles(dir, (fileName) => fileName.endsWith(".html"));
6588
6602
  }
6589
- function toRelativeImport(fromFile, targetFile) {
6590
- const relative = normalizePathForImport(path$1.relative(path$1.dirname(fromFile), targetFile));
6591
- return relative.startsWith(".") ? relative : `./${relative}`;
6592
- }
6593
6603
  function patchSvelteKitStaticHtml() {
6594
6604
  const buildDir = path$1.resolve(viteConfig.root, "build");
6595
6605
  let initFile = emittedFileName ? path$1.resolve(buildDir, emittedFileName) : void 0;
@@ -6610,10 +6620,10 @@ const __mfCurrentScript = document.currentScript;
6610
6620
  return patched;
6611
6621
  }
6612
6622
  function getRemoteEntryPreloadUrls() {
6613
- const normalizedOptions = federationOptions ?? getNormalizeModuleFederationOptions();
6614
- const isLoadedFirstClientBuild = (_command === "build" || viteConfig?.command === "build") && waitsForInit && !viteConfig?.build?.ssr && normalizedOptions.shareStrategy === "loaded-first";
6623
+ const normalizedOptions = getFederationOptions();
6624
+ const isLoadedFirstClientBuild = isLoadedFirstClientBuildFor(normalizedOptions.shareStrategy);
6615
6625
  if (normalizedOptions.shareStrategy === "loaded-first" && !isLoadedFirstClientBuild) return [];
6616
- const remoteSources = isLoadedFirstClientBuild ? Array.from(getPreloadRemotes(normalizedOptions)) : Object.keys(getUsedRemotesMap(federationOptions));
6626
+ const remoteSources = isLoadedFirstClientBuild ? Array.from(getPreloadRemotes(normalizedOptions)) : Object.keys(getUsedRemotesMap(normalizedOptions));
6617
6627
  return Array.from(new Set(remoteSources.flatMap((remote) => {
6618
6628
  const registration = getRemoteRegistration(remote, normalizedOptions.remotes, federationOptions);
6619
6629
  return registration && (registration.type === "module" || registration.type === "esm") && /^(?:https?:)?\/\//.test(registration.entry) && !/\.json(?:[?#]|$)/i.test(registration.entry) ? [registration.entry] : [];
@@ -6652,10 +6662,10 @@ const __mfCurrentScript = document.currentScript;
6652
6662
  const entryImportDeclaration = isEncodedVirtualEntry ? `const __mfEntryUrl = ${JSON.stringify(entrySrc)};
6653
6663
  ` : "";
6654
6664
  const entryImportExpression = isEncodedVirtualEntry ? "import(/* @vite-ignore */ __mfEntryUrl)" : importExpression(entrySrc);
6655
- const normalizedOptions = federationOptions ?? getNormalizeModuleFederationOptions();
6656
- const isLoadedFirstClientBuild = (_command === "build" || viteConfig?.command === "build") && waitsForInit && !viteConfig?.build?.ssr && normalizedOptions.shareStrategy === "loaded-first";
6665
+ const normalizedOptions = getFederationOptions();
6666
+ const isLoadedFirstClientBuild = isLoadedFirstClientBuildFor(normalizedOptions.shareStrategy);
6657
6667
  const shouldPreloadRemotes = !options?.skipRemotePreload && (normalizedOptions.shareStrategy !== "loaded-first" || isLoadedFirstClientBuild);
6658
- const remoteSources = isLoadedFirstClientBuild ? Array.from(getPreloadRemotes(normalizedOptions)) : Object.entries(getUsedRemotesMap(federationOptions)).flatMap(([, remotes]) => Array.from(remotes)).filter((remote) => !federationOptions || !isDynamicOnlyRemote(remote, federationOptions));
6668
+ const remoteSources = isLoadedFirstClientBuild ? Array.from(getPreloadRemotes(normalizedOptions)) : Object.entries(getUsedRemotesMap(normalizedOptions)).flatMap(([, remotes]) => Array.from(remotes)).filter((remote) => !federationOptions || !isDynamicOnlyRemote(remote, federationOptions));
6659
6669
  const remotePreloads = shouldPreloadRemotes ? remoteSources.sort().map((remote) => {
6660
6670
  const registration = isLoadedFirstClientBuild ? getRemoteRegistration(remote, normalizedOptions.remotes, federationOptions) : void 0;
6661
6671
  return `__mfPreloadRemote(${JSON.stringify(getRuntimeRemoteId(remote, normalizedOptions.remotes, federationOptions))}, ${JSON.stringify(remote)}${registration ? `, ${JSON.stringify(registration)}` : ""})`;
@@ -6670,7 +6680,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
6670
6680
  const shareItem = getNormalizeShareItem(pkg, federationOptions);
6671
6681
  const isExplicitShare = Object.hasOwn(federationOptions.shared, pkg);
6672
6682
  return shareItem?.shareConfig?.singleton === true && shareItem?.shareConfig?.import !== false && !shareItem?.shareConfig?.treeShaking && (isExplicitShare || typeof shareItem?.shareConfig?.import === "string" || Boolean(getProjectResolvedImportPath(pkg)));
6673
- }).map((pkg) => getLoadShareModulePath(pkg, false, federationOptions)) : [];
6683
+ }).map((pkg) => getLoadShareModulePath(pkg, federationOptions)) : [];
6674
6684
  const sharedPreloadBlock = sharedPreloadSources.length === 0 ? "" : options?.isBundled ? `
6675
6685
  await Promise.all([${sharedPreloadSources.map((src) => `[${JSON.stringify(src)}, import(${JSON.stringify(src)})]`).join(", ")}].map(([src, load]) => load.catch((err) => console.warn("[module-federation] shared preload failed:", src, err))));` : `
6676
6686
  const __mfSharedPreloadUrls = ${JSON.stringify(sharedPreloadSources.map(toViteEncodedId))};
@@ -6708,8 +6718,8 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
6708
6718
  if (__mfReactServerModuleCache?.pendingShareLoads) {
6709
6719
  await Promise.all(__mfReactServerModuleCache.pendingShareLoads);
6710
6720
  }`;
6711
- const pendingSharesBlock = waitsForInit && (_command === "build" || viteConfig?.command === "build") ? `
6712
- const __mfPendingShares = await ${importExpression(options?.pendingSharesSrc ?? getPendingSharesPath(federationOptions))}.catch(() => undefined);
6721
+ const pendingSharesBlock = waitsForInit && isBuildCommand() ? `
6722
+ const __mfPendingShares = await ${importExpression(options?.pendingSharesSrc ?? getPendingSharesPath(getFederationOptions()))}.catch(() => undefined);
6713
6723
  if (__mfPendingShares && typeof __mfPendingShares.preloadPendingShares === "function") await __mfPendingShares.preloadPendingShares();` : "";
6714
6724
  const importCode = `
6715
6725
  (async () => {
@@ -6961,6 +6971,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
6961
6971
  if (resolved && !resolved.external && (_command === "serve" || !resolved.id.startsWith("\0"))) addEntryFile(resolveProjectId(resolved.id));
6962
6972
  }
6963
6973
  if (_command === "serve") return;
6974
+ if (entryName === "hostInit" && federationOptions && !hasRemotes(federationOptions) && isServerBuildContext(this, viteConfig)) return;
6964
6975
  if (skipSvelteKitSsrBuild()) return;
6965
6976
  if (this.environment?.name === "ssr") return;
6966
6977
  const hasHash = fileName?.includes?.("[hash");
@@ -6975,7 +6986,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
6975
6986
  if (waitsForInit) pendingSharesEmitId = this.emitFile({
6976
6987
  name: "pendingShares",
6977
6988
  type: "chunk",
6978
- id: getPendingSharesPath(federationOptions),
6989
+ id: getPendingSharesPath(getFederationOptions()),
6979
6990
  preserveSignature: "strict"
6980
6991
  });
6981
6992
  if (htmlFilePath) addHtmlScriptEntries(htmlFilePath);
@@ -6984,7 +6995,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
6984
6995
  if (isBundledDevRemote && _command === "serve") {
6985
6996
  const remoteEntryChunk = Object.values(bundle).find((output) => output.type === "chunk" && output.isEntry && output.facadeModuleId === getEntryPath());
6986
6997
  if (remoteEntryChunk?.type === "chunk") {
6987
- const code = `export { ${remoteEntryChunk.exports.join(", ")} } from ${JSON.stringify(`./${remoteEntryChunk.fileName}`)};\n`;
6998
+ const code = `${Object.values(bundle).some((output) => output.type === "chunk" && output.code.includes("new ViteDevRuntime(")) ? "" : `import ${JSON.stringify(`${viteConfig.base}bundledDevClient.mjs`)};\n`}export { ${remoteEntryChunk.exports.join(", ")} } from ${JSON.stringify(`./${remoteEntryChunk.fileName}`)};\n`;
6988
6999
  bundledDevRemoteEntryCode = Promise.resolve(code);
6989
7000
  resolveBundledDevRemoteEntryCode?.(code);
6990
7001
  }
@@ -7027,7 +7038,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
7027
7038
  let bootstrapIndex = 0;
7028
7039
  for (const fileName of htmlFileNames) {
7029
7040
  let htmlAsset = bundle[fileName];
7030
- if (htmlAsset.type === "chunk") return;
7041
+ if (htmlAsset.type === "chunk") continue;
7031
7042
  let htmlContent = htmlAsset.source.toString() || "";
7032
7043
  const initPath = resolvePath(file, fileName);
7033
7044
  const scriptRegex = /<script\b(?=[^>]*\btype=["']module["'])(?=[^>]*\bsrc=["']([^"']+)["'])[^>]*>\s*<\/script>/gi;
@@ -7077,7 +7088,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
7077
7088
  load(id) {
7078
7089
  return virtualEntryCode.get(id);
7079
7090
  },
7080
- transform(code, id) {
7091
+ transform(code, id, transformOptions) {
7081
7092
  if (skipSvelteKitSsrBuild()) return;
7082
7093
  if (viteConfig?.command === "build" && !waitsForInit) return;
7083
7094
  if (isSvelteKitServerModule(id)) return;
@@ -7089,7 +7100,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
7089
7100
  if (normalizeModuleId(id).endsWith(".html")) return;
7090
7101
  const projectId = resolveProjectId(id);
7091
7102
  if (skipTransformIds.has(projectId)) return;
7092
- if (!isClientEnvironment(this)) return;
7103
+ if (isServerBuildContext(this, viteConfig) || transformOptions?.ssr) return;
7093
7104
  const isVinext = hasPackageDependency("vinext");
7094
7105
  if (isVinext && inject === "html" && id.includes("virtual:vite-rsc/remove-duplicate-server-css")) {
7095
7106
  const namespaceReactImport = `import * as React from 'react';`;
@@ -7390,21 +7401,6 @@ const vueAdapter = {
7390
7401
  } }
7391
7402
  };
7392
7403
  //#endregion
7393
- //#region src/utils/devServerHost.ts
7394
- const UNSPECIFIED_HOSTS = /* @__PURE__ */ new Set(["0.0.0.0", "::"]);
7395
- /**
7396
- * Hostname for client-facing HTTP/WS origins built from Vite `server.host`.
7397
- *
7398
- * Unspecified bind addresses (`0.0.0.0`, `::`) map to `localhost`, matching
7399
- * Vite's own printed local URL. IPv6 addresses are wrapped in brackets so
7400
- * `http://[::1]:5173` / `ws://[::1]:5173` parse as valid URLs.
7401
- */
7402
- function formatDevServerHostForOrigin(host) {
7403
- if (typeof host !== "string" || UNSPECIFIED_HOSTS.has(host)) return "localhost";
7404
- if (host.startsWith("[") && host.endsWith("]")) return host;
7405
- return isIPv6(host) ? `[${host}]` : host;
7406
- }
7407
- //#endregion
7408
7404
  //#region src/plugins/hmr/fullReload.ts
7409
7405
  const REMOTE_HMR_ENDPOINT = "__mf_hmr";
7410
7406
  const REMOTE_HMR_EVENT = "mf:remote-update";
@@ -7412,7 +7408,7 @@ const REMOTE_HMR_CONNECT_RETRY_DELAY_MS = 1e3;
7412
7408
  const REMOTE_HMR_CONNECT_MAX_RETRIES = 10;
7413
7409
  function getBasePath(base) {
7414
7410
  if (!base) return "/";
7415
- if (base.startsWith("http://") || base.startsWith("https://")) try {
7411
+ if (isHttpUrl(base)) try {
7416
7412
  return new URL(base).pathname || "/";
7417
7413
  } catch {
7418
7414
  return "/";
@@ -7511,14 +7507,8 @@ function setupRemoteBroadcast(server, options) {
7511
7507
  }
7512
7508
  });
7513
7509
  };
7514
- server.watcher.on("change", broadcast);
7515
- server.watcher.on("add", broadcast);
7516
- server.watcher.on("unlink", broadcast);
7517
- server.httpServer?.once("close", () => {
7518
- server.watcher.off("change", broadcast);
7519
- server.watcher.off("add", broadcast);
7520
- server.watcher.off("unlink", broadcast);
7521
- });
7510
+ const stopWatching = watchFileEvents(server.watcher, broadcast);
7511
+ server.httpServer?.once("close", stopWatching);
7522
7512
  }
7523
7513
  /**
7524
7514
  * Installs the host-side full-reload relay. For each configured remote:
@@ -7580,9 +7570,13 @@ function setupHostFullReloadRelay(server, options) {
7580
7570
  if (!message || message.event !== "mf:remote-update") return;
7581
7571
  server.ws.send({ type: "full-reload" });
7582
7572
  };
7583
- ws.onopen = () => clearReconnectTimer(remoteName);
7573
+ let opened = false;
7574
+ ws.onopen = () => {
7575
+ opened = true;
7576
+ clearReconnectTimer(remoteName);
7577
+ };
7584
7578
  ws.onerror = (error) => mfWarn(`Remote HMR socket error for "${remoteName}":`, error);
7585
- ws.onclose = () => scheduleReconnect(remoteName, remote, attempt, "socket closed");
7579
+ ws.onclose = () => scheduleReconnect(remoteName, remote, opened ? 0 : attempt, "socket closed");
7586
7580
  connections.push(ws);
7587
7581
  } catch (error) {
7588
7582
  mfWarn(`Failed to connect remote HMR for "${remoteName}" on attempt ${attempt + 1}: ${getStringPreview(error)}`);
@@ -7603,9 +7597,7 @@ function setupHostFullReloadRelay(server, options) {
7603
7597
  if (shouldIgnoreFile(file, options)) return;
7604
7598
  server.ws.send({ type: "full-reload" });
7605
7599
  };
7606
- server.watcher.on("change", triggerHostReload);
7607
- server.watcher.on("add", triggerHostReload);
7608
- server.watcher.on("unlink", triggerHostReload);
7600
+ watchFileEvents(server.watcher, triggerHostReload);
7609
7601
  server.httpServer?.once("close", teardown);
7610
7602
  }
7611
7603
  //#endregion
@@ -7676,8 +7668,8 @@ function collectHostTags(server, options, adapters) {
7676
7668
  return tags;
7677
7669
  }
7678
7670
  function pluginDevRemoteHmr(options) {
7679
- const isHost = Object.keys(options.remotes).length > 0;
7680
- const isRemote = Object.keys(options.exposes).length > 0;
7671
+ const isHost = hasRemotes(options);
7672
+ const isRemote = isRemoteContainer(options);
7681
7673
  let adapters = [];
7682
7674
  let strategy = "full-reload";
7683
7675
  let root;
@@ -7955,9 +7947,10 @@ function pluginExternalRuntimeCore() {
7955
7947
  //#endregion
7956
7948
  //#region src/virtualModules/index.ts
7957
7949
  function initVirtualModules(command, remoteEntryId, enableSsrInit = false, options) {
7958
- writeLocalSharedImportMap(options);
7959
- writeHostAutoInit(remoteEntryId, command, options);
7960
- writeRuntimeInitStatus(command, enableSsrInit, getHostAutoInitPath(options), options, options ? getSsrRuntimeRemotes(options.remotes, options) : void 0);
7950
+ const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
7951
+ writeLocalSharedImportMap(resolvedOptions);
7952
+ writeHostAutoInit(remoteEntryId, command, resolvedOptions);
7953
+ writeRuntimeInitStatus(command, enableSsrInit, getHostAutoInitPath(resolvedOptions), options, options ? getSsrRuntimeRemotes(options.remotes, options) : void 0);
7961
7954
  }
7962
7955
  //#endregion
7963
7956
  //#region src/utils/cssModuleHelpers.ts
@@ -8206,16 +8199,15 @@ function pluginLazyConsumeOnlyShares(options) {
8206
8199
  renderChunk(code, chunk, _outputOptions, meta) {
8207
8200
  const renderedChunk = chunk;
8208
8201
  const chunks = meta?.chunks;
8209
- if (!chunks || Object.keys(options.exposes).length === 0) return null;
8202
+ if (!chunks || !isRemoteContainer(options)) return null;
8210
8203
  if (isServerBuildContext(this, viteConfig)) return null;
8211
8204
  let graph = graphs.get(chunks);
8212
8205
  if (!graph) {
8213
- const isRolldown = getIsRolldown(this);
8214
8206
  const wrapperShares = /* @__PURE__ */ new Map();
8215
8207
  for (const shareKey of getUsedShares(options)) {
8216
8208
  const shareConfig = getNormalizeShareItem(shareKey, options)?.shareConfig;
8217
8209
  if (shareConfig?.import !== false || shareConfig.eager || shareConfig.treeShaking) continue;
8218
- wrapperShares.set(normalizeVirtualModuleId(getLoadShareModulePath(shareKey, isRolldown, options)), shareKey);
8210
+ wrapperShares.set(normalizeVirtualModuleId(getLoadShareModulePath(shareKey, options)), shareKey);
8219
8211
  }
8220
8212
  const root = viteConfig?.root ?? process.cwd();
8221
8213
  graph = buildLazyShareGraph(chunks, wrapperShares, new Set(Object.values(options.exposes).map((expose) => stripKnownJsExtension(path$1.resolve(root, expose.import)))));
@@ -8235,15 +8227,16 @@ function pluginLazyConsumeOnlyShares(options) {
8235
8227
  break;
8236
8228
  }
8237
8229
  const chunkDir = path$1.posix.dirname(renderedChunk.fileName);
8238
- const codePositions = createCodePositionMap(code);
8230
+ let codePositions;
8239
8231
  let usesHelper = false;
8240
8232
  for (const match of isImportMapChunk ? [] : code.matchAll(DYNAMIC_IMPORT_REGEX)) {
8241
8233
  const [expression, , specifier] = match;
8242
8234
  const start = match.index;
8243
- if (!codePositions[start]) continue;
8244
8235
  const target = path$1.posix.normalize(path$1.posix.join(chunkDir, specifier));
8245
8236
  const shares = graph.sharesByChunk.get(target);
8246
8237
  if (!shares || !renderedChunk.dynamicImports.includes(target)) continue;
8238
+ codePositions ??= createCodePositionMap(code);
8239
+ if (!codePositions[start]) continue;
8247
8240
  rewriter.overwrite(start, start + expression.length, `${helperName}(${JSON.stringify(shares)}).then(() => ${expression})`);
8248
8241
  usesHelper = edited = true;
8249
8242
  }
@@ -8266,7 +8259,7 @@ function ${helperName}(names) {
8266
8259
  }
8267
8260
  //#endregion
8268
8261
  //#region package.json
8269
- var version$1 = "1.23.4";
8262
+ var version$1 = "1.23.6";
8270
8263
  //#endregion
8271
8264
  //#region src/virtualModules/virtualExposesSSR.ts
8272
8265
  /**
@@ -8363,7 +8356,7 @@ function generateRemoteEntrySSR(options) {
8363
8356
  const virtualExposesSSRId = getVirtualExposesSSRId(options);
8364
8357
  const sharedSingletons = getSsrSharedSingletons(options);
8365
8358
  return `
8366
- import { init as runtimeInit } from "@module-federation/runtime";
8359
+ ${hasRemotes(options) ? `import { hostInitPromise } from ${JSON.stringify(getHostAutoInitPath(options))};` : "import { init as runtimeInit } from \"@module-federation/runtime\";"}
8367
8360
 
8368
8361
  const sharedSingletons = ${JSON.stringify(sharedSingletons)};
8369
8362
  const moduleCacheKey = Symbol.for(${JSON.stringify(MODULE_CACHE_SHARE_SCOPE_KEY)});
@@ -8393,11 +8386,11 @@ function generateRemoteEntrySSR(options) {
8393
8386
  * to set up a minimal runtime instance for the remote container.
8394
8387
  */
8395
8388
  async function init(shared = {}, initScope = []) {
8396
- const initRes = runtimeInit({
8389
+ const initRes = ${hasRemotes(options) ? "await hostInitPromise" : `runtimeInit({
8397
8390
  name: ${JSON.stringify(options.name)},
8398
8391
  remotes: [],
8399
8392
  shared: {},
8400
- });
8393
+ })`};
8401
8394
  if (initScope.indexOf(initToken) >= 0) return;
8402
8395
  initScope.push(initToken);
8403
8396
  const shareScopeNames = Array.isArray(${JSON.stringify(options.shareScope)})
@@ -8542,13 +8535,13 @@ function collectImportedCss(chunks) {
8542
8535
  * dependency even though the expose statically imports it. Advertising it as a sync
8543
8536
  * asset makes a preloader fetch a provider the host is going to supply anyway.
8544
8537
  */
8545
- function collectDeferredShareModules(options, isRolldown) {
8538
+ function collectDeferredShareModules(options) {
8546
8539
  const deferred = /* @__PURE__ */ new Set();
8547
8540
  for (const shareKey of getUsedShares(options)) {
8548
8541
  const shareConfig = getNormalizeShareItem(shareKey, options)?.shareConfig;
8549
8542
  if (shareConfig?.eager === true) continue;
8550
8543
  if (shareConfig?.import === false) continue;
8551
- deferred.add(normalizeVirtualModuleId(getLoadShareModulePath(shareKey, isRolldown, options)));
8544
+ deferred.add(normalizeVirtualModuleId(getLoadShareModulePath(shareKey, options)));
8552
8545
  }
8553
8546
  return deferred;
8554
8547
  }
@@ -8563,9 +8556,9 @@ function isDeferredShareChunk(chunk, deferredShareModules) {
8563
8556
  if (!chunk || chunk.type !== "chunk" || deferredShareModules.size === 0) return false;
8564
8557
  return [chunk.facadeModuleId, ...chunk.moduleIds ?? []].some((id) => typeof id === "string" && deferredShareModules.has(normalizeVirtualModuleId(id)));
8565
8558
  }
8566
- function expandExposeAssets(filesMap, exposeModules, bundle, remoteEntryFileName, options, isRolldown) {
8559
+ function expandExposeAssets(filesMap, exposeModules, bundle, remoteEntryFileName, options) {
8567
8560
  if (exposeModules.length === 0) return;
8568
- const deferredShareModules = collectDeferredShareModules(options, isRolldown);
8561
+ const deferredShareModules = collectDeferredShareModules(options);
8569
8562
  const containerChunks = remoteEntryFileName ? collectStaticChunks(bundle, [remoteEntryFileName]) : [];
8570
8563
  const bootstrapChunks = containerChunks.slice(1);
8571
8564
  const seen = new Set(containerChunks.map((chunk) => chunk.fileName));
@@ -8624,15 +8617,8 @@ const Manifest = (providedOptions) => {
8624
8617
  const { name, filename, getPublicPath, manifest: manifestOptions, varFilename } = mfOptions;
8625
8618
  let mfManifestName = manifestOptions === true ? "mf-manifest.json" : typeof manifestOptions === "object" ? normalizePathForImport(path$1.join(manifestOptions?.filePath || "", manifestOptions?.fileName || "mf-manifest.json")) : void 0;
8626
8619
  let mfManifestStatsName = mfManifestName ? getStatsFileName(mfManifestName) : void 0;
8627
- const isConsumerProject = Object.keys(mfOptions.exposes).length === 0;
8620
+ const isConsumerProject = !isRemoteContainer(mfOptions);
8628
8621
  let disableAssetsAnalyze = false;
8629
- const getDefaultDisableAssetsAnalyze = (command) => command === "serve" && isConsumerProject && (typeof manifestOptions !== "object" || !Object.hasOwn(manifestOptions, "disableAssetsAnalyze"));
8630
- const getConfiguredDisableAssetsAnalyze = (command) => {
8631
- if (typeof manifestOptions === "object" && manifestOptions !== null) {
8632
- if (Object.hasOwn(manifestOptions, "disableAssetsAnalyze")) return manifestOptions.disableAssetsAnalyze === true;
8633
- }
8634
- return getDefaultDisableAssetsAnalyze(command);
8635
- };
8636
8622
  let root;
8637
8623
  let remoteEntryFile;
8638
8624
  let ssrRemoteEntryFile;
@@ -8660,7 +8646,7 @@ const Manifest = (providedOptions) => {
8660
8646
  configureServer(server) {
8661
8647
  server.middlewares.use((req, res, next) => {
8662
8648
  const devRemoteEntryFile = resolveHashPlaceholderFileName(filename);
8663
- if (devRemoteEntryFile !== filename && Object.keys(mfOptions.exposes).length > 0 && req.url?.startsWith((viteConfig.base + devRemoteEntryFile).replace(/^\/?/, "/"))) {
8649
+ if (devRemoteEntryFile !== filename && isRemoteContainer(mfOptions) && req.url?.startsWith((viteConfig.base + devRemoteEntryFile).replace(/^\/?/, "/"))) {
8664
8650
  req.url = req.url.replace(devRemoteEntryFile, filename);
8665
8651
  next();
8666
8652
  return;
@@ -8703,7 +8689,7 @@ const Manifest = (providedOptions) => {
8703
8689
  types: resolveTypesMeta(mfOptions.dts),
8704
8690
  globalName: name,
8705
8691
  pluginVersion: version$1,
8706
- publicPath
8692
+ ...getPublicPath ? { getPublicPath } : { publicPath }
8707
8693
  }
8708
8694
  });
8709
8695
  res.end(JSON.stringify(manifest));
@@ -8723,7 +8709,7 @@ const Manifest = (providedOptions) => {
8723
8709
  _command = command;
8724
8710
  if (!config.build) config.build = {};
8725
8711
  if (!config.build.manifest) config.build.manifest = config.build.manifest || !!mfManifestName;
8726
- disableAssetsAnalyze = getConfiguredDisableAssetsAnalyze(command);
8712
+ disableAssetsAnalyze = resolveDisableAssetsAnalyze(manifestOptions, command === "serve" && isConsumerProject);
8727
8713
  _originalConfigBase = config.base;
8728
8714
  },
8729
8715
  configResolved(config) {
@@ -8802,7 +8788,7 @@ const Manifest = (providedOptions) => {
8802
8788
  root,
8803
8789
  stripKnownJsExtensions: true
8804
8790
  });
8805
- expandExposeAssets(filesMap, exposesModules, bundle, foundRemoteEntryFile, mfOptions, getIsRolldown(this));
8791
+ expandExposeAssets(filesMap, exposesModules, bundle, foundRemoteEntryFile, mfOptions);
8806
8792
  const fileToShareKey = await buildFileToShareKeyMap(getUsedShares(mfOptions), this.resolve.bind(this), mfOptions);
8807
8793
  processModuleAssets(Object.fromEntries(Object.entries(bundle).filter(([, file]) => !isTreeShakingProviderChunk(file))), filesMap, (modulePath) => fileToShareKey.get(modulePath));
8808
8794
  const deferredSharedAssets = {
@@ -8988,43 +8974,89 @@ function getStatsFileName(manifestFileName) {
8988
8974
  //#endregion
8989
8975
  //#region src/utils/sharedSource.ts
8990
8976
  const pendingEntryLookups = /* @__PURE__ */ new Map();
8977
+ const pendingLookupImporters = /* @__PURE__ */ new Map();
8978
+ const increment = (map, key) => map.set(key, (map.get(key) ?? 0) + 1);
8979
+ const decrement = (map, key) => {
8980
+ const remaining = map.get(key) - 1;
8981
+ if (remaining) map.set(key, remaining);
8982
+ else map.delete(key);
8983
+ };
8991
8984
  const getEntryLookupKey = (source, importer) => `${source}\0${importer}`;
8985
+ /**
8986
+ * Rolldown saves each this.resolve() call's options under the map's current size and deletes the
8987
+ * entry when the call settles, so an overlapping call can receive the wrong `custom` metadata.
8988
+ * Taking the first free key keeps every in-flight entry intact. A no-op when the internals differ.
8989
+ */
8990
+ function patchRolldownResolveOptionKeys(context) {
8991
+ const data = context?.data;
8992
+ const map = data?.resolveOptionsMap;
8993
+ if (!data || !(map instanceof Map) || typeof data.saveResolveOptions !== "function") return;
8994
+ if (data.__mfFreeKeyPatch) return;
8995
+ data.saveResolveOptions = (options) => {
8996
+ let index = map.size;
8997
+ while (map.has(index)) index++;
8998
+ map.set(index, options);
8999
+ return index;
9000
+ };
9001
+ data.__mfFreeKeyPatch = true;
9002
+ }
8992
9003
  /** Whether a resolveId call is one of the shared source resolver's own entry lookups. */
8993
9004
  function isSharedEntryLookup(source, importer, options) {
8994
- return options.custom?.__mfSharedEntryLookup === true || pendingEntryLookups.has(getEntryLookupKey(source, importer));
9005
+ if (pendingEntryLookups.has(getEntryLookupKey(source, importer))) return true;
9006
+ return options?.custom?.__mfSharedEntryLookupImporter === importer && pendingLookupImporters.has(importer);
8995
9007
  }
8996
9008
  /**
8997
9009
  * Runs one of the plugin's own `this.resolve()` calls (a shared entry lookup, a
8998
- * parse-barrier external probe), marked so `isSharedEntryLookup` recognizes it
9010
+ * parse-barrier external probe), tracked so `isSharedEntryLookup` recognizes it
8999
9011
  * and the share hooks neither proxy it nor register a used share for it.
9000
9012
  */
9001
9013
  async function resolveInternally(context, source, importer, options = {}) {
9002
9014
  const lookupKey = getEntryLookupKey(source, importer);
9003
- pendingEntryLookups.set(lookupKey, (pendingEntryLookups.get(lookupKey) ?? 0) + 1);
9015
+ increment(pendingEntryLookups, lookupKey);
9016
+ increment(pendingLookupImporters, importer);
9004
9017
  try {
9005
9018
  return await context.resolve(source, importer, {
9006
9019
  ...options,
9007
- skipSelf: true,
9008
9020
  custom: {
9009
9021
  ...options.custom,
9010
- __mfSharedEntryLookup: true
9011
- }
9022
+ __mfSharedEntryLookupImporter: importer
9023
+ },
9024
+ skipSelf: true
9012
9025
  });
9013
9026
  } finally {
9014
- const remaining = pendingEntryLookups.get(lookupKey) - 1;
9015
- if (remaining) pendingEntryLookups.set(lookupKey, remaining);
9016
- else pendingEntryLookups.delete(lookupKey);
9027
+ decrement(pendingEntryLookups, lookupKey);
9028
+ decrement(pendingLookupImporters, importer);
9017
9029
  }
9018
9030
  }
9019
9031
  /** Identify shared entries through Vite, with a cache scoped to this federation instance. */
9020
9032
  function createSharedSourceResolver(shared, getResolutionConfig) {
9021
9033
  const caches = /* @__PURE__ */ new Map();
9022
- async function matchEntry(source, suffix, resolveEntry) {
9034
+ const wildcardSubpathCaches = /* @__PURE__ */ new Map();
9035
+ async function resolveEntry(context, request, options, { root, conditions }) {
9036
+ if (!path$1.isAbsolute(request) && !isPackageExportAvailable(request, {
9037
+ cwd: root,
9038
+ conditions
9039
+ })) return void 0;
9040
+ const importer = path$1.join(root, "package.json");
9041
+ try {
9042
+ const resolved = await resolveInternally(context, request, importer, options);
9043
+ return resolved && !resolved.external ? resolved.id : void 0;
9044
+ } catch {
9045
+ return;
9046
+ }
9047
+ }
9048
+ async function matchEntry(source, suffix, entryOptions, resolveEntry) {
9023
9049
  const packageName = getPackageNameFromNodeModulePath(source);
9024
9050
  if (!packageName) return;
9025
9051
  const candidates = /* @__PURE__ */ new Set();
9026
9052
  if (findSharedKey(packageName, shared)) candidates.add(packageName);
9027
- if (findSharedKey(suffix, shared)) candidates.add(suffix);
9053
+ const packageSubpath = suffix.slice(packageName.length + 1);
9054
+ if (packageSubpath) {
9055
+ for (const specifier of getPackageExportSpecifiersForFile(packageName, packageSubpath, {
9056
+ ...entryOptions,
9057
+ fromResolvedEntry: source
9058
+ })) if (findSharedKey(specifier, shared)) candidates.add(specifier);
9059
+ }
9028
9060
  for (const key of Object.keys(shared)) {
9029
9061
  const request = getSharedRequest(key, shared[key]);
9030
9062
  if (getPackageName(request) !== packageName) continue;
@@ -9044,6 +9076,7 @@ function createSharedSourceResolver(shared, getResolutionConfig) {
9044
9076
  return {
9045
9077
  clear() {
9046
9078
  caches.clear();
9079
+ wildcardSubpathCaches.clear();
9047
9080
  },
9048
9081
  async resolve(context, source, options = {}) {
9049
9082
  if (source.startsWith("\0") || source.includes("#")) return;
@@ -9054,32 +9087,39 @@ function createSharedSourceResolver(shared, getResolutionConfig) {
9054
9087
  "t",
9055
9088
  "import"
9056
9089
  ].includes(key))) return;
9057
- if (findSharedKey(source, shared)) return source;
9058
- const suffix = getNodeModulesSuffix(source);
9059
- if (!suffix) return;
9060
- const normalizedSource = stripViteFsPrefix(normalizeNodeModulePath(source));
9061
9090
  const environment = context.environment ?? !!options.ssr;
9062
9091
  const cacheable = !options.isEntry && !options.scan && (!options.kind || options.kind === "import-statement") && Object.keys(options.attributes ?? {}).length === 0 && Object.keys(options.custom ?? {}).length === 0;
9063
- let cache = cacheable ? caches.get(environment) : void 0;
9064
- if (cacheable && !cache) {
9065
- cache = /* @__PURE__ */ new Map();
9066
- caches.set(environment, cache);
9092
+ const getCache = (byEnvironment) => {
9093
+ if (!cacheable) return;
9094
+ let cache = byEnvironment.get(environment);
9095
+ if (!cache) {
9096
+ cache = /* @__PURE__ */ new Map();
9097
+ byEnvironment.set(environment, cache);
9098
+ }
9099
+ return cache;
9100
+ };
9101
+ const directKey = findSharedKey(source, shared);
9102
+ if (directKey) {
9103
+ const request = getSharedRequest(directKey, shared[directKey]);
9104
+ if (!(request.endsWith("/") && source !== removeTrailingSlash(request) && !getCommonSharedSubpaths(request).includes(source))) return source;
9105
+ const cache = getCache(wildcardSubpathCaches);
9106
+ let resolvable = cache?.get(source);
9107
+ if (resolvable === void 0) {
9108
+ resolvable = await resolveEntry(context, source, options, getResolutionConfig(context, options)) !== void 0;
9109
+ cache?.set(source, resolvable);
9110
+ }
9111
+ return resolvable ? source : void 0;
9067
9112
  }
9113
+ const suffix = getNodeModulesSuffix(source);
9114
+ if (!suffix) return;
9115
+ const normalizedSource = stripViteFsPrefix(normalizeNodeModulePath(source));
9116
+ const cache = getCache(caches);
9068
9117
  if (cache?.has(normalizedSource)) return cache.get(normalizedSource);
9069
- const { root, conditions } = getResolutionConfig(context, options);
9070
- const result = await matchEntry(normalizedSource, suffix, async (request) => {
9071
- if (!path$1.isAbsolute(request) && !isPackageExportAvailable(request, {
9072
- cwd: root,
9073
- conditions
9074
- })) return void 0;
9075
- const importer = path$1.join(root, "package.json");
9076
- try {
9077
- const resolved = await resolveInternally(context, request, importer, options);
9078
- return resolved && !resolved.external ? resolved.id : void 0;
9079
- } catch {
9080
- return;
9081
- }
9082
- });
9118
+ const config = getResolutionConfig(context, options);
9119
+ const result = await matchEntry(normalizedSource, suffix, {
9120
+ cwd: config.root,
9121
+ conditions: config.conditions
9122
+ }, (request) => resolveEntry(context, request, options, config));
9083
9123
  cache?.set(normalizedSource, result);
9084
9124
  return result;
9085
9125
  }
@@ -9101,6 +9141,8 @@ function createModuleParseController() {
9101
9141
  discardWarned: false,
9102
9142
  externalSet: /* @__PURE__ */ new Set(),
9103
9143
  resolutionProbed: /* @__PURE__ */ new Set(),
9144
+ reached: /* @__PURE__ */ new Set(),
9145
+ deferredImports: /* @__PURE__ */ new Map(),
9104
9146
  lastLoadedModule: "",
9105
9147
  lastParsedModule: ""
9106
9148
  };
@@ -9124,6 +9166,8 @@ function resetParseState(controller) {
9124
9166
  controller.parseEndSet = /* @__PURE__ */ new Set();
9125
9167
  controller.externalSet = /* @__PURE__ */ new Set();
9126
9168
  controller.resolutionProbed = /* @__PURE__ */ new Set();
9169
+ controller.reached = /* @__PURE__ */ new Set();
9170
+ controller.deferredImports = /* @__PURE__ */ new Map();
9127
9171
  controller.discardWarned = false;
9128
9172
  controller.lastLoadedModule = "";
9129
9173
  controller.lastParsedModule = "";
@@ -9195,12 +9239,14 @@ function pluginModuleParseEnd_default(excludeFn, options, controller = createMod
9195
9239
  },
9196
9240
  async buildStart() {
9197
9241
  resetParseState(controller);
9198
- if (idleTimeout) resetIdleTimeout(controller, idleTimeout);
9199
- else if (options.moduleParseTimeout) setParseTimeout(controller, options.moduleParseTimeout);
9242
+ if (!idleTimeout && options.moduleParseTimeout) setParseTimeout(controller, options.moduleParseTimeout);
9200
9243
  const entryImports = /* @__PURE__ */ new Set([...options.exposedModuleImports || [], ...configuredInputImports]);
9201
9244
  for (const importSource of entryImports) {
9202
9245
  const resolved = await this.resolve(importSource);
9203
- if (resolved && !resolved.external && !excludeFn(resolved.id)) controller.parseStartSet.add(resolved.id);
9246
+ if (resolved && !resolved.external && !excludeFn(resolved.id)) {
9247
+ controller.parseStartSet.add(resolved.id);
9248
+ controller.reached.add(resolved.id);
9249
+ }
9204
9250
  }
9205
9251
  },
9206
9252
  load(id) {
@@ -9221,7 +9267,11 @@ function pluginModuleParseEnd_default(excludeFn, options, controller = createMod
9221
9267
  if (idleTimeout) resetIdleTimeout(controller, idleTimeout);
9222
9268
  const parsedModule = module;
9223
9269
  const addPendingResolutions = (resolutions) => {
9224
- for (const resolution of resolutions || []) if (!resolution.external && !excludeFn(resolution.id)) controller.parseStartSet.add(resolution.id);
9270
+ for (const resolution of resolutions || []) {
9271
+ if (resolution.external) continue;
9272
+ if (excludeFn(resolution.id)) reach(resolution.id);
9273
+ else addPending(resolution.id);
9274
+ }
9225
9275
  };
9226
9276
  const probeExternal = (pendingId) => {
9227
9277
  if (typeof this.resolve !== "function") return;
@@ -9236,15 +9286,39 @@ function pluginModuleParseEnd_default(excludeFn, options, controller = createMod
9236
9286
  };
9237
9287
  const addPendingIds = (ids) => {
9238
9288
  for (const pendingId of ids || []) {
9239
- if (controller.externalSet.has(pendingId) || matchesExternal(configuredExternal, pendingId, id) || excludeFn(pendingId)) continue;
9240
- controller.parseStartSet.add(pendingId);
9289
+ if (controller.externalSet.has(pendingId) || matchesExternal(configuredExternal, pendingId, id)) continue;
9290
+ if (excludeFn(pendingId)) {
9291
+ reach(pendingId);
9292
+ continue;
9293
+ }
9294
+ addPending(pendingId);
9241
9295
  if (!controller.parseEndSet.has(pendingId)) probeExternal(pendingId);
9242
9296
  }
9243
9297
  };
9244
- addPendingResolutions(parsedModule.importedIdResolutions);
9245
- addPendingResolutions(parsedModule.dynamicallyImportedIdResolutions);
9246
- if (parsedModule.importedIdResolutions === void 0) addPendingIds(module.importedIds);
9247
- if (parsedModule.dynamicallyImportedIdResolutions === void 0) addPendingIds(module.dynamicallyImportedIds);
9298
+ const seedImports = (resolutions, ids) => {
9299
+ if (resolutions === void 0) addPendingIds(ids);
9300
+ else addPendingResolutions(resolutions);
9301
+ };
9302
+ const reach = (moduleId) => {
9303
+ if (controller.reached.has(moduleId)) return;
9304
+ controller.reached.add(moduleId);
9305
+ const seedDeferred = controller.deferredImports.get(moduleId);
9306
+ controller.deferredImports.delete(moduleId);
9307
+ seedDeferred?.();
9308
+ };
9309
+ const addPending = (pendingId) => {
9310
+ controller.parseStartSet.add(pendingId);
9311
+ reach(pendingId);
9312
+ };
9313
+ const seedAllImports = () => {
9314
+ seedImports(parsedModule.importedIdResolutions, module.importedIds);
9315
+ seedImports(parsedModule.dynamicallyImportedIdResolutions, module.dynamicallyImportedIds);
9316
+ };
9317
+ if (module.isEntry === false && !controller.reached.has(id)) controller.deferredImports.set(id, seedAllImports);
9318
+ else {
9319
+ controller.reached.add(id);
9320
+ seedAllImports();
9321
+ }
9248
9322
  if (!excludeFn(id)) controller.parseEndSet.add(id);
9249
9323
  scheduleParseCompletionCheck(controller);
9250
9324
  },
@@ -9257,80 +9331,256 @@ function pluginModuleParseEnd_default(excludeFn, options, controller = createMod
9257
9331
  }];
9258
9332
  }
9259
9333
  //#endregion
9260
- //#region src/plugins/pluginProxyRemoteEntry.ts
9261
- function resolveAbsoluteDevRemoteEntryUrl(publicPath, fileName) {
9262
- const base = new URL(publicPath);
9263
- base.pathname = ensureTrailingSlash(base.pathname);
9264
- return new URL(fileName, base).href;
9334
+ //#region src/utils/hostProvidesAllShared.ts
9335
+ /** Virtual-module prefix of the host's per-share re-export entries. */
9336
+ const SHARE_MODULE_PREFIX = "\0mf-host-provided-share:";
9337
+ /** `./a/b` → `a/b`, `.` → `index`: the fixed entry name of an expose, without `.js`. */
9338
+ function exposeEntryName(exposeKey) {
9339
+ return exposeKey === "." ? "index" : exposeKey.replace(/^\.\//, "");
9265
9340
  }
9266
- function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposesId, getParsePromise = () => Promise.resolve() }) {
9267
- let viteConfig, _command, root, originalConfigBase;
9268
- let exposeRemoteDependencies = {};
9269
- let exposeRemoteDependenciesDirty = true;
9270
- let refreshPromise;
9271
- let dependencyInvalidationVersion = 0;
9272
- let reactIslandExposes = /* @__PURE__ */ new Set();
9273
- const isHostAutoInitId = (id) => {
9274
- const cleanId = id.split("?")[0];
9275
- return cleanId.includes(getHostAutoInitPath(options)) || cleanId.includes(getHostAutoInitPath());
9276
- };
9277
- const getEnvironmentConditions = (context) => context.environment?.config?.resolve?.conditions;
9278
- const isSsrBuild = (context) => isServerBuildContext(context, viteConfig);
9279
- function isRemoteImport(source) {
9280
- return Object.keys(options.remotes).some((name) => source === name || source.startsWith(name + "/"));
9281
- }
9282
- function collectImportSources(code) {
9283
- const sources = /* @__PURE__ */ new Map();
9284
- for (const { source, kind, syntax, typeOnly } of findModuleImportDescriptors(code)) {
9285
- if (syntax !== "import" || typeOnly) continue;
9286
- const dynamic = kind === "dynamic";
9287
- sources.set(source, (sources.get(source) ?? true) && dynamic);
9288
- }
9289
- return Array.from(sources, ([source, dynamic]) => ({
9290
- source,
9291
- dynamic
9292
- })).sort((a, b) => a.source.localeCompare(b.source));
9293
- }
9294
- function shouldScanResolvedImport(id) {
9295
- if (!id || id.includes("\0")) return false;
9296
- if (id.includes("/node_modules/") || id.includes("\\node_modules\\")) return false;
9297
- return /\.(?:[cm]?[jt]sx?|vue|svelte)(?:\?|$)/.test(id);
9298
- }
9299
- async function collectRemoteDependencies(ctx, id, seen = /* @__PURE__ */ new Set()) {
9300
- if (seen.has(id) || !shouldScanResolvedImport(id)) return [];
9301
- seen.add(id);
9302
- let code;
9303
- try {
9304
- code = getScannableModuleSource(id, readFileSync$1(id, "utf8"));
9305
- } catch {
9306
- return [];
9307
- }
9308
- const dependencies = /* @__PURE__ */ new Set();
9309
- for (const { source, dynamic } of collectImportSources(code)) {
9310
- if (isRemoteImport(source)) {
9311
- if (!dynamic) dependencies.add(source);
9312
- continue;
9313
- }
9314
- let resolved;
9315
- try {
9316
- resolved = await ctx.resolve(source, id);
9317
- } catch {
9318
- continue;
9319
- }
9320
- if (!resolved?.id || !shouldScanResolvedImport(resolved.id)) continue;
9321
- for (const dependency of await collectRemoteDependencies(ctx, resolved.id, seen)) dependencies.add(dependency);
9341
+ /** Bare specifier a host uses for an expose: `remote` for `.`, `remote/a/b` otherwise. */
9342
+ function remoteSpecifier(remoteName, exposeKey) {
9343
+ const entry = exposeEntryName(exposeKey);
9344
+ return entry === "index" ? remoteName : `${remoteName}/${entry}`;
9345
+ }
9346
+ /** `id` is a remote alias or a subpath of one. */
9347
+ function isRemoteSpecifier(id, remoteKeys) {
9348
+ return remoteKeys.some((key) => id === key || id.startsWith(`${key}/`));
9349
+ }
9350
+ /**
9351
+ * The shared key that owns `id`: an exact match, else the longest key `id` is a subpath
9352
+ * of (`lodash-es/debounce` → `lodash-es`). Used to spot an unshared subpath of a shared
9353
+ * package, which would bundle a private copy of that package into a remote.
9354
+ */
9355
+ function sharedKeyOwning(id, sharedKeys) {
9356
+ let owner;
9357
+ for (const key of sharedKeys) {
9358
+ if (id !== key && !id.startsWith(`${key}/`)) continue;
9359
+ if (!owner || key.length > owner.length) owner = key;
9360
+ }
9361
+ return owner;
9362
+ }
9363
+ /** Chunk name of the host's re-export entry for a shared key. */
9364
+ function shareChunkName(key) {
9365
+ return `shared/${key.replace(/^@/, "").replace(/[^\w-]+/g, "-")}`;
9366
+ }
9367
+ /** Reads a remote's `mf-manifest.json` from a URL or a path relative to `root`. */
9368
+ async function readHostProvidesAllSharedManifest(location, root) {
9369
+ let source;
9370
+ if (isAbsoluteUrl(location)) {
9371
+ const response = await fetch(location);
9372
+ if (!response.ok) throw new Error(`Failed to fetch ${location}: ${response.status} ${response.statusText}`);
9373
+ source = await response.text();
9374
+ } else source = await readFile(path$1.resolve(root, location), "utf8");
9375
+ const manifest = JSON.parse(source);
9376
+ if (!manifest.metaData || !Array.isArray(manifest.exposes)) throw new Error(`${location} is not a Module Federation manifest.`);
9377
+ if (manifest.metaData.remoteEntry) throw new Error(`${location} describes a Module Federation runtime remote (it has a remoteEntry). Build the remote with \`experiments: { hostProvidesAllShared: true }\`.`);
9378
+ return manifest;
9379
+ }
9380
+ /** URL prefix of a remote's files: `metaData.publicPath`, `auto` inferred from the manifest URL. */
9381
+ function remotePublicPath(manifest, location) {
9382
+ const publicPath = manifest.metaData.publicPath ?? "auto";
9383
+ if (publicPath !== "auto") return ensureTrailingSlash(publicPath);
9384
+ if (!isAbsoluteUrl(location)) throw new Error(`${location}: publicPath is "auto", which can only be inferred from a manifest URL. Reference the manifest by URL or set \`base\` / \`publicPath\` in the remote build.`);
9385
+ return ensureTrailingSlash(inferAutoPublicPath(location));
9386
+ }
9387
+ /** Import-map entries (`remote/Expose` → URL) for every expose of every remote. */
9388
+ async function collectRemoteImports(remotes, root) {
9389
+ const imports = {};
9390
+ for (const [alias, remote] of Object.entries(remotes)) {
9391
+ const manifest = await readHostProvidesAllSharedManifest(remote.entry, root);
9392
+ const publicPath = remotePublicPath(manifest, remote.entry);
9393
+ for (const expose of manifest.exposes) {
9394
+ const file = expose.assets.js.sync[0];
9395
+ if (!expose.path || !file) continue;
9396
+ imports[remoteSpecifier(alias, expose.path)] = isAbsoluteUrl(remote.entry) ? new URL(file, new URL(publicPath, remote.entry)).href : publicPath + file;
9397
+ }
9398
+ }
9399
+ return imports;
9400
+ }
9401
+ /** Top-level options that only the Module Federation runtime or `remoteEntry.js` pipeline reads. */
9402
+ const IGNORED_OPTIONS = [
9403
+ "filename",
9404
+ "ssrFilename",
9405
+ "varFilename",
9406
+ "library",
9407
+ "runtime",
9408
+ "shareScope",
9409
+ "shareStrategy",
9410
+ "runtimePlugins",
9411
+ "implementation",
9412
+ "getPublicPath",
9413
+ "ignoreOrigin",
9414
+ "virtualModuleDir",
9415
+ "hostInitInjectLocation",
9416
+ "bundleAllCSS",
9417
+ "treeShakingDir",
9418
+ "injectTreeShakingUsedExports",
9419
+ "treeShakingSharedPlugins",
9420
+ "treeShakingSharedExcludePlugins",
9421
+ "moduleParseTimeout",
9422
+ "moduleParseIdleTimeout",
9423
+ "target",
9424
+ "ssrExternals",
9425
+ "ssrEntryLoader",
9426
+ "disableRemote",
9427
+ "disableShared",
9428
+ "disableSnapshot"
9429
+ ];
9430
+ const IGNORED_EXPERIMENTS = [
9431
+ "externalRuntime",
9432
+ "provideExternalRuntime",
9433
+ "ssrMode"
9434
+ ];
9435
+ /** Per-share options: version negotiation, aliasing and fallbacks do not exist in this mode. */
9436
+ const IGNORED_SHARE_OPTIONS = [
9437
+ "eager",
9438
+ "requiredVersion",
9439
+ "strictVersion",
9440
+ "import",
9441
+ "request",
9442
+ "shareKey",
9443
+ "name",
9444
+ "version",
9445
+ "shareScope",
9446
+ "treeShaking",
9447
+ "allowNodeModulesSuffixMatch",
9448
+ "suppressMissingImportWarning"
9449
+ ];
9450
+ const isSet = (value) => value !== void 0 && value !== false && !(Array.isArray(value) && value.length === 0);
9451
+ /** A single warning naming every option the user set that import-map mode ignores. */
9452
+ function getIgnoredOptionWarning(options) {
9453
+ const shared = options.shared;
9454
+ const ignored = [
9455
+ ...IGNORED_OPTIONS.filter((key) => isSet(options[key])).map((key) => `\`${key}\``),
9456
+ ...IGNORED_EXPERIMENTS.filter((key) => isSet(options.experiments?.[key])).map((key) => `\`experiments.${key}\``),
9457
+ ...shared && !Array.isArray(shared) ? Object.entries(shared).flatMap(([key, config]) => typeof config === "object" && config !== null ? IGNORED_SHARE_OPTIONS.filter((option) => option === "import" ? config.import !== void 0 : isSet(config[option])).map((option) => `\`shared.${key}.${option}\``) : []) : []
9458
+ ];
9459
+ if (ignored.length === 0) return void 0;
9460
+ return `experiments.hostProvidesAllShared: ${ignored.join(", ")} ignored. The Module Federation runtime is not used and the host provides the only copy of every shared key.`;
9461
+ }
9462
+ //#endregion
9463
+ //#region src/utils/remoteDependencies.ts
9464
+ function collectImportSources(code) {
9465
+ const sources = /* @__PURE__ */ new Map();
9466
+ for (const { source, kind, syntax, typeOnly } of findModuleImportDescriptors(code)) {
9467
+ if (syntax !== "import" || typeOnly) continue;
9468
+ const dynamic = kind === "dynamic";
9469
+ sources.set(source, (sources.get(source) ?? true) && dynamic);
9470
+ }
9471
+ return Array.from(sources, ([source, dynamic]) => ({
9472
+ source,
9473
+ dynamic
9474
+ })).sort((a, b) => a.source.localeCompare(b.source));
9475
+ }
9476
+ function shouldScanResolvedImport(id) {
9477
+ if (!id || id.includes("\0")) return false;
9478
+ if (isNodeModulePath(id)) return false;
9479
+ return /\.(?:[cm]?[jt]sx?|vue|svelte)(?:\?|$)/.test(id);
9480
+ }
9481
+ async function readModuleEdges(ctx, id, isRemoteImport) {
9482
+ let code;
9483
+ try {
9484
+ code = getScannableModuleSource(id, readFileSync$1(id, "utf8"));
9485
+ } catch {
9486
+ return {
9487
+ remotes: [],
9488
+ staticImports: [],
9489
+ dynamicImports: []
9490
+ };
9491
+ }
9492
+ const edges = {
9493
+ remotes: [],
9494
+ staticImports: [],
9495
+ dynamicImports: []
9496
+ };
9497
+ for (const { source, dynamic } of collectImportSources(code)) {
9498
+ if (isRemoteImport(source)) {
9499
+ if (!dynamic) edges.remotes.push(source);
9500
+ continue;
9501
+ }
9502
+ let resolved;
9503
+ try {
9504
+ resolved = await ctx.resolve(source, id);
9505
+ } catch {
9506
+ continue;
9507
+ }
9508
+ if (resolved?.id && shouldScanResolvedImport(resolved.id)) (dynamic ? edges.dynamicImports : edges.staticImports).push(resolved.id);
9509
+ }
9510
+ return edges;
9511
+ }
9512
+ /**
9513
+ * Static remote imports in the module graph rooted at `id`: the remotes whose
9514
+ * bindings must be ready before the graph is used. `followDynamicImports: false`
9515
+ * stops at local `import()` boundaries, which wait for their own remotes.
9516
+ */
9517
+ async function collectRemoteDependencies(ctx, id, isRemoteImport, { followDynamicImports = true, cache = /* @__PURE__ */ new Map() } = {}) {
9518
+ const dependencies = /* @__PURE__ */ new Set();
9519
+ const seen = /* @__PURE__ */ new Set();
9520
+ const pending = [id];
9521
+ while (pending.length) {
9522
+ const current = pending.pop();
9523
+ if (seen.has(current) || !shouldScanResolvedImport(current)) continue;
9524
+ seen.add(current);
9525
+ let edges = cache.get(current);
9526
+ if (!edges) {
9527
+ edges = readModuleEdges(ctx, current, isRemoteImport);
9528
+ cache.set(current, edges);
9322
9529
  }
9323
- return Array.from(dependencies).sort();
9530
+ const { remotes, staticImports, dynamicImports } = await edges;
9531
+ for (const remote of remotes) dependencies.add(remote);
9532
+ pending.push(...staticImports);
9533
+ if (followDynamicImports) pending.push(...dynamicImports);
9534
+ }
9535
+ return Array.from(dependencies).sort();
9536
+ }
9537
+ //#endregion
9538
+ //#region src/plugins/pluginProxyRemoteEntry.ts
9539
+ function resolveAbsoluteDevRemoteEntryUrl(publicPath, fileName) {
9540
+ const base = new URL(publicPath);
9541
+ base.pathname = ensureTrailingSlash(base.pathname);
9542
+ return new URL(fileName, base).href;
9543
+ }
9544
+ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposesId, getParsePromise = () => Promise.resolve() }) {
9545
+ let viteConfig, _command, root, originalConfigBase;
9546
+ let exposeRemoteDependencies = {};
9547
+ let exposeRemoteDependenciesDirty = true;
9548
+ let refreshPromise;
9549
+ let dependencyInvalidationVersion = 0;
9550
+ let reactIslandExposes = /* @__PURE__ */ new Set();
9551
+ let isTanStackStart = false;
9552
+ const isHostAutoInitId = (id) => {
9553
+ return id.split("?")[0].includes(getHostAutoInitPath(options));
9554
+ };
9555
+ const getEnvironmentConditions = (context) => context.environment?.config?.resolve?.conditions;
9556
+ const isSsrBuild = (context) => isServerBuildContext(context, viteConfig);
9557
+ const loadRemoteEntryCode = (context) => getParsePromise().then((_) => generateRemoteEntry(options, virtualExposesId, _command, getEnvironmentConditions(context), isSsrBuild(context)));
9558
+ const loadExposesCode = async (context) => {
9559
+ await refreshExposeRemoteDependencies(context);
9560
+ return generateExposes(options, exposeRemoteDependencies, _command, reactIslandExposes);
9561
+ };
9562
+ function isRemoteImport(source) {
9563
+ return isRemoteSpecifier(source, Object.keys(options.remotes));
9324
9564
  }
9325
9565
  async function refreshExposeRemoteDependencies(ctx) {
9326
9566
  if (!exposeRemoteDependenciesDirty) return;
9567
+ if (!hasRemotes(options)) {
9568
+ exposeRemoteDependencies = {};
9569
+ exposeRemoteDependenciesDirty = false;
9570
+ return;
9571
+ }
9327
9572
  if (!refreshPromise) {
9328
9573
  const refreshVersion = dependencyInvalidationVersion;
9329
9574
  refreshPromise = (async () => {
9330
9575
  const next = {};
9576
+ const cache = /* @__PURE__ */ new Map();
9577
+ const followDynamicImports = options.shareStrategy !== "loaded-first";
9331
9578
  for (const [exposeKey, expose] of Object.entries(options.exposes)) {
9332
9579
  const resolved = await ctx.resolve(expose.import);
9333
- next[exposeKey] = resolved?.id ? await collectRemoteDependencies(ctx, resolved.id) : [];
9580
+ next[exposeKey] = resolved?.id ? await collectRemoteDependencies(ctx, resolved.id, isRemoteImport, {
9581
+ followDynamicImports,
9582
+ cache
9583
+ }) : [];
9334
9584
  }
9335
9585
  exposeRemoteDependencies = next;
9336
9586
  if (refreshVersion === dependencyInvalidationVersion) exposeRemoteDependenciesDirty = false;
@@ -9350,6 +9600,7 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
9350
9600
  configResolved(config) {
9351
9601
  viteConfig = config;
9352
9602
  root = config.root;
9603
+ isTanStackStart = config.plugins?.some((plugin) => plugin.name === "tanstack-start-core:config") ?? false;
9353
9604
  reactIslandExposes = getReactIslandExposes(options, root);
9354
9605
  },
9355
9606
  config(config, { command }) {
@@ -9358,7 +9609,7 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
9358
9609
  },
9359
9610
  async buildStart() {
9360
9611
  await refreshExposeRemoteDependencies(this);
9361
- if (_command !== "build" || hasPackageDependency("@tanstack/react-start", root)) return;
9612
+ if (_command !== "build" || isTanStackStart) return;
9362
9613
  for (const expose of Object.values(options.exposes)) {
9363
9614
  const resolved = await this.resolve(expose.import);
9364
9615
  if (resolved) this.emitFile({
@@ -9384,21 +9635,15 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
9384
9635
  }
9385
9636
  },
9386
9637
  async load(id) {
9387
- if (id === remoteEntryId) return getParsePromise().then((_) => generateRemoteEntry(options, virtualExposesId, _command, getEnvironmentConditions(this), isSsrBuild(this)));
9388
- if (id === virtualExposesId) {
9389
- await refreshExposeRemoteDependencies(this);
9390
- return generateExposes(options, exposeRemoteDependencies, _command, reactIslandExposes);
9391
- }
9638
+ if (id === remoteEntryId) return loadRemoteEntryCode(this);
9639
+ if (id === virtualExposesId) return loadExposesCode(this);
9392
9640
  if (_command === "serve" && isHostAutoInitId(id)) return id;
9393
9641
  },
9394
9642
  async transform(code, id) {
9395
9643
  return mapCodeToCodeWithSourcemap(await (async () => {
9396
9644
  if (!filterId(id)) return;
9397
- if (id.includes(remoteEntryId)) return getParsePromise().then((_) => generateRemoteEntry(options, virtualExposesId, _command, getEnvironmentConditions(this), isSsrBuild(this)));
9398
- if (id === virtualExposesId) {
9399
- await refreshExposeRemoteDependencies(this);
9400
- return generateExposes(options, exposeRemoteDependencies, _command, reactIslandExposes);
9401
- }
9645
+ if (id.includes(remoteEntryId)) return loadRemoteEntryCode(this);
9646
+ if (id === virtualExposesId) return loadExposesCode(this);
9402
9647
  if (isHostAutoInitId(id)) {
9403
9648
  if (_command === "serve") {
9404
9649
  const host = formatDevServerHostForOrigin(viteConfig.server?.host);
@@ -9512,7 +9757,7 @@ function pluginProxyRemotes_default(options) {
9512
9757
  },
9513
9758
  configResolved(config) {
9514
9759
  hasMultiEnvironment = Boolean(config.environments?.ssr);
9515
- enableSsrInit = getSsrCapabilities(parseInt(version, 10), command, Object.keys(remotes).length > 0, isSsrConfig(config)).enableSsrInitBootstrap;
9760
+ enableSsrInit = getSsrCapabilities(parseInt(version, 10), command, hasRemotes(options), isSsrConfig(config)).enableSsrInitBootstrap;
9516
9761
  },
9517
9762
  resolveId(source, importer) {
9518
9763
  const resolvedIslandConsumerId = resolveReactIslandConsumerId(source);
@@ -9645,6 +9890,20 @@ function getSharedPackageFromFile(importer, shared, cwd = getPackageDetectionCwd
9645
9890
  const normalizedImporter = normalizePathForImport(importer);
9646
9891
  return [...cached.entries].find(([dir]) => normalizedImporter === dir || normalizedImporter.startsWith(`${dir}/`))?.[1] ?? getWorkspacePackageNameFromFile(normalizedImporter);
9647
9892
  }
9893
+ /**
9894
+ * Whether an import of its own package from `importer` keeps an ordinary module edge. Internal
9895
+ * files and files of shared subpaths do; a file published only under an unshared subpath (e.g.
9896
+ * `vue/sub` when only `vue` is shared) imports the shared root like any consumer.
9897
+ */
9898
+ function keepsOwnPackageEdge(importer, shared, cwd = getPackageDetectionCwd()) {
9899
+ const nodeModulePackage = importer && getPackageNameFromNodeModulePath(importer);
9900
+ if (!nodeModulePackage) return true;
9901
+ if (getInstalledPackageJson(nodeModulePackage, { cwd })?.packageJson.exports == null) return true;
9902
+ const packageSubpath = getNodeModulesSuffix(importer)?.slice(nodeModulePackage.length + 1);
9903
+ if (!packageSubpath) return true;
9904
+ const specifiers = getPackageExportSpecifiersForFile(nodeModulePackage, packageSubpath, { cwd });
9905
+ return specifiers.length === 0 || specifiers.some((specifier) => findSharedKey(specifier, shared));
9906
+ }
9648
9907
  const workspacePackageNameCache = /* @__PURE__ */ new Map();
9649
9908
  /** Name from the nearest `package.json` above `file`, for files outside `node_modules`. */
9650
9909
  function getWorkspacePackageNameFromFile(file) {
@@ -9939,7 +10198,6 @@ function proxySharedModule(options) {
9939
10198
  const getBuildImportAnalysis = (environment) => getImportAnalysis(environment ?? _config ?? options);
9940
10199
  let _command = "serve";
9941
10200
  let useDirectReactImport = false;
9942
- let useRolldown = false;
9943
10201
  let isProduction = false;
9944
10202
  let rootResolveConditions;
9945
10203
  let ssrResolveConditions;
@@ -9968,7 +10226,7 @@ function proxySharedModule(options) {
9968
10226
  root: _config?.root || getPackageDetectionCwd(),
9969
10227
  conditions: getRuntimeDependencyConditions(context, resolveOptions)
9970
10228
  }));
9971
- const refreshTreeShakingForEnvironment = (context) => refreshTreeShakingModules(federationOptions, _command, getIsRolldown(context), getEnvironmentConditions(context));
10229
+ const refreshTreeShakingForEnvironment = (context) => refreshTreeShakingModules(federationOptions, _command, getEnvironmentConditions(context));
9972
10230
  const normalizeTreeShakingOutputPath = (value) => {
9973
10231
  const normalized = normalizePathForImport(value);
9974
10232
  if (path$1.posix.isAbsolute(normalized) || /^[A-Za-z]:\//.test(normalized) || normalized.split("/").includes("..")) throw new Error(`Invalid treeShakingDir "${value}": absolute paths and parent segments are not allowed.`);
@@ -9980,8 +10238,7 @@ function proxySharedModule(options) {
9980
10238
  };
9981
10239
  const getTreeShakingProviderFileName = (pkg, shareItem) => {
9982
10240
  if (!shareItem.shareConfig.treeShaking) return void 0;
9983
- const normalizedOptions = federationOptions ?? getNormalizeModuleFederationOptions();
9984
- const outputDir = normalizedOptions.treeShakingDir ? normalizeTreeShakingOutputPath(normalizedOptions.treeShakingDir) : void 0;
10241
+ const outputDir = federationOptions.treeShakingDir ? normalizeTreeShakingOutputPath(federationOptions.treeShakingDir) : void 0;
9985
10242
  const fileName = outputDir ? path$1.posix.join(outputDir, `${getTreeShakingSharedProviderName(pkg, federationOptions)}.js`) : void 0;
9986
10243
  if (!fileName) return void 0;
9987
10244
  return fileName;
@@ -10045,9 +10302,7 @@ function proxySharedModule(options) {
10045
10302
  workspacePackageNameCache.clear();
10046
10303
  const isVinext = hasPackageDependency("vinext");
10047
10304
  const isAstro = hasPackageDependency("astro");
10048
- const isRolldown = getIsRolldown(this);
10049
10305
  _command = command;
10050
- useRolldown = isRolldown;
10051
10306
  useDirectReactImport = isVinext || isAstro;
10052
10307
  if (command === "serve") excludeSharedSubDependencies(shared);
10053
10308
  },
@@ -10057,9 +10312,7 @@ function proxySharedModule(options) {
10057
10312
  rootResolveConditions = config.resolve?.conditions ? [...config.resolve.conditions] : void 0;
10058
10313
  ssrResolveConditions = config.ssr?.resolve?.conditions ? [...config.ssr.resolve.conditions] : void 0;
10059
10314
  ssrTarget = config.ssr?.target ?? "node";
10060
- const isRolldown = getIsRolldown(this);
10061
- const resolvedOptions = federationOptions ?? getNormalizeModuleFederationOptions();
10062
- const registerConfiguredShare = _command === "build" && Object.keys(resolvedOptions.exposes).length > 0 ? addUsedShares : addConfiguredShare;
10315
+ const registerConfiguredShare = _command === "build" && isRemoteContainer(federationOptions) ? addUsedShares : addConfiguredShare;
10063
10316
  Object.keys(shared).forEach((key) => {
10064
10317
  if (key.endsWith("/") || getSharedRequest(key, shared[key]).endsWith("/")) return;
10065
10318
  const runtimeKey = getSharedRuntimeKey(key, shared[key]);
@@ -10067,7 +10320,7 @@ function proxySharedModule(options) {
10067
10320
  registerConfiguredShare(runtimeKey, federationOptions);
10068
10321
  return;
10069
10322
  }
10070
- writeLoadShareModule(runtimeKey, shared[key], _command, isRolldown, federationOptions);
10323
+ writeLoadShareModule(runtimeKey, shared[key], _command, federationOptions);
10071
10324
  if (shared[key].shareConfig.import !== false) writePreBuildLibPath(runtimeKey, shared[key], federationOptions);
10072
10325
  registerConfiguredShare(runtimeKey, federationOptions);
10073
10326
  });
@@ -10079,6 +10332,7 @@ function proxySharedModule(options) {
10079
10332
  },
10080
10333
  buildStart() {
10081
10334
  sharedSourceResolver.clear();
10335
+ patchRolldownResolveOptionKeys(this);
10082
10336
  if (_command !== "build") return;
10083
10337
  if (hasAnalyzableShares) getBuildImportAnalysis(this.environment).clear();
10084
10338
  resetTreeShakingExports(federationOptions);
@@ -10153,7 +10407,7 @@ function proxySharedModule(options) {
10153
10407
  return taggedModule.name === sharedKey || matchesSharedSource(sharedSource, taggedModule.name);
10154
10408
  };
10155
10409
  const importerPackage = getSharedPackageFromFile(importer, shared);
10156
- if (importerPackage === getPackageName(key)) return;
10410
+ if (importerPackage === getPackageName(key) && keepsOwnPackageEdge(importer, shared)) return;
10157
10411
  if (importerPackage && shared[key].shareConfig.import !== false) {
10158
10412
  const importerIsUnsharedWorkspacePackage = !isNodeModulePath(importer) && !Object.keys(shared).some((sharedKey) => getPackageName(sharedKey) === importerPackage);
10159
10413
  const request = getSharedRequest(key, shared[key]);
@@ -10173,10 +10427,10 @@ function proxySharedModule(options) {
10173
10427
  const localSource = getPrebuildResolutionSource(shareSource, shared[key]);
10174
10428
  return tryResolveFromProjectRoot(localSource) || localSource;
10175
10429
  }
10176
- const loadSharePath = getLoadShareModulePath(shareSource, useRolldown, federationOptions);
10430
+ const loadSharePath = getLoadShareModulePath(shareSource, federationOptions);
10177
10431
  if (!materializedLoadShareSources.has(shareSource)) {
10178
10432
  materializedLoadShareSources.add(shareSource);
10179
- writeLoadShareModule(shareSource, shared[key], _command, useRolldown, federationOptions);
10433
+ writeLoadShareModule(shareSource, shared[key], _command, federationOptions);
10180
10434
  if (shared[key].shareConfig.import !== false) writePreBuildLibPath(shareSource, shared[key], federationOptions);
10181
10435
  addUsedShares(shareSource, federationOptions);
10182
10436
  writeLocalSharedImportMap(federationOptions);
@@ -10309,6 +10563,13 @@ function applyRewrites(code, imports, id) {
10309
10563
  ms.overwrite(imp.start, imp.end, wrapDynamicImport(imp.originalText));
10310
10564
  changed = true;
10311
10565
  break;
10566
+ case "local-dynamic": {
10567
+ if (imp.remotes.length === 0) break;
10568
+ const ready = imp.remotes.map((remote) => `import(${JSON.stringify(remote)}).then(function(__mf_m__) { return __mf_m__.__mf_remote_pending; })`);
10569
+ ms.overwrite(imp.start, imp.end, `Promise.all([${imp.originalText}, ${ready.join(", ")}]).then(function(__mf_r__) { return __mf_r__[0]; })`);
10570
+ changed = true;
10571
+ break;
10572
+ }
10312
10573
  }
10313
10574
  if (!changed) return;
10314
10575
  if (dependencyPendingIds.length > 0) ms.overwrite(code.length, code.length, `\nexport const __mf_remote_dependency_pending = Promise.all([${dependencyPendingIds.join(", ")}]);`);
@@ -10317,7 +10578,7 @@ function applyRewrites(code, imports, id) {
10317
10578
  map: ms.generateMap(id)
10318
10579
  };
10319
10580
  }
10320
- async function collectFromAST(ast, code, isRemoteImport) {
10581
+ async function collectFromAST(ast, code, isRemoteImport, collectLocalDynamic) {
10321
10582
  const result = [];
10322
10583
  walkAST(ast, { enter(node) {
10323
10584
  if (node.type === "ImportDeclaration" && node.source?.value) {
@@ -10367,19 +10628,28 @@ async function collectFromAST(ast, code, isRemoteImport) {
10367
10628
  const source = node.source;
10368
10629
  if (source.type !== "Literal" && source.type !== "StringLiteral" && source.type !== "TemplateLiteral") return;
10369
10630
  const value = source.type === "TemplateLiteral" ? source.quasis?.length === 1 ? source.quasis[0].value?.cooked : void 0 : source.value;
10370
- if (!value || !isRemoteImport(value)) return;
10371
- result.push({
10631
+ if (!value) return;
10632
+ const originalText = code.slice(node.start, node.end);
10633
+ if (isRemoteImport(value)) result.push({
10372
10634
  kind: "dynamic",
10373
10635
  source: value,
10374
10636
  start: node.start,
10375
10637
  end: node.end,
10376
- originalText: code.slice(node.start, node.end)
10638
+ originalText
10639
+ });
10640
+ else if (collectLocalDynamic) result.push({
10641
+ kind: "local-dynamic",
10642
+ source: value,
10643
+ start: node.start,
10644
+ end: node.end,
10645
+ originalText,
10646
+ remotes: []
10377
10647
  });
10378
10648
  }
10379
10649
  } });
10380
10650
  return result;
10381
10651
  }
10382
- function collectFromRegex(code, isRemoteImport) {
10652
+ function collectFromRegex(code, isRemoteImport, collectLocalDynamic) {
10383
10653
  const result = [];
10384
10654
  const codePositions = createCodePositionMap(code);
10385
10655
  const importAttributes = String.raw`(?:\s+(?:with|assert)\s+\{[^;]*\})?`;
@@ -10446,26 +10716,35 @@ function collectFromRegex(code, isRemoteImport) {
10446
10716
  for (const match of code.matchAll(/import\(\s*(?:\/\*[\s\S]*?\*\/\s*)?(['"])([^'"]+)\1\s*\)/g)) {
10447
10717
  const [full, , source] = match;
10448
10718
  if (!codePositions[match.index]) continue;
10449
- if (!isRemoteImport(source)) continue;
10450
- result.push({
10451
- kind: "dynamic",
10719
+ const position = {
10452
10720
  source,
10453
10721
  start: match.index,
10454
- end: match.index + full.length,
10722
+ end: match.index + full.length
10723
+ };
10724
+ if (isRemoteImport(source)) result.push({
10725
+ kind: "dynamic",
10726
+ ...position,
10455
10727
  originalText: full
10456
10728
  });
10729
+ else if (collectLocalDynamic) result.push({
10730
+ kind: "local-dynamic",
10731
+ ...position,
10732
+ originalText: full,
10733
+ remotes: []
10734
+ });
10457
10735
  }
10458
10736
  return result.length > 0 ? result : void 0;
10459
10737
  }
10460
10738
  function pluginRemoteNamedExports(options) {
10461
10739
  const remoteNames = Object.keys(options.remotes);
10740
+ const waitsAtDynamicImports = options.shareStrategy === "loaded-first";
10741
+ let remoteDependencyCache = /* @__PURE__ */ new Map();
10462
10742
  let root = process.cwd();
10463
- const isNodeModulesId = (id) => id.includes("/node_modules/") || id.includes("\\node_modules\\");
10464
10743
  function isRemoteImport(source, importerId) {
10465
10744
  return remoteNames.some((name) => {
10466
10745
  if (source.startsWith(name + "/")) return true;
10467
10746
  if (source !== name) return false;
10468
- return !isNodeModulesId(importerId) || !getInstalledPackageEntry(source, { cwd: root });
10747
+ return !isNodeModulePath(importerId) || !getInstalledPackageEntry(source, { cwd: root });
10469
10748
  }) || source.includes("__loadRemote__");
10470
10749
  }
10471
10750
  return {
@@ -10474,21 +10753,46 @@ function pluginRemoteNamedExports(options) {
10474
10753
  configResolved(config) {
10475
10754
  root = config.root || process.cwd();
10476
10755
  },
10756
+ watchChange() {
10757
+ remoteDependencyCache = /* @__PURE__ */ new Map();
10758
+ },
10477
10759
  async transform(code, id) {
10478
10760
  if (remoteNames.length === 0) return;
10479
10761
  if (id.includes("__loadRemote__") || id.includes("__loadShare__")) return;
10480
10762
  if (!JS_EXTENSIONS_RE.test(id)) return;
10481
- if (!remoteNames.some((name) => code.includes(name))) return;
10482
- const matchesRemoteImport = (source) => isRemoteImport(source, id);
10483
- for (const { kind, source, typeOnly } of findModuleImportDescriptors(code)) if (kind === "static" && !typeOnly && matchesRemoteImport(source)) markStaticRemote(source, options);
10763
+ const collectLocalDynamic = waitsAtDynamicImports && !isNodeModulePath(id) && /\bimport\s*\(/.test(code);
10764
+ if (!collectLocalDynamic && !remoteNames.some((name) => code.includes(name))) return;
10765
+ const descriptors = findModuleImportDescriptors(code);
10766
+ const resolvedElsewhere = /* @__PURE__ */ new Set();
10767
+ for (const source of new Set(descriptors.map((d) => d.source))) {
10768
+ if (source.includes("__loadRemote__") || !isRemoteImport(source, id)) continue;
10769
+ const resolved = await this.resolve(source, id);
10770
+ if (resolved && !resolved.id.includes("__loadRemote__")) resolvedElsewhere.add(source);
10771
+ }
10772
+ const matchesRemoteImport = (source) => !resolvedElsewhere.has(source) && isRemoteImport(source, id);
10773
+ for (const { kind, source, typeOnly } of descriptors) if (kind === "static" && !typeOnly && matchesRemoteImport(source)) markStaticRemote(source, options);
10484
10774
  let imports;
10485
10775
  try {
10486
- imports = await collectFromAST(this.parse(code), code, matchesRemoteImport);
10776
+ imports = await collectFromAST(this.parse(code), code, matchesRemoteImport, collectLocalDynamic);
10487
10777
  } catch {
10488
10778
  if ((id.includes(".vue") || id.includes(".svelte")) && /^\s*</.test(code)) return;
10489
- imports = collectFromRegex(code, matchesRemoteImport);
10779
+ imports = collectFromRegex(code, matchesRemoteImport, collectLocalDynamic);
10490
10780
  }
10491
10781
  if (!imports) return;
10782
+ for (const localImport of imports) {
10783
+ if (localImport.kind !== "local-dynamic") continue;
10784
+ let resolved;
10785
+ try {
10786
+ resolved = await this.resolve(localImport.source, id);
10787
+ } catch {
10788
+ continue;
10789
+ }
10790
+ if (!resolved?.id) continue;
10791
+ localImport.remotes = await collectRemoteDependencies(this, resolved.id, (source) => isRemoteSpecifier(source, remoteNames), {
10792
+ followDynamicImports: false,
10793
+ cache: remoteDependencyCache
10794
+ });
10795
+ }
10492
10796
  for (const remoteImport of imports) if (remoteImport.kind === "dynamic") markDynamicRemote(remoteImport.source, options);
10493
10797
  return applyRewrites(code, imports, id);
10494
10798
  }
@@ -10654,7 +10958,7 @@ function pluginSSRRemoteEntry(options) {
10654
10958
  const environmentName = environment?.name;
10655
10959
  const hasSsrEnvironment = Boolean(viteConfig?.environments?.ssr);
10656
10960
  const isLegacySsrBuild = Boolean(environment?.config?.build?.ssr ?? viteConfig?.build?.ssr);
10657
- return Object.keys(options.exposes).length > 0 && !(hasSsrEnvironment && environmentName !== "ssr" || !hasSsrEnvironment && !isLegacySsrBuild);
10961
+ return isRemoteContainer(options) && !(hasSsrEnvironment && environmentName !== "ssr" || !hasSsrEnvironment && !isLegacySsrBuild);
10658
10962
  };
10659
10963
  const getSsrRemoteEntrySource = () => {
10660
10964
  if (cachedSsrRemoteEntrySource === void 0) cachedSsrRemoteEntrySource = generateRemoteEntrySSR(options);
@@ -10756,8 +11060,13 @@ function pluginSSRRemoteEntry(options) {
10756
11060
  } };
10757
11061
  } catch {}
10758
11062
  }
11063
+ const fetchedId = body.data.name === "fetchModule" ? body.data.data[0] : void 0;
11064
+ const shared = typeof fetchedId === "string" && !!findSharedKey(fetchedId, options.shared);
10759
11065
  res.setHeader("Content-Type", "application/json");
10760
- res.end(JSON.stringify(result));
11066
+ res.end(JSON.stringify(shared ? {
11067
+ ...result,
11068
+ shared
11069
+ } : result));
10761
11070
  } catch (e) {
10762
11071
  res.setHeader("Content-Type", "application/json");
10763
11072
  res.end(JSON.stringify({ error: { message: String(e instanceof Error ? e.message : e) } }));
@@ -10793,6 +11102,12 @@ function pluginSSRRemoteEntry(options) {
10793
11102
  const isRolldown = getIsRolldown(this);
10794
11103
  const environment = this.environment;
10795
11104
  if (!isSsrRemoteEntryBuild(environment)) return;
11105
+ if (!isRolldown && hasRemotes(options)) this.emitFile({
11106
+ type: "chunk",
11107
+ id: getHostAutoInitPath(options),
11108
+ name: "hostInit",
11109
+ preserveSignature: "strict"
11110
+ });
10796
11111
  if (isRolldown) this.emitFile({
10797
11112
  type: "chunk",
10798
11113
  id: remoteEntrySSRId,
@@ -10800,7 +11115,7 @@ function pluginSSRRemoteEntry(options) {
10800
11115
  fileName: ssrOutputFilename,
10801
11116
  preserveSignature: "strict"
10802
11117
  });
10803
- else if (Object.keys(options.exposes).length > 0 && !isNuxtLike()) this.emitFile({
11118
+ else if (isRemoteContainer(options) && !isNuxtLike()) this.emitFile({
10804
11119
  type: "chunk",
10805
11120
  id: virtualExposesSSRId,
10806
11121
  name: "ssrExposes",
@@ -10815,11 +11130,12 @@ function pluginSSRRemoteEntry(options) {
10815
11130
  const exposesChunk = findNuxtExposesChunk(bundle) ?? findEmittedExposesChunk(bundle);
10816
11131
  if (!isRolldown && isSsrRemoteEntryBuild(environment)) {
10817
11132
  let source = getSsrRemoteEntrySource();
10818
- if (exposesChunk) {
10819
- let exposesImport = path$1.posix.relative(path$1.posix.dirname(ssrOutputFilename), exposesChunk);
10820
- if (!exposesImport.startsWith(".")) exposesImport = `./${exposesImport}`;
10821
- source = source.replace(/import\("virtual:mf-exposes-ssr:[^"]+"\)/g, `import("${exposesImport}")`);
11133
+ if (hasRemotes(options)) {
11134
+ const hostInitId = getHostAutoInitPath(options);
11135
+ const hostInitChunk = Object.values(bundle).find((file) => file.type === "chunk" && file.facadeModuleId?.includes(hostInitId));
11136
+ if (hostInitChunk) source = source.replace(JSON.stringify(hostInitId), JSON.stringify(toRelativeImport(ssrOutputFilename, hostInitChunk.fileName)));
10822
11137
  }
11138
+ if (exposesChunk) source = source.replace(/import\("virtual:mf-exposes-ssr:[^"]+"\)/g, `import("${toRelativeImport(ssrOutputFilename, exposesChunk)}")`);
10823
11139
  this.emitFile({
10824
11140
  type: "asset",
10825
11141
  fileName: ssrOutputFilename,
@@ -10983,6 +11299,68 @@ const VarRemoteEntry = (providedOptions) => {
10983
11299
  }
10984
11300
  };
10985
11301
  //#endregion
11302
+ //#region src/plugins/pluginSsrRuntimeInit.ts
11303
+ /** Register the SSR host before application evaluation, without preloading remotes. */
11304
+ function pluginSsrRuntimeInit(options) {
11305
+ if (!hasRemotes(options)) return [];
11306
+ let command;
11307
+ let legacySsr = false;
11308
+ let supported = false;
11309
+ const server = (ctx, ssr) => supported && isServerContext(ctx, ssr === true || legacySsr);
11310
+ return [{
11311
+ name: "module-federation-ssr-runtime-init",
11312
+ enforce: "post",
11313
+ config(_config, env) {
11314
+ command = env.command;
11315
+ },
11316
+ configResolved(config) {
11317
+ legacySsr = Boolean(config.build.ssr);
11318
+ supported = getSsrCapabilities(parseInt(version, 10), command, true, isSsrConfig(config)).enableSsrInitBootstrap;
11319
+ },
11320
+ resolveId: {
11321
+ order: "pre",
11322
+ handler(id, _importer, resolveOptions) {
11323
+ if (server(this, resolveOptions.ssr) && id === options.implementation) return {
11324
+ id: options.implementation,
11325
+ external: false
11326
+ };
11327
+ }
11328
+ },
11329
+ transform(code, id, transformOptions) {
11330
+ if (!server(this, transformOptions?.ssr)) return;
11331
+ if (isOwnedHostAutoInitId(id, options)) {
11332
+ const pluginImports = options.runtimePlugins.map((plugin, index) => `import plugin${index} from ${toSafeJsLiteral(getRuntimePluginSpecifier(plugin))};`).join("\n");
11333
+ const plugins = options.runtimePlugins.map((plugin, index) => `plugin${index}(${Array.isArray(plugin) ? serializeRuntimeOptions(plugin[1]) : ""})`).join(",");
11334
+ return {
11335
+ code: `
11336
+ import { init } from ${toSafeJsLiteral(options.implementation)};
11337
+ import { usedShared, usedRemotes } from ${toSafeJsLiteral(getLocalSharedImportMapPath(options))};
11338
+ ${pluginImports}
11339
+ ${getRuntimeInitBootstrapCode(false, getRuntimeInitStatusImportId(options))}
11340
+ globalThis[globalKey].ssrInitStarted = true;
11341
+ const runtime = init({
11342
+ name: ${toSafeJsLiteral(options.name)},
11343
+ remotes: usedRemotes,
11344
+ shared: usedShared,
11345
+ plugins: [${plugins}],
11346
+ shareStrategy: ${toSafeJsLiteral(options.shareStrategy)},
11347
+ });
11348
+ const hostInitPromise = Promise.resolve(runtime);
11349
+ globalThis[globalKey].initResolve(runtime);
11350
+ function initHost() { return hostInitPromise; }
11351
+ export { initHost, hostInitPromise };
11352
+ `,
11353
+ map: null
11354
+ };
11355
+ }
11356
+ if (!(command === "build" && this.getModuleInfo(id)?.isEntry) && !findModuleImportSources(code).includes("@module-federation/runtime")) return;
11357
+ const injection = `import ${toSafeJsLiteral(getHostAutoInitPath(options))};\n`;
11358
+ if (code.includes(injection.trim())) return;
11359
+ return mapCodeToCodeWithSourcemap(injection + code);
11360
+ }
11361
+ }];
11362
+ }
11363
+ //#endregion
10986
11364
  //#region src/utils/aliasToArrayPlugin.ts
10987
11365
  var aliasToArrayPlugin_default = {
10988
11366
  name: "alias-transform-plugin",
@@ -11131,145 +11509,6 @@ function sanitizeFederationControlChunk(code, fileName, filename) {
11131
11509
  return nextCode;
11132
11510
  }
11133
11511
  //#endregion
11134
- //#region src/utils/isTestEnv.ts
11135
- /**
11136
- * Detects whether the current process is running in a test environment
11137
- * Set `MFE_VITE_NO_TEST_ENV_CHECK=true` to load federation plugins during tests.
11138
- */
11139
- function isTestEnv() {
11140
- if (process.env.MFE_VITE_NO_TEST_ENV_CHECK === "true") return false;
11141
- return process.env.NODE_ENV === "test" || process.env.VITEST != null || process.env.JEST_WORKER_ID != null;
11142
- }
11143
- //#endregion
11144
- //#region src/utils/hostProvidesAllShared.ts
11145
- /** Virtual-module prefix of the host's per-share re-export entries. */
11146
- const SHARE_MODULE_PREFIX = "\0mf-host-provided-share:";
11147
- /** `./a/b` → `a/b`, `.` → `index`: the fixed entry name of an expose, without `.js`. */
11148
- function exposeEntryName(exposeKey) {
11149
- return exposeKey === "." ? "index" : exposeKey.replace(/^\.\//, "");
11150
- }
11151
- /** Bare specifier a host uses for an expose: `remote` for `.`, `remote/a/b` otherwise. */
11152
- function remoteSpecifier(remoteName, exposeKey) {
11153
- const entry = exposeEntryName(exposeKey);
11154
- return entry === "index" ? remoteName : `${remoteName}/${entry}`;
11155
- }
11156
- /** `id` is a remote alias or a subpath of one. */
11157
- function isRemoteSpecifier(id, remoteKeys) {
11158
- return remoteKeys.some((key) => id === key || id.startsWith(`${key}/`));
11159
- }
11160
- /**
11161
- * The shared key that owns `id`: an exact match, else the longest key `id` is a subpath
11162
- * of (`lodash-es/debounce` → `lodash-es`). Used to spot an unshared subpath of a shared
11163
- * package, which would bundle a private copy of that package into a remote.
11164
- */
11165
- function sharedKeyOwning(id, sharedKeys) {
11166
- let owner;
11167
- for (const key of sharedKeys) {
11168
- if (id !== key && !id.startsWith(`${key}/`)) continue;
11169
- if (!owner || key.length > owner.length) owner = key;
11170
- }
11171
- return owner;
11172
- }
11173
- /** Chunk name of the host's re-export entry for a shared key. */
11174
- function shareChunkName(key) {
11175
- return `shared/${key.replace(/^@/, "").replace(/[^\w-]+/g, "-")}`;
11176
- }
11177
- /** Reads a remote's `mf-manifest.json` from a URL or a path relative to `root`. */
11178
- async function readHostProvidesAllSharedManifest(location, root) {
11179
- let source;
11180
- if (isAbsoluteUrl(location)) {
11181
- const response = await fetch(location);
11182
- if (!response.ok) throw new Error(`Failed to fetch ${location}: ${response.status} ${response.statusText}`);
11183
- source = await response.text();
11184
- } else source = await readFile(path$1.resolve(root, location), "utf8");
11185
- const manifest = JSON.parse(source);
11186
- if (!manifest.metaData || !Array.isArray(manifest.exposes)) throw new Error(`${location} is not a Module Federation manifest.`);
11187
- if (manifest.metaData.remoteEntry) throw new Error(`${location} describes a Module Federation runtime remote (it has a remoteEntry). Build the remote with \`experiments: { hostProvidesAllShared: true }\`.`);
11188
- return manifest;
11189
- }
11190
- /** URL prefix of a remote's files: `metaData.publicPath`, `auto` inferred from the manifest URL. */
11191
- function remotePublicPath(manifest, location) {
11192
- const publicPath = manifest.metaData.publicPath ?? "auto";
11193
- if (publicPath !== "auto") return ensureTrailingSlash(publicPath);
11194
- if (!isAbsoluteUrl(location)) throw new Error(`${location}: publicPath is "auto", which can only be inferred from a manifest URL. Reference the manifest by URL or set \`base\` / \`publicPath\` in the remote build.`);
11195
- return ensureTrailingSlash(inferAutoPublicPath(location));
11196
- }
11197
- /** Import-map entries (`remote/Expose` → URL) for every expose of every remote. */
11198
- async function collectRemoteImports(remotes, root) {
11199
- const imports = {};
11200
- for (const [alias, remote] of Object.entries(remotes)) {
11201
- const manifest = await readHostProvidesAllSharedManifest(remote.entry, root);
11202
- const publicPath = remotePublicPath(manifest, remote.entry);
11203
- for (const expose of manifest.exposes) {
11204
- const file = expose.assets.js.sync[0];
11205
- if (!expose.path || !file) continue;
11206
- imports[remoteSpecifier(alias, expose.path)] = isAbsoluteUrl(remote.entry) ? new URL(file, new URL(publicPath, remote.entry)).href : publicPath + file;
11207
- }
11208
- }
11209
- return imports;
11210
- }
11211
- /** Top-level options that only the Module Federation runtime or `remoteEntry.js` pipeline reads. */
11212
- const IGNORED_OPTIONS = [
11213
- "filename",
11214
- "ssrFilename",
11215
- "varFilename",
11216
- "library",
11217
- "runtime",
11218
- "shareScope",
11219
- "shareStrategy",
11220
- "runtimePlugins",
11221
- "implementation",
11222
- "getPublicPath",
11223
- "ignoreOrigin",
11224
- "virtualModuleDir",
11225
- "hostInitInjectLocation",
11226
- "bundleAllCSS",
11227
- "treeShakingDir",
11228
- "injectTreeShakingUsedExports",
11229
- "treeShakingSharedPlugins",
11230
- "treeShakingSharedExcludePlugins",
11231
- "moduleParseTimeout",
11232
- "moduleParseIdleTimeout",
11233
- "target",
11234
- "ssrExternals",
11235
- "ssrEntryLoader",
11236
- "disableRemote",
11237
- "disableShared",
11238
- "disableSnapshot"
11239
- ];
11240
- const IGNORED_EXPERIMENTS = [
11241
- "externalRuntime",
11242
- "provideExternalRuntime",
11243
- "ssrMode"
11244
- ];
11245
- /** Per-share options: version negotiation, aliasing and fallbacks do not exist in this mode. */
11246
- const IGNORED_SHARE_OPTIONS = [
11247
- "eager",
11248
- "requiredVersion",
11249
- "strictVersion",
11250
- "import",
11251
- "request",
11252
- "shareKey",
11253
- "name",
11254
- "version",
11255
- "shareScope",
11256
- "treeShaking",
11257
- "allowNodeModulesSuffixMatch",
11258
- "suppressMissingImportWarning"
11259
- ];
11260
- const isSet = (value) => value !== void 0 && value !== false && !(Array.isArray(value) && value.length === 0);
11261
- /** A single warning naming every option the user set that import-map mode ignores. */
11262
- function getIgnoredOptionWarning(options) {
11263
- const shared = options.shared;
11264
- const ignored = [
11265
- ...IGNORED_OPTIONS.filter((key) => isSet(options[key])).map((key) => `\`${key}\``),
11266
- ...IGNORED_EXPERIMENTS.filter((key) => isSet(options.experiments?.[key])).map((key) => `\`experiments.${key}\``),
11267
- ...shared && !Array.isArray(shared) ? Object.entries(shared).flatMap(([key, config]) => typeof config === "object" && config !== null ? IGNORED_SHARE_OPTIONS.filter((option) => option === "import" ? config.import !== void 0 : isSet(config[option])).map((option) => `\`shared.${key}.${option}\``) : []) : []
11268
- ];
11269
- if (ignored.length === 0) return void 0;
11270
- return `experiments.hostProvidesAllShared: ${ignored.join(", ")} ignored. The Module Federation runtime is not used and the host provides the only copy of every shared key.`;
11271
- }
11272
- //#endregion
11273
11512
  //#region src/plugins/pluginHostProvidesAllSharedHost.ts
11274
11513
  const ESM_SYNTAX_RE = /(^|[\s;])(export|import)[\s{*]/m;
11275
11514
  const DEFAULT_EXPORT_RE = /export\s+default\b|export\s*\{[^}]*\bas\s+default\b/;
@@ -11495,28 +11734,6 @@ function pluginHostProvidesAllSharedRemote(options) {
11495
11734
  };
11496
11735
  }
11497
11736
  //#endregion
11498
- //#region src/utils/normalizeOptimizeDeps.ts
11499
- var normalizeOptimizeDeps_default = {
11500
- name: "normalizeOptimizeDeps",
11501
- config: (config) => {
11502
- let { optimizeDeps } = config;
11503
- if (!optimizeDeps) {
11504
- config.optimizeDeps = {};
11505
- optimizeDeps = config.optimizeDeps;
11506
- }
11507
- if (!optimizeDeps.include) optimizeDeps.include = [];
11508
- if (!optimizeDeps.exclude) optimizeDeps.exclude = [];
11509
- if (!optimizeDeps.needsInterop) optimizeDeps.needsInterop = [];
11510
- },
11511
- configResolved: (config) => {
11512
- const include = config.optimizeDeps?.include;
11513
- const exclude = config.optimizeDeps?.exclude;
11514
- if (!include?.length || !exclude?.length) return;
11515
- const included = new Set(include);
11516
- config.optimizeDeps.exclude = exclude.filter((dep) => !included.has(dep));
11517
- }
11518
- };
11519
- //#endregion
11520
11737
  //#region src/utils/runtimeCapabilityOptimization.ts
11521
11738
  const RUNTIME_CAPABILITIES = [
11522
11739
  {
@@ -11546,11 +11763,11 @@ function applyRuntimeCapabilityDefines(define, options, { defaultDisableSnapshot
11546
11763
  }
11547
11764
  if (explicitValue !== void 0 && !isEquivalentBooleanDefine(define[capability.define], explicitValue)) onConflict?.(`${capability.define} define (${define[capability.define]}) differs from ${capability.option} option (${explicitValue}). The existing define will not be overridden.`);
11548
11765
  }
11549
- if (!("FEDERATION_HAS_EXPOSES" in define)) define["FEDERATION_HAS_EXPOSES"] = JSON.stringify(Object.keys(options.exposes).length > 0);
11766
+ if (!("FEDERATION_HAS_EXPOSES" in define)) define["FEDERATION_HAS_EXPOSES"] = JSON.stringify(isRemoteContainer(options));
11550
11767
  }
11551
11768
  function getRuntimeCapabilityConfigurationWarnings(options) {
11552
11769
  const warnings = [];
11553
- if (options.disableRemote && Object.keys(options.remotes).length > 0) warnings.push("disableRemote is true, but remotes are configured. Remote loading will be unavailable at runtime.");
11770
+ if (options.disableRemote && hasRemotes(options)) warnings.push("disableRemote is true, but remotes are configured. Remote loading will be unavailable at runtime.");
11554
11771
  if (options.disableShared && hasShared(options)) warnings.push("disableShared is true, but shared dependencies are configured. Shared dependency loading will be unavailable at runtime.");
11555
11772
  return warnings;
11556
11773
  }
@@ -11718,15 +11935,8 @@ function isBarePackageSubpath(specifier) {
11718
11935
  * Vite then resolves the package's own dependency graph using its normal
11719
11936
  * scanner, preserving package and peer-dependency resolution semantics.
11720
11937
  */
11721
- function includeLinkedSharedEntries(optimizeDeps, shared, projectRoot, exposes, outDir) {
11938
+ function collectLinkedSharedEntries(shared, projectRoot, exposes) {
11722
11939
  const additions = /* @__PURE__ */ new Set();
11723
- const entries = new Set(Array.isArray(optimizeDeps.entries) ? optimizeDeps.entries : optimizeDeps.entries ? [optimizeDeps.entries] : [
11724
- "**/*.html",
11725
- "!**/node_modules/**",
11726
- `!**/${outDir.replace(/\\/g, "/")}/**`,
11727
- "!**/__tests__/**",
11728
- "!**/coverage/**"
11729
- ]);
11730
11940
  for (const [packageName, share] of Object.entries(shared ?? {})) {
11731
11941
  if (share?.shareConfig?.import === false) continue;
11732
11942
  const configuredImport = share?.shareConfig?.import;
@@ -11749,13 +11959,7 @@ function includeLinkedSharedEntries(optimizeDeps, shared, projectRoot, exposes,
11749
11959
  if (existsSync(entry)) additions.add(entry);
11750
11960
  }
11751
11961
  }
11752
- if (additions.size === 0) return;
11753
- for (const entry of additions) entries.add(entry);
11754
- optimizeDeps.entries = [...entries];
11755
- }
11756
- function stabilizeOptimizeDeps(optimizeDeps) {
11757
- optimizeDeps.include = [...new Set(optimizeDeps.include ?? [])].sort();
11758
- optimizeDeps.exclude = [...new Set(optimizeDeps.exclude ?? [])].sort();
11962
+ return [...additions];
11759
11963
  }
11760
11964
  function isFile(candidate) {
11761
11965
  try {
@@ -11878,7 +12082,7 @@ function createEarlyVirtualModulesPlugin(options) {
11878
12082
  const isVinext = hasPackageDependency("vinext");
11879
12083
  initVirtualModules(_command, getRemoteEntryId(options), false, options);
11880
12084
  const isRolldown = getIsRolldown(this);
11881
- if (remotes && Object.keys(remotes).length > 0) {
12085
+ if (hasRemotes(options)) {
11882
12086
  for (const key of Object.keys(remotes)) ensureUsedRemote(key, options);
11883
12087
  if (_command === "serve") {
11884
12088
  config.optimizeDeps = config.optimizeDeps || {};
@@ -11900,7 +12104,7 @@ function createEarlyVirtualModulesPlugin(options) {
11900
12104
  const preparedShares = /* @__PURE__ */ new Map();
11901
12105
  const writeSharedModules = (source, shareItem) => {
11902
12106
  if (preparedShares.get(source) === shareItem) return;
11903
- writeLoadShareModule(source, shareItem, _command, isRolldown, options);
12107
+ writeLoadShareModule(source, shareItem, _command, options);
11904
12108
  if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(source, shareItem, options);
11905
12109
  preparedShares.set(source, shareItem);
11906
12110
  };
@@ -11916,7 +12120,7 @@ function createEarlyVirtualModulesPlugin(options) {
11916
12120
  if (!id.startsWith("module-federation:optimized-require-")) return;
11917
12121
  const sourcePackage = id.slice(36);
11918
12122
  if (sourcePackage !== "react" && sourcePackage !== "react-dom") return;
11919
- const loadSharePath = getLoadShareModulePath(sourcePackage, isRolldown, options);
12123
+ const loadSharePath = getLoadShareModulePath(sourcePackage, options);
11920
12124
  const source = JSON.stringify(loadSharePath);
11921
12125
  return "import * as __mfShared from " + source + ";\nexport * from " + source + ";\nexport default __mfShared.default ?? __mfShared;";
11922
12126
  },
@@ -11929,7 +12133,7 @@ function createEarlyVirtualModulesPlugin(options) {
11929
12133
  const key = findSharedKey(source, shared);
11930
12134
  if (!key) return;
11931
12135
  const importerPackage = getSharedPackageFromFile(importer, shared, root);
11932
- if (!isReactDomSelfReference(source, importer) && (importerPackage === getPackageName(key) || importerPackage && isSharedPackageDependency(key, importerPackage))) return;
12136
+ if (!isReactDomSelfReference(source, importer) && (importerPackage === getPackageName(key) && keepsOwnPackageEdge(importer, shared, root) || importerPackage && isSharedPackageDependency(key, importerPackage))) return;
11933
12137
  if (isAssetLikeImport(source)) return;
11934
12138
  const shareItem = shared[key];
11935
12139
  const isReactSingleton = source === "react" && key === "react" && shareItem.shareConfig?.singleton === true;
@@ -11942,7 +12146,7 @@ function createEarlyVirtualModulesPlugin(options) {
11942
12146
  writeSharedModules(source, shareItem);
11943
12147
  return { id: `module-federation:optimized-require-${source}` };
11944
12148
  }
11945
- const loadSharePath = getLoadShareModulePath(source, isRolldown, options);
12149
+ const loadSharePath = getLoadShareModulePath(source, options);
11946
12150
  writeSharedModules(source, shareItem);
11947
12151
  return {
11948
12152
  id: loadSharePath,
@@ -11970,12 +12174,12 @@ function createEarlyVirtualModulesPlugin(options) {
11970
12174
  const key = findSharedKey(args.path, shared);
11971
12175
  if (!key || isAssetLikeImport(args.path)) return;
11972
12176
  const importerPackage = getSharedPackageFromFile(args.importer, shared, root);
11973
- if (importerPackage === getPackageName(args.path) && !isReactDomSelfReference(args.path, args.importer)) return;
12177
+ if (importerPackage === getPackageName(args.path) && !isReactDomSelfReference(args.path, args.importer) && keepsOwnPackageEdge(args.importer, shared, root)) return;
11974
12178
  if (importerPackage && isSharedPackageDependency(key, importerPackage)) return;
11975
12179
  addUsedShares(args.path, options);
11976
12180
  if (args.kind === "import-statement" || args.kind === "dynamic-import") {
11977
12181
  const shareItem = shared[key];
11978
- const loadSharePath = getLoadShareModulePath(args.path, isRolldown, options);
12182
+ const loadSharePath = getLoadShareModulePath(args.path, options);
11979
12183
  writeSharedModules(args.path, shareItem);
11980
12184
  return {
11981
12185
  path: loadSharePath,
@@ -11994,7 +12198,7 @@ function createEarlyVirtualModulesPlugin(options) {
11994
12198
  const key = findSharedKey(args.path, shared);
11995
12199
  if (!key) return;
11996
12200
  const shareItem = shared[key];
11997
- const loadSharePath = getLoadShareModulePath(args.path, isRolldown, options);
12201
+ const loadSharePath = getLoadShareModulePath(args.path, options);
11998
12202
  writeSharedModules(args.path, shareItem);
11999
12203
  return {
12000
12204
  loader: "js",
@@ -12029,8 +12233,8 @@ export default __mfShared.default ?? __mfShared;`
12029
12233
  addConfiguredShare(runtimeKey, options);
12030
12234
  continue;
12031
12235
  }
12032
- getLoadShareModulePath(runtimeKey, isRolldown, options);
12033
- writeLoadShareModule(runtimeKey, shareItem, _command, isRolldown, options);
12236
+ getLoadShareModulePath(runtimeKey, options);
12237
+ writeLoadShareModule(runtimeKey, shareItem, _command, options);
12034
12238
  if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(runtimeKey, shareItem, options);
12035
12239
  addConfiguredShare(runtimeKey, options);
12036
12240
  if (_command === "serve" && shareItem.shareConfig?.import !== false) {
@@ -12052,8 +12256,8 @@ export default __mfShared.default ?? __mfShared;`
12052
12256
  optimizeDeps.exclude.push(subpath);
12053
12257
  continue;
12054
12258
  }
12055
- getLoadShareModulePath(subpath, isRolldown, options);
12056
- writeLoadShareModule(subpath, shareItem, _command, isRolldown, options);
12259
+ getLoadShareModulePath(subpath, options);
12260
+ writeLoadShareModule(subpath, shareItem, _command, options);
12057
12261
  writePreBuildLibPath(subpath, shareItem, options);
12058
12262
  addConfiguredShare(subpath, options);
12059
12263
  if (canResolveSubpath) {
@@ -12066,9 +12270,19 @@ export default __mfShared.default ?? __mfShared;`
12066
12270
  writeLocalSharedImportMap(options);
12067
12271
  }
12068
12272
  if (_command === "serve") {
12069
- config.optimizeDeps ??= {};
12070
- includeLinkedSharedEntries(config.optimizeDeps, shared, root, options.exposes, config.build?.outDir ?? "dist");
12071
- stabilizeOptimizeDeps(config.optimizeDeps);
12273
+ const generatedEntries = collectLinkedSharedEntries(shared, root, options.exposes);
12274
+ if (generatedEntries.length > 0) {
12275
+ config.optimizeDeps ??= {};
12276
+ const outDir = config.build?.outDir ?? "dist";
12277
+ const { entries } = config.optimizeDeps;
12278
+ config.optimizeDeps.entries = [.../* @__PURE__ */ new Set([...entries === void 0 ? [
12279
+ "**/*.html",
12280
+ "!**/node_modules/**",
12281
+ `!**/${outDir.replace(/\\/g, "/")}/**`,
12282
+ "!**/__tests__/**",
12283
+ "!**/coverage/**"
12284
+ ] : typeof entries === "string" ? [entries] : entries, ...generatedEntries])];
12285
+ }
12072
12286
  }
12073
12287
  },
12074
12288
  configResolved(config) {
@@ -12103,6 +12317,7 @@ export default __mfShared.default ?? __mfShared;`
12103
12317
  resolveImportPath(ssrEntryLoaderSpecifier);
12104
12318
  options.runtimePlugins.push([ssrEntryLoaderSpecifier, {
12105
12319
  resolvedShared,
12320
+ ...config.command === "build" && { rebaseSharedAtRuntime: true },
12106
12321
  ...options.ssrEntryLoader
12107
12322
  }]);
12108
12323
  } catch {}
@@ -12132,7 +12347,7 @@ function withoutDynamicRemoteTypeHints(options) {
12132
12347
  }
12133
12348
  function loadPluginDts(options) {
12134
12349
  if (options.dts === false) return [];
12135
- return [import("./pluginDts-CVyHPAEq.js").then(({ default: pluginDts }) => pluginDts(options))];
12350
+ return [import("./pluginDts-rZMRTCTz.js").then(({ default: pluginDts }) => pluginDts(options))];
12136
12351
  }
12137
12352
  const INJECT_EXTERNAL_RUNTIME_CORE_PLUGIN = "@module-federation/vite/injectExternalRuntimeCorePlugin";
12138
12353
  function isInjectExternalRuntimeCorePlugin(specifier) {
@@ -12159,13 +12374,13 @@ function applyExternalRuntimeExperiments(options) {
12159
12374
  }
12160
12375
  }
12161
12376
  function federation(mfUserOptions) {
12162
- if (isTestEnv()) return [];
12377
+ if (process.env.MFE_VITE_NO_TEST_ENV_CHECK !== "true" && (process.env.NODE_ENV === "test" || process.env.VITEST != null || process.env.JEST_WORKER_ID != null)) return [];
12163
12378
  const options = normalizeModuleFederationOptions(mfUserOptions);
12164
12379
  if (!options.name) throw createModuleFederationError("name is required");
12165
12380
  if (options.experiments.hostProvidesAllShared) {
12166
12381
  const ignored = getIgnoredOptionWarning(mfUserOptions);
12167
12382
  if (ignored) mfWarn(ignored);
12168
- return [Object.keys(options.exposes).length > 0 ? pluginHostProvidesAllSharedRemote(options) : pluginHostProvidesAllSharedHost(options), ...loadPluginDts(withoutDynamicRemoteTypeHints(options))];
12383
+ return [isRemoteContainer(options) ? pluginHostProvidesAllSharedRemote(options) : pluginHostProvidesAllSharedHost(options), ...loadPluginDts(withoutDynamicRemoteTypeHints(options))];
12169
12384
  }
12170
12385
  applyExternalRuntimeExperiments(options);
12171
12386
  const isVinext = hasPackageDependency("vinext");
@@ -12220,9 +12435,9 @@ function federation(mfUserOptions) {
12220
12435
  const key = findSharedKey(pkg, shared);
12221
12436
  if (!key) return "not-applicable";
12222
12437
  const requestedModule = VirtualModule.findById(id);
12223
- const ownedModule = VirtualModule.findById(getLoadShareModulePath(pkg, false, options));
12438
+ const ownedModule = VirtualModule.findById(getLoadShareModulePath(pkg, options));
12224
12439
  if (!requestedModule || requestedModule !== ownedModule) return "not-owned";
12225
- writeLoadShareModule(pkg, shared[key], command, getIsRolldown(context), options, getLoadHookExportConditions(context, loadOptions), importFalseExportUsage);
12440
+ writeLoadShareModule(pkg, shared[key], command, options, getLoadHookExportConditions(context, loadOptions), importFalseExportUsage);
12226
12441
  return "refreshed";
12227
12442
  };
12228
12443
  const getCompleteImportFalseExportUsage = (id) => {
@@ -12365,9 +12580,7 @@ function federation(mfUserOptions) {
12365
12580
  name: "vite:module-federation-virtual-modules",
12366
12581
  enforce: "pre",
12367
12582
  configureServer(server) {
12368
- server.watcher.on("change", invalidateSharedExportInspectionCache);
12369
- server.watcher.on("add", invalidateSharedExportInspectionCache);
12370
- server.watcher.on("unlink", invalidateSharedExportInspectionCache);
12583
+ watchFileEvents(server.watcher, invalidateSharedExportInspectionCache);
12371
12584
  },
12372
12585
  resolveId(id) {
12373
12586
  if (id === "@module-federation/vite/ssrEntryLoader") return resolveImportPath(id);
@@ -12377,7 +12590,6 @@ function federation(mfUserOptions) {
12377
12590
  id,
12378
12591
  shared: options.shared,
12379
12592
  command,
12380
- isRolldown: getIsRolldown(this),
12381
12593
  findSharedKey,
12382
12594
  addUsedShares: (pkg) => addUsedShares(pkg, options),
12383
12595
  writeLocalSharedImportMap: () => writeLocalSharedImportMap(options),
@@ -12438,14 +12650,29 @@ function federation(mfUserOptions) {
12438
12650
  ssrResolveConditions = config.ssr?.resolve?.conditions ? [...config.ssr.resolve.conditions] : void 0;
12439
12651
  ssrTarget = config.ssr?.target ?? "node";
12440
12652
  isProduction = config.isProduction;
12441
- const ssrCapabilities = getSsrCapabilities(parseInt(version, 10), command, Object.keys(options.remotes).length > 0, isSsrConfig(config));
12653
+ const ssrCapabilities = getSsrCapabilities(parseInt(version, 10), command, hasRemotes(options), isSsrConfig(config));
12442
12654
  resolveSharedVersions(shared, config.root);
12443
12655
  initVirtualModules(command, remoteEntryId, ssrCapabilities.enableSsrInitBootstrap, options);
12444
12656
  }
12445
12657
  },
12446
12658
  aliasToArrayPlugin_default,
12447
12659
  checkAliasConflicts({ shared }),
12448
- normalizeOptimizeDeps_default,
12660
+ {
12661
+ name: "normalizeOptimizeDeps",
12662
+ config(config) {
12663
+ config.optimizeDeps ||= {};
12664
+ config.optimizeDeps.include ||= [];
12665
+ config.optimizeDeps.exclude ||= [];
12666
+ config.optimizeDeps.needsInterop ||= [];
12667
+ },
12668
+ configResolved(config) {
12669
+ const include = config.optimizeDeps?.include;
12670
+ const exclude = config.optimizeDeps?.exclude;
12671
+ if (!include?.length || !exclude?.length) return;
12672
+ const included = new Set(include);
12673
+ config.optimizeDeps.exclude = exclude.filter((dep) => !included.has(dep));
12674
+ }
12675
+ },
12449
12676
  ...loadPluginDts(options),
12450
12677
  pluginDevRemoteHmr(options),
12451
12678
  {
@@ -12470,7 +12697,7 @@ function federation(mfUserOptions) {
12470
12697
  entryName: "hostInit",
12471
12698
  entryPath: () => getHostAutoInitPath(options),
12472
12699
  inject: hostInitInjectLocation,
12473
- forceClientInjected: Object.keys(options.exposes).length > 0,
12700
+ forceClientInjected: isRemoteContainer(options),
12474
12701
  skipTransformFor: Object.values(options.exposes).map((expose) => expose.import),
12475
12702
  federationOptions: options
12476
12703
  }),
@@ -12668,10 +12895,6 @@ function federation(mfUserOptions) {
12668
12895
  config.optimizeDeps.include.push(optimizeDep);
12669
12896
  }
12670
12897
  });
12671
- if (isRolldown) {
12672
- config.build ??= {};
12673
- config.build.target ??= "esnext";
12674
- }
12675
12898
  const isBundledDev = Boolean(config.experimental?.bundledDev);
12676
12899
  if (isRolldown && _command === "serve" && isBundledDev) {
12677
12900
  config.build.rolldownOptions ??= {};
@@ -12715,6 +12938,7 @@ function federation(mfUserOptions) {
12715
12938
  },
12716
12939
  ...Manifest(options),
12717
12940
  ...pluginSSRRemoteEntry(options),
12941
+ ...pluginSsrRuntimeInit(options),
12718
12942
  ...VarRemoteEntry(options),
12719
12943
  {
12720
12944
  name: "module-federation-vinext-fix-rsc-preload-as",
@@ -12751,20 +12975,12 @@ function federation(mfUserOptions) {
12751
12975
  },
12752
12976
  ...(function() {
12753
12977
  let disablePreload = false;
12754
- return Object.keys(options.exposes).length > 0 ? [{
12978
+ return isRemoteContainer(options) ? [{
12755
12979
  name: "module-federation-fix-preload",
12756
12980
  enforce: "post",
12757
12981
  apply: "build",
12758
- config(_config, { command }) {
12759
- const manifest = options.manifest;
12760
- const getDefaultDisableAssetsAnalyze = (cfgCommand) => cfgCommand === "serve" && (typeof manifest !== "object" || !Object.hasOwn(manifest, "disableAssetsAnalyze"));
12761
- const getConfiguredDisableAssetsAnalyze = (cfgCommand) => {
12762
- if (typeof manifest === "object" && manifest !== null) {
12763
- if (Object.hasOwn(manifest, "disableAssetsAnalyze")) return manifest.disableAssetsAnalyze === true;
12764
- }
12765
- return getDefaultDisableAssetsAnalyze(cfgCommand);
12766
- };
12767
- disablePreload = getConfiguredDisableAssetsAnalyze(command);
12982
+ config() {
12983
+ disablePreload = resolveDisableAssetsAnalyze(options.manifest, false);
12768
12984
  },
12769
12985
  generateBundle(_outputOptions, bundle, _isWrite) {
12770
12986
  if (disablePreload) return;