@module-federation/vite 1.23.5 → 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 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, y as stripQueryAndHash } from "./sharedKeyMatcher-CHp4QRNq.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 REACT_DOM_CLIENT_SHARE, S as REACT_CLIENT_INTERNALS_KEY, _ as resolveImportPath, a as getIsRolldown, b as sharedCacheHelperCode, c as getPackageName, d as hasPackageDependency, f as isNuxtProjectRoot, g as packageNameEncode, h as packageNameDecode, i as getInstalledPackageJson, l as getPackageNameFromNodeModulePath, m as isPackageInstalled, n as getDependencyNames, o as getPackageDetectionCwd, p as isPackageExportAvailable, r as getInstalledPackageEntry, s as getPackageExportSpecifiersForFile, u as getSharedCacheDescriptor, v as resolveModulePath, w as isReactCoreShare, x as supportsCodeSplittingGroupDebugName, y as setPackageDetectionCwd } from "./dtsConstants-BQdFpgKb.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;
@@ -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
  }
@@ -2484,160 +2526,59 @@ function resolveReExportModule(filePath, specifier, exportConditions) {
2484
2526
  return;
2485
2527
  }
2486
2528
  }
2487
- /** Marks a template-literal frame whose text (not its interpolation) is being scanned. */
2488
- const TEMPLATE_TEXT = Symbol("templateText");
2489
2529
  function getAdditionalTopLevelDeclaratorNames(source, start, codePositions) {
2490
2530
  const names = [];
2491
2531
  let depth = 0;
2492
- let quote;
2493
- let escaped = false;
2494
- let canStartRegex = true;
2495
- const templateFrames = [];
2496
- const inTemplateText = () => templateFrames[templateFrames.length - 1] === TEMPLATE_TEXT;
2497
2532
  for (let index = start; index < source.length; index++) {
2498
2533
  const char = source[index];
2499
- if (inTemplateText()) {
2500
- if (escaped) escaped = false;
2501
- else if (char === "\\") escaped = true;
2502
- else if (char === "$" && source[index + 1] === "{") {
2503
- templateFrames.push(depth);
2504
- index++;
2505
- canStartRegex = true;
2506
- } else if (char === "`") {
2507
- templateFrames.pop();
2508
- canStartRegex = false;
2509
- }
2510
- continue;
2511
- }
2512
- if (quote) {
2513
- if (escaped) escaped = false;
2514
- else if (char === "\\") escaped = true;
2515
- else if (char === quote) quote = void 0;
2516
- continue;
2517
- }
2518
- if (char === "`") {
2519
- templateFrames.push(TEMPLATE_TEXT);
2520
- canStartRegex = false;
2521
- continue;
2522
- }
2523
- if (char === "\"" || char === "'") {
2524
- quote = char;
2525
- canStartRegex = false;
2526
- continue;
2527
- }
2534
+ if (!codePositions[index]) continue;
2528
2535
  if (char === "<" && source[index + 1] === "/") {
2529
2536
  const jsxClosingTag = source.slice(index).match(/^<\/\s*(?:[$_\p{ID_Start}][$_\u200C\u200D\p{ID_Continue}.:-]*\s*)?>/u);
2530
2537
  if (jsxClosingTag) {
2531
2538
  index += jsxClosingTag[0].length - 1;
2532
- canStartRegex = false;
2533
2539
  continue;
2534
2540
  }
2535
2541
  }
2536
- if (char === "/" && source[index + 1] === "/") {
2537
- index = source.indexOf("\n", index + 2);
2538
- if (index === -1) return names;
2539
- continue;
2540
- }
2541
- if (char === "/" && source[index + 1] === "*") {
2542
- const commentEnd = source.indexOf("*/", index + 2);
2543
- if (commentEnd === -1) return void 0;
2544
- index = commentEnd + 1;
2545
- continue;
2546
- }
2547
- if (char === "/" && canStartRegex) {
2548
- let regexEscaped = false;
2549
- let inCharacterClass = false;
2550
- let closed = false;
2551
- for (index++; index < source.length; index++) {
2552
- const regexChar = source[index];
2553
- if (regexEscaped) {
2554
- regexEscaped = false;
2555
- continue;
2556
- }
2557
- if (regexChar === "\\") {
2558
- regexEscaped = true;
2559
- continue;
2560
- }
2561
- if (regexChar === "[") {
2562
- inCharacterClass = true;
2563
- continue;
2564
- }
2565
- if (regexChar === "]" && inCharacterClass) {
2566
- inCharacterClass = false;
2567
- continue;
2568
- }
2569
- if (regexChar === "/" && !inCharacterClass) {
2570
- closed = true;
2571
- while (/[$_\p{ID_Continue}]/u.test(source[index + 1] || "")) index++;
2572
- break;
2573
- }
2574
- if (regexChar === "\n" || regexChar === "\r") return void 0;
2575
- }
2576
- if (!closed) return void 0;
2577
- canStartRegex = false;
2578
- continue;
2579
- }
2580
- if (char === "/") {
2581
- canStartRegex = true;
2582
- continue;
2583
- }
2584
2542
  if (/[$_\p{ID_Start}]/u.test(char)) {
2585
2543
  const tokenStart = index;
2586
2544
  while (/[$_\u200C\u200D\p{ID_Continue}]/u.test(source[index + 1] || "")) index++;
2587
2545
  const token = source.slice(tokenStart, index + 1);
2588
- if (depth === 0 && templateFrames.length === 0 && token === "export") {
2546
+ if (depth === 0 && token === "export") {
2589
2547
  let previous = tokenStart - 1;
2590
2548
  while (/\s/.test(source[previous] || "")) previous--;
2591
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;
2592
2550
  }
2593
- canStartRegex = /^(?:await|case|delete|in|instanceof|new|return|throw|typeof|void|yield)$/.test(token);
2594
2551
  continue;
2595
2552
  }
2596
2553
  if (/\d/.test(char)) {
2597
2554
  while (/[\w.]/.test(source[index + 1] || "")) index++;
2598
- canStartRegex = false;
2599
2555
  continue;
2600
2556
  }
2601
- if ((char === "+" || char === "-") && source[index + 1] === char) {
2602
- index++;
2603
- continue;
2604
- }
2605
- if (char === "!" && source[index + 1] !== "=") continue;
2606
2557
  if (char === "<") {
2607
2558
  const typeArgumentEnd = findLikelyTypeArgumentEnd(source, index, codePositions);
2608
2559
  if (typeArgumentEnd !== void 0) {
2609
2560
  index = typeArgumentEnd;
2610
- canStartRegex = false;
2611
2561
  continue;
2612
2562
  }
2613
2563
  }
2614
2564
  if (char === "(" || char === "[" || char === "{") {
2615
2565
  depth++;
2616
- canStartRegex = true;
2617
2566
  continue;
2618
2567
  }
2619
2568
  if (char === ")" || char === "]" || char === "}") {
2620
- if (char === "}" && templateFrames.length > 0 && templateFrames[templateFrames.length - 1] === depth) {
2621
- templateFrames.pop();
2622
- canStartRegex = false;
2623
- continue;
2624
- }
2625
2569
  depth = Math.max(0, depth - 1);
2626
- canStartRegex = false;
2627
2570
  continue;
2628
2571
  }
2629
- if (templateFrames.length === 0 && depth === 0 && char === ",") {
2572
+ if (depth === 0 && char === ",") {
2630
2573
  let bindingStart = index + 1;
2631
2574
  while (/\s/.test(source[bindingStart] || "")) bindingStart++;
2632
2575
  const binding = source.slice(bindingStart).match(new RegExp(`^(${JS_IDENTIFIER_PATTERN})`, "u"));
2633
2576
  if (!binding || !isValidEsmExportName(binding[1])) return void 0;
2634
2577
  names.push(binding[1]);
2635
2578
  index = bindingStart + binding[1].length - 1;
2636
- canStartRegex = false;
2637
2579
  continue;
2638
2580
  }
2639
- if (templateFrames.length === 0 && depth === 0 && char === ";") return names;
2640
- if (!/\s/.test(char)) canStartRegex = char !== ".";
2581
+ if (depth === 0 && char === ";") return names;
2641
2582
  }
2642
2583
  return names;
2643
2584
  }
@@ -3030,24 +2971,9 @@ function resolveConcreteSharedImportSource(pkg, projectRoot) {
3030
2971
  }
3031
2972
  const TREE_SHAKING_PROVIDER_TAG = "__treeShakingProvider__";
3032
2973
  const TREE_SHAKING_GRAPH_QUERY = "__mf_tree_shaking_graph__";
3033
- const legacySharedVirtualModuleState = {
3034
- preBuildCacheMap: {},
3035
- preBuildShareItemMap: {},
3036
- treeShakingProviderCacheMap: {},
3037
- materializedTreeShakingProviders: /* @__PURE__ */ new Set(),
3038
- loadShareCacheMap: {},
3039
- warnedMissingImportFalse: /* @__PURE__ */ new Set(),
3040
- coalescableLoadShares: /* @__PURE__ */ new Set()
3041
- };
3042
2974
  const sharedVirtualModuleStates = /* @__PURE__ */ new WeakMap();
3043
2975
  const sharedVirtualModuleStatesByOwner = /* @__PURE__ */ new Map();
3044
2976
  function getSharedVirtualModuleState(options) {
3045
- if (!options) try {
3046
- const currentOptions = getNormalizeModuleFederationOptions();
3047
- return sharedVirtualModuleStates.get(currentOptions) ?? legacySharedVirtualModuleState;
3048
- } catch {
3049
- return legacySharedVirtualModuleState;
3050
- }
3051
2977
  let state = sharedVirtualModuleStates.get(options);
3052
2978
  if (!state) {
3053
2979
  state = {
@@ -3107,8 +3033,7 @@ function getConcreteTreeShakingExportUsage(pkg, shareItem, options) {
3107
3033
  return getTreeShakingExportUsage(pkg, shareItem, shareItem?.name, options);
3108
3034
  }
3109
3035
  function getTreeShakingSharedProviderName(pkg, options) {
3110
- const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
3111
- 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)}`;
3112
3037
  }
3113
3038
  function getTreeShakingSharedProviderImportId(pkg, options) {
3114
3039
  const { treeShakingProviderCacheMap } = getSharedVirtualModuleState(options);
@@ -3166,7 +3091,6 @@ export default { get, init };
3166
3091
  materializedTreeShakingProviders.add(pkg);
3167
3092
  }
3168
3093
  function writePreBuildLibPath(pkg, shareItem, options, exportConditions) {
3169
- const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
3170
3094
  const { preBuildCacheMap, preBuildShareItemMap } = getSharedVirtualModuleState(options);
3171
3095
  if (!preBuildCacheMap[pkg]) preBuildCacheMap[pkg] = createScopedSharedVirtualModule(pkg, PREBUILD_TAG, options);
3172
3096
  preBuildShareItemMap[pkg] = shareItem;
@@ -3195,9 +3119,8 @@ function writePreBuildLibPath(pkg, shareItem, options, exportConditions) {
3195
3119
  }
3196
3120
  if (pkg === "react/jsx-dev-runtime") {
3197
3121
  preBuildCacheMap[pkg].writeSync(`
3198
- import __mfPrebuildDefault from ${escapeGeneratedStringLiteral(importSource)};
3199
3122
  import * as __mfPrebuildNamespace from ${escapeGeneratedStringLiteral(importSource)};
3200
- const __mfPrebuildExports = __mfPrebuildDefault ?? __mfPrebuildNamespace;
3123
+ const __mfPrebuildExports = ${getDefaultOrNamespaceExpression("__mfPrebuildNamespace")};
3201
3124
  export const Fragment = __mfPrebuildExports.Fragment;
3202
3125
  export const jsxDEV = __mfPrebuildExports.jsxDEV;
3203
3126
  export default __mfPrebuildExports;
@@ -3206,9 +3129,8 @@ function writePreBuildLibPath(pkg, shareItem, options, exportConditions) {
3206
3129
  }
3207
3130
  if (pkg === "react/jsx-runtime") {
3208
3131
  preBuildCacheMap[pkg].writeSync(`
3209
- import __mfPrebuildDefault from ${escapeGeneratedStringLiteral(importSource)};
3210
3132
  import * as __mfPrebuildNamespace from ${escapeGeneratedStringLiteral(importSource)};
3211
- const __mfPrebuildExports = __mfPrebuildDefault ?? __mfPrebuildNamespace;
3133
+ const __mfPrebuildExports = ${getDefaultOrNamespaceExpression("__mfPrebuildNamespace")};
3212
3134
  export const Fragment = __mfPrebuildExports.Fragment;
3213
3135
  export const jsx = __mfPrebuildExports.jsx;
3214
3136
  export const jsxs = __mfPrebuildExports.jsxs;
@@ -3218,7 +3140,7 @@ function writePreBuildLibPath(pkg, shareItem, options, exportConditions) {
3218
3140
  }
3219
3141
  const namedExports = getSharedNamedExports(pkg, shareItem, exportConditions) ?? [];
3220
3142
  if (namedExports.length > 0) {
3221
- const mutableExports = new Set(isLocalOnlyContainer(resolvedOptions) ? getSharedMutableExports(pkg, shareItem, exportConditions) : []);
3143
+ const mutableExports = new Set(isLocalOnlyContainer(options) ? getSharedMutableExports(pkg, shareItem, exportConditions) : []);
3222
3144
  const copiedExports = namedExports.filter((name) => !mutableExports.has(name));
3223
3145
  const liveExports = namedExports.filter((name) => mutableExports.has(name));
3224
3146
  const namedExportVars = copiedExports.map((_name, i) => `__mf_${i}`);
@@ -3231,26 +3153,23 @@ function writePreBuildLibPath(pkg, shareItem, options, exportConditions) {
3231
3153
  ${declarations}
3232
3154
  ${namedExportLine}
3233
3155
  ${liveExportLine}
3234
- export default Reflect.get(__mfPrebuildNamespace, "default") ?? __mfPrebuildNamespace;
3156
+ export default ${getDefaultOrNamespaceExpression("__mfPrebuildNamespace")};
3235
3157
  `, true);
3236
3158
  return;
3237
3159
  }
3238
3160
  preBuildCacheMap[pkg].writeSync(`
3239
3161
  import * as __mfPrebuildExports from ${escapeGeneratedStringLiteral(importSource)};
3240
3162
  export * from ${escapeGeneratedStringLiteral(importSource)};
3241
- // Reflect access avoids bundler warnings for ESM packages without a
3242
- // default export (for example antd/es/index.js), while preserving the
3243
- // namespace fallback for packages that do provide one.
3244
- export default Reflect.get(__mfPrebuildExports, "default") ?? __mfPrebuildExports;
3163
+ export default ${getDefaultOrNamespaceExpression("__mfPrebuildExports")};
3245
3164
  `, true);
3246
3165
  }
3247
3166
  /** Re-render already materialized wrappers after import analysis discovers exports. */
3248
- function refreshTreeShakingModules(options, command = "build", isRolldown = false, exportConditions) {
3167
+ function refreshTreeShakingModules(options, command = "build", exportConditions) {
3249
3168
  const { preBuildShareItemMap } = getSharedVirtualModuleState(options);
3250
3169
  for (const [pkg, shareItem] of Object.entries(preBuildShareItemMap)) {
3251
3170
  if (!shareItem?.shareConfig.treeShaking) continue;
3252
3171
  writePreBuildLibPath(pkg, shareItem, options, exportConditions);
3253
- writeLoadShareModule(pkg, shareItem, command, isRolldown, options, exportConditions);
3172
+ writeLoadShareModule(pkg, shareItem, command, options, exportConditions);
3254
3173
  }
3255
3174
  }
3256
3175
  function getPreBuildLibImportId(pkg, options) {
@@ -3264,16 +3183,11 @@ function getPreBuildShareItem(pkg, options) {
3264
3183
  function getSharedImportSource(pkg, shareItem, options) {
3265
3184
  return getConcreteSharedImportSource(pkg, shareItem) || getPreBuildLibImportId(pkg, options);
3266
3185
  }
3267
- function getLoadShareImportId(pkg, _isRolldown, options) {
3186
+ function getLoadShareModulePath(pkg, options) {
3268
3187
  const { loadShareCacheMap } = getSharedVirtualModuleState(options);
3269
3188
  if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = createScopedSharedVirtualModule(pkg, LOAD_SHARE_TAG, options);
3270
3189
  return loadShareCacheMap[pkg].getImportId();
3271
3190
  }
3272
- function getLoadShareModulePath(pkg, isRolldown, options) {
3273
- const { loadShareCacheMap } = getSharedVirtualModuleState(options);
3274
- if (!loadShareCacheMap[pkg]) getLoadShareImportId(pkg, isRolldown, options);
3275
- return loadShareCacheMap[pkg].getImportId();
3276
- }
3277
3191
  function getCachedSharedVirtualPkg(id, tag) {
3278
3192
  if (!id.includes(tag)) return;
3279
3193
  const normalized = normalizeVirtualModuleId(id);
@@ -3297,7 +3211,7 @@ function materializeCachedLoadShareModule(options) {
3297
3211
  const key = options.findSharedKey(pkg, options.shared);
3298
3212
  if (!key) return;
3299
3213
  const shareItem = options.shared[key];
3300
- writeLoadShareModule(pkg, shareItem, options.command, options.isRolldown, options.federationOptions);
3214
+ writeLoadShareModule(pkg, shareItem, options.command, options.federationOptions);
3301
3215
  if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(pkg, shareItem, options.federationOptions);
3302
3216
  options.addUsedShares(pkg);
3303
3217
  options.writeLocalSharedImportMap();
@@ -3542,23 +3456,37 @@ function markLoadShareWrapperNotCoalescable(pkg, options, id) {
3542
3456
  function isCoalescableLoadShareWrapper(pkg, options, id) {
3543
3457
  return getSharedVirtualModuleStateForId(id, options).coalescableLoadShares.has(pkg);
3544
3458
  }
3545
- function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exportConditions, importFalseExportUsage) {
3546
- 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) {
3547
3475
  const { loadShareCacheMap, coalescableLoadShares } = getSharedVirtualModuleState(options);
3548
3476
  const edges = createLocalPayloadEdges();
3549
3477
  if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = createScopedSharedVirtualModule(pkg, LOAD_SHARE_TAG, options);
3550
3478
  let importLine = getRuntimeModuleCacheBootstrapCode(exportConditions);
3551
3479
  const cacheDescriptor = getSharedCacheDescriptorLiteral(pkg, shareItem);
3552
- const cacheOwner = JSON.stringify(resolvedOptions.name);
3553
- const runtimeInitOwnerImportId = options ? getRuntimeInitStatusImportId(options) : void 0;
3554
- 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;
3555
3483
  if (shareItem.shareConfig.import === false) {
3556
3484
  const detectedNamedExports = getPackageNamedExports(pkg, exportConditions);
3557
3485
  const namedExports = selectImportFalseNamedExports(detectedNamedExports, importFalseExportUsage);
3558
3486
  let exportLine;
3559
3487
  if (namedExports.length > 0) exportLine = generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor, treeShakingConsumer);
3560
3488
  else {
3561
- const { warnedMissingImportFalse } = getSharedVirtualModuleState(resolvedOptions);
3489
+ const { warnedMissingImportFalse } = getSharedVirtualModuleState(options);
3562
3490
  if (detectedNamedExports === void 0 && !shareItem.shareConfig.suppressMissingImportWarning && !warnedMissingImportFalse.has(pkg)) {
3563
3491
  warnedMissingImportFalse.add(pkg);
3564
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.`);
@@ -3584,20 +3512,22 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3584
3512
  const skipServePrebuildWarmup = command !== "build" && (pkg === "lit" || pkg.startsWith("lit/"));
3585
3513
  const detectedNamedExports = getSharedNamedExports(pkg, shareItem, exportConditions);
3586
3514
  const namedExports = detectedNamedExports ?? [];
3587
- const mutableExports = new Set(isLocalOnlyContainer(resolvedOptions) ? getSharedMutableExports(pkg, shareItem, exportConditions) : []);
3515
+ const mutableExports = new Set(isLocalOnlyContainer(options) ? getSharedMutableExports(pkg, shareItem, exportConditions) : []);
3588
3516
  const copiedNamedExports = namedExports.filter((name) => !mutableExports.has(name));
3589
3517
  const liveNamedExports = namedExports.filter((name) => mutableExports.has(name));
3590
3518
  const liveNamedExportLine = edges.reExportNames(liveNamedExports, sharedImportSource);
3591
3519
  const hasCompleteExportCoverage = detectedNamedExports !== void 0;
3592
- const isWorkspaceSingleton = isWorkspacePackage && shareItem.shareConfig.singleton === true;
3593
- const usesDeferredSingletonFallback = hasCompleteExportCoverage && shareItem.shareConfig.eager !== true && (isWorkspacePackage || command !== "build" && isRemoteOnlyContainer(resolvedOptions) && shareItem.shareConfig.singleton === true || command === "build" && isRemoteContainer(resolvedOptions) && !isSharedSingletonConsumedByPeer(pkg, resolvedOptions, true));
3594
- const servesRemoteSingletonFallback = command !== "build" && isRemoteOnlyContainer(resolvedOptions) && shareItem.shareConfig.singleton === true;
3595
- const isConsumedByPeerSingleton = isSharedSingletonConsumedByPeer(pkg, resolvedOptions);
3596
- const usesEntryInjectedRemoteFallback = hasCompleteExportCoverage && !isWorkspaceSingleton && isRemoteContainer(resolvedOptions) && shareItem.shareConfig.singleton === true && resolvedOptions.hostInitInjectLocation === "entry" && (command === "build" || isConsumedByPeerSingleton);
3597
- 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));
3598
3527
  const usesEagerWorkspaceFallback = hasCompleteExportCoverage && isWorkspaceSingleton && !servesRemoteSingletonFallback && (isConsumedByPeerSingleton || shareItem.shareConfig.eager === true);
3599
3528
  const usesDeferredTreeShakingFallback = hasCompleteExportCoverage && Boolean(treeShakingConsumer);
3600
- const reactMixedModeGuard = pkg === "react" ? createReactMixedModeRuntimeGuard() : "";
3529
+ const rebindsSharedExports = isSingleton || options.shareStrategy === "version-first";
3530
+ const reactMixedModeGuard = pkg === "react" && isSingleton ? REACT_MIXED_MODE_GUARD : "";
3601
3531
  let exportLine;
3602
3532
  let initBlock = "";
3603
3533
  if (usesDeferredTreeShakingFallback) {
@@ -3622,7 +3552,7 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3622
3552
  ${edges.reExportAll(coherentLocalSource)}`;
3623
3553
  initBlock = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
3624
3554
  __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});`;
3625
- } else if (namedExports.length > 0 && shareItem.shareConfig.singleton === true) {
3555
+ } else if (namedExports.length > 0 && rebindsSharedExports) {
3626
3556
  const namedExportVars = copiedNamedExports.map((_name, i) => `__mf_${i}`);
3627
3557
  exportLine = `${["let __mfDefaultExport;", ...namedExportVars.map((name) => `let ${name};`)].join("\n ")}
3628
3558
  const __mfApplySharedExports = (mod) => {
@@ -3661,7 +3591,7 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3661
3591
  ${liveNamedExportLine}`;
3662
3592
  initBlock = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
3663
3593
  __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});`;
3664
- } else if (shareItem.shareConfig.singleton === true) {
3594
+ } else if (rebindsSharedExports) {
3665
3595
  exportLine = `let __mfDefaultExport;
3666
3596
  const __mfApplySharedDefaultExport = (mod) => {
3667
3597
  ${reactMixedModeGuard}
@@ -3681,7 +3611,7 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3681
3611
  const staticLocalShareSource = detectedNamedExports === void 0 ? coherentLocalSource : skipServePrebuildWarmup ? devImportSource : sharedImportSource;
3682
3612
  const prebuildImportLine = usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback ? "" : usesDeferredSingletonFallback || usesDeferredTreeShakingFallback ? !servesRemoteSingletonFallback && usesDeferredSingletonFallback && command !== "build" && (isWorkspaceSingleton || isWorkspacePackage) ? edges.importNamespace(lazyLocalFallbackSource) : "" : edges.importNamespace(staticLocalShareSource);
3683
3613
  const devDynamicImportLine = isWorkspacePackage ? "" : usesDeferredSingletonFallback || usesDeferredTreeShakingFallback || usesDeferredEntryInjectedSingletonFallback ? "" : command !== "build" && !skipServePrebuildWarmup ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
3684
- 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;
3685
3615
  const moduleBody = usesDeferredSingletonFallback || usesDeferredTreeShakingFallback || usesDeferredEntryInjectedSingletonFallback || usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback ? `
3686
3616
  ${usesDeferredEntryInjectedSingletonFallback ? "" : prebuildImportLine}
3687
3617
  ${devDynamicImportLine}
@@ -3706,10 +3636,9 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3706
3636
  }
3707
3637
  //#endregion
3708
3638
  //#region src/virtualModules/virtualRemoteEntry.ts
3709
- let usedShares = /* @__PURE__ */ new Set();
3710
3639
  const usedSharesByOptions = /* @__PURE__ */ new WeakMap();
3711
3640
  const materializedSharesByOptions = /* @__PURE__ */ new WeakMap();
3712
- function getScopedUsedShares(options) {
3641
+ function getUsedShares(options) {
3713
3642
  let scoped = usedSharesByOptions.get(options);
3714
3643
  if (!scoped) {
3715
3644
  scoped = /* @__PURE__ */ new Set();
@@ -3717,25 +3646,17 @@ function getScopedUsedShares(options) {
3717
3646
  }
3718
3647
  return scoped;
3719
3648
  }
3720
- function getUsedShares(options) {
3721
- if (options) return getScopedUsedShares(options);
3722
- return usedShares;
3723
- }
3724
3649
  function addUsedShares(pkg, options) {
3725
- usedShares.add(pkg);
3726
- if (options) getScopedUsedShares(options).add(pkg);
3727
- if (options) {
3728
- let scoped = materializedSharesByOptions.get(options);
3729
- if (!scoped) {
3730
- scoped = /* @__PURE__ */ new Set();
3731
- materializedSharesByOptions.set(options, scoped);
3732
- }
3733
- 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);
3734
3655
  }
3656
+ scoped.add(pkg);
3735
3657
  }
3736
3658
  function addConfiguredShare(pkg, options) {
3737
- usedShares.add(pkg);
3738
- if (options) getScopedUsedShares(options).add(pkg);
3659
+ getUsedShares(options).add(pkg);
3739
3660
  }
3740
3661
  const LOCAL_SHARED_IMPORT_MAP_ID = "virtual:mf-localSharedImportMap";
3741
3662
  const LAZY_CONSUME_ONLY_SHARES_PLACEHOLDER = "__MF_LAZY_CONSUME_ONLY_SHARES__";
@@ -3757,15 +3678,13 @@ function getLocalSharedImportMapPath(options) {
3757
3678
  function getResolvedLocalSharedImportMapId(options) {
3758
3679
  return `\0${getLocalSharedImportMapPath(options)}`;
3759
3680
  }
3760
- let invalidateLocalSharedImportMap;
3761
3681
  const localSharedImportMapInvalidators = /* @__PURE__ */ new WeakMap();
3762
3682
  function setLocalSharedImportMapInvalidator(invalidator, options) {
3763
- if (!options) invalidateLocalSharedImportMap = invalidator;
3764
- else if (invalidator) localSharedImportMapInvalidators.set(options, invalidator);
3683
+ if (invalidator) localSharedImportMapInvalidators.set(options, invalidator);
3765
3684
  else localSharedImportMapInvalidators.delete(options);
3766
3685
  }
3767
3686
  function writeLocalSharedImportMap(options) {
3768
- (options ? localSharedImportMapInvalidators.get(options) : invalidateLocalSharedImportMap)?.();
3687
+ localSharedImportMapInvalidators.get(options)?.();
3769
3688
  }
3770
3689
  function shouldUseDirectReactImport() {
3771
3690
  const isVinext = hasPackageDependency("vinext");
@@ -3786,15 +3705,15 @@ function getDirectSharedCacheSeedImportPath(pkg, shareItem) {
3786
3705
  function generateLocalSharedImportMap(options) {
3787
3706
  const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
3788
3707
  const useDirectReactImport = shouldUseDirectReactImport();
3789
- const orderedShares = getOrderedUsedShares(options);
3790
- const sharesToMaterialize = new Set(getMaterializedShares(options));
3708
+ const orderedShares = getOrderedUsedShares(resolvedOptions);
3709
+ const sharesToMaterialize = new Set(getMaterializedShares(resolvedOptions));
3791
3710
  const hasConsumeOnlyShare = orderedShares.some((pkg) => getNormalizeShareItem(pkg, resolvedOptions)?.shareConfig.import === false);
3792
3711
  return `
3793
3712
  import {loadShare} from "@module-federation/runtime";
3794
3713
  ${orderedShares.map((pkg, index) => {
3795
3714
  const shareItem = getNormalizeShareItem(pkg, resolvedOptions);
3796
3715
  if (!shareItem || !shareItem.shareConfig.eager || shareItem.shareConfig.import === false) return "";
3797
- return `import * as __mfEagerShare_${index} from ${toSafeJsLiteral(getLocalSharedPackagePath(pkg, shareItem, options))};`;
3716
+ return `import * as __mfEagerShare_${index} from ${toSafeJsLiteral(getLocalSharedPackagePath(pkg, shareItem, resolvedOptions))};`;
3798
3717
  }).filter(Boolean).join("\n")}
3799
3718
  ${normalizeRuntimeShareCode}
3800
3719
  const __mfGetCachedReactFamily = (keys, reactKeys, localVersion, requiredExport) => {
@@ -3867,7 +3786,7 @@ function generateLocalSharedImportMap(options) {
3867
3786
  return `
3868
3787
  ${toSafeJsLiteral(pkg)}: async () => {
3869
3788
  ${shareItem?.shareConfig.eager ? `let pkg = __mfEagerShare_${index};
3870
- return pkg;` : `let pkg = await import(${toSafeJsLiteral(getLocalSharedPackagePath(pkg, shareItem, options))});
3789
+ return pkg;` : `let pkg = await import(${toSafeJsLiteral(getLocalSharedPackagePath(pkg, shareItem, resolvedOptions))});
3871
3790
  return pkg;`}
3872
3791
  }
3873
3792
  `;
@@ -3891,11 +3810,11 @@ function generateLocalSharedImportMap(options) {
3891
3810
  const treeShakingConfig = canLiveRebind ? shareItem.shareConfig.treeShaking : void 0;
3892
3811
  if (shareItem.shareConfig.import === false && !treeShakingConfig) return `
3893
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)},` : ""}})`;
3894
- const treeShakingUsage = treeShakingConfig ? getTreeShakingExportUsage(key, shareItem, shareItem.name, options) : void 0;
3813
+ const treeShakingUsage = treeShakingConfig ? getTreeShakingExportUsage(key, shareItem, shareItem.name, resolvedOptions) : void 0;
3895
3814
  const treeShakingProviderExports = treeShakingUsage?.kind === "exports" ? treeShakingUsage.usedExports : [];
3896
3815
  const treeShakingUsedExports = resolvedOptions.injectTreeShakingUsedExports === false ? treeShakingConfig?.usedExports || [] : treeShakingProviderExports;
3897
3816
  const disableRuntimeInference = treeShakingConfig?.mode === "runtime-infer" && resolvedOptions.injectTreeShakingUsedExports === false;
3898
- 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;
3899
3818
  const treeShakingStatus = treeShakingUsage?.kind === "full" || disableRuntimeInference || treeShakingConfig?.mode === "runtime-infer" && !treeShakingProviderImportId && shareItem.shareConfig.import !== false ? 0 : 1;
3900
3819
  return `
3901
3820
  ${toSafeJsLiteral(key)}: {
@@ -3980,7 +3899,7 @@ function generateLocalSharedImportMap(options) {
3980
3899
  `;
3981
3900
  }).filter((x) => x !== null).join(",")}
3982
3901
  }
3983
- const usedRemotes = [${Object.keys(getUsedRemotesMap(options)).map((key) => {
3902
+ const usedRemotes = [${Object.keys(getUsedRemotesMap(resolvedOptions)).map((key) => {
3984
3903
  const remote = resolvedOptions.remotes[key];
3985
3904
  if (!remote) return null;
3986
3905
  return `
@@ -4013,30 +3932,27 @@ function expandSharedPrefixKey(prefixKey, used) {
4013
3932
  return [...expanded];
4014
3933
  }
4015
3934
  function getOrderedUsedShares(options) {
4016
- const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
4017
3935
  const used = getUsedShares(options);
4018
3936
  const shares = /* @__PURE__ */ new Set();
4019
3937
  const addShare = (pkg) => {
4020
- const shareItem = getNormalizeShareItem(pkg, resolvedOptions);
3938
+ const shareItem = getNormalizeShareItem(pkg, options);
4021
3939
  shares.add(shareItem ? getCanonicalSharedKey(pkg, shareItem) : pkg);
4022
3940
  };
4023
3941
  used.forEach(addShare);
4024
- Object.keys(resolvedOptions.shared ?? {}).forEach((pkg) => {
4025
- const share = resolvedOptions.shared?.[pkg];
3942
+ Object.keys(options.shared ?? {}).forEach((pkg) => {
3943
+ const share = options.shared?.[pkg];
4026
3944
  if (share && !getSharedRequest(pkg, share).endsWith("/")) addShare(pkg);
4027
3945
  });
4028
- 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);
4029
3947
  return orderSharedDependenciesFirst(Array.from(shares).sort((a, b) => {
4030
3948
  const priority = (pkg) => pkg === "react" ? 0 : pkg === "react-dom" ? 1 : pkg.startsWith("react/") ? 2 : 3;
4031
3949
  return priority(a) - priority(b) || a.localeCompare(b);
4032
3950
  }));
4033
3951
  }
4034
3952
  function getMaterializedShares(options) {
4035
- const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
4036
- const scopedRegistrations = options ? usedSharesByOptions.get(options) : void 0;
4037
- const shares = new Set(options && scopedRegistrations?.size ? materializedSharesByOptions.get(options) ?? [] : usedShares);
4038
- const usedForEager = options ? usedSharesByOptions.get(options) ?? [] : usedShares;
4039
- 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 ?? {})) {
4040
3956
  if (!share.shareConfig?.eager) continue;
4041
3957
  const request = getSharedRequest(pkg, share);
4042
3958
  if (request.endsWith("/")) for (const concrete of expandSharedPrefixKey(request, usedForEager)) shares.add(concrete);
@@ -4050,7 +3966,7 @@ function getMaterializedShares(options) {
4050
3966
  const pending = [...shares];
4051
3967
  while (pending.length) {
4052
3968
  const pkg = pending.pop();
4053
- const share = getNormalizeShareItem(pkg, resolvedOptions);
3969
+ const share = getNormalizeShareItem(pkg, options);
4054
3970
  const packageName = getPackageName(pkg);
4055
3971
  const packageJson = getInstalledPackageJson(pkg)?.packageJson ?? (pkg !== packageName ? getInstalledPackageJson(packageName)?.packageJson : void 0);
4056
3972
  const dependencies = {
@@ -4061,7 +3977,7 @@ function getMaterializedShares(options) {
4061
3977
  };
4062
3978
  for (const dependency of Object.keys(dependencies)) {
4063
3979
  const sharedDependency = configured.get(dependency);
4064
- const dependencyShare = sharedDependency ? getNormalizeShareItem(sharedDependency, resolvedOptions) : void 0;
3980
+ const dependencyShare = sharedDependency ? getNormalizeShareItem(sharedDependency, options) : void 0;
4065
3981
  if (sharedDependency && !shares.has(sharedDependency) && dependencyShare?.scope === share?.scope) {
4066
3982
  shares.add(sharedDependency);
4067
3983
  pending.push(sharedDependency);
@@ -4073,7 +3989,7 @@ function getMaterializedShares(options) {
4073
3989
  return priority(a) - priority(b) || a.localeCompare(b);
4074
3990
  });
4075
3991
  return orderSharedDependenciesFirst([...new Set(sorted.map((pkg) => {
4076
- const shareItem = getNormalizeShareItem(pkg, resolvedOptions);
3992
+ const shareItem = getNormalizeShareItem(pkg, options);
4077
3993
  return shareItem ? getCanonicalSharedKey(pkg, shareItem) : pkg;
4078
3994
  }))]);
4079
3995
  }
@@ -4487,6 +4403,19 @@ function generateRuntimeSharedCacheSeedCode(shareStrategy, options, command = "b
4487
4403
  );
4488
4404
  return;
4489
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
+ }
4490
4419
  // Leave an unloaded webpack provider to the late bridge, which only takes a
4491
4420
  // non-singleton of this share's own version; any other version seeds locally.
4492
4421
  if (
@@ -4596,10 +4525,9 @@ function getBrowserImportPath(importPath) {
4596
4525
  return importPath;
4597
4526
  }
4598
4527
  function getHostAutoInitSharedSeedItems(options) {
4599
- const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
4600
4528
  return getMaterializedShares(options).map((pkg) => ({
4601
4529
  pkg,
4602
- shareItem: getShareItemForPreload(pkg, resolvedOptions)
4530
+ shareItem: getShareItemForPreload(pkg, options)
4603
4531
  })).filter(({ shareItem }) => shareItem?.shareConfig?.import === false).sort((a, b) => {
4604
4532
  const priority = (pkg) => pkg === "vue" ? 0 : pkg === "pinia" ? 1 : 2;
4605
4533
  const aIsLocal = !!getLocalProviderImportPath(a.pkg);
@@ -4610,7 +4538,7 @@ function getHostAutoInitSharedSeedItems(options) {
4610
4538
  function generateHostAutoInitSharedCacheSeedCode(command = "build", options) {
4611
4539
  if (command === "build") return "";
4612
4540
  const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
4613
- return getHostAutoInitSharedSeedItems(options).map(({ pkg, shareItem }) => {
4541
+ return getHostAutoInitSharedSeedItems(resolvedOptions).map(({ pkg, shareItem }) => {
4614
4542
  if (!shareItem) return null;
4615
4543
  return generateSharedCacheSeedItem(pkg, shareItem, getBrowserImportPath(getDirectSharedCacheSeedImportPath(pkg, shareItem)), resolvedOptions);
4616
4544
  }).filter((item) => item !== null).join("\n");
@@ -5796,13 +5724,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
5796
5724
  */
5797
5725
  const HOST_AUTO_INIT_TAG = "__H_A_I__";
5798
5726
  const hostAutoInitStates = /* @__PURE__ */ new WeakMap();
5799
- const legacyHostAutoInitState = {
5800
- module: new VirtualModule("hostAutoInit", HOST_AUTO_INIT_TAG),
5801
- remoteEntryId: REMOTE_ENTRY_ID,
5802
- command: "build"
5803
- };
5804
5727
  function getHostAutoInitState(options) {
5805
- if (!options) return legacyHostAutoInitState;
5806
5728
  let state = hostAutoInitStates.get(options);
5807
5729
  if (!state) {
5808
5730
  const ownerKey = getLocalOwnerKey(options);
@@ -5818,7 +5740,7 @@ function getHostAutoInitState(options) {
5818
5740
  function generateHostAutoInitCode(remoteEntryImport, _command = "build", options, exportConditions) {
5819
5741
  const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
5820
5742
  const shouldPreloadShares = resolvedOptions.shareStrategy !== "loaded-first";
5821
- const hostInitShareBatches = toSafeJsLiteral(getShareBatches(options, false));
5743
+ const hostInitShareBatches = toSafeJsLiteral(getShareBatches(resolvedOptions, false));
5822
5744
  const cacheOwner = toSafeJsLiteral(resolvedOptions.name);
5823
5745
  const preferLocalVinextReact = hasPackageDependency("vinext") && (!exportConditions?.includes("browser") || exportConditions.includes("worker"));
5824
5746
  const hasConfiguredShared = hasShared(resolvedOptions);
@@ -5862,6 +5784,15 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build", options
5862
5784
  )
5863
5785
  );
5864
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
+ }
5865
5796
  ${hostInitSharedProviderHelperCode}
5866
5797
  for (const __mfHostInitShareBatch of __mfHostInitShareBatches) {
5867
5798
  await Promise.all(__mfHostInitShareBatch.map(async (pkg) => {
@@ -5876,9 +5807,10 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build", options
5876
5807
  if (
5877
5808
  __mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined &&
5878
5809
  ${_command === "serve" ? `__mfReadSharedCacheOwner(__mfModuleCache.share, cacheDescriptor) !== undefined &&
5879
- !(share.shareConfig?.singleton && __mfHasAlternativeSharedVersion(pkg, share))` : `(
5880
- (!share.shareConfig?.singleton && __mfReadSharedCacheOwner(__mfModuleCache.share, cacheDescriptor) === ${cacheOwner}) ||
5881
- (share.shareConfig?.singleton && !__mfHasAlternativeSharedVersion(pkg, share))
5810
+ !__mfHasAlternativeSharedVersion(pkg, share)` : `(
5811
+ !__mfHasAlternativeSharedVersion(pkg, share) &&
5812
+ (share.shareConfig?.singleton ||
5813
+ __mfReadSharedCacheOwner(__mfModuleCache.share, cacheDescriptor) === ${cacheOwner})
5882
5814
  )`}
5883
5815
  ) return;
5884
5816
  // An import:false share has nothing to load until a foreign provider
@@ -5968,7 +5900,7 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build", options
5968
5900
  export { initHost, hostInitPromise };
5969
5901
  `;
5970
5902
  }
5971
- function writeHostAutoInit(remoteEntryId = REMOTE_ENTRY_ID, command = "build", options, exportConditions) {
5903
+ function writeHostAutoInit(remoteEntryId = REMOTE_ENTRY_ID, command, options, exportConditions) {
5972
5904
  const state = getHostAutoInitState(options);
5973
5905
  state.remoteEntryId = remoteEntryId;
5974
5906
  state.command = command;
@@ -5996,13 +5928,8 @@ function isOwnedHostAutoInitId(id, options) {
5996
5928
  * free of wrapper references.
5997
5929
  */
5998
5930
  const PENDING_SHARES_TAG = "__P_S__";
5999
- const legacyPendingSharesState = {
6000
- module: new VirtualModule("pendingShares", PENDING_SHARES_TAG),
6001
- command: "build"
6002
- };
6003
5931
  const pendingSharesStates = /* @__PURE__ */ new WeakMap();
6004
5932
  function getPendingSharesState(options) {
6005
- if (!options) return legacyPendingSharesState;
6006
5933
  let state = pendingSharesStates.get(options);
6007
5934
  if (!state) {
6008
5935
  state = {
@@ -6015,14 +5942,14 @@ function getPendingSharesState(options) {
6015
5942
  }
6016
5943
  function generatePendingSharesCode(command = "build", options) {
6017
5944
  const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
6018
- const pendingSharePkgs = command === "build" ? getMaterializedShares(options).filter((pkg) => {
5945
+ const pendingSharePkgs = command === "build" ? getMaterializedShares(resolvedOptions).filter((pkg) => {
6019
5946
  const shareItem = getShareItemForPreload(pkg, resolvedOptions);
6020
5947
  if (!shareItem || pkg.endsWith("/")) return false;
6021
5948
  if (shareItem.shareConfig.eager) return false;
6022
5949
  return shareItem.shareConfig.import !== false && !shareItem.shareConfig.treeShaking;
6023
5950
  }) : [];
6024
5951
  if (command === "build" && shouldPreloadEntryDeferredReactDomClient(resolvedOptions) && !pendingSharePkgs.includes("react-dom/client")) pendingSharePkgs.push(REACT_DOM_CLIENT_SHARE);
6025
- 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))})]`);
6026
5953
  return `
6027
5954
  ${getRuntimeModuleCacheBootstrapCode()}
6028
5955
  ${sharedCacheHelperCode}
@@ -6048,7 +5975,7 @@ function generatePendingSharesCode(command = "build", options) {
6048
5975
  }
6049
5976
  `;
6050
5977
  }
6051
- function writePendingShares(command = "build", options) {
5978
+ function writePendingShares(command, options) {
6052
5979
  const state = getPendingSharesState(options);
6053
5980
  state.command = command;
6054
5981
  state.module.writeSync(generatePendingSharesCode(command, options), true);
@@ -6107,20 +6034,11 @@ function refreshRemoteModuleForEnvironment(id, options, exportConditions) {
6107
6034
  virtual.write(generateRemotes(metadata.remote, metadata.command, metadata.enableSsrInit, metadata.consumer, options, exportConditions));
6108
6035
  return true;
6109
6036
  }
6110
- const usedRemotesMap = {};
6111
6037
  const usedRemotesByOptions = /* @__PURE__ */ new WeakMap();
6112
6038
  const dynamicRemotesByOptions = /* @__PURE__ */ new WeakMap();
6113
6039
  const staticRemotesByOptions = /* @__PURE__ */ new WeakMap();
6114
6040
  const preloadRemotesByOptions = /* @__PURE__ */ new WeakMap();
6115
6041
  const EMPTY_STATIC_REMOTES = /* @__PURE__ */ new Set();
6116
- function getScopedUsedRemotesMap(options) {
6117
- let scoped = usedRemotesByOptions.get(options);
6118
- if (!scoped) {
6119
- scoped = {};
6120
- usedRemotesByOptions.set(options, scoped);
6121
- }
6122
- return scoped;
6123
- }
6124
6042
  function recordUsedRemote(map, remoteKey, remoteModule) {
6125
6043
  ensureUsedRemoteKey(map, remoteKey).add(remoteModule);
6126
6044
  }
@@ -6129,16 +6047,18 @@ function ensureUsedRemoteKey(map, remoteKey) {
6129
6047
  return map[remoteKey];
6130
6048
  }
6131
6049
  function ensureUsedRemote(remoteKey, options) {
6132
- ensureUsedRemoteKey(usedRemotesMap, remoteKey);
6133
- if (options) ensureUsedRemoteKey(getScopedUsedRemotesMap(options), remoteKey);
6050
+ ensureUsedRemoteKey(getUsedRemotesMap(options), remoteKey);
6134
6051
  }
6135
6052
  function addUsedRemote(remoteKey, remoteModule, options) {
6136
- recordUsedRemote(usedRemotesMap, remoteKey, remoteModule);
6137
- if (options) recordUsedRemote(getScopedUsedRemotesMap(options), remoteKey, remoteModule);
6053
+ recordUsedRemote(getUsedRemotesMap(options), remoteKey, remoteModule);
6138
6054
  }
6139
6055
  function getUsedRemotesMap(options) {
6140
- if (options) return getScopedUsedRemotesMap(options);
6141
- return usedRemotesMap;
6056
+ let usedRemotes = usedRemotesByOptions.get(options);
6057
+ if (!usedRemotes) {
6058
+ usedRemotes = {};
6059
+ usedRemotesByOptions.set(options, usedRemotes);
6060
+ }
6061
+ return usedRemotes;
6142
6062
  }
6143
6063
  function markDynamicRemote(remote, options) {
6144
6064
  let remotes = dynamicRemotesByOptions.get(options);
@@ -6208,12 +6128,6 @@ function getEagerDeferredClientInit() {
6208
6128
  return `__mfRemotePending = __mfStartRemoteLoad().then(__mfAssignRemoteModule);
6209
6129
  exportModule = __mfCreateDeferredRemoteProxy();`;
6210
6130
  }
6211
- function shouldIncludeDeferredProxy(initMode, consumer, eagerLoadClientRemote, deferRemoteLoad) {
6212
- if (eagerLoadClientRemote && consumer !== "server") return true;
6213
- if (initMode === "eager") return consumer !== "server" && (consumer === "unified" || !eagerLoadClientRemote);
6214
- if (consumer === "client" && eagerLoadClientRemote) return false;
6215
- return deferRemoteLoad || consumer !== "server";
6216
- }
6217
6131
  /** Codegen shared by every remote virtual module (no top-level await). */
6218
6132
  function getRemoteModuleRuntimeHelpers() {
6219
6133
  return `
@@ -6254,12 +6168,16 @@ function getDeferredProxyHelper(remoteCacheKey) {
6254
6168
  function __mfCreateDeferredRemoteProxy() {
6255
6169
  let pendingPromise;
6256
6170
  const ensurePending = () => {
6257
- 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
+ }
6258
6176
  return pendingPromise;
6259
6177
  };
6260
6178
  const getModule = () => __mfModuleCache.remote[${JSON.stringify(remoteCacheKey)}];
6261
6179
  const proxyTarget = function (...args) {
6262
- pendingPromise ||= __mfStartRemoteLoad();
6180
+ ensurePending();
6263
6181
  const mod = getModule();
6264
6182
  const fn = mod && (mod.default ?? mod);
6265
6183
  if (fn !== undefined && fn !== null) {
@@ -6278,7 +6196,7 @@ function getDeferredProxyHelper(remoteCacheKey) {
6278
6196
  if (mod) {
6279
6197
  return prop in mod ? mod[prop] : mod.default?.[prop];
6280
6198
  }
6281
- pendingPromise ||= __mfStartRemoteLoad();
6199
+ ensurePending();
6282
6200
  if (prop === "default") return proxyTarget;
6283
6201
  throw ensurePending();
6284
6202
  },
@@ -6318,9 +6236,19 @@ function getDeferredProxyHelper(remoteCacheKey) {
6318
6236
  }`;
6319
6237
  }
6320
6238
  function getLazyRemotePendingExport() {
6321
- 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 = {
6322
6246
  then(onFulfilled, onRejected) {
6323
- 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);
6324
6252
  },
6325
6253
  };`;
6326
6254
  }
@@ -6380,12 +6308,11 @@ export { __mfDefaultExport as default };`;
6380
6308
  function generateRemotes(id, command, enableSsrInit = false, consumer = "unified", options, exportConditions) {
6381
6309
  const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
6382
6310
  const isLoadedFirst = resolvedOptions.shareStrategy === "loaded-first";
6383
- const initMode = resolveRemoteInitMode(resolvedOptions.shareStrategy, consumer);
6384
- const deferRemoteLoad = shouldDeferRemoteLoad(initMode);
6311
+ const deferRemoteLoad = shouldDeferRemoteLoad(resolveRemoteInitMode(resolvedOptions.shareStrategy, consumer));
6385
6312
  const runtimeRemoteId = getRuntimeRemoteId(id, resolvedOptions.remotes, options);
6386
6313
  const remoteRegistration = getRemoteRegistration(id, resolvedOptions.remotes, options);
6387
6314
  const registerRemoteCode = isLoadedFirst && remoteRegistration ? `runtime.registerRemotes([${JSON.stringify(remoteRegistration)}]);` : "";
6388
- const hostAutoInitPath = getHostAutoInitPath(options);
6315
+ const hostAutoInitPath = getHostAutoInitPath(resolvedOptions);
6389
6316
  const ssrRemotes = getSsrRuntimeRemotes(resolvedOptions.remotes, options);
6390
6317
  const browserHostInitCode = `import(${JSON.stringify(hostAutoInitPath)})
6391
6318
  .then((mod) => mod.hostInitPromise)
@@ -6398,20 +6325,13 @@ function generateRemotes(id, command, enableSsrInit = false, consumer = "unified
6398
6325
  ${command === "serve" && consumer !== "server" ? browserHostInitCode : ""}`;
6399
6326
  const remoteLoadRuntimePromise = command === "build" ? "__mfHostInitPromise()" : "initPromise";
6400
6327
  const remoteCacheKey = `${getRuntimeRemoteCachePrefix(options)}${id}`;
6401
- const remoteLoadFailureHandler = command === "build" ? `.catch((error) => {
6402
- delete __mfModuleCache.remote[pendingKey];
6403
- throw error;
6404
- })` : `.catch((error) => {
6405
- delete __mfModuleCache.remote[pendingKey];
6406
- throw error;
6407
- })`;
6408
6328
  const remoteLoadCode = `
6409
6329
  function __mfStartRemoteLoad() {
6410
6330
  ${`
6411
6331
  const remoteCacheKey = ${JSON.stringify(remoteCacheKey)};
6412
6332
  const pendingKey = "__mf_pending__" + remoteCacheKey;
6413
6333
  if (!__mfModuleCache.remote[pendingKey]) {
6414
- __mfModuleCache.remote[pendingKey] = ${remoteLoadRuntimePromise}
6334
+ const pending = ${remoteLoadRuntimePromise}
6415
6335
  .then((runtime) => {
6416
6336
  ${registerRemoteCode}
6417
6337
  const moduleCacheKey = Symbol.for(${JSON.stringify(MODULE_CACHE_SHARE_SCOPE_KEY)});
@@ -6428,22 +6348,25 @@ function generateRemotes(id, command, enableSsrInit = false, consumer = "unified
6428
6348
  delete __mfModuleCache.remote[pendingKey];
6429
6349
  return mod;
6430
6350
  })
6431
- ${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;
6432
6358
  }
6433
6359
  return __mfModuleCache.remote[pendingKey];`}
6434
6360
  }`;
6435
6361
  const realRemoteInit = `__mfRemotePending = __mfStartRemoteLoad().then(__mfAssignRemoteModule);`;
6436
- const deferredClientInit = `exportModule = __mfCreateDeferredRemoteProxy();`;
6437
- const eagerLoadClientRemote = id === remoteRegistration?.alias || shouldEagerLoadClientRemoteInDev(command, enableSsrInit);
6438
- const eagerClientInit = eagerLoadClientRemote ? getEagerDeferredClientInit() : deferredClientInit;
6439
- const loadedFirstClientInit = eagerLoadClientRemote ? getEagerDeferredClientInit() : deferredClientInit;
6362
+ const clientInit = id === remoteRegistration?.alias || shouldEagerLoadClientRemoteInDev(command, enableSsrInit) ? getEagerDeferredClientInit() : `exportModule = __mfCreateDeferredRemoteProxy();`;
6440
6363
  const environmentSplitInit = (clientInit, serverInit) => consumer === "client" ? clientInit : consumer === "server" ? serverInit : `if (${SERVER_ENV_GUARD}) {
6441
6364
  ${serverInit}
6442
6365
  } else {
6443
6366
  ${clientInit}
6444
6367
  }`;
6445
- const initExportModule = initMode === "eager" ? environmentSplitInit(eagerClientInit, realRemoteInit) : environmentSplitInit(loadedFirstClientInit, realRemoteInit);
6446
- const includeProxyHelper = shouldIncludeDeferredProxy(initMode, consumer, eagerLoadClientRemote, deferRemoteLoad);
6368
+ const initExportModule = environmentSplitInit(clientInit, realRemoteInit);
6369
+ const includeProxyHelper = consumer !== "server";
6447
6370
  const deferredProxyCode = getDeferredProxyHelper(remoteCacheKey);
6448
6371
  return `
6449
6372
  ${importLine}
@@ -6464,9 +6387,9 @@ const isPreloadableVirtualMfChunk = (name) => name.includes("virtual_mf") && !na
6464
6387
  const HOST_INIT_PRELOAD_CHUNKS = [
6465
6388
  (name) => name === "hostInit",
6466
6389
  (name) => name === "remoteEntry",
6467
- isPreloadableVirtualMfChunk,
6468
- (name) => name === "index"
6390
+ isPreloadableVirtualMfChunk
6469
6391
  ];
6392
+ const isHostInitPreloadSeed = (chunk) => chunk.isEntry || HOST_INIT_PRELOAD_CHUNKS.some((match) => match(chunk.name));
6470
6393
  const isRemoteWarmupExcluded = (name) => name.includes("__prebuild__") || name.includes("__loadShare__");
6471
6394
  const REMOTE_ENTRY_WARMUP_CHUNKS = [(name) => name === "hostInit", (name) => isPreloadableVirtualMfChunk(name) && !isRemoteWarmupExcluded(name)];
6472
6395
  function getChunksByFileName(bundle) {
@@ -6503,7 +6426,7 @@ function injectHostInitPreloads(html, bundle, resolvePath, externalHrefs = []) {
6503
6426
  hrefs.push(href);
6504
6427
  }
6505
6428
  const chunksByFileName = getChunksByFileName(bundle);
6506
- 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);
6507
6430
  for (const fileName of collectPreloadChunkFiles(chunksByFileName, seeds)) {
6508
6431
  const href = resolvePath(fileName);
6509
6432
  if (existingHrefs.has(href)) continue;
@@ -6598,7 +6521,7 @@ const ROLLDOWN_RUNTIME_GLOBAL = "__rolldown_runtime__";
6598
6521
  * in every chunk and HMR patch it serves.
6599
6522
  */
6600
6523
  function renameBundledDevRuntime(req, res, remoteName) {
6601
- if (!req.url || !stripQueryAndHash(req.url).endsWith(".js")) return;
6524
+ if (!req.url || !/\.m?js$/.test(stripQueryAndHash(req.url))) return;
6602
6525
  const runtimeGlobal = `__mf_rt_${createHash("sha256").update(remoteName).digest("hex").slice(0, 10)}__`;
6603
6526
  const end = res.end;
6604
6527
  res.end = function(chunk, ...args) {
@@ -6615,6 +6538,7 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
6615
6538
  const ENTRY_BOOTSTRAP_QUERY = `?${ENTRY_BOOTSTRAP_PARAM}`;
6616
6539
  const waitsForInit = entryName === "hostInit";
6617
6540
  const getEntryPath = () => typeof entryPath === "function" ? entryPath() : entryPath;
6541
+ const getFederationOptions = () => federationOptions ?? getNormalizeModuleFederationOptions();
6618
6542
  let devEntryPath = "";
6619
6543
  let entryFiles = [];
6620
6544
  let htmlFilePath;
@@ -6634,8 +6558,14 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
6634
6558
  let isBundledDevRemote = false;
6635
6559
  let bundledDevRemoteEntryCode;
6636
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
+ }
6637
6567
  function skipSvelteKitSsrBuild() {
6638
- return (_command === "build" || viteConfig?.command === "build") && viteConfig?.build?.ssr && hasPackageDependency("@sveltejs/kit");
6568
+ return isBuildCommand() && viteConfig?.build?.ssr && hasPackageDependency("@sveltejs/kit");
6639
6569
  }
6640
6570
  function isSvelteKitServerModule(id) {
6641
6571
  return hasPackageDependency("@sveltejs/kit") && (id.includes(".svelte-kit/generated/") || id.includes("/@sveltejs/kit/src/runtime/server/"));
@@ -6670,10 +6600,6 @@ const __mfCurrentScript = document.currentScript;
6670
6600
  function walkHtmlFiles(dir) {
6671
6601
  return walkFiles(dir, (fileName) => fileName.endsWith(".html"));
6672
6602
  }
6673
- function toRelativeImport(fromFile, targetFile) {
6674
- const relative = normalizePathForImport(path$1.relative(path$1.dirname(fromFile), targetFile));
6675
- return relative.startsWith(".") ? relative : `./${relative}`;
6676
- }
6677
6603
  function patchSvelteKitStaticHtml() {
6678
6604
  const buildDir = path$1.resolve(viteConfig.root, "build");
6679
6605
  let initFile = emittedFileName ? path$1.resolve(buildDir, emittedFileName) : void 0;
@@ -6694,10 +6620,10 @@ const __mfCurrentScript = document.currentScript;
6694
6620
  return patched;
6695
6621
  }
6696
6622
  function getRemoteEntryPreloadUrls() {
6697
- const normalizedOptions = federationOptions ?? getNormalizeModuleFederationOptions();
6698
- 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);
6699
6625
  if (normalizedOptions.shareStrategy === "loaded-first" && !isLoadedFirstClientBuild) return [];
6700
- const remoteSources = isLoadedFirstClientBuild ? Array.from(getPreloadRemotes(normalizedOptions)) : Object.keys(getUsedRemotesMap(federationOptions));
6626
+ const remoteSources = isLoadedFirstClientBuild ? Array.from(getPreloadRemotes(normalizedOptions)) : Object.keys(getUsedRemotesMap(normalizedOptions));
6701
6627
  return Array.from(new Set(remoteSources.flatMap((remote) => {
6702
6628
  const registration = getRemoteRegistration(remote, normalizedOptions.remotes, federationOptions);
6703
6629
  return registration && (registration.type === "module" || registration.type === "esm") && /^(?:https?:)?\/\//.test(registration.entry) && !/\.json(?:[?#]|$)/i.test(registration.entry) ? [registration.entry] : [];
@@ -6736,10 +6662,10 @@ const __mfCurrentScript = document.currentScript;
6736
6662
  const entryImportDeclaration = isEncodedVirtualEntry ? `const __mfEntryUrl = ${JSON.stringify(entrySrc)};
6737
6663
  ` : "";
6738
6664
  const entryImportExpression = isEncodedVirtualEntry ? "import(/* @vite-ignore */ __mfEntryUrl)" : importExpression(entrySrc);
6739
- const normalizedOptions = federationOptions ?? getNormalizeModuleFederationOptions();
6740
- 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);
6741
6667
  const shouldPreloadRemotes = !options?.skipRemotePreload && (normalizedOptions.shareStrategy !== "loaded-first" || isLoadedFirstClientBuild);
6742
- 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));
6743
6669
  const remotePreloads = shouldPreloadRemotes ? remoteSources.sort().map((remote) => {
6744
6670
  const registration = isLoadedFirstClientBuild ? getRemoteRegistration(remote, normalizedOptions.remotes, federationOptions) : void 0;
6745
6671
  return `__mfPreloadRemote(${JSON.stringify(getRuntimeRemoteId(remote, normalizedOptions.remotes, federationOptions))}, ${JSON.stringify(remote)}${registration ? `, ${JSON.stringify(registration)}` : ""})`;
@@ -6754,7 +6680,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
6754
6680
  const shareItem = getNormalizeShareItem(pkg, federationOptions);
6755
6681
  const isExplicitShare = Object.hasOwn(federationOptions.shared, pkg);
6756
6682
  return shareItem?.shareConfig?.singleton === true && shareItem?.shareConfig?.import !== false && !shareItem?.shareConfig?.treeShaking && (isExplicitShare || typeof shareItem?.shareConfig?.import === "string" || Boolean(getProjectResolvedImportPath(pkg)));
6757
- }).map((pkg) => getLoadShareModulePath(pkg, false, federationOptions)) : [];
6683
+ }).map((pkg) => getLoadShareModulePath(pkg, federationOptions)) : [];
6758
6684
  const sharedPreloadBlock = sharedPreloadSources.length === 0 ? "" : options?.isBundled ? `
6759
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))));` : `
6760
6686
  const __mfSharedPreloadUrls = ${JSON.stringify(sharedPreloadSources.map(toViteEncodedId))};
@@ -6792,8 +6718,8 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
6792
6718
  if (__mfReactServerModuleCache?.pendingShareLoads) {
6793
6719
  await Promise.all(__mfReactServerModuleCache.pendingShareLoads);
6794
6720
  }`;
6795
- const pendingSharesBlock = waitsForInit && (_command === "build" || viteConfig?.command === "build") ? `
6796
- 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);
6797
6723
  if (__mfPendingShares && typeof __mfPendingShares.preloadPendingShares === "function") await __mfPendingShares.preloadPendingShares();` : "";
6798
6724
  const importCode = `
6799
6725
  (async () => {
@@ -7045,6 +6971,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
7045
6971
  if (resolved && !resolved.external && (_command === "serve" || !resolved.id.startsWith("\0"))) addEntryFile(resolveProjectId(resolved.id));
7046
6972
  }
7047
6973
  if (_command === "serve") return;
6974
+ if (entryName === "hostInit" && federationOptions && !hasRemotes(federationOptions) && isServerBuildContext(this, viteConfig)) return;
7048
6975
  if (skipSvelteKitSsrBuild()) return;
7049
6976
  if (this.environment?.name === "ssr") return;
7050
6977
  const hasHash = fileName?.includes?.("[hash");
@@ -7059,7 +6986,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
7059
6986
  if (waitsForInit) pendingSharesEmitId = this.emitFile({
7060
6987
  name: "pendingShares",
7061
6988
  type: "chunk",
7062
- id: getPendingSharesPath(federationOptions),
6989
+ id: getPendingSharesPath(getFederationOptions()),
7063
6990
  preserveSignature: "strict"
7064
6991
  });
7065
6992
  if (htmlFilePath) addHtmlScriptEntries(htmlFilePath);
@@ -7068,7 +6995,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
7068
6995
  if (isBundledDevRemote && _command === "serve") {
7069
6996
  const remoteEntryChunk = Object.values(bundle).find((output) => output.type === "chunk" && output.isEntry && output.facadeModuleId === getEntryPath());
7070
6997
  if (remoteEntryChunk?.type === "chunk") {
7071
- 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`;
7072
6999
  bundledDevRemoteEntryCode = Promise.resolve(code);
7073
7000
  resolveBundledDevRemoteEntryCode?.(code);
7074
7001
  }
@@ -7111,7 +7038,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
7111
7038
  let bootstrapIndex = 0;
7112
7039
  for (const fileName of htmlFileNames) {
7113
7040
  let htmlAsset = bundle[fileName];
7114
- if (htmlAsset.type === "chunk") return;
7041
+ if (htmlAsset.type === "chunk") continue;
7115
7042
  let htmlContent = htmlAsset.source.toString() || "";
7116
7043
  const initPath = resolvePath(file, fileName);
7117
7044
  const scriptRegex = /<script\b(?=[^>]*\btype=["']module["'])(?=[^>]*\bsrc=["']([^"']+)["'])[^>]*>\s*<\/script>/gi;
@@ -7161,7 +7088,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
7161
7088
  load(id) {
7162
7089
  return virtualEntryCode.get(id);
7163
7090
  },
7164
- transform(code, id) {
7091
+ transform(code, id, transformOptions) {
7165
7092
  if (skipSvelteKitSsrBuild()) return;
7166
7093
  if (viteConfig?.command === "build" && !waitsForInit) return;
7167
7094
  if (isSvelteKitServerModule(id)) return;
@@ -7173,7 +7100,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
7173
7100
  if (normalizeModuleId(id).endsWith(".html")) return;
7174
7101
  const projectId = resolveProjectId(id);
7175
7102
  if (skipTransformIds.has(projectId)) return;
7176
- if (!isClientEnvironment(this)) return;
7103
+ if (isServerBuildContext(this, viteConfig) || transformOptions?.ssr) return;
7177
7104
  const isVinext = hasPackageDependency("vinext");
7178
7105
  if (isVinext && inject === "html" && id.includes("virtual:vite-rsc/remove-duplicate-server-css")) {
7179
7106
  const namespaceReactImport = `import * as React from 'react';`;
@@ -7474,21 +7401,6 @@ const vueAdapter = {
7474
7401
  } }
7475
7402
  };
7476
7403
  //#endregion
7477
- //#region src/utils/devServerHost.ts
7478
- const UNSPECIFIED_HOSTS = /* @__PURE__ */ new Set(["0.0.0.0", "::"]);
7479
- /**
7480
- * Hostname for client-facing HTTP/WS origins built from Vite `server.host`.
7481
- *
7482
- * Unspecified bind addresses (`0.0.0.0`, `::`) map to `localhost`, matching
7483
- * Vite's own printed local URL. IPv6 addresses are wrapped in brackets so
7484
- * `http://[::1]:5173` / `ws://[::1]:5173` parse as valid URLs.
7485
- */
7486
- function formatDevServerHostForOrigin(host) {
7487
- if (typeof host !== "string" || UNSPECIFIED_HOSTS.has(host)) return "localhost";
7488
- if (host.startsWith("[") && host.endsWith("]")) return host;
7489
- return isIPv6(host) ? `[${host}]` : host;
7490
- }
7491
- //#endregion
7492
7404
  //#region src/plugins/hmr/fullReload.ts
7493
7405
  const REMOTE_HMR_ENDPOINT = "__mf_hmr";
7494
7406
  const REMOTE_HMR_EVENT = "mf:remote-update";
@@ -7496,7 +7408,7 @@ const REMOTE_HMR_CONNECT_RETRY_DELAY_MS = 1e3;
7496
7408
  const REMOTE_HMR_CONNECT_MAX_RETRIES = 10;
7497
7409
  function getBasePath(base) {
7498
7410
  if (!base) return "/";
7499
- if (base.startsWith("http://") || base.startsWith("https://")) try {
7411
+ if (isHttpUrl(base)) try {
7500
7412
  return new URL(base).pathname || "/";
7501
7413
  } catch {
7502
7414
  return "/";
@@ -7595,14 +7507,8 @@ function setupRemoteBroadcast(server, options) {
7595
7507
  }
7596
7508
  });
7597
7509
  };
7598
- server.watcher.on("change", broadcast);
7599
- server.watcher.on("add", broadcast);
7600
- server.watcher.on("unlink", broadcast);
7601
- server.httpServer?.once("close", () => {
7602
- server.watcher.off("change", broadcast);
7603
- server.watcher.off("add", broadcast);
7604
- server.watcher.off("unlink", broadcast);
7605
- });
7510
+ const stopWatching = watchFileEvents(server.watcher, broadcast);
7511
+ server.httpServer?.once("close", stopWatching);
7606
7512
  }
7607
7513
  /**
7608
7514
  * Installs the host-side full-reload relay. For each configured remote:
@@ -7664,9 +7570,13 @@ function setupHostFullReloadRelay(server, options) {
7664
7570
  if (!message || message.event !== "mf:remote-update") return;
7665
7571
  server.ws.send({ type: "full-reload" });
7666
7572
  };
7667
- ws.onopen = () => clearReconnectTimer(remoteName);
7573
+ let opened = false;
7574
+ ws.onopen = () => {
7575
+ opened = true;
7576
+ clearReconnectTimer(remoteName);
7577
+ };
7668
7578
  ws.onerror = (error) => mfWarn(`Remote HMR socket error for "${remoteName}":`, error);
7669
- ws.onclose = () => scheduleReconnect(remoteName, remote, attempt, "socket closed");
7579
+ ws.onclose = () => scheduleReconnect(remoteName, remote, opened ? 0 : attempt, "socket closed");
7670
7580
  connections.push(ws);
7671
7581
  } catch (error) {
7672
7582
  mfWarn(`Failed to connect remote HMR for "${remoteName}" on attempt ${attempt + 1}: ${getStringPreview(error)}`);
@@ -7687,9 +7597,7 @@ function setupHostFullReloadRelay(server, options) {
7687
7597
  if (shouldIgnoreFile(file, options)) return;
7688
7598
  server.ws.send({ type: "full-reload" });
7689
7599
  };
7690
- server.watcher.on("change", triggerHostReload);
7691
- server.watcher.on("add", triggerHostReload);
7692
- server.watcher.on("unlink", triggerHostReload);
7600
+ watchFileEvents(server.watcher, triggerHostReload);
7693
7601
  server.httpServer?.once("close", teardown);
7694
7602
  }
7695
7603
  //#endregion
@@ -7760,8 +7668,8 @@ function collectHostTags(server, options, adapters) {
7760
7668
  return tags;
7761
7669
  }
7762
7670
  function pluginDevRemoteHmr(options) {
7763
- const isHost = Object.keys(options.remotes).length > 0;
7764
- const isRemote = Object.keys(options.exposes).length > 0;
7671
+ const isHost = hasRemotes(options);
7672
+ const isRemote = isRemoteContainer(options);
7765
7673
  let adapters = [];
7766
7674
  let strategy = "full-reload";
7767
7675
  let root;
@@ -8039,9 +7947,10 @@ function pluginExternalRuntimeCore() {
8039
7947
  //#endregion
8040
7948
  //#region src/virtualModules/index.ts
8041
7949
  function initVirtualModules(command, remoteEntryId, enableSsrInit = false, options) {
8042
- writeLocalSharedImportMap(options);
8043
- writeHostAutoInit(remoteEntryId, command, options);
8044
- 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);
8045
7954
  }
8046
7955
  //#endregion
8047
7956
  //#region src/utils/cssModuleHelpers.ts
@@ -8290,16 +8199,15 @@ function pluginLazyConsumeOnlyShares(options) {
8290
8199
  renderChunk(code, chunk, _outputOptions, meta) {
8291
8200
  const renderedChunk = chunk;
8292
8201
  const chunks = meta?.chunks;
8293
- if (!chunks || Object.keys(options.exposes).length === 0) return null;
8202
+ if (!chunks || !isRemoteContainer(options)) return null;
8294
8203
  if (isServerBuildContext(this, viteConfig)) return null;
8295
8204
  let graph = graphs.get(chunks);
8296
8205
  if (!graph) {
8297
- const isRolldown = getIsRolldown(this);
8298
8206
  const wrapperShares = /* @__PURE__ */ new Map();
8299
8207
  for (const shareKey of getUsedShares(options)) {
8300
8208
  const shareConfig = getNormalizeShareItem(shareKey, options)?.shareConfig;
8301
8209
  if (shareConfig?.import !== false || shareConfig.eager || shareConfig.treeShaking) continue;
8302
- wrapperShares.set(normalizeVirtualModuleId(getLoadShareModulePath(shareKey, isRolldown, options)), shareKey);
8210
+ wrapperShares.set(normalizeVirtualModuleId(getLoadShareModulePath(shareKey, options)), shareKey);
8303
8211
  }
8304
8212
  const root = viteConfig?.root ?? process.cwd();
8305
8213
  graph = buildLazyShareGraph(chunks, wrapperShares, new Set(Object.values(options.exposes).map((expose) => stripKnownJsExtension(path$1.resolve(root, expose.import)))));
@@ -8319,15 +8227,16 @@ function pluginLazyConsumeOnlyShares(options) {
8319
8227
  break;
8320
8228
  }
8321
8229
  const chunkDir = path$1.posix.dirname(renderedChunk.fileName);
8322
- const codePositions = createCodePositionMap(code);
8230
+ let codePositions;
8323
8231
  let usesHelper = false;
8324
8232
  for (const match of isImportMapChunk ? [] : code.matchAll(DYNAMIC_IMPORT_REGEX)) {
8325
8233
  const [expression, , specifier] = match;
8326
8234
  const start = match.index;
8327
- if (!codePositions[start]) continue;
8328
8235
  const target = path$1.posix.normalize(path$1.posix.join(chunkDir, specifier));
8329
8236
  const shares = graph.sharesByChunk.get(target);
8330
8237
  if (!shares || !renderedChunk.dynamicImports.includes(target)) continue;
8238
+ codePositions ??= createCodePositionMap(code);
8239
+ if (!codePositions[start]) continue;
8331
8240
  rewriter.overwrite(start, start + expression.length, `${helperName}(${JSON.stringify(shares)}).then(() => ${expression})`);
8332
8241
  usesHelper = edited = true;
8333
8242
  }
@@ -8350,7 +8259,7 @@ function ${helperName}(names) {
8350
8259
  }
8351
8260
  //#endregion
8352
8261
  //#region package.json
8353
- var version$1 = "1.23.5";
8262
+ var version$1 = "1.23.6";
8354
8263
  //#endregion
8355
8264
  //#region src/virtualModules/virtualExposesSSR.ts
8356
8265
  /**
@@ -8447,7 +8356,7 @@ function generateRemoteEntrySSR(options) {
8447
8356
  const virtualExposesSSRId = getVirtualExposesSSRId(options);
8448
8357
  const sharedSingletons = getSsrSharedSingletons(options);
8449
8358
  return `
8450
- 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\";"}
8451
8360
 
8452
8361
  const sharedSingletons = ${JSON.stringify(sharedSingletons)};
8453
8362
  const moduleCacheKey = Symbol.for(${JSON.stringify(MODULE_CACHE_SHARE_SCOPE_KEY)});
@@ -8477,11 +8386,11 @@ function generateRemoteEntrySSR(options) {
8477
8386
  * to set up a minimal runtime instance for the remote container.
8478
8387
  */
8479
8388
  async function init(shared = {}, initScope = []) {
8480
- const initRes = runtimeInit({
8389
+ const initRes = ${hasRemotes(options) ? "await hostInitPromise" : `runtimeInit({
8481
8390
  name: ${JSON.stringify(options.name)},
8482
8391
  remotes: [],
8483
8392
  shared: {},
8484
- });
8393
+ })`};
8485
8394
  if (initScope.indexOf(initToken) >= 0) return;
8486
8395
  initScope.push(initToken);
8487
8396
  const shareScopeNames = Array.isArray(${JSON.stringify(options.shareScope)})
@@ -8626,13 +8535,13 @@ function collectImportedCss(chunks) {
8626
8535
  * dependency even though the expose statically imports it. Advertising it as a sync
8627
8536
  * asset makes a preloader fetch a provider the host is going to supply anyway.
8628
8537
  */
8629
- function collectDeferredShareModules(options, isRolldown) {
8538
+ function collectDeferredShareModules(options) {
8630
8539
  const deferred = /* @__PURE__ */ new Set();
8631
8540
  for (const shareKey of getUsedShares(options)) {
8632
8541
  const shareConfig = getNormalizeShareItem(shareKey, options)?.shareConfig;
8633
8542
  if (shareConfig?.eager === true) continue;
8634
8543
  if (shareConfig?.import === false) continue;
8635
- deferred.add(normalizeVirtualModuleId(getLoadShareModulePath(shareKey, isRolldown, options)));
8544
+ deferred.add(normalizeVirtualModuleId(getLoadShareModulePath(shareKey, options)));
8636
8545
  }
8637
8546
  return deferred;
8638
8547
  }
@@ -8647,9 +8556,9 @@ function isDeferredShareChunk(chunk, deferredShareModules) {
8647
8556
  if (!chunk || chunk.type !== "chunk" || deferredShareModules.size === 0) return false;
8648
8557
  return [chunk.facadeModuleId, ...chunk.moduleIds ?? []].some((id) => typeof id === "string" && deferredShareModules.has(normalizeVirtualModuleId(id)));
8649
8558
  }
8650
- function expandExposeAssets(filesMap, exposeModules, bundle, remoteEntryFileName, options, isRolldown) {
8559
+ function expandExposeAssets(filesMap, exposeModules, bundle, remoteEntryFileName, options) {
8651
8560
  if (exposeModules.length === 0) return;
8652
- const deferredShareModules = collectDeferredShareModules(options, isRolldown);
8561
+ const deferredShareModules = collectDeferredShareModules(options);
8653
8562
  const containerChunks = remoteEntryFileName ? collectStaticChunks(bundle, [remoteEntryFileName]) : [];
8654
8563
  const bootstrapChunks = containerChunks.slice(1);
8655
8564
  const seen = new Set(containerChunks.map((chunk) => chunk.fileName));
@@ -8708,15 +8617,8 @@ const Manifest = (providedOptions) => {
8708
8617
  const { name, filename, getPublicPath, manifest: manifestOptions, varFilename } = mfOptions;
8709
8618
  let mfManifestName = manifestOptions === true ? "mf-manifest.json" : typeof manifestOptions === "object" ? normalizePathForImport(path$1.join(manifestOptions?.filePath || "", manifestOptions?.fileName || "mf-manifest.json")) : void 0;
8710
8619
  let mfManifestStatsName = mfManifestName ? getStatsFileName(mfManifestName) : void 0;
8711
- const isConsumerProject = Object.keys(mfOptions.exposes).length === 0;
8620
+ const isConsumerProject = !isRemoteContainer(mfOptions);
8712
8621
  let disableAssetsAnalyze = false;
8713
- const getDefaultDisableAssetsAnalyze = (command) => command === "serve" && isConsumerProject && (typeof manifestOptions !== "object" || !Object.hasOwn(manifestOptions, "disableAssetsAnalyze"));
8714
- const getConfiguredDisableAssetsAnalyze = (command) => {
8715
- if (typeof manifestOptions === "object" && manifestOptions !== null) {
8716
- if (Object.hasOwn(manifestOptions, "disableAssetsAnalyze")) return manifestOptions.disableAssetsAnalyze === true;
8717
- }
8718
- return getDefaultDisableAssetsAnalyze(command);
8719
- };
8720
8622
  let root;
8721
8623
  let remoteEntryFile;
8722
8624
  let ssrRemoteEntryFile;
@@ -8744,7 +8646,7 @@ const Manifest = (providedOptions) => {
8744
8646
  configureServer(server) {
8745
8647
  server.middlewares.use((req, res, next) => {
8746
8648
  const devRemoteEntryFile = resolveHashPlaceholderFileName(filename);
8747
- 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(/^\/?/, "/"))) {
8748
8650
  req.url = req.url.replace(devRemoteEntryFile, filename);
8749
8651
  next();
8750
8652
  return;
@@ -8787,7 +8689,7 @@ const Manifest = (providedOptions) => {
8787
8689
  types: resolveTypesMeta(mfOptions.dts),
8788
8690
  globalName: name,
8789
8691
  pluginVersion: version$1,
8790
- publicPath
8692
+ ...getPublicPath ? { getPublicPath } : { publicPath }
8791
8693
  }
8792
8694
  });
8793
8695
  res.end(JSON.stringify(manifest));
@@ -8807,7 +8709,7 @@ const Manifest = (providedOptions) => {
8807
8709
  _command = command;
8808
8710
  if (!config.build) config.build = {};
8809
8711
  if (!config.build.manifest) config.build.manifest = config.build.manifest || !!mfManifestName;
8810
- disableAssetsAnalyze = getConfiguredDisableAssetsAnalyze(command);
8712
+ disableAssetsAnalyze = resolveDisableAssetsAnalyze(manifestOptions, command === "serve" && isConsumerProject);
8811
8713
  _originalConfigBase = config.base;
8812
8714
  },
8813
8715
  configResolved(config) {
@@ -8886,7 +8788,7 @@ const Manifest = (providedOptions) => {
8886
8788
  root,
8887
8789
  stripKnownJsExtensions: true
8888
8790
  });
8889
- expandExposeAssets(filesMap, exposesModules, bundle, foundRemoteEntryFile, mfOptions, getIsRolldown(this));
8791
+ expandExposeAssets(filesMap, exposesModules, bundle, foundRemoteEntryFile, mfOptions);
8890
8792
  const fileToShareKey = await buildFileToShareKeyMap(getUsedShares(mfOptions), this.resolve.bind(this), mfOptions);
8891
8793
  processModuleAssets(Object.fromEntries(Object.entries(bundle).filter(([, file]) => !isTreeShakingProviderChunk(file))), filesMap, (modulePath) => fileToShareKey.get(modulePath));
8892
8794
  const deferredSharedAssets = {
@@ -9239,6 +9141,8 @@ function createModuleParseController() {
9239
9141
  discardWarned: false,
9240
9142
  externalSet: /* @__PURE__ */ new Set(),
9241
9143
  resolutionProbed: /* @__PURE__ */ new Set(),
9144
+ reached: /* @__PURE__ */ new Set(),
9145
+ deferredImports: /* @__PURE__ */ new Map(),
9242
9146
  lastLoadedModule: "",
9243
9147
  lastParsedModule: ""
9244
9148
  };
@@ -9262,6 +9166,8 @@ function resetParseState(controller) {
9262
9166
  controller.parseEndSet = /* @__PURE__ */ new Set();
9263
9167
  controller.externalSet = /* @__PURE__ */ new Set();
9264
9168
  controller.resolutionProbed = /* @__PURE__ */ new Set();
9169
+ controller.reached = /* @__PURE__ */ new Set();
9170
+ controller.deferredImports = /* @__PURE__ */ new Map();
9265
9171
  controller.discardWarned = false;
9266
9172
  controller.lastLoadedModule = "";
9267
9173
  controller.lastParsedModule = "";
@@ -9337,7 +9243,10 @@ function pluginModuleParseEnd_default(excludeFn, options, controller = createMod
9337
9243
  const entryImports = /* @__PURE__ */ new Set([...options.exposedModuleImports || [], ...configuredInputImports]);
9338
9244
  for (const importSource of entryImports) {
9339
9245
  const resolved = await this.resolve(importSource);
9340
- 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
+ }
9341
9250
  }
9342
9251
  },
9343
9252
  load(id) {
@@ -9358,7 +9267,11 @@ function pluginModuleParseEnd_default(excludeFn, options, controller = createMod
9358
9267
  if (idleTimeout) resetIdleTimeout(controller, idleTimeout);
9359
9268
  const parsedModule = module;
9360
9269
  const addPendingResolutions = (resolutions) => {
9361
- 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
+ }
9362
9275
  };
9363
9276
  const probeExternal = (pendingId) => {
9364
9277
  if (typeof this.resolve !== "function") return;
@@ -9373,15 +9286,39 @@ function pluginModuleParseEnd_default(excludeFn, options, controller = createMod
9373
9286
  };
9374
9287
  const addPendingIds = (ids) => {
9375
9288
  for (const pendingId of ids || []) {
9376
- if (controller.externalSet.has(pendingId) || matchesExternal(configuredExternal, pendingId, id) || excludeFn(pendingId)) continue;
9377
- 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);
9378
9295
  if (!controller.parseEndSet.has(pendingId)) probeExternal(pendingId);
9379
9296
  }
9380
9297
  };
9381
- addPendingResolutions(parsedModule.importedIdResolutions);
9382
- addPendingResolutions(parsedModule.dynamicallyImportedIdResolutions);
9383
- if (parsedModule.importedIdResolutions === void 0) addPendingIds(module.importedIds);
9384
- 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
+ }
9385
9322
  if (!excludeFn(id)) controller.parseEndSet.add(id);
9386
9323
  scheduleParseCompletionCheck(controller);
9387
9324
  },
@@ -9394,88 +9331,264 @@ function pluginModuleParseEnd_default(excludeFn, options, controller = createMod
9394
9331
  }];
9395
9332
  }
9396
9333
  //#endregion
9397
- //#region src/plugins/pluginProxyRemoteEntry.ts
9398
- function resolveAbsoluteDevRemoteEntryUrl(publicPath, fileName) {
9399
- const base = new URL(publicPath);
9400
- base.pathname = ensureTrailingSlash(base.pathname);
9401
- 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(/^\.\//, "");
9402
9340
  }
9403
- function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposesId, getParsePromise = () => Promise.resolve() }) {
9404
- let viteConfig, _command, root, originalConfigBase;
9405
- let exposeRemoteDependencies = {};
9406
- let exposeRemoteDependenciesDirty = true;
9407
- let refreshPromise;
9408
- let dependencyInvalidationVersion = 0;
9409
- let reactIslandExposes = /* @__PURE__ */ new Set();
9410
- const isHostAutoInitId = (id) => {
9411
- const cleanId = id.split("?")[0];
9412
- return cleanId.includes(getHostAutoInitPath(options)) || cleanId.includes(getHostAutoInitPath());
9413
- };
9414
- const getEnvironmentConditions = (context) => context.environment?.config?.resolve?.conditions;
9415
- const isSsrBuild = (context) => isServerBuildContext(context, viteConfig);
9416
- function isRemoteImport(source) {
9417
- return Object.keys(options.remotes).some((name) => source === name || source.startsWith(name + "/"));
9418
- }
9419
- function collectImportSources(code) {
9420
- const sources = /* @__PURE__ */ new Map();
9421
- for (const { source, kind, syntax, typeOnly } of findModuleImportDescriptors(code)) {
9422
- if (syntax !== "import" || typeOnly) continue;
9423
- const dynamic = kind === "dynamic";
9424
- sources.set(source, (sources.get(source) ?? true) && dynamic);
9425
- }
9426
- return Array.from(sources, ([source, dynamic]) => ({
9427
- source,
9428
- dynamic
9429
- })).sort((a, b) => a.source.localeCompare(b.source));
9430
- }
9431
- function shouldScanResolvedImport(id) {
9432
- if (!id || id.includes("\0")) return false;
9433
- if (id.includes("/node_modules/") || id.includes("\\node_modules\\")) return false;
9434
- return /\.(?:[cm]?[jt]sx?|vue|svelte)(?:\?|$)/.test(id);
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;
9435
9360
  }
9436
- async function collectRemoteDependencies(ctx, id, seen = /* @__PURE__ */ new Set()) {
9437
- if (seen.has(id) || !shouldScanResolvedImport(id)) return [];
9438
- seen.add(id);
9439
- let code;
9440
- try {
9441
- code = getScannableModuleSource(id, readFileSync$1(id, "utf8"));
9442
- } catch {
9443
- return [];
9444
- }
9445
- const dependencies = /* @__PURE__ */ new Set();
9446
- for (const { source, dynamic } of collectImportSources(code)) {
9447
- if (isRemoteImport(source)) {
9448
- if (!dynamic) dependencies.add(source);
9449
- continue;
9450
- }
9451
- let resolved;
9452
- try {
9453
- resolved = await ctx.resolve(source, id);
9454
- } catch {
9455
- continue;
9456
- }
9457
- if (!resolved?.id || !shouldScanResolvedImport(resolved.id)) continue;
9458
- for (const dependency of await collectRemoteDependencies(ctx, resolved.id, seen)) dependencies.add(dependency);
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;
9459
9397
  }
9460
- return Array.from(dependencies).sort();
9461
9398
  }
9462
- async function refreshExposeRemoteDependencies(ctx) {
9463
- if (!exposeRemoteDependenciesDirty) return;
9464
- if (!refreshPromise) {
9465
- const refreshVersion = dependencyInvalidationVersion;
9466
- refreshPromise = (async () => {
9467
- const next = {};
9468
- for (const [exposeKey, expose] of Object.entries(options.exposes)) {
9469
- const resolved = await ctx.resolve(expose.import);
9470
- next[exposeKey] = resolved?.id ? await collectRemoteDependencies(ctx, resolved.id) : [];
9471
- }
9472
- exposeRemoteDependencies = next;
9473
- if (refreshVersion === dependencyInvalidationVersion) exposeRemoteDependenciesDirty = false;
9474
- })().finally(() => {
9475
- refreshPromise = void 0;
9476
- });
9477
- }
9478
- await refreshPromise;
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);
9529
+ }
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));
9564
+ }
9565
+ async function refreshExposeRemoteDependencies(ctx) {
9566
+ if (!exposeRemoteDependenciesDirty) return;
9567
+ if (!hasRemotes(options)) {
9568
+ exposeRemoteDependencies = {};
9569
+ exposeRemoteDependenciesDirty = false;
9570
+ return;
9571
+ }
9572
+ if (!refreshPromise) {
9573
+ const refreshVersion = dependencyInvalidationVersion;
9574
+ refreshPromise = (async () => {
9575
+ const next = {};
9576
+ const cache = /* @__PURE__ */ new Map();
9577
+ const followDynamicImports = options.shareStrategy !== "loaded-first";
9578
+ for (const [exposeKey, expose] of Object.entries(options.exposes)) {
9579
+ const resolved = await ctx.resolve(expose.import);
9580
+ next[exposeKey] = resolved?.id ? await collectRemoteDependencies(ctx, resolved.id, isRemoteImport, {
9581
+ followDynamicImports,
9582
+ cache
9583
+ }) : [];
9584
+ }
9585
+ exposeRemoteDependencies = next;
9586
+ if (refreshVersion === dependencyInvalidationVersion) exposeRemoteDependenciesDirty = false;
9587
+ })().finally(() => {
9588
+ refreshPromise = void 0;
9589
+ });
9590
+ }
9591
+ await refreshPromise;
9479
9592
  }
9480
9593
  function invalidateExposeRemoteDependencies() {
9481
9594
  exposeRemoteDependenciesDirty = true;
@@ -9487,6 +9600,7 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
9487
9600
  configResolved(config) {
9488
9601
  viteConfig = config;
9489
9602
  root = config.root;
9603
+ isTanStackStart = config.plugins?.some((plugin) => plugin.name === "tanstack-start-core:config") ?? false;
9490
9604
  reactIslandExposes = getReactIslandExposes(options, root);
9491
9605
  },
9492
9606
  config(config, { command }) {
@@ -9495,7 +9609,7 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
9495
9609
  },
9496
9610
  async buildStart() {
9497
9611
  await refreshExposeRemoteDependencies(this);
9498
- if (_command !== "build" || hasPackageDependency("@tanstack/react-start", root)) return;
9612
+ if (_command !== "build" || isTanStackStart) return;
9499
9613
  for (const expose of Object.values(options.exposes)) {
9500
9614
  const resolved = await this.resolve(expose.import);
9501
9615
  if (resolved) this.emitFile({
@@ -9521,21 +9635,15 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
9521
9635
  }
9522
9636
  },
9523
9637
  async load(id) {
9524
- if (id === remoteEntryId) return getParsePromise().then((_) => generateRemoteEntry(options, virtualExposesId, _command, getEnvironmentConditions(this), isSsrBuild(this)));
9525
- if (id === virtualExposesId) {
9526
- await refreshExposeRemoteDependencies(this);
9527
- return generateExposes(options, exposeRemoteDependencies, _command, reactIslandExposes);
9528
- }
9638
+ if (id === remoteEntryId) return loadRemoteEntryCode(this);
9639
+ if (id === virtualExposesId) return loadExposesCode(this);
9529
9640
  if (_command === "serve" && isHostAutoInitId(id)) return id;
9530
9641
  },
9531
9642
  async transform(code, id) {
9532
9643
  return mapCodeToCodeWithSourcemap(await (async () => {
9533
9644
  if (!filterId(id)) return;
9534
- if (id.includes(remoteEntryId)) return getParsePromise().then((_) => generateRemoteEntry(options, virtualExposesId, _command, getEnvironmentConditions(this), isSsrBuild(this)));
9535
- if (id === virtualExposesId) {
9536
- await refreshExposeRemoteDependencies(this);
9537
- return generateExposes(options, exposeRemoteDependencies, _command, reactIslandExposes);
9538
- }
9645
+ if (id.includes(remoteEntryId)) return loadRemoteEntryCode(this);
9646
+ if (id === virtualExposesId) return loadExposesCode(this);
9539
9647
  if (isHostAutoInitId(id)) {
9540
9648
  if (_command === "serve") {
9541
9649
  const host = formatDevServerHostForOrigin(viteConfig.server?.host);
@@ -9649,7 +9757,7 @@ function pluginProxyRemotes_default(options) {
9649
9757
  },
9650
9758
  configResolved(config) {
9651
9759
  hasMultiEnvironment = Boolean(config.environments?.ssr);
9652
- 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;
9653
9761
  },
9654
9762
  resolveId(source, importer) {
9655
9763
  const resolvedIslandConsumerId = resolveReactIslandConsumerId(source);
@@ -9782,6 +9890,20 @@ function getSharedPackageFromFile(importer, shared, cwd = getPackageDetectionCwd
9782
9890
  const normalizedImporter = normalizePathForImport(importer);
9783
9891
  return [...cached.entries].find(([dir]) => normalizedImporter === dir || normalizedImporter.startsWith(`${dir}/`))?.[1] ?? getWorkspacePackageNameFromFile(normalizedImporter);
9784
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
+ }
9785
9907
  const workspacePackageNameCache = /* @__PURE__ */ new Map();
9786
9908
  /** Name from the nearest `package.json` above `file`, for files outside `node_modules`. */
9787
9909
  function getWorkspacePackageNameFromFile(file) {
@@ -10076,7 +10198,6 @@ function proxySharedModule(options) {
10076
10198
  const getBuildImportAnalysis = (environment) => getImportAnalysis(environment ?? _config ?? options);
10077
10199
  let _command = "serve";
10078
10200
  let useDirectReactImport = false;
10079
- let useRolldown = false;
10080
10201
  let isProduction = false;
10081
10202
  let rootResolveConditions;
10082
10203
  let ssrResolveConditions;
@@ -10105,7 +10226,7 @@ function proxySharedModule(options) {
10105
10226
  root: _config?.root || getPackageDetectionCwd(),
10106
10227
  conditions: getRuntimeDependencyConditions(context, resolveOptions)
10107
10228
  }));
10108
- const refreshTreeShakingForEnvironment = (context) => refreshTreeShakingModules(federationOptions, _command, getIsRolldown(context), getEnvironmentConditions(context));
10229
+ const refreshTreeShakingForEnvironment = (context) => refreshTreeShakingModules(federationOptions, _command, getEnvironmentConditions(context));
10109
10230
  const normalizeTreeShakingOutputPath = (value) => {
10110
10231
  const normalized = normalizePathForImport(value);
10111
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.`);
@@ -10117,8 +10238,7 @@ function proxySharedModule(options) {
10117
10238
  };
10118
10239
  const getTreeShakingProviderFileName = (pkg, shareItem) => {
10119
10240
  if (!shareItem.shareConfig.treeShaking) return void 0;
10120
- const normalizedOptions = federationOptions ?? getNormalizeModuleFederationOptions();
10121
- const outputDir = normalizedOptions.treeShakingDir ? normalizeTreeShakingOutputPath(normalizedOptions.treeShakingDir) : void 0;
10241
+ const outputDir = federationOptions.treeShakingDir ? normalizeTreeShakingOutputPath(federationOptions.treeShakingDir) : void 0;
10122
10242
  const fileName = outputDir ? path$1.posix.join(outputDir, `${getTreeShakingSharedProviderName(pkg, federationOptions)}.js`) : void 0;
10123
10243
  if (!fileName) return void 0;
10124
10244
  return fileName;
@@ -10182,9 +10302,7 @@ function proxySharedModule(options) {
10182
10302
  workspacePackageNameCache.clear();
10183
10303
  const isVinext = hasPackageDependency("vinext");
10184
10304
  const isAstro = hasPackageDependency("astro");
10185
- const isRolldown = getIsRolldown(this);
10186
10305
  _command = command;
10187
- useRolldown = isRolldown;
10188
10306
  useDirectReactImport = isVinext || isAstro;
10189
10307
  if (command === "serve") excludeSharedSubDependencies(shared);
10190
10308
  },
@@ -10194,9 +10312,7 @@ function proxySharedModule(options) {
10194
10312
  rootResolveConditions = config.resolve?.conditions ? [...config.resolve.conditions] : void 0;
10195
10313
  ssrResolveConditions = config.ssr?.resolve?.conditions ? [...config.ssr.resolve.conditions] : void 0;
10196
10314
  ssrTarget = config.ssr?.target ?? "node";
10197
- const isRolldown = getIsRolldown(this);
10198
- const resolvedOptions = federationOptions ?? getNormalizeModuleFederationOptions();
10199
- const registerConfiguredShare = _command === "build" && Object.keys(resolvedOptions.exposes).length > 0 ? addUsedShares : addConfiguredShare;
10315
+ const registerConfiguredShare = _command === "build" && isRemoteContainer(federationOptions) ? addUsedShares : addConfiguredShare;
10200
10316
  Object.keys(shared).forEach((key) => {
10201
10317
  if (key.endsWith("/") || getSharedRequest(key, shared[key]).endsWith("/")) return;
10202
10318
  const runtimeKey = getSharedRuntimeKey(key, shared[key]);
@@ -10204,7 +10320,7 @@ function proxySharedModule(options) {
10204
10320
  registerConfiguredShare(runtimeKey, federationOptions);
10205
10321
  return;
10206
10322
  }
10207
- writeLoadShareModule(runtimeKey, shared[key], _command, isRolldown, federationOptions);
10323
+ writeLoadShareModule(runtimeKey, shared[key], _command, federationOptions);
10208
10324
  if (shared[key].shareConfig.import !== false) writePreBuildLibPath(runtimeKey, shared[key], federationOptions);
10209
10325
  registerConfiguredShare(runtimeKey, federationOptions);
10210
10326
  });
@@ -10291,7 +10407,7 @@ function proxySharedModule(options) {
10291
10407
  return taggedModule.name === sharedKey || matchesSharedSource(sharedSource, taggedModule.name);
10292
10408
  };
10293
10409
  const importerPackage = getSharedPackageFromFile(importer, shared);
10294
- if (importerPackage === getPackageName(key)) return;
10410
+ if (importerPackage === getPackageName(key) && keepsOwnPackageEdge(importer, shared)) return;
10295
10411
  if (importerPackage && shared[key].shareConfig.import !== false) {
10296
10412
  const importerIsUnsharedWorkspacePackage = !isNodeModulePath(importer) && !Object.keys(shared).some((sharedKey) => getPackageName(sharedKey) === importerPackage);
10297
10413
  const request = getSharedRequest(key, shared[key]);
@@ -10311,10 +10427,10 @@ function proxySharedModule(options) {
10311
10427
  const localSource = getPrebuildResolutionSource(shareSource, shared[key]);
10312
10428
  return tryResolveFromProjectRoot(localSource) || localSource;
10313
10429
  }
10314
- const loadSharePath = getLoadShareModulePath(shareSource, useRolldown, federationOptions);
10430
+ const loadSharePath = getLoadShareModulePath(shareSource, federationOptions);
10315
10431
  if (!materializedLoadShareSources.has(shareSource)) {
10316
10432
  materializedLoadShareSources.add(shareSource);
10317
- writeLoadShareModule(shareSource, shared[key], _command, useRolldown, federationOptions);
10433
+ writeLoadShareModule(shareSource, shared[key], _command, federationOptions);
10318
10434
  if (shared[key].shareConfig.import !== false) writePreBuildLibPath(shareSource, shared[key], federationOptions);
10319
10435
  addUsedShares(shareSource, federationOptions);
10320
10436
  writeLocalSharedImportMap(federationOptions);
@@ -10447,6 +10563,13 @@ function applyRewrites(code, imports, id) {
10447
10563
  ms.overwrite(imp.start, imp.end, wrapDynamicImport(imp.originalText));
10448
10564
  changed = true;
10449
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
+ }
10450
10573
  }
10451
10574
  if (!changed) return;
10452
10575
  if (dependencyPendingIds.length > 0) ms.overwrite(code.length, code.length, `\nexport const __mf_remote_dependency_pending = Promise.all([${dependencyPendingIds.join(", ")}]);`);
@@ -10455,7 +10578,7 @@ function applyRewrites(code, imports, id) {
10455
10578
  map: ms.generateMap(id)
10456
10579
  };
10457
10580
  }
10458
- async function collectFromAST(ast, code, isRemoteImport) {
10581
+ async function collectFromAST(ast, code, isRemoteImport, collectLocalDynamic) {
10459
10582
  const result = [];
10460
10583
  walkAST(ast, { enter(node) {
10461
10584
  if (node.type === "ImportDeclaration" && node.source?.value) {
@@ -10505,19 +10628,28 @@ async function collectFromAST(ast, code, isRemoteImport) {
10505
10628
  const source = node.source;
10506
10629
  if (source.type !== "Literal" && source.type !== "StringLiteral" && source.type !== "TemplateLiteral") return;
10507
10630
  const value = source.type === "TemplateLiteral" ? source.quasis?.length === 1 ? source.quasis[0].value?.cooked : void 0 : source.value;
10508
- if (!value || !isRemoteImport(value)) return;
10509
- result.push({
10631
+ if (!value) return;
10632
+ const originalText = code.slice(node.start, node.end);
10633
+ if (isRemoteImport(value)) result.push({
10510
10634
  kind: "dynamic",
10511
10635
  source: value,
10512
10636
  start: node.start,
10513
10637
  end: node.end,
10514
- 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: []
10515
10647
  });
10516
10648
  }
10517
10649
  } });
10518
10650
  return result;
10519
10651
  }
10520
- function collectFromRegex(code, isRemoteImport) {
10652
+ function collectFromRegex(code, isRemoteImport, collectLocalDynamic) {
10521
10653
  const result = [];
10522
10654
  const codePositions = createCodePositionMap(code);
10523
10655
  const importAttributes = String.raw`(?:\s+(?:with|assert)\s+\{[^;]*\})?`;
@@ -10584,26 +10716,35 @@ function collectFromRegex(code, isRemoteImport) {
10584
10716
  for (const match of code.matchAll(/import\(\s*(?:\/\*[\s\S]*?\*\/\s*)?(['"])([^'"]+)\1\s*\)/g)) {
10585
10717
  const [full, , source] = match;
10586
10718
  if (!codePositions[match.index]) continue;
10587
- if (!isRemoteImport(source)) continue;
10588
- result.push({
10589
- kind: "dynamic",
10719
+ const position = {
10590
10720
  source,
10591
10721
  start: match.index,
10592
- end: match.index + full.length,
10722
+ end: match.index + full.length
10723
+ };
10724
+ if (isRemoteImport(source)) result.push({
10725
+ kind: "dynamic",
10726
+ ...position,
10593
10727
  originalText: full
10594
10728
  });
10729
+ else if (collectLocalDynamic) result.push({
10730
+ kind: "local-dynamic",
10731
+ ...position,
10732
+ originalText: full,
10733
+ remotes: []
10734
+ });
10595
10735
  }
10596
10736
  return result.length > 0 ? result : void 0;
10597
10737
  }
10598
10738
  function pluginRemoteNamedExports(options) {
10599
10739
  const remoteNames = Object.keys(options.remotes);
10740
+ const waitsAtDynamicImports = options.shareStrategy === "loaded-first";
10741
+ let remoteDependencyCache = /* @__PURE__ */ new Map();
10600
10742
  let root = process.cwd();
10601
- const isNodeModulesId = (id) => id.includes("/node_modules/") || id.includes("\\node_modules\\");
10602
10743
  function isRemoteImport(source, importerId) {
10603
10744
  return remoteNames.some((name) => {
10604
10745
  if (source.startsWith(name + "/")) return true;
10605
10746
  if (source !== name) return false;
10606
- return !isNodeModulesId(importerId) || !getInstalledPackageEntry(source, { cwd: root });
10747
+ return !isNodeModulePath(importerId) || !getInstalledPackageEntry(source, { cwd: root });
10607
10748
  }) || source.includes("__loadRemote__");
10608
10749
  }
10609
10750
  return {
@@ -10612,11 +10753,15 @@ function pluginRemoteNamedExports(options) {
10612
10753
  configResolved(config) {
10613
10754
  root = config.root || process.cwd();
10614
10755
  },
10756
+ watchChange() {
10757
+ remoteDependencyCache = /* @__PURE__ */ new Map();
10758
+ },
10615
10759
  async transform(code, id) {
10616
10760
  if (remoteNames.length === 0) return;
10617
10761
  if (id.includes("__loadRemote__") || id.includes("__loadShare__")) return;
10618
10762
  if (!JS_EXTENSIONS_RE.test(id)) return;
10619
- if (!remoteNames.some((name) => code.includes(name))) return;
10763
+ const collectLocalDynamic = waitsAtDynamicImports && !isNodeModulePath(id) && /\bimport\s*\(/.test(code);
10764
+ if (!collectLocalDynamic && !remoteNames.some((name) => code.includes(name))) return;
10620
10765
  const descriptors = findModuleImportDescriptors(code);
10621
10766
  const resolvedElsewhere = /* @__PURE__ */ new Set();
10622
10767
  for (const source of new Set(descriptors.map((d) => d.source))) {
@@ -10628,12 +10773,26 @@ function pluginRemoteNamedExports(options) {
10628
10773
  for (const { kind, source, typeOnly } of descriptors) if (kind === "static" && !typeOnly && matchesRemoteImport(source)) markStaticRemote(source, options);
10629
10774
  let imports;
10630
10775
  try {
10631
- imports = await collectFromAST(this.parse(code), code, matchesRemoteImport);
10776
+ imports = await collectFromAST(this.parse(code), code, matchesRemoteImport, collectLocalDynamic);
10632
10777
  } catch {
10633
10778
  if ((id.includes(".vue") || id.includes(".svelte")) && /^\s*</.test(code)) return;
10634
- imports = collectFromRegex(code, matchesRemoteImport);
10779
+ imports = collectFromRegex(code, matchesRemoteImport, collectLocalDynamic);
10635
10780
  }
10636
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
+ }
10637
10796
  for (const remoteImport of imports) if (remoteImport.kind === "dynamic") markDynamicRemote(remoteImport.source, options);
10638
10797
  return applyRewrites(code, imports, id);
10639
10798
  }
@@ -10799,7 +10958,7 @@ function pluginSSRRemoteEntry(options) {
10799
10958
  const environmentName = environment?.name;
10800
10959
  const hasSsrEnvironment = Boolean(viteConfig?.environments?.ssr);
10801
10960
  const isLegacySsrBuild = Boolean(environment?.config?.build?.ssr ?? viteConfig?.build?.ssr);
10802
- return Object.keys(options.exposes).length > 0 && !(hasSsrEnvironment && environmentName !== "ssr" || !hasSsrEnvironment && !isLegacySsrBuild);
10961
+ return isRemoteContainer(options) && !(hasSsrEnvironment && environmentName !== "ssr" || !hasSsrEnvironment && !isLegacySsrBuild);
10803
10962
  };
10804
10963
  const getSsrRemoteEntrySource = () => {
10805
10964
  if (cachedSsrRemoteEntrySource === void 0) cachedSsrRemoteEntrySource = generateRemoteEntrySSR(options);
@@ -10901,8 +11060,13 @@ function pluginSSRRemoteEntry(options) {
10901
11060
  } };
10902
11061
  } catch {}
10903
11062
  }
11063
+ const fetchedId = body.data.name === "fetchModule" ? body.data.data[0] : void 0;
11064
+ const shared = typeof fetchedId === "string" && !!findSharedKey(fetchedId, options.shared);
10904
11065
  res.setHeader("Content-Type", "application/json");
10905
- res.end(JSON.stringify(result));
11066
+ res.end(JSON.stringify(shared ? {
11067
+ ...result,
11068
+ shared
11069
+ } : result));
10906
11070
  } catch (e) {
10907
11071
  res.setHeader("Content-Type", "application/json");
10908
11072
  res.end(JSON.stringify({ error: { message: String(e instanceof Error ? e.message : e) } }));
@@ -10938,6 +11102,12 @@ function pluginSSRRemoteEntry(options) {
10938
11102
  const isRolldown = getIsRolldown(this);
10939
11103
  const environment = this.environment;
10940
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
+ });
10941
11111
  if (isRolldown) this.emitFile({
10942
11112
  type: "chunk",
10943
11113
  id: remoteEntrySSRId,
@@ -10945,7 +11115,7 @@ function pluginSSRRemoteEntry(options) {
10945
11115
  fileName: ssrOutputFilename,
10946
11116
  preserveSignature: "strict"
10947
11117
  });
10948
- else if (Object.keys(options.exposes).length > 0 && !isNuxtLike()) this.emitFile({
11118
+ else if (isRemoteContainer(options) && !isNuxtLike()) this.emitFile({
10949
11119
  type: "chunk",
10950
11120
  id: virtualExposesSSRId,
10951
11121
  name: "ssrExposes",
@@ -10960,11 +11130,12 @@ function pluginSSRRemoteEntry(options) {
10960
11130
  const exposesChunk = findNuxtExposesChunk(bundle) ?? findEmittedExposesChunk(bundle);
10961
11131
  if (!isRolldown && isSsrRemoteEntryBuild(environment)) {
10962
11132
  let source = getSsrRemoteEntrySource();
10963
- if (exposesChunk) {
10964
- let exposesImport = path$1.posix.relative(path$1.posix.dirname(ssrOutputFilename), exposesChunk);
10965
- if (!exposesImport.startsWith(".")) exposesImport = `./${exposesImport}`;
10966
- 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)));
10967
11137
  }
11138
+ if (exposesChunk) source = source.replace(/import\("virtual:mf-exposes-ssr:[^"]+"\)/g, `import("${toRelativeImport(ssrOutputFilename, exposesChunk)}")`);
10968
11139
  this.emitFile({
10969
11140
  type: "asset",
10970
11141
  fileName: ssrOutputFilename,
@@ -11128,6 +11299,68 @@ const VarRemoteEntry = (providedOptions) => {
11128
11299
  }
11129
11300
  };
11130
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
11131
11364
  //#region src/utils/aliasToArrayPlugin.ts
11132
11365
  var aliasToArrayPlugin_default = {
11133
11366
  name: "alias-transform-plugin",
@@ -11276,145 +11509,6 @@ function sanitizeFederationControlChunk(code, fileName, filename) {
11276
11509
  return nextCode;
11277
11510
  }
11278
11511
  //#endregion
11279
- //#region src/utils/isTestEnv.ts
11280
- /**
11281
- * Detects whether the current process is running in a test environment
11282
- * Set `MFE_VITE_NO_TEST_ENV_CHECK=true` to load federation plugins during tests.
11283
- */
11284
- function isTestEnv() {
11285
- if (process.env.MFE_VITE_NO_TEST_ENV_CHECK === "true") return false;
11286
- return process.env.NODE_ENV === "test" || process.env.VITEST != null || process.env.JEST_WORKER_ID != null;
11287
- }
11288
- //#endregion
11289
- //#region src/utils/hostProvidesAllShared.ts
11290
- /** Virtual-module prefix of the host's per-share re-export entries. */
11291
- const SHARE_MODULE_PREFIX = "\0mf-host-provided-share:";
11292
- /** `./a/b` → `a/b`, `.` → `index`: the fixed entry name of an expose, without `.js`. */
11293
- function exposeEntryName(exposeKey) {
11294
- return exposeKey === "." ? "index" : exposeKey.replace(/^\.\//, "");
11295
- }
11296
- /** Bare specifier a host uses for an expose: `remote` for `.`, `remote/a/b` otherwise. */
11297
- function remoteSpecifier(remoteName, exposeKey) {
11298
- const entry = exposeEntryName(exposeKey);
11299
- return entry === "index" ? remoteName : `${remoteName}/${entry}`;
11300
- }
11301
- /** `id` is a remote alias or a subpath of one. */
11302
- function isRemoteSpecifier(id, remoteKeys) {
11303
- return remoteKeys.some((key) => id === key || id.startsWith(`${key}/`));
11304
- }
11305
- /**
11306
- * The shared key that owns `id`: an exact match, else the longest key `id` is a subpath
11307
- * of (`lodash-es/debounce` → `lodash-es`). Used to spot an unshared subpath of a shared
11308
- * package, which would bundle a private copy of that package into a remote.
11309
- */
11310
- function sharedKeyOwning(id, sharedKeys) {
11311
- let owner;
11312
- for (const key of sharedKeys) {
11313
- if (id !== key && !id.startsWith(`${key}/`)) continue;
11314
- if (!owner || key.length > owner.length) owner = key;
11315
- }
11316
- return owner;
11317
- }
11318
- /** Chunk name of the host's re-export entry for a shared key. */
11319
- function shareChunkName(key) {
11320
- return `shared/${key.replace(/^@/, "").replace(/[^\w-]+/g, "-")}`;
11321
- }
11322
- /** Reads a remote's `mf-manifest.json` from a URL or a path relative to `root`. */
11323
- async function readHostProvidesAllSharedManifest(location, root) {
11324
- let source;
11325
- if (isAbsoluteUrl(location)) {
11326
- const response = await fetch(location);
11327
- if (!response.ok) throw new Error(`Failed to fetch ${location}: ${response.status} ${response.statusText}`);
11328
- source = await response.text();
11329
- } else source = await readFile(path$1.resolve(root, location), "utf8");
11330
- const manifest = JSON.parse(source);
11331
- if (!manifest.metaData || !Array.isArray(manifest.exposes)) throw new Error(`${location} is not a Module Federation manifest.`);
11332
- 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 }\`.`);
11333
- return manifest;
11334
- }
11335
- /** URL prefix of a remote's files: `metaData.publicPath`, `auto` inferred from the manifest URL. */
11336
- function remotePublicPath(manifest, location) {
11337
- const publicPath = manifest.metaData.publicPath ?? "auto";
11338
- if (publicPath !== "auto") return ensureTrailingSlash(publicPath);
11339
- 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.`);
11340
- return ensureTrailingSlash(inferAutoPublicPath(location));
11341
- }
11342
- /** Import-map entries (`remote/Expose` → URL) for every expose of every remote. */
11343
- async function collectRemoteImports(remotes, root) {
11344
- const imports = {};
11345
- for (const [alias, remote] of Object.entries(remotes)) {
11346
- const manifest = await readHostProvidesAllSharedManifest(remote.entry, root);
11347
- const publicPath = remotePublicPath(manifest, remote.entry);
11348
- for (const expose of manifest.exposes) {
11349
- const file = expose.assets.js.sync[0];
11350
- if (!expose.path || !file) continue;
11351
- imports[remoteSpecifier(alias, expose.path)] = isAbsoluteUrl(remote.entry) ? new URL(file, new URL(publicPath, remote.entry)).href : publicPath + file;
11352
- }
11353
- }
11354
- return imports;
11355
- }
11356
- /** Top-level options that only the Module Federation runtime or `remoteEntry.js` pipeline reads. */
11357
- const IGNORED_OPTIONS = [
11358
- "filename",
11359
- "ssrFilename",
11360
- "varFilename",
11361
- "library",
11362
- "runtime",
11363
- "shareScope",
11364
- "shareStrategy",
11365
- "runtimePlugins",
11366
- "implementation",
11367
- "getPublicPath",
11368
- "ignoreOrigin",
11369
- "virtualModuleDir",
11370
- "hostInitInjectLocation",
11371
- "bundleAllCSS",
11372
- "treeShakingDir",
11373
- "injectTreeShakingUsedExports",
11374
- "treeShakingSharedPlugins",
11375
- "treeShakingSharedExcludePlugins",
11376
- "moduleParseTimeout",
11377
- "moduleParseIdleTimeout",
11378
- "target",
11379
- "ssrExternals",
11380
- "ssrEntryLoader",
11381
- "disableRemote",
11382
- "disableShared",
11383
- "disableSnapshot"
11384
- ];
11385
- const IGNORED_EXPERIMENTS = [
11386
- "externalRuntime",
11387
- "provideExternalRuntime",
11388
- "ssrMode"
11389
- ];
11390
- /** Per-share options: version negotiation, aliasing and fallbacks do not exist in this mode. */
11391
- const IGNORED_SHARE_OPTIONS = [
11392
- "eager",
11393
- "requiredVersion",
11394
- "strictVersion",
11395
- "import",
11396
- "request",
11397
- "shareKey",
11398
- "name",
11399
- "version",
11400
- "shareScope",
11401
- "treeShaking",
11402
- "allowNodeModulesSuffixMatch",
11403
- "suppressMissingImportWarning"
11404
- ];
11405
- const isSet = (value) => value !== void 0 && value !== false && !(Array.isArray(value) && value.length === 0);
11406
- /** A single warning naming every option the user set that import-map mode ignores. */
11407
- function getIgnoredOptionWarning(options) {
11408
- const shared = options.shared;
11409
- const ignored = [
11410
- ...IGNORED_OPTIONS.filter((key) => isSet(options[key])).map((key) => `\`${key}\``),
11411
- ...IGNORED_EXPERIMENTS.filter((key) => isSet(options.experiments?.[key])).map((key) => `\`experiments.${key}\``),
11412
- ...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}\``) : []) : []
11413
- ];
11414
- if (ignored.length === 0) return void 0;
11415
- return `experiments.hostProvidesAllShared: ${ignored.join(", ")} ignored. The Module Federation runtime is not used and the host provides the only copy of every shared key.`;
11416
- }
11417
- //#endregion
11418
11512
  //#region src/plugins/pluginHostProvidesAllSharedHost.ts
11419
11513
  const ESM_SYNTAX_RE = /(^|[\s;])(export|import)[\s{*]/m;
11420
11514
  const DEFAULT_EXPORT_RE = /export\s+default\b|export\s*\{[^}]*\bas\s+default\b/;
@@ -11640,28 +11734,6 @@ function pluginHostProvidesAllSharedRemote(options) {
11640
11734
  };
11641
11735
  }
11642
11736
  //#endregion
11643
- //#region src/utils/normalizeOptimizeDeps.ts
11644
- var normalizeOptimizeDeps_default = {
11645
- name: "normalizeOptimizeDeps",
11646
- config: (config) => {
11647
- let { optimizeDeps } = config;
11648
- if (!optimizeDeps) {
11649
- config.optimizeDeps = {};
11650
- optimizeDeps = config.optimizeDeps;
11651
- }
11652
- if (!optimizeDeps.include) optimizeDeps.include = [];
11653
- if (!optimizeDeps.exclude) optimizeDeps.exclude = [];
11654
- if (!optimizeDeps.needsInterop) optimizeDeps.needsInterop = [];
11655
- },
11656
- configResolved: (config) => {
11657
- const include = config.optimizeDeps?.include;
11658
- const exclude = config.optimizeDeps?.exclude;
11659
- if (!include?.length || !exclude?.length) return;
11660
- const included = new Set(include);
11661
- config.optimizeDeps.exclude = exclude.filter((dep) => !included.has(dep));
11662
- }
11663
- };
11664
- //#endregion
11665
11737
  //#region src/utils/runtimeCapabilityOptimization.ts
11666
11738
  const RUNTIME_CAPABILITIES = [
11667
11739
  {
@@ -11691,11 +11763,11 @@ function applyRuntimeCapabilityDefines(define, options, { defaultDisableSnapshot
11691
11763
  }
11692
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.`);
11693
11765
  }
11694
- 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));
11695
11767
  }
11696
11768
  function getRuntimeCapabilityConfigurationWarnings(options) {
11697
11769
  const warnings = [];
11698
- 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.");
11699
11771
  if (options.disableShared && hasShared(options)) warnings.push("disableShared is true, but shared dependencies are configured. Shared dependency loading will be unavailable at runtime.");
11700
11772
  return warnings;
11701
11773
  }
@@ -11863,15 +11935,8 @@ function isBarePackageSubpath(specifier) {
11863
11935
  * Vite then resolves the package's own dependency graph using its normal
11864
11936
  * scanner, preserving package and peer-dependency resolution semantics.
11865
11937
  */
11866
- function includeLinkedSharedEntries(optimizeDeps, shared, projectRoot, exposes, outDir) {
11938
+ function collectLinkedSharedEntries(shared, projectRoot, exposes) {
11867
11939
  const additions = /* @__PURE__ */ new Set();
11868
- const entries = new Set(Array.isArray(optimizeDeps.entries) ? optimizeDeps.entries : optimizeDeps.entries ? [optimizeDeps.entries] : [
11869
- "**/*.html",
11870
- "!**/node_modules/**",
11871
- `!**/${outDir.replace(/\\/g, "/")}/**`,
11872
- "!**/__tests__/**",
11873
- "!**/coverage/**"
11874
- ]);
11875
11940
  for (const [packageName, share] of Object.entries(shared ?? {})) {
11876
11941
  if (share?.shareConfig?.import === false) continue;
11877
11942
  const configuredImport = share?.shareConfig?.import;
@@ -11894,13 +11959,7 @@ function includeLinkedSharedEntries(optimizeDeps, shared, projectRoot, exposes,
11894
11959
  if (existsSync(entry)) additions.add(entry);
11895
11960
  }
11896
11961
  }
11897
- if (additions.size === 0) return;
11898
- for (const entry of additions) entries.add(entry);
11899
- optimizeDeps.entries = [...entries];
11900
- }
11901
- function stabilizeOptimizeDeps(optimizeDeps) {
11902
- optimizeDeps.include = [...new Set(optimizeDeps.include ?? [])].sort();
11903
- optimizeDeps.exclude = [...new Set(optimizeDeps.exclude ?? [])].sort();
11962
+ return [...additions];
11904
11963
  }
11905
11964
  function isFile(candidate) {
11906
11965
  try {
@@ -12023,7 +12082,7 @@ function createEarlyVirtualModulesPlugin(options) {
12023
12082
  const isVinext = hasPackageDependency("vinext");
12024
12083
  initVirtualModules(_command, getRemoteEntryId(options), false, options);
12025
12084
  const isRolldown = getIsRolldown(this);
12026
- if (remotes && Object.keys(remotes).length > 0) {
12085
+ if (hasRemotes(options)) {
12027
12086
  for (const key of Object.keys(remotes)) ensureUsedRemote(key, options);
12028
12087
  if (_command === "serve") {
12029
12088
  config.optimizeDeps = config.optimizeDeps || {};
@@ -12045,7 +12104,7 @@ function createEarlyVirtualModulesPlugin(options) {
12045
12104
  const preparedShares = /* @__PURE__ */ new Map();
12046
12105
  const writeSharedModules = (source, shareItem) => {
12047
12106
  if (preparedShares.get(source) === shareItem) return;
12048
- writeLoadShareModule(source, shareItem, _command, isRolldown, options);
12107
+ writeLoadShareModule(source, shareItem, _command, options);
12049
12108
  if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(source, shareItem, options);
12050
12109
  preparedShares.set(source, shareItem);
12051
12110
  };
@@ -12061,7 +12120,7 @@ function createEarlyVirtualModulesPlugin(options) {
12061
12120
  if (!id.startsWith("module-federation:optimized-require-")) return;
12062
12121
  const sourcePackage = id.slice(36);
12063
12122
  if (sourcePackage !== "react" && sourcePackage !== "react-dom") return;
12064
- const loadSharePath = getLoadShareModulePath(sourcePackage, isRolldown, options);
12123
+ const loadSharePath = getLoadShareModulePath(sourcePackage, options);
12065
12124
  const source = JSON.stringify(loadSharePath);
12066
12125
  return "import * as __mfShared from " + source + ";\nexport * from " + source + ";\nexport default __mfShared.default ?? __mfShared;";
12067
12126
  },
@@ -12074,7 +12133,7 @@ function createEarlyVirtualModulesPlugin(options) {
12074
12133
  const key = findSharedKey(source, shared);
12075
12134
  if (!key) return;
12076
12135
  const importerPackage = getSharedPackageFromFile(importer, shared, root);
12077
- 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;
12078
12137
  if (isAssetLikeImport(source)) return;
12079
12138
  const shareItem = shared[key];
12080
12139
  const isReactSingleton = source === "react" && key === "react" && shareItem.shareConfig?.singleton === true;
@@ -12087,7 +12146,7 @@ function createEarlyVirtualModulesPlugin(options) {
12087
12146
  writeSharedModules(source, shareItem);
12088
12147
  return { id: `module-federation:optimized-require-${source}` };
12089
12148
  }
12090
- const loadSharePath = getLoadShareModulePath(source, isRolldown, options);
12149
+ const loadSharePath = getLoadShareModulePath(source, options);
12091
12150
  writeSharedModules(source, shareItem);
12092
12151
  return {
12093
12152
  id: loadSharePath,
@@ -12115,12 +12174,12 @@ function createEarlyVirtualModulesPlugin(options) {
12115
12174
  const key = findSharedKey(args.path, shared);
12116
12175
  if (!key || isAssetLikeImport(args.path)) return;
12117
12176
  const importerPackage = getSharedPackageFromFile(args.importer, shared, root);
12118
- 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;
12119
12178
  if (importerPackage && isSharedPackageDependency(key, importerPackage)) return;
12120
12179
  addUsedShares(args.path, options);
12121
12180
  if (args.kind === "import-statement" || args.kind === "dynamic-import") {
12122
12181
  const shareItem = shared[key];
12123
- const loadSharePath = getLoadShareModulePath(args.path, isRolldown, options);
12182
+ const loadSharePath = getLoadShareModulePath(args.path, options);
12124
12183
  writeSharedModules(args.path, shareItem);
12125
12184
  return {
12126
12185
  path: loadSharePath,
@@ -12139,7 +12198,7 @@ function createEarlyVirtualModulesPlugin(options) {
12139
12198
  const key = findSharedKey(args.path, shared);
12140
12199
  if (!key) return;
12141
12200
  const shareItem = shared[key];
12142
- const loadSharePath = getLoadShareModulePath(args.path, isRolldown, options);
12201
+ const loadSharePath = getLoadShareModulePath(args.path, options);
12143
12202
  writeSharedModules(args.path, shareItem);
12144
12203
  return {
12145
12204
  loader: "js",
@@ -12174,8 +12233,8 @@ export default __mfShared.default ?? __mfShared;`
12174
12233
  addConfiguredShare(runtimeKey, options);
12175
12234
  continue;
12176
12235
  }
12177
- getLoadShareModulePath(runtimeKey, isRolldown, options);
12178
- writeLoadShareModule(runtimeKey, shareItem, _command, isRolldown, options);
12236
+ getLoadShareModulePath(runtimeKey, options);
12237
+ writeLoadShareModule(runtimeKey, shareItem, _command, options);
12179
12238
  if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(runtimeKey, shareItem, options);
12180
12239
  addConfiguredShare(runtimeKey, options);
12181
12240
  if (_command === "serve" && shareItem.shareConfig?.import !== false) {
@@ -12197,8 +12256,8 @@ export default __mfShared.default ?? __mfShared;`
12197
12256
  optimizeDeps.exclude.push(subpath);
12198
12257
  continue;
12199
12258
  }
12200
- getLoadShareModulePath(subpath, isRolldown, options);
12201
- writeLoadShareModule(subpath, shareItem, _command, isRolldown, options);
12259
+ getLoadShareModulePath(subpath, options);
12260
+ writeLoadShareModule(subpath, shareItem, _command, options);
12202
12261
  writePreBuildLibPath(subpath, shareItem, options);
12203
12262
  addConfiguredShare(subpath, options);
12204
12263
  if (canResolveSubpath) {
@@ -12211,9 +12270,19 @@ export default __mfShared.default ?? __mfShared;`
12211
12270
  writeLocalSharedImportMap(options);
12212
12271
  }
12213
12272
  if (_command === "serve") {
12214
- config.optimizeDeps ??= {};
12215
- includeLinkedSharedEntries(config.optimizeDeps, shared, root, options.exposes, config.build?.outDir ?? "dist");
12216
- 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
+ }
12217
12286
  }
12218
12287
  },
12219
12288
  configResolved(config) {
@@ -12248,6 +12317,7 @@ export default __mfShared.default ?? __mfShared;`
12248
12317
  resolveImportPath(ssrEntryLoaderSpecifier);
12249
12318
  options.runtimePlugins.push([ssrEntryLoaderSpecifier, {
12250
12319
  resolvedShared,
12320
+ ...config.command === "build" && { rebaseSharedAtRuntime: true },
12251
12321
  ...options.ssrEntryLoader
12252
12322
  }]);
12253
12323
  } catch {}
@@ -12277,7 +12347,7 @@ function withoutDynamicRemoteTypeHints(options) {
12277
12347
  }
12278
12348
  function loadPluginDts(options) {
12279
12349
  if (options.dts === false) return [];
12280
- return [import("./pluginDts-DShMdjzR.js").then(({ default: pluginDts }) => pluginDts(options))];
12350
+ return [import("./pluginDts-rZMRTCTz.js").then(({ default: pluginDts }) => pluginDts(options))];
12281
12351
  }
12282
12352
  const INJECT_EXTERNAL_RUNTIME_CORE_PLUGIN = "@module-federation/vite/injectExternalRuntimeCorePlugin";
12283
12353
  function isInjectExternalRuntimeCorePlugin(specifier) {
@@ -12304,13 +12374,13 @@ function applyExternalRuntimeExperiments(options) {
12304
12374
  }
12305
12375
  }
12306
12376
  function federation(mfUserOptions) {
12307
- 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 [];
12308
12378
  const options = normalizeModuleFederationOptions(mfUserOptions);
12309
12379
  if (!options.name) throw createModuleFederationError("name is required");
12310
12380
  if (options.experiments.hostProvidesAllShared) {
12311
12381
  const ignored = getIgnoredOptionWarning(mfUserOptions);
12312
12382
  if (ignored) mfWarn(ignored);
12313
- 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))];
12314
12384
  }
12315
12385
  applyExternalRuntimeExperiments(options);
12316
12386
  const isVinext = hasPackageDependency("vinext");
@@ -12365,9 +12435,9 @@ function federation(mfUserOptions) {
12365
12435
  const key = findSharedKey(pkg, shared);
12366
12436
  if (!key) return "not-applicable";
12367
12437
  const requestedModule = VirtualModule.findById(id);
12368
- const ownedModule = VirtualModule.findById(getLoadShareModulePath(pkg, false, options));
12438
+ const ownedModule = VirtualModule.findById(getLoadShareModulePath(pkg, options));
12369
12439
  if (!requestedModule || requestedModule !== ownedModule) return "not-owned";
12370
- writeLoadShareModule(pkg, shared[key], command, getIsRolldown(context), options, getLoadHookExportConditions(context, loadOptions), importFalseExportUsage);
12440
+ writeLoadShareModule(pkg, shared[key], command, options, getLoadHookExportConditions(context, loadOptions), importFalseExportUsage);
12371
12441
  return "refreshed";
12372
12442
  };
12373
12443
  const getCompleteImportFalseExportUsage = (id) => {
@@ -12510,9 +12580,7 @@ function federation(mfUserOptions) {
12510
12580
  name: "vite:module-federation-virtual-modules",
12511
12581
  enforce: "pre",
12512
12582
  configureServer(server) {
12513
- server.watcher.on("change", invalidateSharedExportInspectionCache);
12514
- server.watcher.on("add", invalidateSharedExportInspectionCache);
12515
- server.watcher.on("unlink", invalidateSharedExportInspectionCache);
12583
+ watchFileEvents(server.watcher, invalidateSharedExportInspectionCache);
12516
12584
  },
12517
12585
  resolveId(id) {
12518
12586
  if (id === "@module-federation/vite/ssrEntryLoader") return resolveImportPath(id);
@@ -12522,7 +12590,6 @@ function federation(mfUserOptions) {
12522
12590
  id,
12523
12591
  shared: options.shared,
12524
12592
  command,
12525
- isRolldown: getIsRolldown(this),
12526
12593
  findSharedKey,
12527
12594
  addUsedShares: (pkg) => addUsedShares(pkg, options),
12528
12595
  writeLocalSharedImportMap: () => writeLocalSharedImportMap(options),
@@ -12583,14 +12650,29 @@ function federation(mfUserOptions) {
12583
12650
  ssrResolveConditions = config.ssr?.resolve?.conditions ? [...config.ssr.resolve.conditions] : void 0;
12584
12651
  ssrTarget = config.ssr?.target ?? "node";
12585
12652
  isProduction = config.isProduction;
12586
- 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));
12587
12654
  resolveSharedVersions(shared, config.root);
12588
12655
  initVirtualModules(command, remoteEntryId, ssrCapabilities.enableSsrInitBootstrap, options);
12589
12656
  }
12590
12657
  },
12591
12658
  aliasToArrayPlugin_default,
12592
12659
  checkAliasConflicts({ shared }),
12593
- 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
+ },
12594
12676
  ...loadPluginDts(options),
12595
12677
  pluginDevRemoteHmr(options),
12596
12678
  {
@@ -12615,7 +12697,7 @@ function federation(mfUserOptions) {
12615
12697
  entryName: "hostInit",
12616
12698
  entryPath: () => getHostAutoInitPath(options),
12617
12699
  inject: hostInitInjectLocation,
12618
- forceClientInjected: Object.keys(options.exposes).length > 0,
12700
+ forceClientInjected: isRemoteContainer(options),
12619
12701
  skipTransformFor: Object.values(options.exposes).map((expose) => expose.import),
12620
12702
  federationOptions: options
12621
12703
  }),
@@ -12813,10 +12895,6 @@ function federation(mfUserOptions) {
12813
12895
  config.optimizeDeps.include.push(optimizeDep);
12814
12896
  }
12815
12897
  });
12816
- if (isRolldown) {
12817
- config.build ??= {};
12818
- config.build.target ??= "esnext";
12819
- }
12820
12898
  const isBundledDev = Boolean(config.experimental?.bundledDev);
12821
12899
  if (isRolldown && _command === "serve" && isBundledDev) {
12822
12900
  config.build.rolldownOptions ??= {};
@@ -12860,6 +12938,7 @@ function federation(mfUserOptions) {
12860
12938
  },
12861
12939
  ...Manifest(options),
12862
12940
  ...pluginSSRRemoteEntry(options),
12941
+ ...pluginSsrRuntimeInit(options),
12863
12942
  ...VarRemoteEntry(options),
12864
12943
  {
12865
12944
  name: "module-federation-vinext-fix-rsc-preload-as",
@@ -12896,20 +12975,12 @@ function federation(mfUserOptions) {
12896
12975
  },
12897
12976
  ...(function() {
12898
12977
  let disablePreload = false;
12899
- return Object.keys(options.exposes).length > 0 ? [{
12978
+ return isRemoteContainer(options) ? [{
12900
12979
  name: "module-federation-fix-preload",
12901
12980
  enforce: "post",
12902
12981
  apply: "build",
12903
- config(_config, { command }) {
12904
- const manifest = options.manifest;
12905
- const getDefaultDisableAssetsAnalyze = (cfgCommand) => cfgCommand === "serve" && (typeof manifest !== "object" || !Object.hasOwn(manifest, "disableAssetsAnalyze"));
12906
- const getConfiguredDisableAssetsAnalyze = (cfgCommand) => {
12907
- if (typeof manifest === "object" && manifest !== null) {
12908
- if (Object.hasOwn(manifest, "disableAssetsAnalyze")) return manifest.disableAssetsAnalyze === true;
12909
- }
12910
- return getDefaultDisableAssetsAnalyze(cfgCommand);
12911
- };
12912
- disablePreload = getConfiguredDisableAssetsAnalyze(command);
12982
+ config() {
12983
+ disablePreload = resolveDisableAssetsAnalyze(options.manifest, false);
12913
12984
  },
12914
12985
  generateBundle(_outputOptions, bundle, _isWrite) {
12915
12986
  if (disablePreload) return;