@module-federation/vite 1.21.2 → 1.21.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js CHANGED
@@ -1,10 +1,10 @@
1
1
  import { n as normalizePathForImport, r as rebaseImport } from "./buildPaths-BkaQHrd2.js";
2
- import { a as getPackageDetectionCwd, c as getSharedCacheDescriptor, d as packageNameDecode, f as packageNameEncode, g as createModuleFederationError, h as sharedCacheHelperCode, i as getIsRolldown, l as hasPackageDependency, m as setPackageDetectionCwd, n as getInstalledPackageEntry, o as getPackageName, p as resolveImportPath, r as getInstalledPackageJson, s as getPackageNameFromNodeModulePath, u as isNuxtProjectRoot, v as mfWarn } from "./dtsConstants-DyJrx8ah.js";
3
- import { a as getCommonSharedSubpaths, c as isNodeModulePath, d as normalizeNodeModulePath, f as resolvePublicPath, i as getCommonSharedSubpathFromNodeModulePath, l as isNuxtClientBase, n as filterId, o as getMatchingNodeModuleSubpath, r as getBasePath$1, s as isAssetLikeImport, t as ensureTrailingSlash, u as isViteOptimizableEntry } from "./pathNormalization-CHct3UwV.js";
2
+ import { a as getPackageDetectionCwd, c as getSharedCacheDescriptor, d as packageNameDecode, f as packageNameEncode, g as createModuleFederationError, h as sharedCacheHelperCode, i as getIsRolldown, l as hasPackageDependency, m as setPackageDetectionCwd, n as getInstalledPackageEntry, o as getPackageName, p as resolveImportPath, r as getInstalledPackageJson, s as getPackageNameFromNodeModulePath, u as isNuxtProjectRoot, v as mfWarn } from "./dtsConstants-BsaLBaaK.js";
3
+ import { a as filterId, c as getCommonSharedSubpaths, d as isNodeModulePath, f as isNuxtClientBase, h as resolvePublicPath, i as ensureTrailingSlash, l as getMatchingNodeModuleSubpath, m as normalizeNodeModulePath, n as invalidateSharedKeyMatcher, o as getBasePath$1, p as isViteOptimizableEntry, r as matchesSharedSource, s as getCommonSharedSubpathFromNodeModulePath, t as findSharedKey, u as isAssetLikeImport } from "./sharedKeyMatcher-DiUzRVH1.js";
4
4
  import { createRequire } from "node:module";
5
5
  import * as fs$2 from "fs";
6
- import { existsSync, readFileSync, realpathSync, statSync, writeFileSync } from "fs";
7
- import { createRequire as createRequire$1 } from "module";
6
+ import { existsSync, readFileSync, readdirSync, realpathSync, statSync, writeFileSync } from "fs";
7
+ import { createRequire as createRequire$1, isBuiltin } from "module";
8
8
  import * as path$1 from "node:path";
9
9
  import path, { basename } from "node:path";
10
10
  import { fileURLToPath, pathToFileURL } from "url";
@@ -13,6 +13,7 @@ import { createHash } from "node:crypto";
13
13
  import * as fs$1 from "node:fs";
14
14
  import { existsSync as existsSync$1, readFileSync as readFileSync$1 } from "node:fs";
15
15
  import { pathToFileURL as pathToFileURL$1 } from "node:url";
16
+ import { isIPv6 } from "node:net";
16
17
  //#region src/utils/bundleHelpers.ts
17
18
  function isOutputChunk$1(chunk) {
18
19
  return chunk.type === "chunk";
@@ -502,68 +503,119 @@ function createCodePositionMap(code) {
502
503
  }
503
504
  //#endregion
504
505
  //#region src/utils/htmlEntryUtils.ts
505
- function isTypeOnlyClause(clause) {
506
- const normalized = clause.trim();
507
- if (/^type\b/.test(normalized)) return true;
508
- const namedSpecifiers = normalized.match(/^\{([\s\S]*)\}$/)?.[1];
509
- if (!namedSpecifiers) return false;
506
+ const IDENTIFIER = String.raw`[$_\p{ID_Start}][$_\u200C\u200D\p{ID_Continue}]*`;
507
+ const NAMED_SPECIFIERS = String.raw`\{[^{}]*\}`;
508
+ const NAMESPACE_SPECIFIER = String.raw`\*\s*as\s+${IDENTIFIER}`;
509
+ const IMPORT_CLAUSE = String.raw`(?:(?<importType>type)\s+)?(?<importClause>${NAMESPACE_SPECIFIER}|${NAMED_SPECIFIERS}|${IDENTIFIER}(?:\s*,\s*(?:${NAMESPACE_SPECIFIER}|${NAMED_SPECIFIERS}))?)`;
510
+ const EXPORT_CLAUSE = String.raw`(?:(?<exportType>type)\s+)?(?<exportClause>\*(?:\s*as\s+(?:${IDENTIFIER}|"[^"]*"|'[^']*'))?|${NAMED_SPECIFIERS})`;
511
+ const SPECIFIER = String.raw`(?<quote>["'])(?<source>[^"'\r\n]*)\k<quote>`;
512
+ const KEYWORD_BOUNDARY = String.raw`(?<![.$\w])`;
513
+ const KEYWORD_GAP = String.raw`(?:\s+|(?=[{*]))`;
514
+ const STATIC_PATTERN = new RegExp(String.raw`${KEYWORD_BOUNDARY}(?:import${KEYWORD_GAP}${IMPORT_CLAUSE}|export${KEYWORD_GAP}${EXPORT_CLAUSE})\s*from\s*${SPECIFIER}`, "gud");
515
+ const DYNAMIC_PATTERN = new RegExp(String.raw`${KEYWORD_BOUNDARY}import\s*\(\s*${SPECIFIER}`, "gud");
516
+ const REQUIRE_PATTERN = new RegExp(String.raw`${KEYWORD_BOUNDARY}require\s*\(\s*${SPECIFIER}\s*\)`, "gud");
517
+ const SIDE_EFFECT_PATTERN = new RegExp(String.raw`${KEYWORD_BOUNDARY}import\s*${SPECIFIER}`, "gud");
518
+ /**
519
+ * Returns `code` with every non-code region blanked out to spaces so that
520
+ * regexes can run against real syntax only. String literals keep their
521
+ * delimiters (with a blank interior) so import specifiers stay locatable;
522
+ * comments, template literals, and regular expressions vanish entirely.
523
+ * The result has the same length as `code`, so match indices map back 1:1.
524
+ */
525
+ function blankNonCode(code) {
526
+ const codePositions = createCodePositionMap(code);
527
+ const chars = code.split("");
528
+ let index = 0;
529
+ while (index < code.length) {
530
+ if (codePositions[index]) {
531
+ index++;
532
+ continue;
533
+ }
534
+ const start = index;
535
+ while (index < code.length && !codePositions[index]) index++;
536
+ const quote = code[start];
537
+ const isString = (quote === "\"" || quote === "'") && index - start >= 2 && code[index - 1] === quote;
538
+ for (let position = start; position < index; position++) chars[position] = isString && (position === start || position === index - 1) ? quote : code[position] === "\n" ? "\n" : " ";
539
+ }
540
+ return chars.join("");
541
+ }
542
+ function isTypeOnlyNamedClause(clause) {
543
+ const namedSpecifiers = clause.trim().match(/^\{([\s\S]*)\}$/)?.[1];
544
+ if (namedSpecifiers === void 0) return false;
510
545
  const specifiers = namedSpecifiers.split(",").map((specifier) => specifier.trim()).filter(Boolean);
511
- return specifiers.length > 0 && specifiers.every((specifier) => /^type\s+\S/.test(specifier));
546
+ return specifiers.length > 0 && specifiers.every((specifier) => /^type\s+(?!as(?:\s|$))\S/.test(specifier));
547
+ }
548
+ function readSource(code, match) {
549
+ const range = match.indices?.groups?.source;
550
+ if (!range) return void 0;
551
+ const source = code.slice(range[0], range[1]);
552
+ return source.length > 0 ? source : void 0;
512
553
  }
513
554
  /**
514
555
  * Finds module imports while ignoring comments, strings, and regular expressions.
515
556
  * The descriptor keeps enough information for callers to distinguish runtime
516
557
  * static imports from type-only imports without introducing a parser dependency.
558
+ *
559
+ * Matching runs against a blanked copy of the code (see `blankNonCode`), so an
560
+ * `import` inside a comment or string can never match, comments inside a
561
+ * statement never change its classification, and a clause can never span
562
+ * multiple statements.
517
563
  */
518
564
  function findModuleImportDescriptors(code) {
519
- const codePositions = createCodePositionMap(code);
565
+ const blanked = blankNonCode(code);
520
566
  const descriptors = [];
521
- const staticFromPattern = /\b(?:import|export)\s+([\s\S]*?)\s+from\s*(["'])([^"']+)\2/g;
522
- const dynamicPattern = /\bimport\s*\(\s*(?:\/\*[\s\S]*?\*\/\s*)?(["'])([^"']+)\1\s*\)/g;
523
- const requirePattern = /\brequire\s*\(\s*(["'])([^"']+)\1\s*\)/g;
524
- const sideEffectPattern = /\bimport\s*(["'])([^"']+)\1/g;
525
- let match;
526
- while (match = staticFromPattern.exec(code)) {
527
- if (!codePositions[match.index]) {
528
- staticFromPattern.lastIndex = match.index + 1;
529
- continue;
530
- }
567
+ for (const match of blanked.matchAll(STATIC_PATTERN)) {
568
+ const source = readSource(code, match);
569
+ if (!source) continue;
570
+ const groups = match.groups;
571
+ const typeOnly = groups.importType !== void 0 || groups.exportType !== void 0 || isTypeOnlyNamedClause(groups.importClause ?? groups.exportClause ?? "");
531
572
  descriptors.push({
532
573
  kind: "static",
533
574
  syntax: "import",
534
- source: match[3],
535
- typeOnly: isTypeOnlyClause(match[1])
575
+ source,
576
+ typeOnly
536
577
  });
537
578
  }
538
- for (const match of code.matchAll(dynamicPattern)) {
539
- if (!codePositions[match.index]) continue;
540
- descriptors.push({
579
+ for (const match of blanked.matchAll(DYNAMIC_PATTERN)) {
580
+ const source = readSource(code, match);
581
+ if (source) descriptors.push({
541
582
  kind: "dynamic",
542
583
  syntax: "import",
543
- source: match[2],
584
+ source,
544
585
  typeOnly: false
545
586
  });
546
587
  }
547
- for (const match of code.matchAll(requirePattern)) {
548
- if (!codePositions[match.index]) continue;
549
- descriptors.push({
588
+ for (const match of blanked.matchAll(REQUIRE_PATTERN)) {
589
+ const source = readSource(code, match);
590
+ if (source) descriptors.push({
550
591
  kind: "dynamic",
551
592
  syntax: "require",
552
- source: match[2],
593
+ source,
553
594
  typeOnly: false
554
595
  });
555
596
  }
556
- for (const match of code.matchAll(sideEffectPattern)) {
557
- if (!codePositions[match.index]) continue;
558
- descriptors.push({
597
+ for (const match of blanked.matchAll(SIDE_EFFECT_PATTERN)) {
598
+ const source = readSource(code, match);
599
+ if (source) descriptors.push({
559
600
  kind: "static",
560
601
  syntax: "import",
561
- source: match[2],
602
+ source,
562
603
  typeOnly: false
563
604
  });
564
605
  }
565
606
  return descriptors;
566
607
  }
608
+ /**
609
+ * Returns the JavaScript/TypeScript portion of a module for import scanning.
610
+ * Vue and Svelte single-file components only contribute their `<script>`
611
+ * blocks so template markup and styles are never misread as code.
612
+ */
613
+ function getScannableModuleSource(id, code) {
614
+ if (!/\.(?:vue|svelte)(?:\?|$)/.test(id)) return code;
615
+ const blocks = [];
616
+ for (const match of code.matchAll(/<script\b[^>]*>([\s\S]*?)<\/script(?:\s[^>]*)?>/gi)) blocks.push(match[1]);
617
+ return blocks.join("\n");
618
+ }
567
619
  function findModuleImportSources(code) {
568
620
  return Array.from(new Set(findModuleImportDescriptors(code).filter(({ syntax, typeOnly }) => syntax === "import" && !typeOnly).map(({ source }) => source)));
569
621
  }
@@ -588,7 +640,8 @@ function rewriteEntryScripts(html, createProxySrc) {
588
640
  }
589
641
  function injectEntryScript(html, initSrc) {
590
642
  const src = sanitizeDevEntryPath(initSrc);
591
- return html.replace("<head>", `<head><script type="module" src=${JSON.stringify(src)}><\/script>`);
643
+ const script = `<script type="module" src=${JSON.stringify(src)}><\/script>`;
644
+ return html.replace(/<head\b[^>]*>/i, (openTag) => `${openTag}${script}`);
592
645
  }
593
646
  //#endregion
594
647
  //#region src/utils/normalizeModuleFederationOptions.ts
@@ -673,7 +726,30 @@ function searchPackageVersion(sharedName) {
673
726
  }
674
727
  function inferVersionFromRequiredVersion(requiredVersion) {
675
728
  if (typeof requiredVersion !== "string") return void 0;
676
- return requiredVersion.match(/\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?/)?.[0];
729
+ const isDigit = (char) => char !== void 0 && char >= "0" && char <= "9";
730
+ const isSuffixChar = (char) => char !== void 0 && (char >= "0" && char <= "9" || char >= "A" && char <= "Z" || char >= "a" && char <= "z" || char === "." || char === "-");
731
+ let index = 0;
732
+ while (index < requiredVersion.length) {
733
+ if (!isDigit(requiredVersion[index])) {
734
+ index += 1;
735
+ continue;
736
+ }
737
+ const start = index;
738
+ while (isDigit(requiredVersion[index])) index += 1;
739
+ if (requiredVersion[index] !== ".") continue;
740
+ index += 1;
741
+ if (!isDigit(requiredVersion[index])) continue;
742
+ while (isDigit(requiredVersion[index])) index += 1;
743
+ if (requiredVersion[index] !== ".") continue;
744
+ index += 1;
745
+ if (!isDigit(requiredVersion[index])) continue;
746
+ while (isDigit(requiredVersion[index])) index += 1;
747
+ if ((requiredVersion[index] === "-" || requiredVersion[index] === "+") && isSuffixChar(requiredVersion[index + 1])) {
748
+ index += 1;
749
+ while (isSuffixChar(requiredVersion[index])) index += 1;
750
+ }
751
+ return requiredVersion.slice(start, index);
752
+ }
677
753
  }
678
754
  /** URI-style package specifiers are not semver ranges for runtime satisfy(). */
679
755
  const PACKAGE_SPECIFIER_PROTOCOL_RE = /^[a-z][a-z\d+.-]*:/i;
@@ -854,7 +930,7 @@ function normalizeModuleFederationOptions(options) {
854
930
  injectTreeShakingUsedExports: options.injectTreeShakingUsedExports,
855
931
  treeShakingSharedPlugins: options.treeShakingSharedPlugins,
856
932
  treeShakingSharedExcludePlugins: options.treeShakingSharedExcludePlugins,
857
- moduleParseTimeout: options.moduleParseTimeout || 10,
933
+ moduleParseTimeout: options.moduleParseTimeout ?? 10,
858
934
  moduleParseIdleTimeout: options.moduleParseIdleTimeout,
859
935
  varFilename: options.varFilename,
860
936
  target: options.target,
@@ -1016,7 +1092,7 @@ function serializeRuntimeOptions(options) {
1016
1092
  if (type === "number" || type === "boolean") return String(val);
1017
1093
  if (type === "undefined") return "undefined";
1018
1094
  if (type === "symbol") return `Symbol(${toSafeJsLiteral(val.description ?? "")})`;
1019
- if (type === "function") return val.toString();
1095
+ if (type === "function") return functionToExpression(val);
1020
1096
  if (val instanceof Date) return `new Date(${toSafeJsLiteral(val.toISOString())})`;
1021
1097
  if (val instanceof RegExp) return `new RegExp(${toSafeJsLiteral(val.source)}, ${toSafeJsLiteral(val.flags)})`;
1022
1098
  if (type === "object") {
@@ -1039,9 +1115,49 @@ function serializeRuntimeOptions(options) {
1039
1115
  for (const key in options) if (Object.prototype.hasOwnProperty.call(options, key)) topLevelProps.push(`${toSafeJsLiteral(key)}: ${valueToCode(options[key])}`);
1040
1116
  return `{${topLevelProps.join(", ")}}`;
1041
1117
  }
1118
+ const NATIVE_FUNCTION_SOURCE = /\{\s*\[native code\]\s*\}\s*$/;
1119
+ /**
1120
+ * Turns `Function#toString()` output into a JS expression that is valid as an
1121
+ * object-literal value.
1122
+ *
1123
+ * Method shorthand (`onError() { … }`) is not a valid expression after a `:`,
1124
+ * so it is rewritten as a function expression. Native functions have no
1125
+ * reconstructable source (`function parse() { [native code] }`) and serialize
1126
+ * as `undefined` so the generated object stays loadable.
1127
+ */
1128
+ function functionToExpression(fn) {
1129
+ let source;
1130
+ try {
1131
+ source = Function.prototype.toString.call(fn).trim();
1132
+ } catch {
1133
+ return "undefined";
1134
+ }
1135
+ if (NATIVE_FUNCTION_SOURCE.test(source) || /^(async\s+)?(?:get|set)\s+/.test(source)) return "undefined";
1136
+ if (/^(async\s+)?function\b/.test(source) || /^(async\s*)?\(/.test(source) || /^class\b/.test(source) || /^(async\s+)?[$_\p{ID_Start}][$\p{ID_Continue}]*\s*=>/u.test(source)) return isParsableExpression(source) ? source : "undefined";
1137
+ for (const [pattern, prefix] of [
1138
+ [/^async\s*\*\s*[$_\p{ID_Start}][$\p{ID_Continue}]*\s*(\([\s\S]*)$/u, "async function* "],
1139
+ [/^\*\s*[$_\p{ID_Start}][$\p{ID_Continue}]*\s*(\([\s\S]*)$/u, "function* "],
1140
+ [/^async\s+[$_\p{ID_Start}][$\p{ID_Continue}]*\s*(\([\s\S]*)$/u, "async function "],
1141
+ [/^[$_\p{ID_Start}][$\p{ID_Continue}]*\s*(\([\s\S]*)$/u, "function "]
1142
+ ]) {
1143
+ const match = source.match(pattern);
1144
+ if (!match) continue;
1145
+ const expression = `${prefix}${match[1]}`;
1146
+ return isParsableExpression(expression) ? expression : "undefined";
1147
+ }
1148
+ return "undefined";
1149
+ }
1150
+ function isParsableExpression(source) {
1151
+ try {
1152
+ new Function(`return (${source});`);
1153
+ return true;
1154
+ } catch {
1155
+ return false;
1156
+ }
1157
+ }
1042
1158
  //#endregion
1043
1159
  //#region src/utils/reactIsland.ts
1044
- const SOURCE_EXTENSIONS = [
1160
+ const SOURCE_EXTENSIONS$1 = [
1045
1161
  ".tsx",
1046
1162
  ".jsx",
1047
1163
  ".ts",
@@ -1060,8 +1176,8 @@ function resolveSourceFile(importPath, root) {
1060
1176
  const candidate = path$1.isAbsolute(cleanImport) ? cleanImport : path$1.resolve(root, cleanImport);
1061
1177
  return [
1062
1178
  candidate,
1063
- ...SOURCE_EXTENSIONS.map((extension) => `${candidate}${extension}`),
1064
- ...SOURCE_EXTENSIONS.map((extension) => path$1.join(candidate, `index${extension}`))
1179
+ ...SOURCE_EXTENSIONS$1.map((extension) => `${candidate}${extension}`),
1180
+ ...SOURCE_EXTENSIONS$1.map((extension) => path$1.join(candidate, `index${extension}`))
1065
1181
  ].find((filePath) => {
1066
1182
  try {
1067
1183
  return fs$1.statSync(filePath).isFile();
@@ -1283,6 +1399,49 @@ function loadReactIslandConsumerModule(id) {
1283
1399
  function getVirtualModuleScopeKey(options) {
1284
1400
  return `${options.internalName}__${options.filename}`.replace(/[^a-zA-Z0-9_-]/g, "_");
1285
1401
  }
1402
+ function compareConfigValues(a, b) {
1403
+ const serializedA = JSON.stringify(a);
1404
+ const serializedB = JSON.stringify(b);
1405
+ return serializedA < serializedB ? -1 : serializedA > serializedB ? 1 : 0;
1406
+ }
1407
+ function stableConfigValue(value, ancestors = /* @__PURE__ */ new WeakSet()) {
1408
+ if (typeof value === "function") return value.toString();
1409
+ if (!value || typeof value !== "object") return value;
1410
+ if (value instanceof Date) return {
1411
+ type: "Date",
1412
+ value: value.toISOString()
1413
+ };
1414
+ if (value instanceof RegExp) return {
1415
+ type: "RegExp",
1416
+ source: value.source,
1417
+ flags: value.flags
1418
+ };
1419
+ if (ancestors.has(value)) return "__circular__";
1420
+ ancestors.add(value);
1421
+ let result;
1422
+ if (value instanceof Map) {
1423
+ const entries = [...value.entries()].map(([key, item]) => [stableConfigValue(key, ancestors), stableConfigValue(item, ancestors)]);
1424
+ entries.sort(compareConfigValues);
1425
+ result = {
1426
+ type: "Map",
1427
+ entries
1428
+ };
1429
+ } else if (value instanceof Set) {
1430
+ const values = [...value].map((item) => stableConfigValue(item, ancestors));
1431
+ values.sort(compareConfigValues);
1432
+ result = {
1433
+ type: "Set",
1434
+ values
1435
+ };
1436
+ } else result = Array.isArray(value) ? value.map((item) => stableConfigValue(item, ancestors)) : Object.fromEntries(Object.entries(value).filter(([key]) => key !== "implementation").sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0).map(([key, item]) => [key, stableConfigValue(item, ancestors)]));
1437
+ ancestors.delete(value);
1438
+ return result;
1439
+ }
1440
+ function getFederationScopeKey(options) {
1441
+ const identity = JSON.stringify(stableConfigValue(options));
1442
+ const ownerId = BigInt(`0x${createHash("sha256").update(identity).digest("hex").slice(0, 12)}`);
1443
+ return `${options.internalName}${MF_OWNER_INFIX}${ownerId}`;
1444
+ }
1286
1445
  //#endregion
1287
1446
  //#region src/virtualModules/virtualExposes.ts
1288
1447
  const EXPOSES_CSS_MAP_PLACEHOLDER = "__MF_EXPOSES_CSS_MAP__";
@@ -1432,28 +1591,17 @@ function isReactServerConditions(conditions) {
1432
1591
  //#region src/virtualModules/virtualRuntimeInitStatus.ts
1433
1592
  const virtualRuntimeInitStatus = new VirtualModule("runtimeInit");
1434
1593
  const runtimeInitModules = /* @__PURE__ */ new WeakMap();
1435
- const runtimeInitOwnerIds = /* @__PURE__ */ new WeakMap();
1436
- let nextRuntimeInitOwnerId = 1;
1437
1594
  const MODULE_CACHE_GLOBAL_KEY = "__mf_module_cache__";
1438
1595
  const REACT_SERVER_MODULE_CACHE_GLOBAL_KEY = "__mf_module_cache_react_server__";
1439
1596
  const MODULE_CACHE_SHARE_SCOPE_KEY = "module-federation.vite-module-cache";
1440
1597
  function getModuleCacheGlobalKey(exportConditions) {
1441
1598
  return isReactServerConditions(exportConditions) ? REACT_SERVER_MODULE_CACHE_GLOBAL_KEY : MODULE_CACHE_GLOBAL_KEY;
1442
1599
  }
1443
- function getRuntimeInitOwnerId(options) {
1444
- let ownerId = runtimeInitOwnerIds.get(options);
1445
- if (!ownerId) {
1446
- ownerId = nextRuntimeInitOwnerId++;
1447
- runtimeInitOwnerIds.set(options, ownerId);
1448
- }
1449
- return ownerId;
1450
- }
1451
1600
  function getRuntimeInitModule(options) {
1452
1601
  if (!options) return virtualRuntimeInitStatus;
1453
1602
  let runtimeInitModule = runtimeInitModules.get(options);
1454
1603
  if (!runtimeInitModule) {
1455
- const ownerId = getRuntimeInitOwnerId(options);
1456
- runtimeInitModule = new VirtualModule("runtimeInit", "__mf_v__", "", `${options.internalName}${MF_OWNER_INFIX}${ownerId}`);
1604
+ runtimeInitModule = new VirtualModule("runtimeInit", "__mf_v__", "", getFederationScopeKey(options));
1457
1605
  runtimeInitModules.set(options, runtimeInitModule);
1458
1606
  }
1459
1607
  return runtimeInitModule;
@@ -1466,7 +1614,14 @@ function getRuntimeRemoteCachePrefix(options) {
1466
1614
  }
1467
1615
  function getRuntimeRemoteAlias(alias, options) {
1468
1616
  if (!options) return alias;
1469
- return `${options.internalName}${MF_OWNER_INFIX}${getRuntimeInitOwnerId(options)}__${alias}`;
1617
+ return `${getFederationScopeKey(options)}__${alias}`;
1618
+ }
1619
+ function getSsrRuntimeRemotes(remotes, options) {
1620
+ return Object.entries(remotes).map(([name, item]) => ({
1621
+ name: getRuntimeRemoteAlias(name, options),
1622
+ entry: item.entry,
1623
+ type: item.type ?? "module"
1624
+ }));
1470
1625
  }
1471
1626
  function getRuntimeInitGlobalKey(ownerImportId) {
1472
1627
  return `__mf_init__${ownerImportId ?? virtualRuntimeInitStatus.getImportId()}__`;
@@ -1556,6 +1711,16 @@ globalThis[__mfCacheGlobalKey] ||= { share: {}, remote: {} };
1556
1711
  globalThis[__mfCacheGlobalKey].share ||= {};
1557
1712
  globalThis[__mfCacheGlobalKey].remote ||= {};
1558
1713
  const __mfModuleCache = globalThis[__mfCacheGlobalKey];
1714
+ const __mfTrackPendingShareLoad = (promise) => {
1715
+ const pendingShareLoads = (__mfModuleCache.pendingShareLoads ||= []);
1716
+ pendingShareLoads.push(promise);
1717
+ const cleanup = () => {
1718
+ const index = pendingShareLoads.indexOf(promise);
1719
+ if (index !== -1) pendingShareLoads.splice(index, 1);
1720
+ };
1721
+ void promise.then(cleanup, cleanup);
1722
+ return promise;
1723
+ };
1559
1724
  for (const __mfShareKey of Object.keys(__mfModuleCache.share)) {
1560
1725
  if (__mfShareKey.startsWith("default:")) {
1561
1726
  const __mfLegacyShareKey = __mfShareKey.slice("default:".length);
@@ -1928,6 +2093,7 @@ function hasLikelyTypeArgumentFollower(source, end, codePositions, followsNamedE
1928
2093
  let next = end + 1;
1929
2094
  while (next < source.length && (!codePositions[next] || /\s/.test(source[next]))) next++;
1930
2095
  if (next >= source.length || /[([.!?=;,)\]}:|&]/.test(source[next])) return true;
2096
+ if (source.slice(end + 1, next).includes("\n")) return true;
1931
2097
  const followingToken = source.slice(next).match(/^[$_\p{ID_Start}][$_\u200C\u200D\p{ID_Continue}]*/u)?.[0];
1932
2098
  return followingToken === "as" || followingToken === "satisfies" || !followsNamedExpression && followingToken !== void 0;
1933
2099
  }
@@ -2236,6 +2402,14 @@ function getAdditionalTopLevelDeclaratorNames(source, start, codePositions) {
2236
2402
  canStartRegex = false;
2237
2403
  continue;
2238
2404
  }
2405
+ if (char === "<" && source[index + 1] === "/") {
2406
+ const jsxClosingTag = source.slice(index).match(/^<\/\s*(?:[$_\p{ID_Start}][$_\u200C\u200D\p{ID_Continue}.:-]*\s*)?>/u);
2407
+ if (jsxClosingTag) {
2408
+ index += jsxClosingTag[0].length - 1;
2409
+ canStartRegex = false;
2410
+ continue;
2411
+ }
2412
+ }
2239
2413
  if (char === "/" && source[index + 1] === "/") {
2240
2414
  index = source.indexOf("\n", index + 2);
2241
2415
  if (index === -1) return names;
@@ -2288,6 +2462,11 @@ function getAdditionalTopLevelDeclaratorNames(source, start, codePositions) {
2288
2462
  const tokenStart = index;
2289
2463
  while (/[$_\u200C\u200D\p{ID_Continue}]/u.test(source[index + 1] || "")) index++;
2290
2464
  const token = source.slice(tokenStart, index + 1);
2465
+ if (depth === 0 && templateFrames.length === 0 && token === "export") {
2466
+ let previous = tokenStart - 1;
2467
+ while (/\s/.test(source[previous] || "")) previous--;
2468
+ if (source[previous] !== "." && /^\s+(?:(?:async\s+)?function\b|(?:abstract\s+)?class\b|const\b|let\b|var\b|enum\b|namespace\b|module\b|interface\b|type\b|declare\b|default\b|\{|\*)/.test(source.slice(index + 1))) return names;
2469
+ }
2291
2470
  canStartRegex = /^(?:await|case|delete|in|instanceof|new|return|throw|typeof|void|yield)$/.test(token);
2292
2471
  continue;
2293
2472
  }
@@ -2472,6 +2651,15 @@ function getNamedExportsViaRegex(source, filePath, visited, scanState = { comple
2472
2651
  let previousCodeIndex = match.index - 1;
2473
2652
  while (previousCodeIndex >= 0 && (/\s/.test(source[previousCodeIndex]) || !codePositions[previousCodeIndex])) previousCodeIndex--;
2474
2653
  if (source[previousCodeIndex] === ".") continue;
2654
+ let nextCodeIndex = match.index + match[0].length;
2655
+ while (nextCodeIndex < source.length && (/\s/.test(source[nextCodeIndex]) || !codePositions[nextCodeIndex])) nextCodeIndex++;
2656
+ if (source[nextCodeIndex] === "(") continue;
2657
+ let memberIndex = nextCodeIndex;
2658
+ if (source[memberIndex] === "?") {
2659
+ memberIndex++;
2660
+ while (memberIndex < source.length && (/\s/.test(source[memberIndex]) || !codePositions[memberIndex])) memberIndex++;
2661
+ }
2662
+ if (source[memberIndex] === ":") continue;
2475
2663
  scanState.complete = false;
2476
2664
  break;
2477
2665
  }
@@ -2633,23 +2821,25 @@ function getDependencyNames(packageJson) {
2633
2821
  }
2634
2822
  return Array.from(names);
2635
2823
  }
2636
- function isSharedSingletonConsumedByPeer(pkg, options = getNormalizeModuleFederationOptions()) {
2824
+ function isSharedSingletonConsumedByPeer(pkg, options = getNormalizeModuleFederationOptions(), requireFederationRuntimeDependency = false) {
2637
2825
  const shared = options?.shared || {};
2638
- if (Object.entries(shared).some(([key, item]) => key !== pkg && key.startsWith(`${pkg}/`) && item.shareConfig.singleton === true)) return true;
2826
+ if (!requireFederationRuntimeDependency && Object.entries(shared).some(([key, item]) => key !== pkg && key.startsWith(`${pkg}/`) && item.shareConfig.singleton === true)) return true;
2639
2827
  const sharedKeyByPackageName = /* @__PURE__ */ new Map();
2640
2828
  Object.entries(shared).filter(([, item]) => item.shareConfig.singleton === true).forEach(([key]) => {
2641
2829
  const packageName = getPackageName(key);
2642
2830
  if (!sharedKeyByPackageName.get(packageName) || key === packageName) sharedKeyByPackageName.set(packageName, key);
2643
2831
  });
2644
- const reachesPkg = (current, seen) => {
2645
- const packageJson = getSharedDependencyGraphPackageJson(current);
2646
- for (const dependency of getDependencyNames(packageJson)) {
2832
+ const reachesPkg = (current, seen, hasFederationRuntimeDependency = false) => {
2833
+ const dependencies = getDependencyNames(getSharedDependencyGraphPackageJson(current));
2834
+ const usesFederationRuntime = dependencies.some((dependency) => dependency === "@module-federation/enhanced" || dependency === "@module-federation/runtime" || dependency === "@module-federation/runtime-core");
2835
+ const runtimeIsReachable = hasFederationRuntimeDependency || usesFederationRuntime;
2836
+ for (const dependency of dependencies) {
2647
2837
  const sharedDependency = sharedKeyByPackageName.get(dependency);
2648
2838
  if (!sharedDependency) continue;
2649
- if (sharedDependency === pkg) return true;
2839
+ if (sharedDependency === pkg) return !requireFederationRuntimeDependency || runtimeIsReachable;
2650
2840
  if (seen.has(sharedDependency)) continue;
2651
2841
  seen.add(sharedDependency);
2652
- if (reachesPkg(sharedDependency, seen)) return true;
2842
+ if (reachesPkg(sharedDependency, seen, runtimeIsReachable)) return true;
2653
2843
  }
2654
2844
  return false;
2655
2845
  };
@@ -2710,7 +2900,6 @@ const legacySharedVirtualModuleState = {
2710
2900
  warnedMissingImportFalse: /* @__PURE__ */ new Set()
2711
2901
  };
2712
2902
  const sharedVirtualModuleStates = /* @__PURE__ */ new WeakMap();
2713
- let nextSharedVirtualModuleOwnerId = 1;
2714
2903
  function getSharedVirtualModuleState(options) {
2715
2904
  if (!options) try {
2716
2905
  const currentOptions = getNormalizeModuleFederationOptions();
@@ -2727,7 +2916,7 @@ function getSharedVirtualModuleState(options) {
2727
2916
  materializedTreeShakingProviders: /* @__PURE__ */ new Set(),
2728
2917
  loadShareCacheMap: {},
2729
2918
  warnedMissingImportFalse: /* @__PURE__ */ new Set(),
2730
- ownerKey: `${options.internalName}${MF_OWNER_INFIX}${nextSharedVirtualModuleOwnerId++}`
2919
+ ownerKey: getFederationScopeKey(options)
2731
2920
  };
2732
2921
  sharedVirtualModuleStates.set(options, state);
2733
2922
  }
@@ -2981,6 +3170,12 @@ function findCurrentLoadShareForStaleOwnerId(id, shared, findSharedKey, options)
2981
3170
  function getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer) {
2982
3171
  return treeShakingConsumer ? `__mfReadTreeShakingSharedSelection(__mfModuleCache.share, ${cacheDescriptor}, ${JSON.stringify(treeShakingConsumer)})` : `__mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor})`;
2983
3172
  }
3173
+ /**
3174
+ * Eager workspace singleton wrapper: reads the shared cache synchronously and falls back to the local
3175
+ * namespace. Inside the fallback's own evaluation cycle that namespace is not initialized yet (undefined in
3176
+ * a merged chunk, TDZ bindings otherwise), so the exports stay unassigned until the deferred cache write
3177
+ * re-applies them; a host-provided copy re-applies them through the cache subscription as before.
3178
+ */
2984
3179
  function generateEagerWorkspaceSingletonExports(namedExports, importSource, cacheDescriptor, cacheOwner, treeShakingConsumer, mutableExports = []) {
2985
3180
  const copiedExports = namedExports.filter((name) => !mutableExports.includes(name));
2986
3181
  const namedExportVars = copiedExports.map((_name, i) => `__mf_${i}`);
@@ -2992,8 +3187,10 @@ function generateEagerWorkspaceSingletonExports(namedExports, importSource, cach
2992
3187
  let exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
2993
3188
  if (exportModule === undefined) {
2994
3189
  Promise.resolve().then(() => {
2995
- if (__mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor}) === undefined) {
2996
- __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, __mfNormalizeShareModule(__mfLocalShare), ${cacheOwner});
3190
+ if (__mfReadSharedCache(__mfModuleCache.share, ${cacheDescriptor}) !== undefined) return;
3191
+ const localShare = __mfInitializedLocalShare(__mfLocalShare);
3192
+ if (localShare !== undefined) {
3193
+ __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, localShare, ${cacheOwner});
2997
3194
  }
2998
3195
  });
2999
3196
  exportModule = __mfLocalShare;
@@ -3002,8 +3199,16 @@ function generateEagerWorkspaceSingletonExports(namedExports, importSource, cach
3002
3199
  const __mfApplyEagerShareExports = (mod) => {
3003
3200
  ${assignments}
3004
3201
  };
3202
+ const __mfApplyEagerShareExportsWhenReady = (mod) => {
3203
+ if (mod === undefined) return;
3204
+ try {
3205
+ __mfApplyEagerShareExports(mod);
3206
+ } catch (error) {
3207
+ if (!(error instanceof ReferenceError)) throw error;
3208
+ }
3209
+ };
3005
3210
  __mfSubscribeSharedCache(__mfModuleCache.share, ${cacheDescriptor}, __mfApplyEagerShareExports);
3006
- __mfApplyEagerShareExports(exportModule);
3211
+ __mfApplyEagerShareExportsWhenReady(exportModule);
3007
3212
  export { __mf_default as default };${namedExportLine}${mutableExportLine}`;
3008
3213
  }
3009
3214
  function generateLazyWorkspaceSingletonExports(namedExports, importSource, cacheDescriptor, cacheOwner, treeShakingConsumer, serveLocalFallback = false, mutableExports = []) {
@@ -3026,7 +3231,7 @@ function generateLazyWorkspaceSingletonExports(namedExports, importSource, cache
3026
3231
  if (import.meta.env.SSR${serveLocalFallback ? " || (import.meta.env.DEV && typeof __mfLocalShare !== 'undefined')" : ""}) {
3027
3232
  ${applyLocalFallback}
3028
3233
  } else {
3029
- (__mfModuleCache.pendingShareLoads ||= []).push(initPromise.then(() => {
3234
+ __mfTrackPendingShareLoad(initPromise.then(() => {
3030
3235
  exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
3031
3236
  if (exportModule !== undefined) {
3032
3237
  __mfApplyLazyShareExports(exportModule);
@@ -3071,7 +3276,7 @@ function generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor,
3071
3276
  };
3072
3277
  let exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
3073
3278
  if (exportModule === undefined) {
3074
- (__mfModuleCache.pendingShareLoads ||= []).push(initPromise.then(() => {
3279
+ __mfTrackPendingShareLoad(initPromise.then(() => {
3075
3280
  exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
3076
3281
  if (exportModule === undefined) {
3077
3282
  throw new Error("[Module Federation] Shared module ${pkg} was imported before federation bootstrap finished.");
@@ -3111,6 +3316,15 @@ const normalizeLocalShareModuleCode = `const __mfNormalizeShareModule = (mod) =>
3111
3316
  ? Object.assign({}, normalized)
3112
3317
  : normalized;
3113
3318
  };`;
3319
+ const initializedLocalShareModuleCode = `const __mfInitializedLocalShare = (mod) => {
3320
+ if (mod === undefined) return undefined;
3321
+ try {
3322
+ return __mfNormalizeShareModule(mod);
3323
+ } catch (error) {
3324
+ if (error instanceof ReferenceError) return undefined;
3325
+ throw error;
3326
+ }
3327
+ };`;
3114
3328
  function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exportConditions, importFalseExportUsage) {
3115
3329
  const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
3116
3330
  const { loadShareCacheMap } = getSharedVirtualModuleState(options);
@@ -3158,10 +3372,10 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3158
3372
  const hasCompleteExportCoverage = detectedNamedExports !== void 0;
3159
3373
  const isWorkspaceSingleton = isWorkspacePackage && shareItem.shareConfig.singleton === true;
3160
3374
  const isDefaultShareScope = shareItem.scope === void 0 || shareItem.scope === "default" || Array.isArray(shareItem.scope) && shareItem.scope[0] === "default";
3161
- const usesDeferredSingletonFallback = hasCompleteExportCoverage && (isWorkspacePackage || command !== "build" && isRemoteOnlyContainer(resolvedOptions) && shareItem.shareConfig.singleton === true || command === "build" && isRemoteOnlyContainer(resolvedOptions) && (shareItem.shareConfig.singleton === true ? !isDefaultShareScope : isDefaultShareScope));
3375
+ const usesDeferredSingletonFallback = hasCompleteExportCoverage && shareItem.shareConfig.eager !== true && (isWorkspacePackage || command !== "build" && isRemoteOnlyContainer(resolvedOptions) && shareItem.shareConfig.singleton === true || command === "build" && isRemoteOnlyContainer(resolvedOptions) && (shareItem.shareConfig.singleton === true || isDefaultShareScope) && !isSharedSingletonConsumedByPeer(pkg, resolvedOptions, true));
3162
3376
  const servesRemoteSingletonFallback = command !== "build" && isRemoteOnlyContainer(resolvedOptions) && shareItem.shareConfig.singleton === true;
3163
3377
  const isConsumedByPeerSingleton = isSharedSingletonConsumedByPeer(pkg, resolvedOptions);
3164
- const usesEntryInjectedRemoteFallback = hasCompleteExportCoverage && command !== "build" && !isWorkspaceSingleton && isRemoteOnlyContainer(resolvedOptions) && shareItem.shareConfig.singleton === true && resolvedOptions.hostInitInjectLocation === "entry" && isConsumedByPeerSingleton;
3378
+ const usesEntryInjectedRemoteFallback = hasCompleteExportCoverage && !isWorkspaceSingleton && isRemoteOnlyContainer(resolvedOptions) && shareItem.shareConfig.singleton === true && resolvedOptions.hostInitInjectLocation === "entry" && (command === "build" || isConsumedByPeerSingleton);
3165
3379
  const usesEagerWorkspaceFallback = hasCompleteExportCoverage && isWorkspaceSingleton && !servesRemoteSingletonFallback && (isConsumedByPeerSingleton || shareItem.shareConfig.eager === true);
3166
3380
  const usesDeferredTreeShakingFallback = hasCompleteExportCoverage && Boolean(treeShakingConsumer);
3167
3381
  const reactMixedModeGuard = pkg === "react" ? createReactMixedModeRuntimeGuard() : "";
@@ -3244,12 +3458,13 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3244
3458
  }
3245
3459
  const prebuildImportLine = usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback ? "" : usesDeferredSingletonFallback || usesDeferredTreeShakingFallback ? !servesRemoteSingletonFallback && usesDeferredSingletonFallback && command !== "build" && (isWorkspaceSingleton || isWorkspacePackage) ? `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(lazyLocalFallbackSource)};` : "" : `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(detectedNamedExports === void 0 ? coherentLocalSource : skipServePrebuildWarmup ? devImportSource : sharedImportSource)};`;
3246
3460
  const devDynamicImportLine = isWorkspacePackage ? "" : usesDeferredSingletonFallback || usesDeferredTreeShakingFallback ? "" : command !== "build" && !skipServePrebuildWarmup ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
3247
- const moduleBody = usesDeferredSingletonFallback || usesDeferredTreeShakingFallback ? `
3461
+ const moduleBody = usesDeferredSingletonFallback || usesDeferredTreeShakingFallback || usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback ? `
3248
3462
  ${prebuildImportLine}
3249
3463
  ${devDynamicImportLine}
3250
3464
  ${importLine}
3251
3465
  ${sharedCacheHelperCode}
3252
3466
  ${normalizeLocalShareModuleCode}
3467
+ ${initializedLocalShareModuleCode}
3253
3468
  ${exportLine}
3254
3469
  ` : `
3255
3470
  ${prebuildImportLine}
@@ -3351,6 +3566,7 @@ function generateLocalSharedImportMap(options) {
3351
3566
  if (!shareItem?.shareConfig.eager || shareItem.shareConfig.import === false) return "";
3352
3567
  return `import * as __mfEagerShare_${index} from ${toSafeJsLiteral(getLocalSharedPackagePath(pkg, shareItem, options))};`;
3353
3568
  }).filter(Boolean).join("\n")}
3569
+ ${normalizeRuntimeShareCode}
3354
3570
  const importMap = {
3355
3571
  ${orderedShares.map((pkg, index) => {
3356
3572
  const shareItem = getNormalizeShareItem(pkg, resolvedOptions);
@@ -3395,7 +3611,7 @@ function generateLocalSharedImportMap(options) {
3395
3611
  const res = await pkgDynamicImport()
3396
3612
  const exportModule = ${toSafeJsLiteral(useDirectReactImport)} && ${toSafeJsLiteral(key)} === "react"
3397
3613
  ? (res?.default ?? res)
3398
- : {...res}
3614
+ : __mfNormalizeRuntimeShare({...res})
3399
3615
  // All npm packages pre-built by vite will be converted to esm
3400
3616
  if (exportModule.__esModule !== true) {
3401
3617
  Object.defineProperty(exportModule, "__esModule", {
@@ -3511,9 +3727,8 @@ function getMaterializedShares(options) {
3511
3727
  return priority(a) - priority(b) || a.localeCompare(b);
3512
3728
  }));
3513
3729
  }
3514
- function getShareBatches(options, materializedOnly = true) {
3515
- const ordered = materializedOnly ? getMaterializedShares(options) : getOrderedUsedShares(options);
3516
- const levels = /* @__PURE__ */ new Map();
3730
+ /** Shared keys a share's package.json depends on (roots stand in for their subpaths, subpaths for their root), keyed by share. */
3731
+ function getSharePrerequisites(ordered) {
3517
3732
  const roots = /* @__PURE__ */ new Map();
3518
3733
  const subpaths = /* @__PURE__ */ new Map();
3519
3734
  for (const pkg of ordered) {
@@ -3521,6 +3736,7 @@ function getShareBatches(options, materializedOnly = true) {
3521
3736
  if (pkg === packageName) roots.set(packageName, pkg);
3522
3737
  else subpaths.set(packageName, [...subpaths.get(packageName) ?? [], pkg]);
3523
3738
  }
3739
+ const prerequisitesByShare = /* @__PURE__ */ new Map();
3524
3740
  for (const pkg of ordered) {
3525
3741
  const packageName = getPackageName(pkg);
3526
3742
  const packageJson = getInstalledPackageJson(pkg)?.packageJson ?? (pkg !== packageName ? getInstalledPackageJson(packageName)?.packageJson : void 0);
@@ -3534,8 +3750,15 @@ function getShareBatches(options, materializedOnly = true) {
3534
3750
  const root = roots.get(packageName);
3535
3751
  if (root) prerequisites.push(root);
3536
3752
  } else if (pkg === packageName && packageName !== "react" && packageName !== "react-dom") prerequisites.push(...subpaths.get(packageName) ?? []);
3537
- levels.set(pkg, prerequisites.reduce((level, dependency) => Math.max(level, (levels.get(dependency) ?? 0) + 1), 0));
3753
+ prerequisitesByShare.set(pkg, prerequisites);
3538
3754
  }
3755
+ return prerequisitesByShare;
3756
+ }
3757
+ function getShareBatches(options, materializedOnly = true) {
3758
+ const ordered = materializedOnly ? getMaterializedShares(options) : getOrderedUsedShares(options);
3759
+ const prerequisitesByShare = getSharePrerequisites(ordered);
3760
+ const levels = /* @__PURE__ */ new Map();
3761
+ for (const pkg of ordered) levels.set(pkg, (prerequisitesByShare.get(pkg) ?? []).reduce((level, dependency) => Math.max(level, (levels.get(dependency) ?? 0) + 1), 0));
3539
3762
  const batches = [];
3540
3763
  for (const pkg of ordered) (batches[levels.get(pkg) ?? 0] ??= []).push(pkg);
3541
3764
  return batches.filter(Boolean);
@@ -3655,8 +3878,16 @@ const sharedProviderSelectionHelperCode = `const __mfOriginalProviderKey = Symbo
3655
3878
  strategy
3656
3879
  ) => {
3657
3880
  if (!versions || !share) return undefined;
3881
+ // import:false stubs provide nothing, so they are never a selectable
3882
+ // provider and must not be satisfy-checked. Skip the runtime entirely
3883
+ // when nothing remains: it treats an empty map as version "0" and
3884
+ // warns that it fails even a "*" requirement.
3885
+ const candidates = Object.fromEntries(
3886
+ Object.entries(versions).filter(([, provider]) => provider?.shareConfig?.import !== false)
3887
+ );
3888
+ if (Object.keys(candidates).length === 0) return undefined;
3658
3889
  const scopes = Array.isArray(share.scope) ? share.scope : [share.scope || "default"];
3659
- const selectionVersions = __mfCreateProviderSelectionVersions(versions, strategy);
3890
+ const selectionVersions = __mfCreateProviderSelectionVersions(candidates, strategy);
3660
3891
  const shareScopeMap = {};
3661
3892
  for (const scope of scopes) {
3662
3893
  shareScopeMap[scope || "default"] = { [pkg]: selectionVersions };
@@ -3769,9 +4000,14 @@ const externalSharedProviderSelectionHelperCode = `const __mfSelectExternalShare
3769
4000
  };`;
3770
4001
  function generateRuntimeSharedCacheSeedCode(shareStrategy, options) {
3771
4002
  const seedBatches = getShareBatches(options, false);
4003
+ const seedOrder = seedBatches.flat();
4004
+ const seedIndex = new Map(seedOrder.map((pkg, index) => [pkg, index]));
4005
+ const seedPrerequisites = Object.fromEntries(Array.from(getSharePrerequisites(seedOrder)).filter(([, prerequisites]) => prerequisites.length > 0).map(([pkg, prerequisites]) => [seedIndex.get(pkg), prerequisites.map((prerequisite) => seedIndex.get(prerequisite))]));
3772
4006
  return `
3773
- const __mfSeedOrder = ${toSafeJsLiteral(seedBatches.flat())};
4007
+ const __mfSeedOrder = ${toSafeJsLiteral(seedOrder)};
3774
4008
  const __mfSeedBatches = ${toSafeJsLiteral(seedBatches)};
4009
+ const __mfSeedIndex = new Map(__mfSeedOrder.map((pkg, index) => [pkg, index]));
4010
+ const __mfSeedPrerequisites = ${toSafeJsLiteral(seedPrerequisites)};
3775
4011
  // A share is normally skipped here until the dev scanner has observed a real
3776
4012
  // import and set materialize. An import:false share has no local fallback
3777
4013
  // though, so on a cold request (materialize not set yet) it must still be
@@ -3878,15 +4114,30 @@ function generateRuntimeSharedCacheSeedCode(shareStrategy, options) {
3878
4114
  ${toSafeJsLiteral(shareStrategy)}
3879
4115
  ));
3880
4116
  };
3881
- const __mfFirstRuntimeSeedBarrierIndex = __mfSeedKeys.findIndex(
3882
- __mfNeedsPreInitSeedBarrier
4117
+ const __mfExpandBlockedSeedKeys = (blocked) => {
4118
+ let changed = true;
4119
+ while (changed) {
4120
+ changed = false;
4121
+ for (const pkg of __mfSeedKeys) {
4122
+ const seedIndex = __mfSeedIndex.get(pkg);
4123
+ if (blocked.has(seedIndex)) continue;
4124
+ if ((__mfSeedPrerequisites[seedIndex] || []).some((dependency) => blocked.has(dependency))) {
4125
+ blocked.add(seedIndex);
4126
+ changed = true;
4127
+ }
4128
+ }
4129
+ }
4130
+ return blocked;
4131
+ };
4132
+ const __mfPreInitBlockedSeedKeys = __mfExpandBlockedSeedKeys(new Set(
4133
+ __mfSeedKeys.filter(__mfNeedsPreInitSeedBarrier).map((pkg) => __mfSeedIndex.get(pkg))
4134
+ ));
4135
+ const __mfImmediateSeedKeys = __mfSeedKeys.filter(
4136
+ (pkg) => !__mfPreInitBlockedSeedKeys.has(__mfSeedIndex.get(pkg))
4137
+ );
4138
+ var __mfDeferredSeedKeys = __mfSeedKeys.filter(
4139
+ (pkg) => __mfPreInitBlockedSeedKeys.has(__mfSeedIndex.get(pkg))
3883
4140
  );
3884
- const __mfImmediateSeedKeys = __mfFirstRuntimeSeedBarrierIndex === -1
3885
- ? __mfSeedKeys
3886
- : __mfSeedKeys.slice(0, __mfFirstRuntimeSeedBarrierIndex);
3887
- var __mfDeferredSeedKeys = __mfFirstRuntimeSeedBarrierIndex === -1
3888
- ? []
3889
- : __mfSeedKeys.slice(__mfFirstRuntimeSeedBarrierIndex);
3890
4141
  await __mfSeedLocalShared(__mfImmediateSeedKeys);`;
3891
4142
  }
3892
4143
  function getBrowserImportPath(importPath) {
@@ -4225,7 +4476,21 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
4225
4476
  }
4226
4477
  return runtimeScope;
4227
4478
  };
4479
+ // runtimeInit() lets runtime plugins register providers (public
4480
+ // registerShared) before initShareScopeMap() replaces the runtime's own
4481
+ // scope map. Carry those registrations over; the runtime's own copies of
4482
+ // usedShared keep registering lazily through loadShare().
4483
+ const __mfKeepRegisteredShares = (scopeName, scope) => {
4484
+ for (const [pkg, versions] of Object.entries(initRes.shareScopeMap?.[scopeName] || {})) {
4485
+ for (const [version, provider] of Object.entries(versions || {})) {
4486
+ if (!provider || provider.get === usedShared[pkg]?.get) continue;
4487
+ const target = scope[pkg] ||= {};
4488
+ if (target[version] === undefined) target[version] = provider;
4489
+ }
4490
+ }
4491
+ };
4228
4492
  const __mfGetRuntimeShareScope = (scopeName, hostScope) => {
4493
+ __mfKeepRegisteredShares(scopeName, hostScope);
4229
4494
  const isWebpackScope = !scopeRoot && Object.values(hostScope || {}).some((versions) =>
4230
4495
  Object.values(versions || {}).some(isWebpackProvider)
4231
4496
  );
@@ -4621,6 +4886,9 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
4621
4886
  );
4622
4887
  const providerEntry = __mfFindSharedProviderEntry(versionMap, provider);
4623
4888
  if (!providerEntry) return;
4889
+ if (usedShare.shareConfig?.import === false && __mfMatchesSharedProvider(provider, usedShare)) return;
4890
+ // Another container's consume-only stub has nothing to bridge to: its get() throws by construction.
4891
+ if (provider?.shareConfig?.import === false) return;
4624
4892
  const { version } = providerEntry;
4625
4893
  if (!singleton && version !== usedShare.version) return;
4626
4894
  if (
@@ -4734,6 +5002,9 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
4734
5002
  scopeRootProvider: undefined
4735
5003
  };
4736
5004
  if (usedShare.canLiveRebind === false) return;
5005
+ if (usedShare.shareConfig?.import === false && __mfMatchesSharedProvider(provider, usedShare)) return;
5006
+ // Another container's consume-only stub has nothing to bridge to: its get() throws by construction.
5007
+ if (provider?.shareConfig?.import === false) return;
4737
5008
  // Preserve a singleton already selected by another container. The bridge may
4738
5009
  // only replace the provisional local fallback seeded by this container.
4739
5010
  if (cachedShare !== undefined && cachedShareOwner !== mfName) return;
@@ -4900,6 +5171,11 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
4900
5171
  ) || share;
4901
5172
  const providerEntry = __mfFindSharedProviderEntry(versionMap, provider);
4902
5173
  if (!providerEntry) return;
5174
+ // A provider registered on this instance through the public registerShared
5175
+ // API carries this container's own name, so tell the own stub apart by its
5176
+ // import:false config rather than by provenance.
5177
+ const __mfIsOwnStub = (candidate) => candidate === share || candidate?.shareConfig?.import === false;
5178
+ if (__mfIsOwnStub(provider)) return;
4903
5179
  const { version } = providerEntry;
4904
5180
  const currentProvider = versionMap?.[version];
4905
5181
  const loadedShare = await __mfLoadPinnedRuntimeShare(
@@ -4909,13 +5185,13 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
4909
5185
  version,
4910
5186
  currentProvider,
4911
5187
  provider,
4912
- providerEntry.registered && !__mfMatchesSharedProvider(provider, share)
5188
+ providerEntry.registered
4913
5189
  );
4914
5190
  const providerSelection = loadedShare?.selection;
4915
5191
  const actualProvider = loadedShare?.provider;
4916
5192
  const resolved = loadedShare?.resolved;
4917
5193
  if (!providerSelection) return;
4918
- if (__mfMatchesSharedProvider(actualProvider, share)) return;
5194
+ if (__mfIsOwnStub(actualProvider)) return;
4919
5195
  if (resolved === undefined) return;
4920
5196
  const latestCachedShare = share.treeShaking
4921
5197
  ? __mfReadTreeShakingSharedSelection(__mfModuleCache.share, cacheDescriptor, mfName)
@@ -4950,11 +5226,13 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
4950
5226
  }
4951
5227
  };
4952
5228
  // Resolve runtime-only dependencies and seed local fallbacks in dependency
4953
- // order. Stop at an unresolved provider so its consumers cannot capture an
4954
- // undefined or provisional singleton.
5229
+ // order. An unresolved provider blocks its consumers, which would otherwise
5230
+ // capture an undefined or provisional singleton; unrelated shares still seed.
4955
5231
  const __mfReadyDeferredSeedKeys = [];
5232
+ const __mfBlockedSeedKeys = new Set();
4956
5233
  for (const pkg of __mfDeferredSeedKeys) {
4957
5234
  const share = usedShared[pkg];
5235
+ const seedIndex = __mfSeedIndex.get(pkg);
4958
5236
  if (__mfIsRuntimeOnlySharePending(pkg)) {
4959
5237
  try {
4960
5238
  if (share.treeShaking) {
@@ -4963,18 +5241,22 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
4963
5241
  await __mfResolveImportFalseShared(pkg, share);
4964
5242
  }
4965
5243
  } catch (err) {
4966
- // A rejected provider is an unresolved provider: stop here as the comment above
4967
- // prescribes, instead of escalating to a container-wide init() failure.
5244
+ // A rejected provider is an unresolved provider: block its consumers as the
5245
+ // comment above prescribes, instead of escalating to a container-wide init() failure.
4968
5246
  console.error(
4969
5247
  \`[Module Federation] Failed to resolve runtime-only shared module "\${pkg}"\`,
4970
5248
  err
4971
5249
  );
4972
- break;
4973
5250
  }
4974
5251
  }
4975
- if (__mfIsRuntimeOnlySharePending(pkg)) break;
4976
- __mfReadyDeferredSeedKeys.push(pkg);
5252
+ if (__mfIsRuntimeOnlySharePending(pkg)) {
5253
+ __mfBlockedSeedKeys.add(seedIndex);
5254
+ }
4977
5255
  }
5256
+ __mfExpandBlockedSeedKeys(__mfBlockedSeedKeys);
5257
+ __mfReadyDeferredSeedKeys.push(...__mfDeferredSeedKeys.filter(
5258
+ (pkg) => !__mfBlockedSeedKeys.has(__mfSeedIndex.get(pkg))
5259
+ ));
4978
5260
  await __mfSeedLocalShared(__mfReadyDeferredSeedKeys);
4979
5261
  initResolve(initRes)
4980
5262
  return initRes
@@ -5056,6 +5338,16 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build", options
5056
5338
  __mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined &&
5057
5339
  __mfReadSharedCacheOwner(__mfModuleCache.share, cacheDescriptor) ${_command === "serve" ? "!== undefined" : `=== ${cacheOwner}`}
5058
5340
  ) return;
5341
+ // An import:false share has nothing to load until a foreign provider
5342
+ // registers: its own stub getter throws by construction.
5343
+ if (
5344
+ share.shareConfig?.import === false &&
5345
+ !(Array.isArray(share.scope) ? share.scope : [share.scope || 'default']).some((scopeName) =>
5346
+ Object.values(runtime.shareScopeMap?.[scopeName]?.[pkg] || {}).some(
5347
+ (provider) => provider?.shareConfig?.import !== false
5348
+ )
5349
+ )
5350
+ ) return;
5059
5351
  await runtime.loadShare(pkg, {
5060
5352
  customShareInfo: { shareConfig: share.shareConfig }
5061
5353
  }).then(async (factory) => {
@@ -5110,6 +5402,71 @@ function getHostAutoInitPath(options) {
5110
5402
  function isOwnedHostAutoInitId(id, options) {
5111
5403
  return VirtualModule.findById(id) === getHostAutoInitState(options).module;
5112
5404
  }
5405
+ /**
5406
+ * Build-time list of the loadShare wrappers this container bundles a fallback for, plus a function the host
5407
+ * bootstrap calls after the remote preloads: a share still unseeded then (behind an unresolved runtime-only
5408
+ * share in init()) has a deferred wrapper that only registers its pending load once evaluated. Importing it
5409
+ * here puts that load in front of the bootstrap's pendingShareLoads barrier instead of inside the entry's own
5410
+ * import graph, where module-scope reads would see it undefined. Kept out of hostInit so that chunk stays
5411
+ * free of wrapper references.
5412
+ */
5413
+ const PENDING_SHARES_TAG = "__P_S__";
5414
+ const legacyPendingSharesState = {
5415
+ module: new VirtualModule("pendingShares", PENDING_SHARES_TAG),
5416
+ command: "build"
5417
+ };
5418
+ const pendingSharesStates = /* @__PURE__ */ new WeakMap();
5419
+ function getPendingSharesState(options) {
5420
+ if (!options) return legacyPendingSharesState;
5421
+ let state = pendingSharesStates.get(options);
5422
+ if (!state) {
5423
+ state = {
5424
+ module: new VirtualModule("pendingShares", PENDING_SHARES_TAG, "", getLocalOwnerKey(options)),
5425
+ command: "build"
5426
+ };
5427
+ pendingSharesStates.set(options, state);
5428
+ }
5429
+ return state;
5430
+ }
5431
+ function generatePendingSharesCode(command = "build", options) {
5432
+ const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
5433
+ const pendingShareImports = command === "build" ? getMaterializedShares(options).filter((pkg) => {
5434
+ const shareItem = resolvedOptions.shared?.[pkg];
5435
+ return Boolean(shareItem) && !pkg.endsWith("/") && shareItem.shareConfig.import !== false && !shareItem.shareConfig.treeShaking;
5436
+ }).map((pkg) => `[${toSafeJsLiteral(pkg)}, () => import(${toSafeJsLiteral(getLoadShareModulePath(pkg, false, options))})]`) : [];
5437
+ return `
5438
+ ${getRuntimeModuleCacheBootstrapCode()}
5439
+ ${sharedCacheHelperCode}
5440
+ const __mfPendingShareImports = [${pendingShareImports.join(", ")}];
5441
+ export async function preloadPendingShares() {
5442
+ if (__mfPendingShareImports.length === 0) return;
5443
+ const {usedShared} = await import("${getLocalSharedImportMapPath(options)}");
5444
+ await Promise.all(__mfPendingShareImports.map(async ([pkg, load]) => {
5445
+ const share = usedShared[pkg];
5446
+ if (!share || share.materialize === false || share.treeShaking || share.shareConfig?.import === false) return;
5447
+ const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, share.shareConfig?.singleton, share.version, share.scope);
5448
+ if (__mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined) return;
5449
+ await load().catch((err) => console.warn("[module-federation] shared preload failed:", pkg, err));
5450
+ }));
5451
+ }
5452
+ `;
5453
+ }
5454
+ function writePendingShares(command = "build", options) {
5455
+ const state = getPendingSharesState(options);
5456
+ state.command = command;
5457
+ state.module.writeSync(generatePendingSharesCode(command, options), true);
5458
+ }
5459
+ function refreshPendingShares(options) {
5460
+ try {
5461
+ writePendingShares(getPendingSharesState(options).command, options);
5462
+ } catch {}
5463
+ }
5464
+ function getPendingSharesPath(options) {
5465
+ return getPendingSharesState(options).module.getImportId();
5466
+ }
5467
+ function isOwnedPendingSharesId(id, options) {
5468
+ return VirtualModule.findById(id) === getPendingSharesState(options).module;
5469
+ }
5113
5470
  //#endregion
5114
5471
  //#region src/virtualModules/virtualRemotes.ts
5115
5472
  const cacheRemoteMap = /* @__PURE__ */ new WeakMap();
@@ -5403,11 +5760,7 @@ function generateRemotes(id, command, enableSsrInit = false, consumer = "unified
5403
5760
  const remoteRegistration = getRemoteRegistration(id, resolvedOptions.remotes, options);
5404
5761
  const registerRemoteCode = isLoadedFirst && remoteRegistration ? `runtime.registerRemotes([${JSON.stringify(remoteRegistration)}]);` : "";
5405
5762
  const hostAutoInitPath = getHostAutoInitPath(options);
5406
- const ssrRemotes = Object.entries(resolvedOptions.remotes).map(([name, item]) => ({
5407
- name: getRuntimeRemoteAlias(name, options),
5408
- entry: item.entry,
5409
- type: item.type ?? "module"
5410
- }));
5763
+ const ssrRemotes = getSsrRuntimeRemotes(resolvedOptions.remotes, options);
5411
5764
  const browserHostInitCode = `import(${JSON.stringify(hostAutoInitPath)})
5412
5765
  .then((mod) => mod.hostInitPromise)
5413
5766
  .then(initResolve, initReject);`;
@@ -5633,6 +5986,7 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
5633
5986
  let htmlFilePath;
5634
5987
  let _command;
5635
5988
  let emitFileId;
5989
+ let pendingSharesEmitId;
5636
5990
  let viteConfig;
5637
5991
  let skipHtmlDevFallback = forceClientInjected ?? false;
5638
5992
  let clientInjected = false;
@@ -5776,12 +6130,15 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
5776
6130
  if (__mfReactServerModuleCache?.pendingShareLoads) {
5777
6131
  await Promise.all(__mfReactServerModuleCache.pendingShareLoads);
5778
6132
  }`;
6133
+ const pendingSharesBlock = waitsForInit && (_command === "build" || viteConfig?.command === "build") ? `
6134
+ const __mfPendingShares = await ${importExpression(options?.pendingSharesSrc ?? getPendingSharesPath(federationOptions))}.catch(() => undefined);
6135
+ if (__mfPendingShares && typeof __mfPendingShares.preloadPendingShares === "function") await __mfPendingShares.preloadPendingShares();` : "";
5779
6136
  const importCode = `
5780
6137
  (async () => {
5781
6138
  const __mfHostInit = await ${importExpression(initSrc)};
5782
6139
  await __mfHostInit.__tla;
5783
6140
  const { initHost } = __mfHostInit;
5784
- ${preloadBlock}${sharedPreloadBlock}${pendingShareLoadsAwait}
6141
+ ${preloadBlock}${pendingSharesBlock}${sharedPreloadBlock}${pendingShareLoadsAwait}
5785
6142
  })().then(() => ${entryImportExpression});
5786
6143
  `;
5787
6144
  return [
@@ -5792,8 +6149,8 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
5792
6149
  importCode
5793
6150
  ].join("\n");
5794
6151
  }
5795
- function getSystemBootstrapSource(initSrc, entrySrc) {
5796
- return getBootstrapSource(initSrc, entrySrc, true);
6152
+ function getSystemBootstrapSource(initSrc, entrySrc, pendingSharesSrc) {
6153
+ return getBootstrapSource(initSrc, entrySrc, true, { pendingSharesSrc });
5797
6154
  }
5798
6155
  function injectHtml() {
5799
6156
  return inject === "html" && (htmlFilePath || hasPackageDependency("@sveltejs/kit"));
@@ -5966,6 +6323,10 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
5966
6323
  else if (Array.isArray(inputOptions)) entryFiles = inputOptions.filter((input) => !isReactRouterClientRouteInput(String(input))).map(resolveProjectId);
5967
6324
  else if (typeof inputOptions === "object") entryFiles = Object.values(inputOptions).filter((input) => !isReactRouterClientRouteInput(String(input))).map((input) => resolveProjectId(String(input)));
5968
6325
  if (entryFiles.length > 0) htmlFilePath = getFirstHtmlEntryFile(entryFiles);
6326
+ if (config.command === "serve" && !htmlFilePath) {
6327
+ const rootIndexHtml = path$1.resolve(config.root, "index.html");
6328
+ if (fs$2.existsSync(rootIndexHtml)) htmlFilePath = rootIndexHtml;
6329
+ }
5969
6330
  if (htmlFilePath) addHtmlScriptEntries(htmlFilePath);
5970
6331
  },
5971
6332
  buildStart() {
@@ -5981,6 +6342,12 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
5981
6342
  };
5982
6343
  if (!hasHash) emitFileOptions.fileName = fileName;
5983
6344
  emitFileId = this.emitFile(emitFileOptions);
6345
+ if (waitsForInit) pendingSharesEmitId = this.emitFile({
6346
+ name: "pendingShares",
6347
+ type: "chunk",
6348
+ id: getPendingSharesPath(federationOptions),
6349
+ preserveSignature: "strict"
6350
+ });
5984
6351
  if (htmlFilePath) addHtmlScriptEntries(htmlFilePath);
5985
6352
  },
5986
6353
  generateBundle(_options, bundle) {
@@ -5995,6 +6362,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
5995
6362
  if (htmlFileNames.length === 0) return;
5996
6363
  const file = this.getFileName(emitFileId);
5997
6364
  emittedFileName = file;
6365
+ const pendingSharesFile = pendingSharesEmitId ? this.getFileName(pendingSharesEmitId) : void 0;
5998
6366
  const lastSlash = file.lastIndexOf("/");
5999
6367
  bootstrapDir = lastSlash !== -1 ? file.slice(0, lastSlash + 1) : "";
6000
6368
  const resolvePath = (builtFileName, htmlFileName) => {
@@ -6030,7 +6398,10 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
6030
6398
  rewritten = true;
6031
6399
  const strippedInit = stripBase(initPath);
6032
6400
  const strippedEntry = stripBase(entrySrc);
6033
- const bootstrapSource = getSystemBootstrapSource(bootstrapDir ? rebaseImport(strippedInit, bootstrapDir) : initPath, bootstrapDir ? rebaseImport(strippedEntry, bootstrapDir) : entrySrc);
6401
+ const rebasedInitPath = bootstrapDir ? rebaseImport(strippedInit, bootstrapDir) : initPath;
6402
+ const rebasedEntrySrc = bootstrapDir ? rebaseImport(strippedEntry, bootstrapDir) : entrySrc;
6403
+ const pendingSharesPath = pendingSharesFile ? resolvePath(pendingSharesFile, fileName) : void 0;
6404
+ const bootstrapSource = getSystemBootstrapSource(rebasedInitPath, rebasedEntrySrc, pendingSharesPath && bootstrapDir ? rebaseImport(stripBase(pendingSharesPath), bootstrapDir) : pendingSharesPath);
6034
6405
  const bootstrapHash = createHash("sha256").update(bootstrapSource).digest("hex").slice(0, 8);
6035
6406
  const bootstrapFileName = `${bootstrapDir}mf-entry-bootstrap-${bootstrapIndex++}-${bootstrapHash}.js`;
6036
6407
  const bootstrapRef = this.emitFile({
@@ -6127,7 +6498,12 @@ function checkAliasConflicts(options) {
6127
6498
  const matchesSharedKey = (aliasEntry, sharedKey) => {
6128
6499
  const findPattern = aliasEntry.find;
6129
6500
  if (typeof findPattern === "string") return findPattern === sharedKey || sharedKey.startsWith(findPattern + "/");
6130
- if (findPattern instanceof RegExp) return findPattern.test(sharedKey);
6501
+ if (findPattern instanceof RegExp) {
6502
+ findPattern.lastIndex = 0;
6503
+ const matched = findPattern.test(sharedKey);
6504
+ findPattern.lastIndex = 0;
6505
+ return matched;
6506
+ }
6131
6507
  return false;
6132
6508
  };
6133
6509
  for (const sharedKey of sharedKeys) for (const aliasEntry of userAliases) {
@@ -6318,6 +6694,21 @@ const vueAdapter = {
6318
6694
  } }
6319
6695
  };
6320
6696
  //#endregion
6697
+ //#region src/utils/devServerHost.ts
6698
+ const UNSPECIFIED_HOSTS = /* @__PURE__ */ new Set(["0.0.0.0", "::"]);
6699
+ /**
6700
+ * Hostname for client-facing HTTP/WS origins built from Vite `server.host`.
6701
+ *
6702
+ * Unspecified bind addresses (`0.0.0.0`, `::`) map to `localhost`, matching
6703
+ * Vite's own printed local URL. IPv6 addresses are wrapped in brackets so
6704
+ * `http://[::1]:5173` / `ws://[::1]:5173` parse as valid URLs.
6705
+ */
6706
+ function formatDevServerHostForOrigin(host) {
6707
+ if (typeof host !== "string" || UNSPECIFIED_HOSTS.has(host)) return "localhost";
6708
+ if (host.startsWith("[") && host.endsWith("]")) return host;
6709
+ return isIPv6(host) ? `[${host}]` : host;
6710
+ }
6711
+ //#endregion
6321
6712
  //#region src/plugins/hmr/fullReload.ts
6322
6713
  const REMOTE_HMR_ENDPOINT = "__mf_hmr";
6323
6714
  const REMOTE_HMR_EVENT = "mf:remote-update";
@@ -6343,10 +6734,10 @@ function getHmrWsPath(base, hmrPath) {
6343
6734
  }
6344
6735
  function getRemoteHmrWsUrl(server) {
6345
6736
  const hmr = server.config.server.hmr;
6346
- return `${hmr && typeof hmr === "object" && hmr.protocol ? hmr.protocol : server.config.server.https ? "wss" : "ws"}://${hmr && typeof hmr === "object" && hmr.host ? hmr.host : typeof server.config.server.host === "string" && server.config.server.host !== "0.0.0.0" ? server.config.server.host : "localhost"}:${hmr && typeof hmr === "object" && (hmr.clientPort || hmr.port) ? hmr.clientPort || hmr.port : server.config.server.port}${getHmrWsPath(server.config.base, hmr && typeof hmr === "object" ? hmr.path : "")}?token=${server.config.webSocketToken}`;
6737
+ return `${hmr && typeof hmr === "object" && hmr.protocol ? hmr.protocol : server.config.server.https ? "wss" : "ws"}://${formatDevServerHostForOrigin(hmr && typeof hmr === "object" && hmr.host ? hmr.host : server.config.server.host)}:${hmr && typeof hmr === "object" && (hmr.clientPort || hmr.port) ? hmr.clientPort || hmr.port : server.config.server.port}${getHmrWsPath(server.config.base, hmr && typeof hmr === "object" ? hmr.path : "")}?token=${server.config.webSocketToken}`;
6347
6738
  }
6348
6739
  function getLocalFallbackOrigin(server) {
6349
- return `${server.config.server.https ? "https" : "http"}://${typeof server.config.server.host === "string" && server.config.server.host !== "0.0.0.0" && server.config.server.host !== "::" ? server.config.server.host : "localhost"}:${server.config.server.port || 5173}`;
6740
+ return `${server.config.server.https ? "https" : "http"}://${formatDevServerHostForOrigin(server.config.server.host)}:${server.config.server.port || 5173}`;
6350
6741
  }
6351
6742
  function getRemoteHmrEndpoint(remoteEntry, server) {
6352
6743
  try {
@@ -6844,11 +7235,7 @@ function pluginExternalRuntimeCore() {
6844
7235
  function initVirtualModules(command, remoteEntryId, enableSsrInit = false, options) {
6845
7236
  writeLocalSharedImportMap(options);
6846
7237
  writeHostAutoInit(remoteEntryId, command, options);
6847
- writeRuntimeInitStatus(command, enableSsrInit, getHostAutoInitPath(options), options, options ? Object.entries(options.remotes).map(([name, item]) => ({
6848
- name,
6849
- entry: item.entry,
6850
- type: item.type ?? "module"
6851
- })) : void 0);
7238
+ writeRuntimeInitStatus(command, enableSsrInit, getHostAutoInitPath(options), options, options ? getSsrRuntimeRemotes(options.remotes, options) : void 0);
6852
7239
  }
6853
7240
  //#endregion
6854
7241
  //#region src/utils/cssModuleHelpers.ts
@@ -7071,15 +7458,22 @@ const REMOTE_ENTRY_SSR_ID = "virtual:mf-REMOTE_ENTRY_SSR_ID";
7071
7458
  function getRemoteEntrySSRId(options) {
7072
7459
  return `${REMOTE_ENTRY_SSR_ID}:${getVirtualModuleScopeKey(options)}`;
7073
7460
  }
7461
+ function stripSsrFilenameHashPlaceholder(filename) {
7462
+ if (!filename.includes("[hash")) return filename;
7463
+ filename = filename.replace(/(?:[._-]?\[hash(?::\d+)?\])/g, "");
7464
+ if (!/\.[^.]+$/.test(filename)) filename = `${filename}.js`;
7465
+ return filename;
7466
+ }
7074
7467
  function getSsrRemoteEntryFileName(browserFilename) {
7075
- let filename = browserFilename;
7076
- if (filename.includes("[hash")) {
7077
- filename = filename.replace(/(?:[._-]?\[hash(?::\d+)?\])/g, "");
7078
- if (!/\.[^.]+$/.test(filename)) filename = `${filename}.js`;
7079
- }
7468
+ const filename = stripSsrFilenameHashPlaceholder(browserFilename);
7080
7469
  const ext = filename.match(/\.[^.]+$/)?.[0] || ".js";
7081
7470
  return `${filename.slice(0, filename.length - ext.length)}.ssr${ext}`;
7082
7471
  }
7472
+ function getSsrExposesFileName(browserFilename) {
7473
+ const filename = stripSsrFilenameHashPlaceholder(browserFilename);
7474
+ const ext = filename.match(/\.[^.]+$/)?.[0];
7475
+ return `${ext ? filename.slice(0, filename.length - ext.length) : filename}.exposes.js`;
7476
+ }
7083
7477
  /** Singleton map for SSR loadShare: expand `pkg/` via usedShares; never serialize the prefix. */
7084
7478
  function getSsrSharedSingletons(options) {
7085
7479
  const used = getUsedShares(options);
@@ -7854,12 +8248,10 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
7854
8248
  }
7855
8249
  function collectImportSources(code) {
7856
8250
  const sources = /* @__PURE__ */ new Map();
7857
- for (const match of code.matchAll(/(?:^|[;\n\r])\s*import\s+(?:[\s\S]*?\s+from\s+)?["']([^"']+)["']|import\(\s*["']([^"']+)["']\s*\)/g)) {
7858
- const source = match[1] || match[2];
7859
- if (source) {
7860
- const dynamic = !match[1];
7861
- sources.set(source, (sources.get(source) ?? true) && dynamic);
7862
- }
8251
+ for (const { source, kind, syntax, typeOnly } of findModuleImportDescriptors(code)) {
8252
+ if (syntax !== "import" || typeOnly) continue;
8253
+ const dynamic = kind === "dynamic";
8254
+ sources.set(source, (sources.get(source) ?? true) && dynamic);
7863
8255
  }
7864
8256
  return Array.from(sources, ([source, dynamic]) => ({
7865
8257
  source,
@@ -7876,7 +8268,7 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
7876
8268
  seen.add(id);
7877
8269
  let code;
7878
8270
  try {
7879
- code = readFileSync$1(id, "utf8");
8271
+ code = getScannableModuleSource(id, readFileSync$1(id, "utf8"));
7880
8272
  } catch {
7881
8273
  return [];
7882
8274
  }
@@ -7971,7 +8363,7 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
7971
8363
  }
7972
8364
  if (isHostAutoInitId(id)) {
7973
8365
  if (_command === "serve") {
7974
- const host = typeof viteConfig.server?.host === "string" && viteConfig.server.host !== "0.0.0.0" ? viteConfig.server.host : "localhost";
8366
+ const host = formatDevServerHostForOrigin(viteConfig.server?.host);
7975
8367
  const resolvedPublicPath = resolvePublicPath(options, viteConfig.base, originalConfigBase);
7976
8368
  const devPublicPath = resolvedPublicPath === "auto" ? "/" : resolvedPublicPath;
7977
8369
  const remoteEntryFileName = resolveDevHashEntryFileName(options.filename);
@@ -8173,54 +8565,6 @@ function isBuildConfigImporter(importer) {
8173
8565
  if (!importer) return false;
8174
8566
  return /(^|\/)(?:nuxt|vite|vitest|webpack|rollup|rspack)\.config\.[cm]?[jt]sx?$/.test(importer.replace(/\\/g, "/"));
8175
8567
  }
8176
- function matchesSharedSource(source, key) {
8177
- const keyBase = key.endsWith("/") ? key.slice(0, -1) : key;
8178
- if (keyBase === "vue" && (source === "vue/dist/vue.esm-bundler.js" || source === "vue/dist/vue.runtime.esm-bundler.js")) return true;
8179
- if (key.endsWith("/")) return source === keyBase || source.startsWith(`${keyBase}/`);
8180
- if (getCommonSharedSubpaths(keyBase).includes(source)) return true;
8181
- return source === keyBase;
8182
- }
8183
- function findSharedKey(source, shared) {
8184
- return getSharedKeyMatcher(shared).find(source);
8185
- }
8186
- const emptySharedKeyMatcher = { find: () => void 0 };
8187
- const sharedKeyMatcherCache = /* @__PURE__ */ new WeakMap();
8188
- function getSharedKeyMatcher(shared) {
8189
- if (!shared) return emptySharedKeyMatcher;
8190
- const cached = sharedKeyMatcherCache.get(shared);
8191
- if (cached) return cached;
8192
- const keys = Object.keys(shared);
8193
- const exactKeys = new Set(keys);
8194
- const commonSubpathKeys = /* @__PURE__ */ new Map();
8195
- const wildcardKeys = [];
8196
- let vueKey;
8197
- for (const key of keys) {
8198
- const keyBase = key.endsWith("/") ? key.slice(0, -1) : key;
8199
- const shareItem = shared[key];
8200
- if (!vueKey && keyBase === "vue") vueKey = key;
8201
- if (key.endsWith("/")) wildcardKeys.push({
8202
- key,
8203
- base: keyBase
8204
- });
8205
- if (shareItem.shareConfig?.import !== false) {
8206
- for (const subpath of getCommonSharedSubpaths(keyBase)) if (!commonSubpathKeys.has(subpath)) commonSubpathKeys.set(subpath, key);
8207
- }
8208
- }
8209
- const sourceCache = /* @__PURE__ */ new Map();
8210
- const matcher = { find(source) {
8211
- if (sourceCache.has(source)) return sourceCache.get(source);
8212
- let result = exactKeys.has(source) ? source : void 0;
8213
- if (!result && vueKey) {
8214
- if (source === "vue/dist/vue.esm-bundler.js" || source === "vue/dist/vue.runtime.esm-bundler.js") result = vueKey;
8215
- }
8216
- if (!result) result = commonSubpathKeys.get(source);
8217
- if (!result) result = wildcardKeys.find(({ base }) => source === base || source.startsWith(`${base}/`))?.key;
8218
- sourceCache.set(source, result);
8219
- return result;
8220
- } };
8221
- sharedKeyMatcherCache.set(shared, matcher);
8222
- return matcher;
8223
- }
8224
8568
  function findSharedKeyForSource(source, shared) {
8225
8569
  const key = findSharedKey(source, shared);
8226
8570
  if (key) return key;
@@ -8266,11 +8610,267 @@ function excludeSharedSubDependencies(shared) {
8266
8610
  delete shared[depKey];
8267
8611
  sharedKeys.delete(depKey);
8268
8612
  sharedKeyByBase.delete(dep);
8269
- sharedKeyMatcherCache.delete(shared);
8613
+ invalidateSharedKeyMatcher(shared);
8270
8614
  }
8271
8615
  }
8272
8616
  }
8273
8617
  }
8618
+ const sharedDependencyCache = /* @__PURE__ */ new Map();
8619
+ const sharedPackageDirectoryCache = /* @__PURE__ */ new WeakMap();
8620
+ function getSharedPackageFromFile(importer, shared, cwd = getPackageDetectionCwd()) {
8621
+ if (!importer) return;
8622
+ const nodeModulePackage = getPackageNameFromNodeModulePath(importer);
8623
+ if (nodeModulePackage) return nodeModulePackage;
8624
+ let cached = sharedPackageDirectoryCache.get(shared);
8625
+ if (!cached || cached.cwd !== cwd) {
8626
+ const entries = /* @__PURE__ */ new Map();
8627
+ for (const key of Object.keys(shared)) {
8628
+ const packageName = getPackageName(key);
8629
+ const entry = getInstalledPackageEntry(packageName, { cwd });
8630
+ if (entry && !isNodeModulePath(entry)) entries.set(path$1.dirname(normalizePathForImport(entry)), packageName);
8631
+ }
8632
+ cached = {
8633
+ cwd,
8634
+ entries
8635
+ };
8636
+ sharedPackageDirectoryCache.set(shared, cached);
8637
+ }
8638
+ const normalizedImporter = normalizePathForImport(importer);
8639
+ return [...cached.entries].find(([dir]) => normalizedImporter === dir || normalizedImporter.startsWith(`${dir}/`))?.[1] ?? getWorkspacePackageNameFromFile(normalizedImporter);
8640
+ }
8641
+ const workspacePackageNameCache = /* @__PURE__ */ new Map();
8642
+ /** Name from the nearest `package.json` above `file`, for files outside `node_modules`. */
8643
+ function getWorkspacePackageNameFromFile(file) {
8644
+ const filePath = file.split("?")[0];
8645
+ if (!path$1.isAbsolute(filePath) || isNodeModulePath(filePath)) return;
8646
+ const visited = [];
8647
+ let dir = path$1.dirname(filePath);
8648
+ let name;
8649
+ while (true) {
8650
+ if (workspacePackageNameCache.has(dir)) {
8651
+ name = workspacePackageNameCache.get(dir);
8652
+ break;
8653
+ }
8654
+ visited.push(dir);
8655
+ const manifestPath = path$1.join(dir, "package.json");
8656
+ if (existsSync(manifestPath)) {
8657
+ try {
8658
+ const manifestName = JSON.parse(readFileSync(manifestPath, "utf-8")).name;
8659
+ if (typeof manifestName !== "string") {
8660
+ const parent = path$1.dirname(dir);
8661
+ if (parent === dir) break;
8662
+ dir = parent;
8663
+ continue;
8664
+ }
8665
+ name = manifestName;
8666
+ } catch {
8667
+ name = void 0;
8668
+ }
8669
+ break;
8670
+ }
8671
+ const parent = path$1.dirname(dir);
8672
+ if (parent === dir) break;
8673
+ dir = parent;
8674
+ }
8675
+ for (const visitedDir of visited) workspacePackageNameCache.set(visitedDir, name);
8676
+ return name;
8677
+ }
8678
+ const dependencyManifestCache = /* @__PURE__ */ new Map();
8679
+ /**
8680
+ * The manifest of `dep` as seen from `fromDir`: a plain `node_modules` walk-up first, because the
8681
+ * cycle walk below visits every package in the tree and `getInstalledPackageJson`'s resolver is
8682
+ * far too expensive for that many lookups; it stays the fallback for layouts the walk-up misses.
8683
+ */
8684
+ function getDependencyManifest(dep, fromDir) {
8685
+ const cacheKey = `${fromDir}\0${dep}`;
8686
+ if (dependencyManifestCache.has(cacheKey)) return dependencyManifestCache.get(cacheKey);
8687
+ let found;
8688
+ let currentDir = fromDir;
8689
+ while (true) {
8690
+ const packageJsonPath = path$1.join(currentDir, "node_modules", dep, "package.json");
8691
+ if (existsSync(packageJsonPath)) {
8692
+ try {
8693
+ let dir = path$1.dirname(packageJsonPath);
8694
+ try {
8695
+ dir = realpathSync(dir);
8696
+ } catch {}
8697
+ found = {
8698
+ path: packageJsonPath,
8699
+ dir,
8700
+ packageJson: JSON.parse(readFileSync(packageJsonPath, "utf-8"))
8701
+ };
8702
+ } catch {}
8703
+ break;
8704
+ }
8705
+ const parentDir = path$1.dirname(currentDir);
8706
+ if (parentDir === currentDir) break;
8707
+ currentDir = parentDir;
8708
+ }
8709
+ found ??= getInstalledPackageJson(dep, {
8710
+ cwd: fromDir,
8711
+ packageName: dep
8712
+ });
8713
+ dependencyManifestCache.set(cacheKey, found);
8714
+ return found;
8715
+ }
8716
+ /** Whether `dependency` is reachable through the shared package's manifest dependencies. */
8717
+ function isSharedPackageDependency(sharedKey, dependency) {
8718
+ const sharedPackage = getPackageName(sharedKey);
8719
+ let reachable = sharedDependencyCache.get(sharedPackage);
8720
+ if (!reachable) {
8721
+ reachable = /* @__PURE__ */ new Set();
8722
+ const visited = /* @__PURE__ */ new Set();
8723
+ const queue = [getInstalledPackageJson(sharedPackage, { packageName: sharedPackage })];
8724
+ while (queue.length) {
8725
+ const installed = queue.shift();
8726
+ if (!installed || visited.has(installed.dir)) continue;
8727
+ visited.add(installed.dir);
8728
+ const manifest = installed.packageJson;
8729
+ for (const dep of Object.keys({
8730
+ ...manifest.dependencies,
8731
+ ...manifest.peerDependencies,
8732
+ ...manifest.optionalDependencies
8733
+ })) {
8734
+ reachable.add(dep);
8735
+ queue.push(getDependencyManifest(dep, installed.dir));
8736
+ }
8737
+ }
8738
+ sharedDependencyCache.set(sharedPackage, reachable);
8739
+ }
8740
+ return reachable.has(dependency);
8741
+ }
8742
+ const sharedRuntimeDependencyCache = /* @__PURE__ */ new Map();
8743
+ const SOURCE_FILE_RE = /\.(?:[cm]?js|[cm]?ts|jsx|tsx)$/;
8744
+ const NON_RUNTIME_SOURCE_RE = /(?:\.d\.[cm]?ts|\.(?:test|spec|stories)\.[cm]?[jt]sx?)$/;
8745
+ const NON_RUNTIME_DIRS = /* @__PURE__ */ new Set([
8746
+ "node_modules",
8747
+ "__tests__",
8748
+ "dist",
8749
+ "build"
8750
+ ]);
8751
+ /** Bundled artifacts of a published package never import workspace packages; skip them instead of scanning megabytes. */
8752
+ const MAX_SCANNED_SOURCE_BYTES = 256 * 1024;
8753
+ const BARE_PACKAGE_SPECIFIER_RE = /^(?:@[^\s'"`()\/]+\/)?[^\s'"`()\/.@][^\s'"`()\/]*(?:\/[^\s'"`()]*)?$/;
8754
+ /** Module specifiers evaluated by a source file. */
8755
+ function getRuntimeModuleSpecifiers(code) {
8756
+ return findModuleImportDescriptors(code).filter(({ typeOnly }) => !typeOnly).map(({ source }) => source);
8757
+ }
8758
+ /** Bare specifiers a source file imports at runtime. */
8759
+ function getRuntimeImportSpecifiers(code) {
8760
+ return getRuntimeModuleSpecifiers(code).filter((specifier) => BARE_PACKAGE_SPECIFIER_RE.test(specifier) && !isBuiltin(specifier));
8761
+ }
8762
+ function collectAllRuntimeImports(dir, into) {
8763
+ let entries;
8764
+ try {
8765
+ entries = readdirSync(dir, { withFileTypes: true });
8766
+ } catch {
8767
+ return;
8768
+ }
8769
+ for (const entry of entries) {
8770
+ if (entry.isDirectory()) {
8771
+ if (!NON_RUNTIME_DIRS.has(entry.name)) collectAllRuntimeImports(path$1.join(dir, entry.name), into);
8772
+ continue;
8773
+ }
8774
+ if (!SOURCE_FILE_RE.test(entry.name) || NON_RUNTIME_SOURCE_RE.test(entry.name)) continue;
8775
+ const file = path$1.join(dir, entry.name);
8776
+ let code;
8777
+ try {
8778
+ if (statSync(file).size > MAX_SCANNED_SOURCE_BYTES) continue;
8779
+ code = readFileSync(file, "utf-8");
8780
+ } catch {
8781
+ continue;
8782
+ }
8783
+ for (const specifier of getRuntimeImportSpecifiers(code)) into.add(specifier);
8784
+ }
8785
+ }
8786
+ const SOURCE_EXTENSIONS = [
8787
+ "",
8788
+ ".js",
8789
+ ".mjs",
8790
+ ".cjs",
8791
+ ".ts",
8792
+ ".mts",
8793
+ ".cts",
8794
+ ".jsx",
8795
+ ".tsx"
8796
+ ];
8797
+ function resolveLocalRuntimeImport(importer, specifier) {
8798
+ if (!specifier.startsWith(".")) return;
8799
+ const resolved = path$1.resolve(path$1.dirname(importer), specifier);
8800
+ return SOURCE_EXTENSIONS.flatMap((extension) => [`${resolved}${extension}`, path$1.join(resolved, `index${extension}`)]).find((candidate) => existsSync(candidate));
8801
+ }
8802
+ function collectReachableRuntimeImports(entry, dir, into) {
8803
+ const visited = /* @__PURE__ */ new Set();
8804
+ const queue = [entry];
8805
+ let scanned = false;
8806
+ while (queue.length) {
8807
+ const file = queue.shift();
8808
+ const relative = path$1.relative(dir, file);
8809
+ if (relative.startsWith("..") || path$1.isAbsolute(relative) || visited.has(file)) continue;
8810
+ visited.add(file);
8811
+ let code;
8812
+ try {
8813
+ if (statSync(file).size > MAX_SCANNED_SOURCE_BYTES) continue;
8814
+ code = readFileSync(file, "utf-8");
8815
+ scanned = true;
8816
+ } catch {
8817
+ continue;
8818
+ }
8819
+ for (const specifier of getRuntimeModuleSpecifiers(code)) {
8820
+ if (BARE_PACKAGE_SPECIFIER_RE.test(specifier) && !isBuiltin(specifier)) {
8821
+ into.add(specifier);
8822
+ continue;
8823
+ }
8824
+ const local = resolveLocalRuntimeImport(file, specifier);
8825
+ if (local) queue.push(local);
8826
+ }
8827
+ }
8828
+ return scanned;
8829
+ }
8830
+ /**
8831
+ * Whether `dependency` is reachable from the shared package through the imports its source files
8832
+ * (and those of the workspace packages they pull in) actually evaluate. Unlike the manifest walk
8833
+ * above this ignores `import type` edges and stops at `node_modules` boundaries, so it approximates
8834
+ * the fallback's evaluation graph rather than the package's declared closure — in a monorepo the
8835
+ * latter covers far more than the module graph ever does.
8836
+ */
8837
+ function isSharedPackageRuntimeDependency(sharedKey, dependency) {
8838
+ const sharedPackage = getPackageName(sharedKey);
8839
+ let reachable = sharedRuntimeDependencyCache.get(sharedKey);
8840
+ if (!reachable) {
8841
+ reachable = /* @__PURE__ */ new Set();
8842
+ const visited = /* @__PURE__ */ new Set();
8843
+ const queue = [{
8844
+ request: sharedKey,
8845
+ installed: getInstalledPackageJson(sharedPackage, { packageName: sharedPackage })
8846
+ }];
8847
+ while (queue.length) {
8848
+ const { request, installed } = queue.shift();
8849
+ if (!installed) continue;
8850
+ const visitKey = `${installed.dir}\0${request}`;
8851
+ if (visited.has(visitKey)) continue;
8852
+ visited.add(visitKey);
8853
+ const specifiers = /* @__PURE__ */ new Set();
8854
+ const entry = getInstalledPackageEntry(request, {
8855
+ cwd: installed.dir,
8856
+ packageName: getPackageName(request)
8857
+ });
8858
+ if (!entry || !collectReachableRuntimeImports(entry, installed.dir, specifiers)) collectAllRuntimeImports(installed.dir, specifiers);
8859
+ for (const specifier of specifiers) {
8860
+ const dep = getPackageName(specifier);
8861
+ if (dep === sharedPackage) continue;
8862
+ reachable.add(dep);
8863
+ const manifest = getDependencyManifest(dep, installed.dir);
8864
+ if (manifest && !isNodeModulePath(manifest.dir)) queue.push({
8865
+ request: specifier,
8866
+ installed: manifest
8867
+ });
8868
+ }
8869
+ }
8870
+ sharedRuntimeDependencyCache.set(sharedKey, reachable);
8871
+ }
8872
+ return reachable.has(dependency);
8873
+ }
8274
8874
  function proxySharedModule(options) {
8275
8875
  const { shared = {}, federationOptions, getParsePromise = () => Promise.resolve() } = options;
8276
8876
  let _config;
@@ -8352,6 +8952,10 @@ function proxySharedModule(options) {
8352
8952
  setTreeShakingBuildMode(command === "build", federationOptions);
8353
8953
  resetTreeShakingExports(federationOptions);
8354
8954
  emittedTreeShakingProviders.clear();
8955
+ sharedDependencyCache.clear();
8956
+ dependencyManifestCache.clear();
8957
+ sharedRuntimeDependencyCache.clear();
8958
+ workspacePackageNameCache.clear();
8355
8959
  const isVinext = hasPackageDependency("vinext");
8356
8960
  const isAstro = hasPackageDependency("astro");
8357
8961
  const isRolldown = getIsRolldown(this);
@@ -8440,6 +9044,11 @@ function proxySharedModule(options) {
8440
9044
  }
8441
9045
  const key = findSharedKeyForSource(source, shared);
8442
9046
  if (!key) return;
9047
+ const importerPackage = getSharedPackageFromFile(importer, shared);
9048
+ if (importerPackage === getPackageName(key)) return;
9049
+ if (importerPackage) {
9050
+ if (!isNodeModulePath(importer) && !Object.keys(shared).some((sharedKey) => getPackageName(sharedKey) === importerPackage) ? isSharedPackageRuntimeDependency(key, importerPackage) : isSharedPackageDependency(key, importerPackage)) return;
9051
+ }
8443
9052
  if (useDirectReactImport && key === "react") return;
8444
9053
  if (isAssetLikeImport(source)) return;
8445
9054
  if (isBuildConfigImporter(importer)) return;
@@ -8905,6 +9514,7 @@ function pluginSSRRemoteEntry(options) {
8905
9514
  const virtualExposesSSRId = getVirtualExposesSSRId(options);
8906
9515
  let cachedSsrRemoteEntrySource;
8907
9516
  const ssrOutputFilename = getSsrRemoteEntryFileName(options.filename);
9517
+ const ssrExposesFileName = getSsrExposesFileName(options.filename);
8908
9518
  let ssrOutputFiles = /* @__PURE__ */ new Set();
8909
9519
  let ssrOutputDir = "";
8910
9520
  let clientOutputDir = "";
@@ -9032,13 +9642,13 @@ function pluginSSRRemoteEntry(options) {
9032
9642
  });
9033
9643
  const ssrPath = `${base}/${ssrEntryFileName}`;
9034
9644
  server.middlewares.use(ssrPath, (_req, res) => {
9035
- const exposesUrl = `${base}/${options.filename.replace(/\.[^.]+$/, "")}.exposes.js`;
9645
+ const exposesUrl = `${base}/${ssrExposesFileName}`;
9036
9646
  const code = getSsrRemoteEntrySource().replace(JSON.stringify(virtualExposesSSRId), JSON.stringify(exposesUrl));
9037
9647
  res.setHeader("Content-Type", "application/javascript");
9038
9648
  res.setHeader("Access-Control-Allow-Origin", "*");
9039
9649
  res.end(code);
9040
9650
  });
9041
- const exposesPath = `${base}/${options.filename.replace(/\.[^.]+$/, "")}.exposes.js`;
9651
+ const exposesPath = `${base}/${ssrExposesFileName}`;
9042
9652
  server.middlewares.use(exposesPath, (_req, res) => {
9043
9653
  res.setHeader("Content-Type", "application/javascript");
9044
9654
  res.setHeader("Access-Control-Allow-Origin", "*");
@@ -9049,7 +9659,7 @@ function pluginSSRRemoteEntry(options) {
9049
9659
  if (id === remoteEntrySSRId || id.startsWith(remoteEntrySSRId)) return id;
9050
9660
  if (id === virtualExposesSSRId || id.startsWith(virtualExposesSSRId)) return id;
9051
9661
  if (id === `/__mf_ssr__/${getSsrRemoteEntryFileName(options.filename)}`) return remoteEntrySSRId;
9052
- if (id === `/__mf_ssr__/${options.filename.replace(/\.[^.]+$/, "")}.exposes.js`) return virtualExposesSSRId;
9662
+ if (id === `/__mf_ssr__/${ssrExposesFileName}`) return virtualExposesSSRId;
9053
9663
  },
9054
9664
  load(id) {
9055
9665
  if (id === remoteEntrySSRId || id.startsWith(remoteEntrySSRId)) return getSsrRemoteEntrySource();
@@ -9583,6 +10193,22 @@ function isFile(candidate) {
9583
10193
  function isReactRouterBuildClientRouteInput(entry) {
9584
10194
  return /[?&]__react-router-build-client-route(?:[=&]|$)/.test(entry);
9585
10195
  }
10196
+ /**
10197
+ * Files whose JSX the compiler rewrites to an automatic-runtime import.
10198
+ * Vite only applies the JSX transform to these extensions by default.
10199
+ */
10200
+ const JSX_SOURCE_EXTENSIONS = [".jsx", ".tsx"];
10201
+ function getAutomaticJsxRuntime(config) {
10202
+ for (const candidate of [config.oxc, config.esbuild]) {
10203
+ if (!candidate || typeof candidate !== "object") continue;
10204
+ const transform = candidate;
10205
+ const jsx = transform.jsx;
10206
+ const runtime = typeof jsx === "object" ? jsx.runtime : jsx;
10207
+ if (runtime && runtime !== "automatic") return void 0;
10208
+ if (runtime !== "automatic") continue;
10209
+ return `${(typeof jsx === "object" ? jsx.importSource : void 0) ?? transform.jsxImportSource ?? "react"}/${(typeof jsx === "object" ? jsx.development : void 0) ?? transform.jsxDev ?? true ? "jsx-dev-runtime" : "jsx-runtime"}`;
10210
+ }
10211
+ }
9586
10212
  function registerEntryImports(options, projectRoot, recordShared = true, entryFiles = []) {
9587
10213
  const sourceExtensions = [
9588
10214
  ".mjs",
@@ -9597,6 +10223,7 @@ function registerEntryImports(options, projectRoot, recordShared = true, entryFi
9597
10223
  const root = path$1.resolve(projectRoot);
9598
10224
  const pending = [];
9599
10225
  const visited = /* @__PURE__ */ new Map();
10226
+ let hasJsxSource = false;
9600
10227
  const enqueue = (request, importer = path$1.join(root, "index.html"), preloadRemotes = false) => {
9601
10228
  const cleanRequest = request.replace(/[?#].*$/, "");
9602
10229
  if (!cleanRequest.startsWith(".") && !cleanRequest.startsWith("/") && !path$1.isAbsolute(cleanRequest)) return;
@@ -9628,7 +10255,8 @@ function registerEntryImports(options, projectRoot, recordShared = true, entryFi
9628
10255
  const { file, preloadRemotes } = pending.pop();
9629
10256
  if (visited.get(file) || visited.has(file) && !preloadRemotes) continue;
9630
10257
  visited.set(file, preloadRemotes);
9631
- const code = readFileSync(file, "utf8");
10258
+ const code = getScannableModuleSource(file, readFileSync(file, "utf8"));
10259
+ if (JSX_SOURCE_EXTENSIONS.some((extension) => file.endsWith(extension))) hasJsxSource = true;
9632
10260
  for (const { source: request, kind, typeOnly } of findModuleImportDescriptors(code)) {
9633
10261
  const isStatic = kind === "static" && !typeOnly;
9634
10262
  const remoteKey = preloadRemotes && isStatic && request ? Object.keys(options.remotes).find((name) => request === name || request.startsWith(`${name}/`)) : void 0;
@@ -9641,6 +10269,14 @@ function registerEntryImports(options, projectRoot, recordShared = true, entryFi
9641
10269
  else if (request && !typeOnly) enqueue(request, file, preloadRemotes && isStatic);
9642
10270
  }
9643
10271
  }
10272
+ return hasJsxSource;
10273
+ }
10274
+ function materializeAutomaticJsxRuntime(options, runtime) {
10275
+ if (!findSharedKey(runtime, options.shared)) return false;
10276
+ addUsedShares(runtime, options);
10277
+ const packageName = getPackageName(runtime);
10278
+ if (packageName !== runtime && findSharedKey(packageName, options.shared)) addUsedShares(packageName, options);
10279
+ return true;
9644
10280
  }
9645
10281
  /**
9646
10282
  * Plugin that runs FIRST to register generated virtual modules in the config hook.
@@ -9650,6 +10286,7 @@ function registerEntryImports(options, projectRoot, recordShared = true, entryFi
9650
10286
  function createEarlyVirtualModulesPlugin(options) {
9651
10287
  const { shared, remotes } = options;
9652
10288
  const isLitShare = (pkg) => pkg === "lit" || pkg.startsWith("lit/");
10289
+ let hasClientJsxSource = false;
9653
10290
  return {
9654
10291
  name: "vite:module-federation-early-init",
9655
10292
  enforce: "pre",
@@ -9672,7 +10309,10 @@ function createEarlyVirtualModulesPlugin(options) {
9672
10309
  config.optimizeDeps.exclude.push(...Object.keys(remotes || {}));
9673
10310
  }
9674
10311
  }
9675
- if (!config.build?.ssr && (Object.keys(shared ?? {}).length > 0 || Object.keys(remotes ?? {}).length > 0)) registerEntryImports(options, root, _command === "serve", resolvedConfiguredEntryFiles);
10312
+ if (!config.build?.ssr && (Object.keys(shared ?? {}).length > 0 || Object.keys(remotes ?? {}).length > 0)) {
10313
+ const hasJsxSource = registerEntryImports(options, root, _command === "serve", resolvedConfiguredEntryFiles);
10314
+ if (_command === "serve") hasClientJsxSource = hasJsxSource;
10315
+ }
9676
10316
  if (shared && Object.keys(shared).length > 0) {
9677
10317
  if (_command === "serve") {
9678
10318
  excludeSharedSubDependencies(shared);
@@ -9700,6 +10340,8 @@ function createEarlyVirtualModulesPlugin(options) {
9700
10340
  if (isSharedResolverInternalImporter(importer)) return;
9701
10341
  const key = findSharedKey(source, shared);
9702
10342
  if (!key) return;
10343
+ const importerPackage = getSharedPackageFromFile(importer, shared, root);
10344
+ if (!isReactDomSelfReference(source, importer) && (importerPackage === getPackageName(key) || importerPackage && isSharedPackageDependency(key, importerPackage))) return;
9703
10345
  if (isAssetLikeImport(source)) return;
9704
10346
  const shareItem = shared[key];
9705
10347
  const isReactSingleton = source === "react" && key === "react" && shareItem.shareConfig?.singleton === true;
@@ -9738,7 +10380,9 @@ function createEarlyVirtualModulesPlugin(options) {
9738
10380
  if (isSharedResolverInternalImporter(args.importer)) return;
9739
10381
  const key = findSharedKey(args.path, shared);
9740
10382
  if (!key || isAssetLikeImport(args.path)) return;
9741
- if (getPackageNameFromNodeModulePath(args.importer) === getPackageName(args.path) && !isReactDomSelfReference(args.path, args.importer)) return;
10383
+ const importerPackage = getSharedPackageFromFile(args.importer, shared, root);
10384
+ if (importerPackage === getPackageName(args.path) && !isReactDomSelfReference(args.path, args.importer)) return;
10385
+ if (importerPackage && isSharedPackageDependency(key, importerPackage)) return;
9742
10386
  addUsedShares(args.path, options);
9743
10387
  if (args.kind === "import-statement" || args.kind === "dynamic-import") {
9744
10388
  const shareItem = shared[key];
@@ -9838,6 +10482,10 @@ export default __mfShared.default ?? __mfShared;`
9838
10482
  }
9839
10483
  },
9840
10484
  configResolved(config) {
10485
+ if (hasClientJsxSource) {
10486
+ const automaticJsxRuntime = getAutomaticJsxRuntime(config);
10487
+ if (automaticJsxRuntime && materializeAutomaticJsxRuntime(options, automaticJsxRuntime)) writeLocalSharedImportMap(options);
10488
+ }
9841
10489
  const viteMajor = parseInt(version, 10);
9842
10490
  const hasRemotes = Object.keys(options.remotes).length > 0;
9843
10491
  if (!getSsrCapabilities(viteMajor, config.command, hasRemotes).injectSsrEntryLoader) return;
@@ -9883,7 +10531,7 @@ function applyBuildTimeRuntimeDefines(define, options, { target, isAstro, defaul
9883
10531
  }
9884
10532
  function loadPluginDts(options) {
9885
10533
  if (options.dts === false) return [];
9886
- return [import("./pluginDts-sJeW2nss.js").then(({ default: pluginDts }) => pluginDts(options))];
10534
+ return [import("./pluginDts-BhONN9dR.js").then(({ default: pluginDts }) => pluginDts(options))];
9887
10535
  }
9888
10536
  const INJECT_EXTERNAL_RUNTIME_CORE_PLUGIN = "@module-federation/vite/injectExternalRuntimeCorePlugin";
9889
10537
  function isInjectExternalRuntimeCorePlugin(specifier) {
@@ -9924,7 +10572,7 @@ function federation(mfUserOptions) {
9924
10572
  const virtualExposesId = getVirtualExposesId(options);
9925
10573
  const moduleParseController = createModuleParseController();
9926
10574
  const moduleParsePlugins = pluginModuleParseEnd_default((id) => {
9927
- return id.includes(getHostAutoInitPath(options)) || id.includes(remoteEntryId) || id.includes(virtualExposesId) || id.includes("virtual:mf-localSharedImportMap") || id.includes("__loadShare__") || id.includes("__prebuild__") || id.includes("__treeShakingProvider__") || id.includes("__mf_tree_shaking_graph__");
10575
+ return id.includes(getHostAutoInitPath(options)) || id.includes(getPendingSharesPath(options)) || id.includes(remoteEntryId) || id.includes(virtualExposesId) || id.includes("virtual:mf-localSharedImportMap") || id.includes("__loadShare__") || id.includes("__prebuild__") || id.includes("__treeShakingProvider__") || id.includes("__mf_tree_shaking_graph__");
9928
10576
  }, {
9929
10577
  moduleParseTimeout: options.moduleParseTimeout,
9930
10578
  moduleParseIdleTimeout: options.moduleParseIdleTimeout,
@@ -10026,6 +10674,7 @@ function federation(mfUserOptions) {
10026
10674
  }
10027
10675
  if (id.includes("__prebuild__") && refreshPreBuildModuleForEnvironment(id, this, loadOptions) === "not-owned") return;
10028
10676
  if (id.includes("__H_A_I__") && isOwnedHostAutoInitId(id, options)) refreshHostAutoInit(options, getLoadHookExportConditions(this, loadOptions));
10677
+ if (id.includes("__P_S__") && isOwnedPendingSharesId(id, options)) refreshPendingShares(options);
10029
10678
  const virtualModule = VirtualModule.findById(id);
10030
10679
  if (!virtualModule) return;
10031
10680
  if (command === "build" && (id.includes("__loadShare__") || id.includes("__loadRemote__"))) return;