@module-federation/vite 1.20.1 → 1.20.3

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,3 +1,5 @@
1
+ import { n as normalizePathForImport, r as rebaseImport } from "./buildPaths-BkaQHrd2.js";
2
+ import { a as getMatchingNodeModuleSubpath, c as isNuxtClientBase, d as resolvePublicPath, i as getCommonSharedSubpaths, l as isViteOptimizableEntry, n as getBasePath$2, o as isAssetLikeImport, r as getCommonSharedSubpathFromNodeModulePath, s as isNodeModulePath, t as filterId, u as normalizeNodeModulePath } from "./pathNormalization-CLDIcf9-.js";
1
3
  import { createRequire } from "node:module";
2
4
  import * as fs$2 from "fs";
3
5
  import fs, { existsSync, readFileSync, readdirSync, realpathSync, statSync, writeFileSync } from "fs";
@@ -25,52 +27,6 @@ var __exportAll = (all, no_symbols) => {
25
27
  return target;
26
28
  };
27
29
  //#endregion
28
- //#region src/utils/buildPaths.ts
29
- /**
30
- * Rebase an import path for a bootstrap file that moved from root into `dir`.
31
- *
32
- * When entryFileNames places entries in a subdirectory (e.g. `static/js/`),
33
- * the bootstrap file moves there too. Paths that resolved from the HTML root
34
- * must resolve from the new directory instead.
35
- *
36
- * Cases: `/static/js/hostInit.js` → `./hostInit.js` (strip dir prefix)
37
- * `./src/main.tsx` → `../../src/main.tsx` (climb back up for each dir level)
38
- * `https://cdn.example.com` → unchanged (absolute URL)
39
- */
40
- function rebaseImport(importSrc, dir) {
41
- if (!dir) return importSrc;
42
- if (isAbsoluteUrl(importSrc)) return importSrc;
43
- const normalizedDir = dir.replace(/^\/+|\/+$/g, "");
44
- if (!normalizedDir) return importSrc;
45
- const stripDirPrefix = (src, prefix) => {
46
- if (src === prefix) return "";
47
- if (src.startsWith(prefix + "/")) return src.slice(prefix.length);
48
- };
49
- const absoluteRemainder = stripDirPrefix(importSrc, "/" + normalizedDir);
50
- if (absoluteRemainder !== void 0) {
51
- const remainder = absoluteRemainder.replace(/^\/+/, "");
52
- return remainder ? "./" + remainder : "./";
53
- }
54
- const relativeRemainder = stripDirPrefix(importSrc, normalizedDir);
55
- if (relativeRemainder !== void 0) {
56
- const remainder = relativeRemainder.replace(/^\/+/, "");
57
- return remainder ? "./" + remainder : "./";
58
- }
59
- const upLevels = normalizedDir.split("/").filter(Boolean).length;
60
- const prefix = upLevels > 0 ? "../".repeat(upLevels) : "./";
61
- if (importSrc.startsWith("./")) return prefix + importSrc.slice(2);
62
- if (importSrc.startsWith("/")) return prefix + importSrc.slice(1);
63
- return prefix + importSrc;
64
- }
65
- function normalizePathForImport(path) {
66
- return path.replace(/\\/g, "/");
67
- }
68
- const EXTERNAL_URL_RE = /^(?:[a-z]+:|\/\/)/i;
69
- function isAbsoluteUrl(src) {
70
- if (/^[a-z]:[\\/]/i.test(src)) return false;
71
- return EXTERNAL_URL_RE.test(src);
72
- }
73
- //#endregion
74
30
  //#region src/utils/codeRewriter.ts
75
31
  const BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
76
32
  var CodeRewriter = class {
@@ -851,123 +807,6 @@ function hasPackageDependency(dependencyName, cwd = packageDetectionCwd || proce
851
807
  }
852
808
  }
853
809
  //#endregion
854
- //#region src/utils/pathNormalization.ts
855
- const COMMON_SHARED_SUBPATHS = {
856
- react: [
857
- "react/jsx-runtime",
858
- "react/jsx-dev-runtime",
859
- "react/compiler-runtime"
860
- ],
861
- "react-dom": [
862
- "react-dom/client",
863
- "react-dom/server",
864
- "react-dom/server.browser"
865
- ],
866
- "solid-js": [
867
- "solid-js/web",
868
- "solid-js/store",
869
- "solid-js/html",
870
- "solid-js/h"
871
- ],
872
- zustand: ["zustand/vanilla", "zustand/react"]
873
- };
874
- const VITE_DEFAULT_ASSET_TYPES = [
875
- "apng",
876
- "bmp",
877
- "png",
878
- "jpe?g",
879
- "jfif",
880
- "pjpeg",
881
- "pjp",
882
- "gif",
883
- "svg",
884
- "ico",
885
- "webp",
886
- "avif",
887
- "cur",
888
- "jxl",
889
- "mp4",
890
- "webm",
891
- "ogg",
892
- "mp3",
893
- "wav",
894
- "flac",
895
- "aac",
896
- "opus",
897
- "mov",
898
- "m4a",
899
- "vtt",
900
- "woff2?",
901
- "eot",
902
- "ttf",
903
- "otf",
904
- "webmanifest",
905
- "pdf",
906
- "txt"
907
- ];
908
- const ASSET_LIKE_IMPORT_RE = new RegExp(`\\.(${[...[
909
- "css",
910
- "scss",
911
- "sass",
912
- "less",
913
- "styl",
914
- "stylus"
915
- ], ...VITE_DEFAULT_ASSET_TYPES].join("|")})(?:[?#].*)?$`, "i");
916
- function isAssetLikeImport(source) {
917
- return ASSET_LIKE_IMPORT_RE.test(source);
918
- }
919
- const VITE_OPTIMIZABLE_ENTRY_RE = /\.[cm]?[jt]s$/;
920
- function isViteOptimizableEntry(resolvedPath) {
921
- return VITE_OPTIMIZABLE_ENTRY_RE.test(resolvedPath);
922
- }
923
- function removeTrailingSlash(value) {
924
- return value.endsWith("/") ? value.slice(0, -1) : value;
925
- }
926
- function ensureTrailingSlash(value) {
927
- return `${removeTrailingSlash(value)}/`;
928
- }
929
- function getBasePath$2(base) {
930
- return removeTrailingSlash(base || "/");
931
- }
932
- function isNuxtClientBase(base) {
933
- return getBasePath$2(base).endsWith("/_nuxt");
934
- }
935
- function normalizeNodeModulePath(source) {
936
- return source.replace(/\\/g, "/").replace(/\?.*$/, "");
937
- }
938
- function isNodeModulePath(source) {
939
- return source.includes("/node_modules/") || source.includes("\\node_modules\\");
940
- }
941
- function filterId(id) {
942
- return typeof id === "string" && !id.includes("\0");
943
- }
944
- function getMatchingNodeModuleSubpath(source, candidates) {
945
- const normalized = normalizeNodeModulePath(source);
946
- return [...candidates].sort((a, b) => b.length - a.length).find((candidate) => normalized.includes(`/node_modules/${candidate}/`) || normalized.includes(`/node_modules/${candidate}.`));
947
- }
948
- function getCommonSharedSubpaths(sharedKey) {
949
- return COMMON_SHARED_SUBPATHS[removeTrailingSlash(sharedKey)] || [];
950
- }
951
- function getCommonSharedSubpathFromNodeModulePath(source, sharedKey) {
952
- return getMatchingNodeModuleSubpath(source, getCommonSharedSubpaths(removeTrailingSlash(sharedKey)));
953
- }
954
- /**
955
- * Resolves the public path for remote entries
956
- * @param options - Module Federation options
957
- * @param viteBase - Vite's base config value
958
- * @param originalBase - Original base config before any transformations
959
- * @returns The resolved public path
960
- */
961
- function resolvePublicPath(options, viteBase, originalBase) {
962
- if (options.publicPath && options.publicPath !== "auto") return options.publicPath;
963
- if (!originalBase) return "auto";
964
- if (viteBase) {
965
- if (viteBase === "./") return "auto";
966
- return ensureTrailingSlash(viteBase);
967
- }
968
- return "auto";
969
- }
970
- //#endregion
971
810
  //#region src/utils/normalizeModuleFederationOptions.ts
972
811
  const INTERNAL_NAME_PREFIX = "__mfe_internal__";
973
812
  function toInternalModuleFederationName(name) {
@@ -1914,6 +1753,9 @@ ${exportStatement}
1914
1753
  }
1915
1754
  //#endregion
1916
1755
  //#region src/utils/treeShaking.ts
1756
+ function shouldAnalyzeSharedExports(shareItem) {
1757
+ return !!(shareItem && (shareItem.shareConfig.treeShaking || shareItem.shareConfig.import === false));
1758
+ }
1917
1759
  const legacyTreeShakingState = {
1918
1760
  inferredUsage: /* @__PURE__ */ new Map(),
1919
1761
  buildMode: false
@@ -1987,12 +1829,12 @@ function getExportRecords(sharedKey, request, options) {
1987
1829
  * fallback lookup across keys keeps aliases/backwards-compatible callers
1988
1830
  * working, while still keeping each concrete request's exports isolated.
1989
1831
  */
1990
- function getTreeShakingExportUsage(request, shareItem, sharedKey, options) {
1832
+ function getSharedExportUsage(request, shareItem, sharedKey, options) {
1991
1833
  const treeShaking = shareItem?.shareConfig.treeShaking;
1992
- if (!treeShaking || !getTreeShakingState(options).buildMode) return void 0;
1834
+ if (!shouldAnalyzeSharedExports(shareItem) || !getTreeShakingState(options).buildMode) return;
1993
1835
  const records = getExportRecords(sharedKey, request, options);
1994
1836
  if (records.some((record) => record.requiresFullBundle)) return { kind: "full" };
1995
- const configured = treeShaking.usedExports ?? [];
1837
+ const configured = treeShaking?.usedExports ?? [];
1996
1838
  const result = new Set(configured);
1997
1839
  records.forEach((record) => record.usedExports.forEach((name) => result.add(name)));
1998
1840
  if (result.size > 0) return {
@@ -2004,6 +1846,10 @@ function getTreeShakingExportUsage(request, shareItem, sharedKey, options) {
2004
1846
  usedExports: []
2005
1847
  } : { kind: "unknown" };
2006
1848
  }
1849
+ function getTreeShakingExportUsage(request, shareItem, sharedKey, options) {
1850
+ if (!shareItem?.shareConfig.treeShaking) return void 0;
1851
+ return getSharedExportUsage(request, shareItem, sharedKey, options);
1852
+ }
2007
1853
  function getModuleSource(node) {
2008
1854
  if (!node || typeof node !== "object") return void 0;
2009
1855
  const source = node;
@@ -2118,8 +1964,8 @@ function collectReExport(node, source, record, markUnsafe) {
2118
1964
  *
2119
1965
  * Parsing the module avoids treating import-looking text in comments, strings,
2120
1966
  * templates, or regular expressions as real dependencies. If parsing fails,
2121
- * every configured tree-shaken share is conservatively marked as requiring its
2122
- * full bundle instead of guessing from source text.
1967
+ * every configured share whose exports are analyzed is conservatively marked
1968
+ * as requiring its full export surface instead of guessing from source text.
2123
1969
  *
2124
1970
  * Generated federation wrappers are excluded because their imports describe
2125
1971
  * the wrapper implementation, not the consumer's requirements.
@@ -2132,13 +1978,13 @@ function collectTreeShakingImports(code, id, shared, findSharedKey, record, mark
2132
1978
  ast = parseAst(code);
2133
1979
  } catch {
2134
1980
  Object.entries(shared).forEach(([sharedKey, shareItem]) => {
2135
- if (shareItem.shareConfig.treeShaking) markUnsafe(sharedKey, "*");
1981
+ if (shouldAnalyzeSharedExports(shareItem)) markUnsafe(sharedKey, "*");
2136
1982
  });
2137
1983
  return;
2138
1984
  }
2139
1985
  const matchShared = (source) => {
2140
1986
  const sharedKey = findSharedKey(source, shared);
2141
- return sharedKey && shared[sharedKey]?.shareConfig.treeShaking ? sharedKey : void 0;
1987
+ return sharedKey && shouldAnalyzeSharedExports(shared[sharedKey]) ? sharedKey : void 0;
2142
1988
  };
2143
1989
  const recordSource = (names, source) => {
2144
1990
  const sharedKey = matchShared(source);
@@ -2468,32 +2314,55 @@ function resolveReExportModule(filePath, specifier, exportConditions) {
2468
2314
  return;
2469
2315
  }
2470
2316
  }
2471
- function hasTopLevelDeclaratorComma(source, start, codePositions) {
2317
+ /** Marks a template-literal frame whose text (not its interpolation) is being scanned. */
2318
+ const TEMPLATE_TEXT = Symbol("templateText");
2319
+ function getAdditionalTopLevelDeclaratorNames(source, start, codePositions) {
2320
+ const names = [];
2472
2321
  let depth = 0;
2473
2322
  let quote;
2474
2323
  let escaped = false;
2475
2324
  let canStartRegex = true;
2325
+ const templateFrames = [];
2326
+ const inTemplateText = () => templateFrames[templateFrames.length - 1] === TEMPLATE_TEXT;
2476
2327
  for (let index = start; index < source.length; index++) {
2477
2328
  const char = source[index];
2329
+ if (inTemplateText()) {
2330
+ if (escaped) escaped = false;
2331
+ else if (char === "\\") escaped = true;
2332
+ else if (char === "$" && source[index + 1] === "{") {
2333
+ templateFrames.push(depth);
2334
+ index++;
2335
+ canStartRegex = true;
2336
+ } else if (char === "`") {
2337
+ templateFrames.pop();
2338
+ canStartRegex = false;
2339
+ }
2340
+ continue;
2341
+ }
2478
2342
  if (quote) {
2479
2343
  if (escaped) escaped = false;
2480
2344
  else if (char === "\\") escaped = true;
2481
2345
  else if (char === quote) quote = void 0;
2482
2346
  continue;
2483
2347
  }
2484
- if (char === "\"" || char === "'" || char === "`") {
2348
+ if (char === "`") {
2349
+ templateFrames.push(TEMPLATE_TEXT);
2350
+ canStartRegex = false;
2351
+ continue;
2352
+ }
2353
+ if (char === "\"" || char === "'") {
2485
2354
  quote = char;
2486
2355
  canStartRegex = false;
2487
2356
  continue;
2488
2357
  }
2489
2358
  if (char === "/" && source[index + 1] === "/") {
2490
2359
  index = source.indexOf("\n", index + 2);
2491
- if (index === -1) return false;
2360
+ if (index === -1) return names;
2492
2361
  continue;
2493
2362
  }
2494
2363
  if (char === "/" && source[index + 1] === "*") {
2495
2364
  const commentEnd = source.indexOf("*/", index + 2);
2496
- if (commentEnd === -1) return true;
2365
+ if (commentEnd === -1) return void 0;
2497
2366
  index = commentEnd + 1;
2498
2367
  continue;
2499
2368
  }
@@ -2524,9 +2393,9 @@ function hasTopLevelDeclaratorComma(source, start, codePositions) {
2524
2393
  while (/[$_\p{ID_Continue}]/u.test(source[index + 1] || "")) index++;
2525
2394
  break;
2526
2395
  }
2527
- if (regexChar === "\n" || regexChar === "\r") return true;
2396
+ if (regexChar === "\n" || regexChar === "\r") return void 0;
2528
2397
  }
2529
- if (!closed) return true;
2398
+ if (!closed) return void 0;
2530
2399
  canStartRegex = false;
2531
2400
  continue;
2532
2401
  }
@@ -2565,15 +2434,29 @@ function hasTopLevelDeclaratorComma(source, start, codePositions) {
2565
2434
  continue;
2566
2435
  }
2567
2436
  if (char === ")" || char === "]" || char === "}") {
2437
+ if (char === "}" && templateFrames.length > 0 && templateFrames[templateFrames.length - 1] === depth) {
2438
+ templateFrames.pop();
2439
+ canStartRegex = false;
2440
+ continue;
2441
+ }
2568
2442
  depth = Math.max(0, depth - 1);
2569
2443
  canStartRegex = false;
2570
2444
  continue;
2571
2445
  }
2572
- if (depth === 0 && char === ",") return true;
2573
- if (depth === 0 && char === ";") return false;
2446
+ if (templateFrames.length === 0 && depth === 0 && char === ",") {
2447
+ let bindingStart = index + 1;
2448
+ while (/\s/.test(source[bindingStart] || "")) bindingStart++;
2449
+ const binding = source.slice(bindingStart).match(new RegExp(`^(${JS_IDENTIFIER_PATTERN})`, "u"));
2450
+ if (!binding || !isValidEsmExportName(binding[1])) return void 0;
2451
+ names.push(binding[1]);
2452
+ index = bindingStart + binding[1].length - 1;
2453
+ canStartRegex = false;
2454
+ continue;
2455
+ }
2456
+ if (templateFrames.length === 0 && depth === 0 && char === ";") return names;
2574
2457
  if (!/\s/.test(char)) canStartRegex = char !== ".";
2575
2458
  }
2576
- return false;
2459
+ return names;
2577
2460
  }
2578
2461
  function hasUnsupportedBindingPattern(source, start) {
2579
2462
  const opening = source[start];
@@ -2616,7 +2499,9 @@ function getNamedExportsViaRegex(source, filePath, visited, scanState = { comple
2616
2499
  const exportedVariableDeclarationRegex = /export\s+(?:const|let|var)\s+/g;
2617
2500
  while ((match = exportedVariableDeclarationRegex.exec(source)) !== null) {
2618
2501
  if (!codePositions[match.index]) continue;
2619
- if (hasTopLevelDeclaratorComma(source, exportedVariableDeclarationRegex.lastIndex, codePositions)) scanState.complete = false;
2502
+ const additionalNames = getAdditionalTopLevelDeclaratorNames(source, exportedVariableDeclarationRegex.lastIndex, codePositions);
2503
+ if (additionalNames === void 0) scanState.complete = false;
2504
+ else for (const name of additionalNames) names.add(name);
2620
2505
  if (hasUnsupportedBindingPattern(source, exportedVariableDeclarationRegex.lastIndex)) scanState.complete = false;
2621
2506
  }
2622
2507
  if (hasCodeMatch(source, /export\s+import\s+/g, codePositions) || hasCodeMatch(source, /export\s*=/g, codePositions)) scanState.complete = false;
@@ -2709,7 +2594,22 @@ function getNamedExportsViaRegex(source, filePath, visited, scanState = { comple
2709
2594
  }
2710
2595
  return Array.from(names);
2711
2596
  }
2597
+ /**
2598
+ * Reading a module's export names runs its top-level code inside the build
2599
+ * process, and getPackageNamedExports deliberately resolves the browser entry.
2600
+ * A browser entry may open a handle Node never closes — react-dom/server.browser
2601
+ * holds a module-scope MessageChannel — and one ref'd handle keeps the event loop
2602
+ * alive forever, so `vite build` writes a correct bundle and then never exits.
2603
+ *
2604
+ * Unref'ing whatever the require created is safe here because the module is
2605
+ * loaded purely to read Object.keys off it and is never used afterwards. The
2606
+ * handle list is undocumented, so its absence degrades to the previous behaviour
2607
+ * rather than failing the build. Side effects that are not handles (an exit
2608
+ * listener, a global mutation) are still not contained.
2609
+ */
2712
2610
  function getRequiredNamedExports(specifier) {
2611
+ const getActiveHandles = process._getActiveHandles;
2612
+ const handlesBeforeRequire = typeof getActiveHandles === "function" ? new Set(getActiveHandles.call(process)) : void 0;
2713
2613
  try {
2714
2614
  const mod = createRequire$1(pathToFileURL(path$1.join(getPackageDetectionCwd(), "package.json")))(specifier);
2715
2615
  const runtimeNamedKeys = Object.keys(mod).filter((key) => key !== "default" && key !== "__esModule");
@@ -2717,6 +2617,12 @@ function getRequiredNamedExports(specifier) {
2717
2617
  return runtimeNamedKeys;
2718
2618
  } catch {
2719
2619
  return;
2620
+ } finally {
2621
+ if (handlesBeforeRequire && typeof getActiveHandles === "function") for (const handle of getActiveHandles.call(process)) {
2622
+ if (handlesBeforeRequire.has(handle)) continue;
2623
+ const unref = handle?.unref;
2624
+ if (typeof unref === "function") unref.call(handle);
2625
+ }
2720
2626
  }
2721
2627
  }
2722
2628
  function getPackageNamedExports(pkg, exportConditions = DEFAULT_SHARED_EXPORT_CONDITIONS) {
@@ -3272,6 +3178,12 @@ function generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor,
3272
3178
  }
3273
3179
  export { __mf_default as default };${namedExportLine}`;
3274
3180
  }
3181
+ function selectImportFalseNamedExports(detectedNamedExports, usage) {
3182
+ if (!detectedNamedExports || usage?.kind !== "exports") return detectedNamedExports ?? [];
3183
+ const usedNamedExports = new Set(usage.usedExports.filter((name) => name !== "default"));
3184
+ if ([...usedNamedExports].some((name) => !detectedNamedExports.includes(name))) return detectedNamedExports;
3185
+ return detectedNamedExports.filter((name) => usedNamedExports.has(name));
3186
+ }
3275
3187
  function generateShareModuleUnwrapCode({ source, preserveNamedExports, stopWithReturn }) {
3276
3188
  return `let current = ${source};
3277
3189
  for (let i = 0; i < 5; i++) {
@@ -3294,7 +3206,7 @@ const normalizeLocalShareModuleCode = `const __mfNormalizeShareModule = (mod) =>
3294
3206
  ? Object.assign({}, normalized)
3295
3207
  : normalized;
3296
3208
  };`;
3297
- function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exportConditions) {
3209
+ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exportConditions, importFalseExportUsage) {
3298
3210
  const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
3299
3211
  const { loadShareCacheMap } = getSharedVirtualModuleState(options);
3300
3212
  if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = createScopedSharedVirtualModule(pkg, LOAD_SHARE_TAG, options);
@@ -3305,7 +3217,7 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3305
3217
  const treeShakingConsumer = command === "build" && shareItem.shareConfig.treeShaking ? resolvedOptions.name : void 0;
3306
3218
  if (shareItem.shareConfig.import === false) {
3307
3219
  const detectedNamedExports = getPackageNamedExports(pkg, exportConditions);
3308
- const namedExports = detectedNamedExports ?? [];
3220
+ const namedExports = selectImportFalseNamedExports(detectedNamedExports, importFalseExportUsage);
3309
3221
  let exportLine;
3310
3222
  if (namedExports.length > 0) exportLine = generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor, treeShakingConsumer);
3311
3223
  else {
@@ -3592,7 +3504,7 @@ function generateLocalSharedImportMap(options) {
3592
3504
  if (!remote) return null;
3593
3505
  return `
3594
3506
  {
3595
- alias: ${JSON.stringify(getRuntimeRemoteAlias(key, options))},
3507
+ alias: ${JSON.stringify(key)},
3596
3508
  entryGlobalName: ${JSON.stringify(remote.entryGlobalName)},
3597
3509
  name: ${JSON.stringify(options ? getRuntimeRemoteAlias(key, options) : remote.name)},
3598
3510
  type: ${JSON.stringify(remote.type)},
@@ -4158,7 +4070,6 @@ function generateTreeShakingSnapshotPluginCode(enabled) {
4158
4070
  function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(options), command = "build") {
4159
4071
  const needsSharedProviderSelectionHelper = Object.keys(options.shared ?? {}).length > 0;
4160
4072
  const hasTreeShakingShared = Object.values(options.shared ?? {}).some((share) => !!share?.shareConfig.treeShaking);
4161
- const hasEagerShared = Object.values(options.shared ?? {}).some((share) => share?.shareConfig.eager === true && share.shareConfig.import !== false);
4162
4073
  const hasMultipleShareScopes = Array.isArray(options.shareScope);
4163
4074
  const runtimeImports = [
4164
4075
  "init as runtimeInit",
@@ -4211,7 +4122,6 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
4211
4122
  globalThis.__VUE_HMR_RUNTIME__ = { createRecord() {}, rerender() {}, reload() {} };
4212
4123
  }
4213
4124
  import {${runtimeImports}} from "@module-federation/runtime";
4214
- ${hasEagerShared ? `import * as __mfLocalSharedImportMap from "${getLocalSharedImportMapPath(options)}";` : ""}
4215
4125
  ${runtimeHelperImports.length ? `import {${runtimeHelperImports.join(", ")}} from "@module-federation/runtime/helpers";` : ""}
4216
4126
  ${pluginImportNames.filter((item) => !isSsrOnlyPlugin(item[1])).map((item) => item[1]).join("\n")}
4217
4127
  ${command === "build" ? getRuntimeInitResolveBootstrapCode(false, options ? getRuntimeInitStatusImportId(options) : void 0) : getRuntimeInitBootstrapCode(false, options ? getRuntimeInitStatusImportId(options) : void 0) + "\n const { initResolve } = globalThis[globalKey];"}
@@ -4246,12 +4156,11 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
4246
4156
  ${needsSharedProviderSelectionHelper ? externalSharedProviderSelectionHelperCode : ""}
4247
4157
 
4248
4158
  async function getLocalSharedImportMap() {
4249
- ${hasEagerShared ? "return __mfLocalSharedImportMap;" : ""}
4250
- ${hasEagerShared ? "" : `if (!localSharedImportMapPromise) {
4159
+ if (!localSharedImportMapPromise) {
4251
4160
  localSharedImportMapPromise = retrySharedInit(() => import("${getLocalSharedImportMapPath(options)}"))
4252
4161
  .catch((e) => { localSharedImportMapPromise = undefined; throw e; });
4253
4162
  }
4254
- return localSharedImportMapPromise`}
4163
+ return localSharedImportMapPromise
4255
4164
  }
4256
4165
 
4257
4166
  async function getExposesMap() {
@@ -5074,6 +4983,8 @@ function getRemoteVirtualModule(remote, command, enableSsrInit = false, consumer
5074
4983
  }
5075
4984
  const usedRemotesMap = {};
5076
4985
  const usedRemotesByOptions = /* @__PURE__ */ new WeakMap();
4986
+ const dynamicRemotesByOptions = /* @__PURE__ */ new WeakMap();
4987
+ const staticRemotesByOptions = /* @__PURE__ */ new WeakMap();
5077
4988
  function getScopedUsedRemotesMap(options) {
5078
4989
  let scoped = usedRemotesByOptions.get(options);
5079
4990
  if (!scoped) {
@@ -5094,6 +5005,25 @@ function getUsedRemotesMap(options) {
5094
5005
  if (options) return getScopedUsedRemotesMap(options);
5095
5006
  return usedRemotesMap;
5096
5007
  }
5008
+ function markDynamicRemote(remote, options) {
5009
+ let remotes = dynamicRemotesByOptions.get(options);
5010
+ if (!remotes) {
5011
+ remotes = /* @__PURE__ */ new Set();
5012
+ dynamicRemotesByOptions.set(options, remotes);
5013
+ }
5014
+ remotes.add(remote);
5015
+ }
5016
+ function markStaticRemote(remote, options) {
5017
+ let remotes = staticRemotesByOptions.get(options);
5018
+ if (!remotes) {
5019
+ remotes = /* @__PURE__ */ new Set();
5020
+ staticRemotesByOptions.set(options, remotes);
5021
+ }
5022
+ remotes.add(remote);
5023
+ }
5024
+ function isDynamicOnlyRemote(remote, options) {
5025
+ return (dynamicRemotesByOptions.get(options)?.has(remote) ?? false) && !(staticRemotesByOptions.get(options)?.has(remote) ?? false);
5026
+ }
5097
5027
  function getRemoteAliasFromId(id, remotes) {
5098
5028
  return Object.keys(remotes).filter((name) => id === name || id.startsWith(name + "/")).sort((a, b) => b.length - a.length)[0];
5099
5029
  }
@@ -5278,7 +5208,7 @@ function generateRemotes(id, command, enableSsrInit = false, consumer = "unified
5278
5208
  const registerRemoteCode = isLoadedFirst && remote ? `runtime.registerRemotes([${JSON.stringify({
5279
5209
  entryGlobalName: remote.entryGlobalName,
5280
5210
  name: options ? runtimeRemoteAlias : remote.name,
5281
- alias: runtimeRemoteAlias,
5211
+ alias: remoteAlias,
5282
5212
  type: remote.type,
5283
5213
  entry: remote.entry,
5284
5214
  shareScope: remote.shareScope ?? "default"
@@ -5516,7 +5446,7 @@ const __mfCurrentScript = document.currentScript;
5516
5446
  const entryImportDeclaration = isEncodedVirtualEntry ? `const __mfEntryUrl = ${JSON.stringify(entrySrc)};
5517
5447
  ` : "";
5518
5448
  const entryImportExpression = isEncodedVirtualEntry ? "import(/* @vite-ignore */ __mfEntryUrl)" : importExpression(entrySrc);
5519
- const remotePreloads = !options?.skipRemotePreload && (federationOptions ?? getNormalizeModuleFederationOptions())?.shareStrategy !== "loaded-first" ? Object.entries(getUsedRemotesMap(federationOptions)).flatMap(([, remotes]) => Array.from(remotes)).sort().map((remote) => `__mfPreloadRemote(${JSON.stringify(getRuntimeRemoteId(remote, (federationOptions ?? getNormalizeModuleFederationOptions()).remotes, federationOptions))}, ${JSON.stringify(remote)})`).join(",") : "";
5449
+ const remotePreloads = !options?.skipRemotePreload && (federationOptions ?? getNormalizeModuleFederationOptions())?.shareStrategy !== "loaded-first" ? Object.entries(getUsedRemotesMap(federationOptions)).flatMap(([, remotes]) => Array.from(remotes)).filter((remote) => !federationOptions || !isDynamicOnlyRemote(remote, federationOptions)).sort().map((remote) => `__mfPreloadRemote(${JSON.stringify(getRuntimeRemoteId(remote, (federationOptions ?? getNormalizeModuleFederationOptions()).remotes, federationOptions))}, ${JSON.stringify(remote)})`).join(",") : "";
5520
5450
  const remoteCachePrefix = getRuntimeRemoteCachePrefix(federationOptions);
5521
5451
  const preloadBlock = remotePreloads ? `
5522
5452
  const runtime = await initHost();
@@ -7771,116 +7701,174 @@ function getStatsFileName(manifestFileName) {
7771
7701
  }
7772
7702
  //#endregion
7773
7703
  //#region src/plugins/pluginModuleParseEnd.ts
7774
- let _resolve = null;
7775
- let _parseTimeout = null;
7776
- let _settleTimeout = null;
7777
- let parsePromise = Promise.resolve(1);
7778
- let parseStartSet = /* @__PURE__ */ new Set();
7779
- let parseEndSet = /* @__PURE__ */ new Set();
7780
- let lastLoadedModule = "";
7781
- let lastParsedModule = "";
7782
- function clearParseTimeout() {
7783
- if (_parseTimeout) {
7784
- clearTimeout(_parseTimeout);
7785
- _parseTimeout = null;
7786
- }
7787
- }
7788
- function clearSettleTimeout() {
7789
- if (_settleTimeout) {
7790
- clearTimeout(_settleTimeout);
7791
- _settleTimeout = null;
7792
- }
7793
- }
7794
- function resetParseState() {
7795
- clearParseTimeout();
7796
- clearSettleTimeout();
7797
- parseStartSet = /* @__PURE__ */ new Set();
7798
- parseEndSet = /* @__PURE__ */ new Set();
7799
- lastLoadedModule = "";
7800
- lastParsedModule = "";
7801
- parsePromise = new Promise((resolve) => {
7802
- _resolve = (v) => {
7803
- clearParseTimeout();
7804
- clearSettleTimeout();
7805
- resolve(v);
7704
+ function createModuleParseController() {
7705
+ return {
7706
+ resolve: null,
7707
+ parseTimeout: null,
7708
+ settleTimeout: null,
7709
+ parsePromise: Promise.resolve({
7710
+ complete: false,
7711
+ reason: "initial"
7712
+ }),
7713
+ parseStartSet: /* @__PURE__ */ new Set(),
7714
+ parseEndSet: /* @__PURE__ */ new Set(),
7715
+ discardWarned: false,
7716
+ externalSet: /* @__PURE__ */ new Set(),
7717
+ resolutionProbed: /* @__PURE__ */ new Set(),
7718
+ lastLoadedModule: "",
7719
+ lastParsedModule: ""
7720
+ };
7721
+ }
7722
+ function clearParseTimeout(controller) {
7723
+ if (controller.parseTimeout) {
7724
+ clearTimeout(controller.parseTimeout);
7725
+ controller.parseTimeout = null;
7726
+ }
7727
+ }
7728
+ function clearSettleTimeout(controller) {
7729
+ if (controller.settleTimeout) {
7730
+ clearTimeout(controller.settleTimeout);
7731
+ controller.settleTimeout = null;
7732
+ }
7733
+ }
7734
+ function resetParseState(controller) {
7735
+ clearParseTimeout(controller);
7736
+ clearSettleTimeout(controller);
7737
+ controller.parseStartSet = /* @__PURE__ */ new Set();
7738
+ controller.parseEndSet = /* @__PURE__ */ new Set();
7739
+ controller.externalSet = /* @__PURE__ */ new Set();
7740
+ controller.resolutionProbed = /* @__PURE__ */ new Set();
7741
+ controller.discardWarned = false;
7742
+ controller.lastLoadedModule = "";
7743
+ controller.lastParsedModule = "";
7744
+ controller.parsePromise = new Promise((resolve) => {
7745
+ controller.resolve = (result) => {
7746
+ clearParseTimeout(controller);
7747
+ clearSettleTimeout(controller);
7748
+ resolve(result);
7806
7749
  };
7807
7750
  });
7808
7751
  }
7809
- function setParseTimeout(timeout) {
7810
- if (!_parseTimeout) _parseTimeout = setTimeout(() => {
7752
+ function setParseTimeout(controller, timeout) {
7753
+ if (!controller.parseTimeout) controller.parseTimeout = setTimeout(() => {
7811
7754
  mfWarn(`Parse timeout (${timeout}s) - forcing resolve`);
7812
- _resolve?.(1);
7755
+ controller.resolve?.({
7756
+ complete: false,
7757
+ reason: "timeout"
7758
+ });
7813
7759
  }, timeout * 1e3);
7814
7760
  }
7815
- function resetIdleTimeout(timeout) {
7816
- clearParseTimeout();
7817
- _parseTimeout = setTimeout(() => {
7818
- const pendingModules = Array.from(parseStartSet).filter((moduleId) => !parseEndSet.has(moduleId));
7819
- mfWarn(`moduleParseIdleTimeout: no module activity for ${timeout}s, forcing resolve. Some shared/remote dependencies may be missing. Consider increasing moduleParseIdleTimeout. Tracked modules: ${parseEndSet.size}/${parseStartSet.size}.` + (lastLoadedModule ? ` Last loaded: ${lastLoadedModule}.` : "") + (lastParsedModule ? ` Last parsed: ${lastParsedModule}.` : "") + (pendingModules.length ? ` Pending modules: ${pendingModules.slice(0, 10).join(", ")}` : ""));
7820
- _resolve?.(1);
7761
+ function resetIdleTimeout(controller, timeout) {
7762
+ clearParseTimeout(controller);
7763
+ controller.parseTimeout = setTimeout(() => {
7764
+ const pendingModules = Array.from(controller.parseStartSet).filter((moduleId) => !controller.parseEndSet.has(moduleId));
7765
+ mfWarn(`moduleParseIdleTimeout: no module activity for ${timeout}s, forcing resolve. Some shared/remote dependencies may be missing. Consider increasing moduleParseIdleTimeout. Tracked modules: ${controller.parseEndSet.size}/${controller.parseStartSet.size}.` + (controller.lastLoadedModule ? ` Last loaded: ${controller.lastLoadedModule}.` : "") + (controller.lastParsedModule ? ` Last parsed: ${controller.lastParsedModule}.` : "") + (pendingModules.length ? ` Pending modules: ${pendingModules.slice(0, 10).join(", ")}` : ""));
7766
+ controller.resolve?.({
7767
+ complete: false,
7768
+ reason: "idle-timeout"
7769
+ });
7821
7770
  }, timeout * 1e3);
7822
7771
  }
7823
- function scheduleParseCompletionCheck() {
7824
- clearSettleTimeout();
7825
- _settleTimeout = setTimeout(() => {
7826
- _settleTimeout = null;
7827
- if (parseStartSet.size > 0 && Array.from(parseStartSet).every((moduleId) => parseEndSet.has(moduleId))) _resolve?.(1);
7772
+ function scheduleParseCompletionCheck(controller) {
7773
+ clearSettleTimeout(controller);
7774
+ controller.settleTimeout = setTimeout(() => {
7775
+ controller.settleTimeout = null;
7776
+ if (controller.parseStartSet.size > 0 && Array.from(controller.parseStartSet).every((moduleId) => controller.parseEndSet.has(moduleId))) controller.resolve?.({
7777
+ complete: true,
7778
+ reason: "graph-complete"
7779
+ });
7828
7780
  }, 10);
7829
7781
  }
7830
- function pluginModuleParseEnd_default(excludeFn, options) {
7782
+ function matchesExternal(external, id, importer) {
7783
+ if (!external) return false;
7784
+ if (typeof external === "function") return external(id, importer, true) === true;
7785
+ return (Array.isArray(external) ? external : [external]).some((entry) => {
7786
+ if (typeof entry === "string") return entry === id;
7787
+ entry.lastIndex = 0;
7788
+ return entry.test(id);
7789
+ });
7790
+ }
7791
+ function getConfiguredInputImports(input) {
7792
+ if (typeof input === "string") return [input];
7793
+ if (Array.isArray(input)) return input.filter((entry) => typeof entry === "string");
7794
+ if (!input || typeof input !== "object") return [];
7795
+ return Object.values(input).filter((entry) => typeof entry === "string");
7796
+ }
7797
+ function pluginModuleParseEnd_default(excludeFn, options, controller = createModuleParseController()) {
7831
7798
  const idleTimeout = options.moduleParseIdleTimeout ?? options.moduleParseTimeout;
7832
- return [
7833
- {
7834
- name: "_",
7835
- apply: "serve",
7836
- config() {
7837
- _resolve?.(1);
7799
+ let configuredInputImports = [];
7800
+ let configuredExternal;
7801
+ return [{
7802
+ enforce: "pre",
7803
+ name: "parseStart",
7804
+ apply: "build",
7805
+ configResolved(config) {
7806
+ const buildOptions = config.build;
7807
+ configuredInputImports = getConfiguredInputImports(buildOptions.rollupOptions.input ?? buildOptions.rolldownOptions?.input);
7808
+ configuredExternal = buildOptions.rollupOptions.external ?? buildOptions.rolldownOptions?.external;
7809
+ },
7810
+ async buildStart() {
7811
+ resetParseState(controller);
7812
+ if (idleTimeout) resetIdleTimeout(controller, idleTimeout);
7813
+ else if (options.moduleParseTimeout) setParseTimeout(controller, options.moduleParseTimeout);
7814
+ const entryImports = /* @__PURE__ */ new Set([...options.exposedModuleImports || [], ...configuredInputImports]);
7815
+ for (const importSource of entryImports) {
7816
+ const resolved = await this.resolve(importSource);
7817
+ if (resolved && !resolved.external && !excludeFn(resolved.id)) controller.parseStartSet.add(resolved.id);
7838
7818
  }
7839
7819
  },
7840
- {
7841
- enforce: "pre",
7842
- name: "parseStart",
7843
- apply: "build",
7844
- async buildStart() {
7845
- resetParseState();
7846
- if (idleTimeout) resetIdleTimeout(idleTimeout);
7847
- else if (options.moduleParseTimeout) setParseTimeout(options.moduleParseTimeout);
7848
- for (const importSource of options.exposedModuleImports || []) {
7849
- const resolved = await this.resolve(importSource);
7850
- if (resolved && !resolved.external && !excludeFn(resolved.id)) parseStartSet.add(resolved.id);
7820
+ load(id) {
7821
+ controller.lastLoadedModule = id;
7822
+ if (excludeFn(id)) return;
7823
+ clearSettleTimeout(controller);
7824
+ if (idleTimeout) resetIdleTimeout(controller, idleTimeout);
7825
+ controller.parseStartSet.add(id);
7826
+ }
7827
+ }, {
7828
+ enforce: "post",
7829
+ name: "parseEnd",
7830
+ apply: "build",
7831
+ moduleParsed(module) {
7832
+ clearSettleTimeout(controller);
7833
+ const id = module.id;
7834
+ controller.lastParsedModule = id;
7835
+ if (idleTimeout) resetIdleTimeout(controller, idleTimeout);
7836
+ const parsedModule = module;
7837
+ const addPendingResolutions = (resolutions) => {
7838
+ for (const resolution of resolutions || []) if (!resolution.external && !excludeFn(resolution.id)) controller.parseStartSet.add(resolution.id);
7839
+ };
7840
+ const probeExternal = (pendingId) => {
7841
+ if (typeof this.resolve !== "function") return;
7842
+ if (controller.resolutionProbed.has(pendingId)) return;
7843
+ controller.resolutionProbed.add(pendingId);
7844
+ this.resolve(pendingId, id, { skipSelf: true }).then((resolved) => {
7845
+ if (!resolved?.external) return;
7846
+ controller.externalSet.add(pendingId);
7847
+ controller.parseStartSet.delete(pendingId);
7848
+ scheduleParseCompletionCheck(controller);
7849
+ }).catch(() => {});
7850
+ };
7851
+ const addPendingIds = (ids) => {
7852
+ for (const pendingId of ids || []) {
7853
+ if (!this.getModuleInfo(pendingId) || controller.externalSet.has(pendingId) || matchesExternal(configuredExternal, pendingId, id) || excludeFn(pendingId)) continue;
7854
+ controller.parseStartSet.add(pendingId);
7855
+ if (!controller.parseEndSet.has(pendingId)) probeExternal(pendingId);
7851
7856
  }
7852
- },
7853
- load(id) {
7854
- lastLoadedModule = id;
7855
- if (excludeFn(id)) return;
7856
- clearSettleTimeout();
7857
- if (idleTimeout) resetIdleTimeout(idleTimeout);
7858
- parseStartSet.add(id);
7859
- }
7857
+ };
7858
+ addPendingResolutions(parsedModule.importedIdResolutions);
7859
+ addPendingResolutions(parsedModule.dynamicallyImportedIdResolutions);
7860
+ if (parsedModule.importedIdResolutions === void 0) addPendingIds(module.importedIds);
7861
+ if (parsedModule.dynamicallyImportedIdResolutions === void 0) addPendingIds(module.dynamicallyImportedIds);
7862
+ if (!excludeFn(id)) controller.parseEndSet.add(id);
7863
+ scheduleParseCompletionCheck(controller);
7860
7864
  },
7861
- {
7862
- enforce: "post",
7863
- name: "parseEnd",
7864
- apply: "build",
7865
- moduleParsed(module) {
7866
- clearSettleTimeout();
7867
- const id = module.id;
7868
- lastParsedModule = id;
7869
- if (idleTimeout) resetIdleTimeout(idleTimeout);
7870
- const parsedModule = module;
7871
- const addPendingResolutions = (resolutions) => {
7872
- for (const resolution of resolutions || []) if (!resolution.external && !excludeFn(resolution.id)) parseStartSet.add(resolution.id);
7873
- };
7874
- addPendingResolutions(parsedModule.importedIdResolutions);
7875
- addPendingResolutions(parsedModule.dynamicallyImportedIdResolutions);
7876
- if (!excludeFn(id)) parseEndSet.add(id);
7877
- scheduleParseCompletionCheck();
7878
- },
7879
- buildEnd() {
7880
- _resolve?.(1);
7881
- }
7865
+ buildEnd() {
7866
+ controller.resolve?.({
7867
+ complete: false,
7868
+ reason: "build-end"
7869
+ });
7882
7870
  }
7883
- ];
7871
+ }];
7884
7872
  }
7885
7873
  //#endregion
7886
7874
  //#region src/plugins/pluginProxyRemoteEntry.ts
@@ -7890,7 +7878,7 @@ function resolveDevHashEntryFileName(fileName) {
7890
7878
  const baseName = path$1.basename(normalized);
7891
7879
  return path$1.extname(baseName) ? normalized : `${normalized}.js`;
7892
7880
  }
7893
- function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposesId }) {
7881
+ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposesId, getParsePromise = () => Promise.resolve() }) {
7894
7882
  let viteConfig, _command, root, originalConfigBase;
7895
7883
  let exposeRemoteDependencies = {};
7896
7884
  let exposeRemoteDependenciesDirty = true;
@@ -8000,7 +7988,7 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
8000
7988
  }
8001
7989
  },
8002
7990
  async load(id) {
8003
- if (id === remoteEntryId) return parsePromise.then((_) => generateRemoteEntry(options, virtualExposesId, _command));
7991
+ if (id === remoteEntryId) return getParsePromise().then((_) => generateRemoteEntry(options, virtualExposesId, _command));
8004
7992
  if (id === virtualExposesId) {
8005
7993
  await refreshExposeRemoteDependencies(this);
8006
7994
  return generateExposes(options, exposeRemoteDependencies, _command, reactIslandExposes);
@@ -8010,7 +7998,7 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
8010
7998
  async transform(code, id) {
8011
7999
  return mapCodeToCodeWithSourcemap(await (async () => {
8012
8000
  if (!filterId(id)) return;
8013
- if (id.includes(remoteEntryId)) return parsePromise.then((_) => generateRemoteEntry(options, virtualExposesId, _command));
8001
+ if (id.includes(remoteEntryId)) return getParsePromise().then((_) => generateRemoteEntry(options, virtualExposesId, _command));
8014
8002
  if (id === virtualExposesId) {
8015
8003
  await refreshExposeRemoteDependencies(this);
8016
8004
  return generateExposes(options, exposeRemoteDependencies, _command, reactIslandExposes);
@@ -8167,6 +8155,41 @@ function pluginProxyRemotes_default(options) {
8167
8155
  };
8168
8156
  }
8169
8157
  //#endregion
8158
+ //#region src/plugins/pluginReactMixedModeGuard.ts
8159
+ const REACT_DEVELOPMENT_RUNTIME = /[\\/]react[\\/]cjs[\\/]react(?:-jsx-(?:dev-)?runtime)?\.development\.js$/;
8160
+ const UNSAFE_GET_OWNER = "return null === dispatcher ? null : dispatcher.getOwner();";
8161
+ const SAFE_GET_OWNER = "return typeof dispatcher?.getOwner === \"function\" ? dispatcher.getOwner() : null;";
8162
+ const REACT_MIXED_MODE_ROLLDOWN_PLUGIN = "module-federation:react-mixed-mode-rolldown";
8163
+ const REACT_MIXED_MODE_ESBUILD_PLUGIN = "module-federation:react-mixed-mode-esbuild";
8164
+ function patchReactDevelopmentRuntime(code, id) {
8165
+ if (!REACT_DEVELOPMENT_RUNTIME.test(id)) return;
8166
+ const patched = code.replaceAll(UNSAFE_GET_OWNER, SAFE_GET_OWNER);
8167
+ return patched === code ? void 0 : patched;
8168
+ }
8169
+ function createRolldownReactMixedModeGuard() {
8170
+ return {
8171
+ name: REACT_MIXED_MODE_ROLLDOWN_PLUGIN,
8172
+ transform(code, id) {
8173
+ return patchReactDevelopmentRuntime(code, id);
8174
+ }
8175
+ };
8176
+ }
8177
+ function createEsbuildReactMixedModeGuard() {
8178
+ return {
8179
+ name: REACT_MIXED_MODE_ESBUILD_PLUGIN,
8180
+ setup(build) {
8181
+ build.onLoad({ filter: REACT_DEVELOPMENT_RUNTIME }, (args) => {
8182
+ const patched = patchReactDevelopmentRuntime(readFileSync$1(args.path, "utf8"), args.path);
8183
+ if (patched === void 0) return;
8184
+ return {
8185
+ contents: patched,
8186
+ loader: "js"
8187
+ };
8188
+ });
8189
+ }
8190
+ };
8191
+ }
8192
+ //#endregion
8170
8193
  //#region src/utils/PromiseStore.ts
8171
8194
  /**
8172
8195
  * example:
@@ -8311,7 +8334,7 @@ function excludeSharedSubDependencies(shared) {
8311
8334
  }
8312
8335
  }
8313
8336
  function proxySharedModule(options) {
8314
- const { shared = {}, federationOptions } = options;
8337
+ const { shared = {}, federationOptions, getParsePromise = () => Promise.resolve() } = options;
8315
8338
  let _config;
8316
8339
  let _command = "serve";
8317
8340
  let useDirectReactImport = false;
@@ -8320,6 +8343,7 @@ function proxySharedModule(options) {
8320
8343
  let devServer;
8321
8344
  const materializedLoadShareSources = /* @__PURE__ */ new Set();
8322
8345
  const emittedTreeShakingProviders = /* @__PURE__ */ new Set();
8346
+ const hasAnalyzableShares = Object.values(shared).some((share) => shouldAnalyzeSharedExports(share));
8323
8347
  const normalizeTreeShakingOutputPath = (value) => {
8324
8348
  const normalized = normalizePathForImport(value);
8325
8349
  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.`);
@@ -8364,7 +8388,7 @@ function proxySharedModule(options) {
8364
8388
  if (source === getLocalSharedImportMapPath(federationOptions)) return getResolvedLocalSharedImportMapId(federationOptions);
8365
8389
  },
8366
8390
  load(id) {
8367
- if (id === getResolvedLocalSharedImportMapId(federationOptions)) return parsePromise.then((_) => {
8391
+ if (id === getResolvedLocalSharedImportMapId(federationOptions)) return getParsePromise().then((_) => {
8368
8392
  refreshTreeShakingModules(federationOptions);
8369
8393
  const providerPackages = /* @__PURE__ */ new Set([...Object.keys(shared).filter((pkg) => !pkg.endsWith("/")), ...getUsedShares(federationOptions)]);
8370
8394
  for (const pkg of providerPackages) {
@@ -8419,10 +8443,10 @@ function proxySharedModule(options) {
8419
8443
  refreshTreeShakingModules(federationOptions);
8420
8444
  },
8421
8445
  shouldTransformCachedModule() {
8422
- return _command === "build" && Object.values(shared).some((share) => !!share.shareConfig.treeShaking);
8446
+ return _command === "build" && hasAnalyzableShares;
8423
8447
  },
8424
8448
  transform(code, id) {
8425
- if (_command !== "build" || !Object.keys(shared).some((key) => shared[key].shareConfig.treeShaking)) return;
8449
+ if (_command !== "build" || !hasAnalyzableShares) return;
8426
8450
  collectTreeShakingImports(code, id, shared, findSharedKeyForSource, (sharedKey, exports, request) => recordTreeShakingExports(sharedKey, exports, request, federationOptions), (sharedKey, request) => markTreeShakingPackageUnsafe(sharedKey, request, federationOptions));
8427
8451
  refreshTreeShakingModules(federationOptions);
8428
8452
  }
@@ -8526,6 +8550,15 @@ const JS_EXTENSIONS_RE = /\.(?:[mc]?[jt]sx?|vue|svelte)(?:\?|$)/;
8526
8550
  function isAstNode(value) {
8527
8551
  return !!value && typeof value === "object" && typeof value.type === "string";
8528
8552
  }
8553
+ function findStaticRemoteSources(code, isRemoteImport) {
8554
+ const codePositions = createCodePositionMap(code);
8555
+ const sources = /* @__PURE__ */ new Set();
8556
+ for (const pattern of [/\b(?:import|export)\s+[^;]*?\bfrom\s*["']([^"']+)["']/g, /\bimport\s*["']([^"']+)["']/g]) for (const match of code.matchAll(pattern)) {
8557
+ const source = match[1];
8558
+ if (codePositions[match.index] && isRemoteImport(source)) sources.add(source);
8559
+ }
8560
+ return sources;
8561
+ }
8529
8562
  function walkAST(root, visitor) {
8530
8563
  const seen = /* @__PURE__ */ new WeakSet();
8531
8564
  function visit(node) {
@@ -8678,6 +8711,7 @@ async function collectFromAST(ast, code, isRemoteImport) {
8678
8711
  if (!value || !isRemoteImport(value)) return;
8679
8712
  result.push({
8680
8713
  kind: "dynamic",
8714
+ source: value,
8681
8715
  start: node.start,
8682
8716
  end: node.end,
8683
8717
  originalText: code.slice(node.start, node.end)
@@ -8756,6 +8790,7 @@ function collectFromRegex(code, isRemoteImport) {
8756
8790
  if (!isRemoteImport(source)) continue;
8757
8791
  result.push({
8758
8792
  kind: "dynamic",
8793
+ source,
8759
8794
  start: match.index,
8760
8795
  end: match.index + full.length,
8761
8796
  originalText: full
@@ -8782,6 +8817,7 @@ function pluginRemoteNamedExports(options) {
8782
8817
  if (!JS_EXTENSIONS_RE.test(id)) return;
8783
8818
  if (!remoteNames.some((name) => code.includes(name))) return;
8784
8819
  const matchesRemoteImport = (source) => isRemoteImport(source, id);
8820
+ for (const source of findStaticRemoteSources(code, matchesRemoteImport)) markStaticRemote(source, options);
8785
8821
  let imports;
8786
8822
  try {
8787
8823
  imports = await collectFromAST(this.parse(code), code, matchesRemoteImport);
@@ -8790,6 +8826,7 @@ function pluginRemoteNamedExports(options) {
8790
8826
  imports = collectFromRegex(code, matchesRemoteImport);
8791
8827
  }
8792
8828
  if (!imports) return;
8829
+ for (const remoteImport of imports) if (remoteImport.kind === "dynamic") markDynamicRemote(remoteImport.source, options);
8793
8830
  return applyRewrites(code, imports, id);
8794
8831
  }
8795
8832
  };
@@ -9318,7 +9355,7 @@ function stripEmptyPreloadCalls(code) {
9318
9355
  }
9319
9356
  nextCode = nextCode.replace(/import\s*["'][^"']*__loadShare__[^"']*["']\s*;?/g, "");
9320
9357
  nextCode = nextCode.replace(helperImportRegex, (statement, local) => {
9321
- return new RegExp(`\\b${local}\\s*\\(`).test(nextCode.replace(statement, "")) ? statement : "";
9358
+ return new RegExp(`\\b${local}\\b`).test(nextCode.replace(statement, "")) ? statement : "";
9322
9359
  });
9323
9360
  return nextCode;
9324
9361
  }
@@ -9624,6 +9661,7 @@ function includeLinkedSharedEntries(optimizeDeps, shared, projectRoot, exposes,
9624
9661
  function createEarlyVirtualModulesPlugin(options) {
9625
9662
  const { shared, remotes } = options;
9626
9663
  const isLitShare = (pkg) => pkg === "lit" || pkg.startsWith("lit/");
9664
+ const shouldGuardReactMixedMode = Object.keys(remotes ?? {}).length > 0 && shared?.react?.shareConfig.singleton === true;
9627
9665
  return {
9628
9666
  name: "vite:module-federation-early-init",
9629
9667
  enforce: "pre",
@@ -9651,6 +9689,7 @@ function createEarlyVirtualModulesPlugin(options) {
9651
9689
  if (isRolldown) {
9652
9690
  optimizeDeps.rolldownOptions ??= {};
9653
9691
  optimizeDeps.rolldownOptions.plugins ??= [];
9692
+ if (shouldGuardReactMixedMode) optimizeDeps.rolldownOptions.plugins.push(createRolldownReactMixedModeGuard());
9654
9693
  optimizeDeps.rolldownOptions.plugins.push({
9655
9694
  name: "module-federation:optimize-shared-resolver",
9656
9695
  load(id) {
@@ -9695,6 +9734,7 @@ function createEarlyVirtualModulesPlugin(options) {
9695
9734
  } else {
9696
9735
  optimizeDeps.esbuildOptions ??= {};
9697
9736
  optimizeDeps.esbuildOptions.plugins ??= [];
9737
+ if (shouldGuardReactMixedMode) optimizeDeps.esbuildOptions.plugins.push(createEsbuildReactMixedModeGuard());
9698
9738
  optimizeDeps.esbuildOptions.plugins.push({
9699
9739
  name: "module-federation:optimize-shared-proxy",
9700
9740
  setup(build) {
@@ -9769,7 +9809,7 @@ export default __mfShared.default ?? __mfShared;`
9769
9809
  else optimizeDeps.include.push(key);
9770
9810
  for (const subpath of getCommonSharedSubpaths(key)) {
9771
9811
  const canResolveSubpath = canResolveSharedSubpath(subpath, root);
9772
- if (subpath === "react/compiler-runtime" && !canResolveSubpath) {
9812
+ if (["react/compiler-runtime", "react-dom/client"].includes(subpath) && !canResolveSubpath) {
9773
9813
  optimizeDeps.exclude.push(subpath);
9774
9814
  continue;
9775
9815
  }
@@ -9877,6 +9917,14 @@ function federation(mfUserOptions) {
9877
9917
  if (!name) throw createModuleFederationError("name is required");
9878
9918
  const remoteEntryId = getRemoteEntryId(options);
9879
9919
  const virtualExposesId = getVirtualExposesId(options);
9920
+ const moduleParseController = createModuleParseController();
9921
+ const moduleParsePlugins = pluginModuleParseEnd_default((id) => {
9922
+ return id.includes(getHostAutoInitImportId(options)) || id.includes(remoteEntryId) || id.includes(virtualExposesId) || id.includes("virtual:mf-localSharedImportMap") || id.includes("__loadShare__") || id.includes("__prebuild__") || id.includes("__treeShakingProvider__") || id.includes("__mf_tree_shaking_graph__");
9923
+ }, {
9924
+ moduleParseTimeout: options.moduleParseTimeout,
9925
+ moduleParseIdleTimeout: options.moduleParseIdleTimeout,
9926
+ exposedModuleImports: Object.values(options.exposes).map((expose) => expose.import)
9927
+ }, moduleParseController);
9880
9928
  let command;
9881
9929
  let desiredRolldownOutput;
9882
9930
  let isSsrBuild = false;
@@ -9908,7 +9956,7 @@ function federation(mfUserOptions) {
9908
9956
  writePreBuildLibPath(pkg, shared[key], options, getLoadHookExportConditions(context, loadOptions));
9909
9957
  return "refreshed";
9910
9958
  };
9911
- const refreshLoadShareModuleForEnvironment = (id, context, loadOptions) => {
9959
+ const refreshLoadShareModuleForEnvironment = (id, context, loadOptions, importFalseExportUsage) => {
9912
9960
  const pkg = getCachedLoadSharePkg(id);
9913
9961
  if (!pkg) return "not-applicable";
9914
9962
  const key = findSharedKey(pkg, shared);
@@ -9916,9 +9964,26 @@ function federation(mfUserOptions) {
9916
9964
  const requestedModule = VirtualModule.findById(id);
9917
9965
  const ownedModule = VirtualModule.findById(getLoadShareModulePath(pkg, false, options));
9918
9966
  if (!requestedModule || requestedModule !== ownedModule) return "not-owned";
9919
- writeLoadShareModule(pkg, shared[key], command, getIsRolldown(context), options, getLoadHookExportConditions(context, loadOptions));
9967
+ writeLoadShareModule(pkg, shared[key], command, getIsRolldown(context), options, getLoadHookExportConditions(context, loadOptions), importFalseExportUsage);
9920
9968
  return "refreshed";
9921
9969
  };
9970
+ const getCompleteImportFalseExportUsage = (id) => {
9971
+ if (command !== "build") return void 0;
9972
+ const pkg = getCachedLoadSharePkg(id);
9973
+ if (!pkg) return void 0;
9974
+ const key = findSharedKey(pkg, shared);
9975
+ if (!key || shared[key].shareConfig.import !== false) return void 0;
9976
+ return moduleParseController.parsePromise.then((completion) => {
9977
+ if (!completion.complete) {
9978
+ if (!moduleParseController.discardWarned) {
9979
+ moduleParseController.discardWarned = true;
9980
+ mfWarn(`import: false shared export analysis was discarded (reason: ${completion.reason}) — falling back to the complete export surface, so shared consumers keep every detected named export.` + (completion.reason === "idle-timeout" || completion.reason === "timeout" ? " If the build is simply slow, increasing moduleParseIdleTimeout may let the analysis finish." : ""));
9981
+ }
9982
+ return;
9983
+ }
9984
+ return getSharedExportUsage(pkg, shared[key], key, options);
9985
+ });
9986
+ };
9922
9987
  return [
9923
9988
  {
9924
9989
  name: "vite:module-federation-virtual-modules",
@@ -10024,20 +10089,16 @@ function federation(mfUserOptions) {
10024
10089
  pluginProxyRemoteEntry_default({
10025
10090
  options,
10026
10091
  remoteEntryId,
10027
- virtualExposesId
10092
+ virtualExposesId,
10093
+ getParsePromise: () => moduleParseController.parsePromise
10028
10094
  }),
10029
10095
  pluginProxyRemotes_default(options),
10030
10096
  pluginRemoteNamedExports(options),
10031
- ...pluginModuleParseEnd_default((id) => {
10032
- return id.includes(getHostAutoInitImportId(options)) || id.includes(remoteEntryId) || id.includes(virtualExposesId) || id.includes(getLocalSharedImportMapPath(options)) || id.includes("__loadShare__") || id.includes("__prebuild__") || id.includes("__treeShakingProvider__") || id.includes("__mf_tree_shaking_graph__");
10033
- }, {
10034
- moduleParseTimeout: options.moduleParseTimeout,
10035
- moduleParseIdleTimeout: options.moduleParseIdleTimeout,
10036
- exposedModuleImports: Object.values(options.exposes).map((expose) => expose.import)
10037
- }),
10097
+ ...moduleParsePlugins,
10038
10098
  ...proxySharedModule({
10039
10099
  shared,
10040
- federationOptions: options
10100
+ federationOptions: options,
10101
+ getParsePromise: () => moduleParseController.parsePromise
10041
10102
  }),
10042
10103
  {
10043
10104
  name: "module-federation-esm-shims",
@@ -10165,8 +10226,9 @@ function federation(mfUserOptions) {
10165
10226
  }
10166
10227
  },
10167
10228
  load(id, loadOptions) {
10168
- if (id.includes("__loadShare__") || id.includes("__loadRemote__")) {
10169
- if (id.includes("__loadShare__") && refreshLoadShareModuleForEnvironment(id, this, loadOptions) === "not-owned") return;
10229
+ const loadVirtualModule = (importFalseExportUsage) => {
10230
+ if (!id.includes("__loadShare__") && !id.includes("__loadRemote__")) return;
10231
+ if (id.includes("__loadShare__") && refreshLoadShareModuleForEnvironment(id, this, loadOptions, importFalseExportUsage) === "not-owned") return;
10170
10232
  const virtualModule = VirtualModule.findById(id);
10171
10233
  if (!virtualModule?.code) return null;
10172
10234
  let code = virtualModule.code;
@@ -10183,7 +10245,10 @@ function federation(mfUserOptions) {
10183
10245
  code,
10184
10246
  syntheticNamedExports: "__moduleExports"
10185
10247
  };
10186
- }
10248
+ };
10249
+ const pendingImportFalseExportUsage = id.includes("__loadShare__") ? getCompleteImportFalseExportUsage(id) : void 0;
10250
+ if (pendingImportFalseExportUsage) return pendingImportFalseExportUsage.then(loadVirtualModule);
10251
+ return loadVirtualModule();
10187
10252
  },
10188
10253
  generateBundle(_outputOptions, bundle, _isWrite) {
10189
10254
  for (const [fileName, chunk] of Object.entries(bundle)) {