@module-federation/vite 1.20.7 → 1.20.9

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
@@ -13,6 +13,217 @@ 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
+ //#region src/utils/bundleHelpers.ts
17
+ function isOutputChunk$1(chunk) {
18
+ return chunk.type === "chunk";
19
+ }
20
+ function escapeRegExp$2(value) {
21
+ return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
22
+ }
23
+ /**
24
+ * Whether `code` references `name` as a whole identifier.
25
+ *
26
+ * Not `\b`: a word boundary needs a `\w` on one side, and `$` is not one, so
27
+ * `\b$8\b` matches nothing at all. Minifiers assign `$`-prefixed names to any
28
+ * chunk with more than ~54 module-scope bindings, and a missed match here reads
29
+ * as "unused", which orphans a still-referenced import.
30
+ */
31
+ function isIdentifierReferenced(name, code) {
32
+ return new RegExp(`(?<![$\\w])${escapeRegExp$2(name)}(?![$\\w])`).test(code);
33
+ }
34
+ function getProxyBaseName(fileName) {
35
+ return fileName.replace(/^.*\//, "").replace(/\.js$/, "").replace(/-[A-Za-z0-9_-]+$/, "");
36
+ }
37
+ /**
38
+ * Matches `function <name>(`. Escaped because an unescaped leading `$` is a
39
+ * regex end-anchor, so the pattern would silently match nothing.
40
+ */
41
+ function functionDeclarationRegExp(name) {
42
+ return new RegExp(`function\\s+${escapeRegExp$2(name)}\\s*\\(`);
43
+ }
44
+ function extractFunctionDeclaration(code, functionName) {
45
+ const funcRe = new RegExp(`function\\s+${escapeRegExp$2(functionName)}\\s*\\([^)]*\\)\\s*\\{`);
46
+ const funcStart = code.search(funcRe);
47
+ if (funcStart < 0) return;
48
+ let depth = 0;
49
+ for (let i = code.indexOf("{", funcStart); i < code.length; i++) if (code[i] === "{") depth++;
50
+ else if (code[i] === "}") {
51
+ depth--;
52
+ if (depth === 0) return code.slice(funcStart, i + 1);
53
+ }
54
+ }
55
+ /**
56
+ * Resolve the local alias for a non-inlineable proxy binding.
57
+ * If Rollup's deconflict renamed the alias but didn't update references
58
+ * in the code body, fall back to proxyLocal so they stay in sync.
59
+ */
60
+ function resolveProxyAlias(binding, proxyLocal, code, fullImport, claimedLocals = /* @__PURE__ */ new Set()) {
61
+ const codeWithoutImport = code.replace(fullImport, "");
62
+ const localUsedInCode = isIdentifierReferenced(binding.local, codeWithoutImport);
63
+ const claimedImportLocals = /* @__PURE__ */ new Set();
64
+ const importRe = /import\s*\{([^}]+)\}\s*from\s*["'][^"']+["']\s*;?/g;
65
+ let match;
66
+ while ((match = importRe.exec(codeWithoutImport)) !== null) for (const spec of match[1].split(",")) {
67
+ const parts = spec.trim().split(/\s+as\s+/);
68
+ claimedImportLocals.add((parts[1] || parts[0]).trim());
69
+ }
70
+ const local = !localUsedInCode && !claimedLocals.has(proxyLocal) && !claimedImportLocals.has(proxyLocal) ? proxyLocal : binding.local;
71
+ return {
72
+ imported: binding.imported,
73
+ local
74
+ };
75
+ }
76
+ function collectLoadShareProxyChunks(bundle, loadShareTag) {
77
+ const proxyChunks = /* @__PURE__ */ new Map();
78
+ for (const [fileName, chunk] of Object.entries(bundle)) {
79
+ if (!isOutputChunk$1(chunk)) continue;
80
+ if (fileName.includes(loadShareTag) && fileName.includes("commonjs-proxy")) proxyChunks.set(fileName, {
81
+ code: chunk.code,
82
+ fileName
83
+ });
84
+ }
85
+ return proxyChunks;
86
+ }
87
+ function collectSystemProxyInfos(proxyChunks, loadShareTag) {
88
+ const systemProxyInfo = /* @__PURE__ */ new Map();
89
+ for (const [proxyFileName, proxyInfo] of Array.from(proxyChunks.entries())) {
90
+ const depsMatch = proxyInfo.code.match(/System\.register\(\[([\s\S]*?)\]/);
91
+ if (!depsMatch) continue;
92
+ const loadShareDep = Array.from(depsMatch[1].matchAll(/["']([^"']+)["']/g)).map((m) => m[1]).find((dep) => dep.includes(loadShareTag) && !dep.includes("commonjs-proxy"));
93
+ if (!loadShareDep) continue;
94
+ const loadShareBindings = {};
95
+ for (const m of proxyInfo.code.matchAll(/([A-Za-z_$][\w$]*)\s*=\s*module\d+\.([A-Za-z_$][\w$]*)/g)) loadShareBindings[m[1]] = m[2];
96
+ const exportMap = {};
97
+ const objectExportMatch = proxyInfo.code.match(/exports\(\s*\{([\s\S]*?)\}\s*\)/);
98
+ if (objectExportMatch) for (const m of objectExportMatch[1].matchAll(/([A-Za-z_$][\w$]*)\s*:\s*([A-Za-z_$][\w$]*)/g)) {
99
+ const [, exported, local] = m;
100
+ const funcBody = extractFunctionDeclaration(proxyInfo.code, local);
101
+ if (funcBody) exportMap[exported] = {
102
+ type: "helper",
103
+ code: funcBody
104
+ };
105
+ }
106
+ for (const m of proxyInfo.code.matchAll(/exports\(\s*["']([^"']+)["']\s*,([\s\S]*?)\);/g)) {
107
+ const exported = m[1];
108
+ const expression = m[2];
109
+ for (const [local, exportName] of Object.entries(loadShareBindings).reverse()) if (isIdentifierReferenced(local, expression)) {
110
+ exportMap[exported] = {
111
+ type: "reexport",
112
+ exportName
113
+ };
114
+ break;
115
+ }
116
+ }
117
+ if (Object.keys(exportMap).length > 0) systemProxyInfo.set(proxyFileName, {
118
+ loadShareDep,
119
+ exportMap
120
+ });
121
+ }
122
+ return systemProxyInfo;
123
+ }
124
+ function rewriteEsmProxyConsumers(code, proxyChunks) {
125
+ let nextCode = code;
126
+ const claimedLocals = /* @__PURE__ */ new Set();
127
+ for (const [proxyFileName, proxyInfo] of Array.from(proxyChunks.entries())) {
128
+ const proxyBaseName = getProxyBaseName(proxyFileName);
129
+ const importMatch = new RegExp(`import\\s*\\{([^}]+)\\}\\s*from\\s*["']([^"']*${escapeRegExp$2(proxyBaseName)}[^"']*)["']\\s*;?`).exec(nextCode);
130
+ if (!importMatch) continue;
131
+ const fullImport = importMatch[0];
132
+ const bindings = importMatch[1].split(",").map((s) => {
133
+ const parts = s.trim().split(/\s+as\s+/);
134
+ return {
135
+ imported: parts[0].trim(),
136
+ local: (parts[1] || parts[0]).trim()
137
+ };
138
+ });
139
+ const exportMapMatch = proxyInfo.code.match(/export\s*\{([^}]+)\}/);
140
+ if (!exportMapMatch) continue;
141
+ const exportMap = {};
142
+ for (const entry of exportMapMatch[1].split(",")) {
143
+ const parts = entry.trim().split(/\s+as\s+/);
144
+ if (parts.length === 2) exportMap[parts[1].trim()] = parts[0].trim();
145
+ }
146
+ const inlineable = [];
147
+ const nonInlineable = [];
148
+ const pendingLocals = new Set(bindings.map((binding) => binding.local));
149
+ for (const b of bindings) {
150
+ pendingLocals.delete(b.local);
151
+ const proxyLocal = exportMap[b.imported];
152
+ if (!proxyLocal) {
153
+ claimedLocals.add(b.local);
154
+ nonInlineable.push(b);
155
+ continue;
156
+ }
157
+ const funcBody = extractFunctionDeclaration(proxyInfo.code, proxyLocal);
158
+ if (funcBody) {
159
+ inlineable.push({
160
+ local: b.local,
161
+ funcBody: funcBody.replace(functionDeclarationRegExp(proxyLocal), () => `function ${b.local}(`)
162
+ });
163
+ claimedLocals.add(b.local);
164
+ } else {
165
+ const unavailableLocals = new Set(claimedLocals);
166
+ pendingLocals.forEach((local) => unavailableLocals.add(local));
167
+ const resolvedBinding = resolveProxyAlias(b, proxyLocal, nextCode, fullImport, unavailableLocals);
168
+ claimedLocals.add(resolvedBinding.local);
169
+ nonInlineable.push(resolvedBinding);
170
+ }
171
+ }
172
+ const hasRenamedAlias = nonInlineable.some((b) => bindings.find((ob) => ob.imported === b.imported)?.local !== b.local);
173
+ if (inlineable.length === 0 && !hasRenamedAlias) continue;
174
+ let replacement = "";
175
+ if (nonInlineable.length > 0) replacement = `import{${nonInlineable.map((b) => b.imported === b.local ? b.imported : `${b.imported} as ${b.local}`).join(",")}}from"${importMatch[2]}";`;
176
+ replacement += inlineable.map((f) => f.funcBody).join("");
177
+ nextCode = nextCode.replace(fullImport, () => replacement);
178
+ }
179
+ return nextCode;
180
+ }
181
+ function rewriteSystemProxyConsumers(code, systemProxyInfo) {
182
+ if (!code.includes("System.register(")) return code;
183
+ let nextCode = code;
184
+ for (const [proxyFileName, proxyInfo] of Array.from(systemProxyInfo.entries())) {
185
+ const proxyBaseName = getProxyBaseName(proxyFileName);
186
+ const depMatch = new RegExp(`["']([^"']*${escapeRegExp$2(proxyBaseName)}[^"']*)["']`).exec(nextCode);
187
+ if (!depMatch) continue;
188
+ let setterIndex = 0;
189
+ const depListMatch = nextCode.match(/System\.register\(\[([\s\S]*?)\]/);
190
+ if (depListMatch) setterIndex = Array.from(depListMatch[1].matchAll(/["']([^"']+)["']/g)).map((m) => m[1]).findIndex((dep) => dep.includes(proxyBaseName));
191
+ if (setterIndex < 0) continue;
192
+ const settersStart = nextCode.indexOf("setters: [");
193
+ if (settersStart < 0) continue;
194
+ const setterMatch = Array.from(nextCode.slice(settersStart).matchAll(/\((module\d+)\)\s*=>\s*\{([\s\S]*?)\}/g))[setterIndex];
195
+ if (!setterMatch) continue;
196
+ const [fullSetter, moduleLocal, setterBody] = setterMatch;
197
+ const helpersToInline = [];
198
+ const nextSetterBody = setterBody.replace(new RegExp(`([A-Za-z_$][\\w$]*)\\s*=\\s*${moduleLocal}\\.([A-Za-z_$][\\w$]*);?`, "g"), (assignment, local, imported) => {
199
+ const mapped = proxyInfo.exportMap[imported];
200
+ if (!mapped) return assignment;
201
+ if (mapped.type === "helper") {
202
+ helpersToInline.push(mapped.code.replace(functionDeclarationRegExp(imported), () => `function ${local}(`));
203
+ return "";
204
+ }
205
+ return `${local} = ${moduleLocal}.${mapped.exportName};`;
206
+ });
207
+ if (nextSetterBody === setterBody && helpersToInline.length === 0) continue;
208
+ const nextSetter = fullSetter.replace(setterBody, () => nextSetterBody);
209
+ nextCode = nextCode.replace(fullSetter, () => nextSetter);
210
+ nextCode = nextCode.replace(depMatch[0], JSON.stringify(proxyInfo.loadShareDep));
211
+ if (helpersToInline.length > 0) nextCode = nextCode.replace("execute: (function() {", () => {
212
+ return `execute: (function() {${helpersToInline.join("")}`;
213
+ });
214
+ }
215
+ return nextCode;
216
+ }
217
+ function findRemoteEntryFile(filename, bundle) {
218
+ const strippedName = filename.replace(/[\[\]]/g, "_").replace(/\.[^/.]+$/, "");
219
+ let fallback;
220
+ for (const fileData of Object.values(bundle)) {
221
+ if (fileData.fileName === filename) return fileData.fileName;
222
+ if (fallback === void 0 && (strippedName === fileData.name || fileData.name === "remoteEntry")) fallback = fileData.fileName;
223
+ }
224
+ return fallback;
225
+ }
226
+ //#endregion
16
227
  //#region src/utils/codeRewriter.ts
17
228
  const BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
18
229
  var CodeRewriter = class {
@@ -291,15 +502,66 @@ function createCodePositionMap(code) {
291
502
  }
292
503
  //#endregion
293
504
  //#region src/utils/htmlEntryUtils.ts
294
- function findModuleImportSources(code) {
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;
510
+ const specifiers = namedSpecifiers.split(",").map((specifier) => specifier.trim()).filter(Boolean);
511
+ return specifiers.length > 0 && specifiers.every((specifier) => /^type\s+\S/.test(specifier));
512
+ }
513
+ /**
514
+ * Finds module imports while ignoring comments, strings, and regular expressions.
515
+ * The descriptor keeps enough information for callers to distinguish runtime
516
+ * static imports from type-only imports without introducing a parser dependency.
517
+ */
518
+ function findModuleImportDescriptors(code) {
295
519
  const codePositions = createCodePositionMap(code);
296
- const sources = /* @__PURE__ */ new Set();
297
- for (const pattern of [
298
- /\b(?:import|export)\s+[^;]*?\bfrom\s*["']([^"']+)["']/g,
299
- /\bimport\s*\(\s*["']([^"']+)["']/g,
300
- /\bimport\s*["']([^"']+)["']/g
301
- ]) for (const match of code.matchAll(pattern)) if (codePositions[match.index]) sources.add(match[1]);
302
- return Array.from(sources);
520
+ 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
+ for (const match of code.matchAll(staticFromPattern)) {
526
+ if (!codePositions[match.index]) continue;
527
+ descriptors.push({
528
+ kind: "static",
529
+ syntax: "import",
530
+ source: match[3],
531
+ typeOnly: isTypeOnlyClause(match[1])
532
+ });
533
+ }
534
+ for (const match of code.matchAll(dynamicPattern)) {
535
+ if (!codePositions[match.index]) continue;
536
+ descriptors.push({
537
+ kind: "dynamic",
538
+ syntax: "import",
539
+ source: match[2],
540
+ typeOnly: false
541
+ });
542
+ }
543
+ for (const match of code.matchAll(requirePattern)) {
544
+ if (!codePositions[match.index]) continue;
545
+ descriptors.push({
546
+ kind: "dynamic",
547
+ syntax: "require",
548
+ source: match[2],
549
+ typeOnly: false
550
+ });
551
+ }
552
+ for (const match of code.matchAll(sideEffectPattern)) {
553
+ if (!codePositions[match.index]) continue;
554
+ descriptors.push({
555
+ kind: "static",
556
+ syntax: "import",
557
+ source: match[2],
558
+ typeOnly: false
559
+ });
560
+ }
561
+ return descriptors;
562
+ }
563
+ function findModuleImportSources(code) {
564
+ return Array.from(new Set(findModuleImportDescriptors(code).filter(({ syntax, typeOnly }) => syntax === "import" && !typeOnly).map(({ source }) => source)));
303
565
  }
304
566
  function sanitizeDevEntryPath(devEntryPath) {
305
567
  return devEntryPath.replace(/\\\\?/g, "/");
@@ -440,6 +702,7 @@ function normalizeShareItem(key, shareItem) {
440
702
  eager: shareItem.eager || false,
441
703
  requiredVersion: shareItem.requiredVersion !== void 0 ? shareItem.requiredVersion : isImportFalse || shareItem.version ? "*" : version ? `^${version}` : "*",
442
704
  strictVersion: !!shareItem.strictVersion,
705
+ ...shareItem.suppressMissingImportWarning ? { suppressMissingImportWarning: true } : {},
443
706
  ...treeShaking ? { treeShaking: { ...treeShaking } } : {}
444
707
  }
445
708
  };
@@ -584,11 +847,11 @@ const idCacheMap = {};
584
847
  const VITE_ID_PREFIX = "/@id/";
585
848
  const VITE_ENCODED_NULL_BYTE_PREFIX = `${VITE_ID_PREFIX}__x00__`;
586
849
  const MF_OWNER_INFIX = "__mf_owner__";
587
- function escapeRegExp$2(value) {
850
+ function escapeRegExp$1(value) {
588
851
  return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
589
852
  }
590
853
  function createViteEncodedIdPrefixRegExp(sourcePrefix = "") {
591
- return new RegExp(`^(?:${escapeRegExp$2(VITE_ENCODED_NULL_BYTE_PREFIX)})?${sourcePrefix}`);
854
+ return new RegExp(`^(?:${escapeRegExp$1(VITE_ENCODED_NULL_BYTE_PREFIX)})?${sourcePrefix}`);
592
855
  }
593
856
  function toViteEncodedId(id) {
594
857
  return `${VITE_ENCODED_NULL_BYTE_PREFIX}${id}`;
@@ -686,6 +949,17 @@ function getSsrCapabilities(viteMajor, command, hasRemotes) {
686
949
  }
687
950
  //#endregion
688
951
  //#region src/utils/serializeRuntimeOptions.ts
952
+ const UNSAFE_JS_CHAR_MAP = {
953
+ "<": "\\u003C",
954
+ "\u2028": "\\u2028",
955
+ "\u2029": "\\u2029"
956
+ };
957
+ const UNSAFE_JS_CHAR_PATTERN = /[<\u2028\u2029]/g;
958
+ function toSafeJsLiteral(value) {
959
+ const json = JSON.stringify(value);
960
+ if (json === void 0) return "undefined";
961
+ return json.replace(UNSAFE_JS_CHAR_PATTERN, (char) => UNSAFE_JS_CHAR_MAP[char]);
962
+ }
689
963
  /**
690
964
  * Serializes a JavaScript object into a string of source code that can be evaluated.
691
965
  * This function is used to create runtime plugin options without relying solely on JSON.stringify,
@@ -703,16 +977,13 @@ function serializeRuntimeOptions(options) {
703
977
  function valueToCode(val) {
704
978
  if (val === null) return "null";
705
979
  const type = typeof val;
706
- if (type === "string") return JSON.stringify(val);
980
+ if (type === "string") return toSafeJsLiteral(val);
707
981
  if (type === "number" || type === "boolean") return String(val);
708
982
  if (type === "undefined") return "undefined";
709
- if (type === "symbol") {
710
- const desc = val.description ?? "";
711
- return `Symbol(${JSON.stringify(desc)})`;
712
- }
983
+ if (type === "symbol") return `Symbol(${toSafeJsLiteral(val.description ?? "")})`;
713
984
  if (type === "function") return val.toString();
714
- if (val instanceof Date) return `new Date(${JSON.stringify(val.toISOString())})`;
715
- if (val instanceof RegExp) return `new RegExp(${JSON.stringify(val.source)}, ${JSON.stringify(val.flags)})`;
985
+ if (val instanceof Date) return `new Date(${toSafeJsLiteral(val.toISOString())})`;
986
+ if (val instanceof RegExp) return `new RegExp(${toSafeJsLiteral(val.source)}, ${toSafeJsLiteral(val.flags)})`;
716
987
  if (type === "object") {
717
988
  if (ancestors.has(val)) return `"__circular__"`;
718
989
  ancestors.add(val);
@@ -721,16 +992,16 @@ function serializeRuntimeOptions(options) {
721
992
  if (val instanceof Map) return `new Map([${Array.from(val.entries()).map(([k, v]) => `[${valueToCode(k)}, ${valueToCode(v)}]`).join(", ")}])`;
722
993
  if (val instanceof Set) return `new Set([${Array.from(val.values()).map(valueToCode).join(", ")}])`;
723
994
  const properties = [];
724
- for (const key in val) if (Object.prototype.hasOwnProperty.call(val, key)) properties.push(`${JSON.stringify(key)}: ${valueToCode(val[key])}`);
995
+ for (const key in val) if (Object.prototype.hasOwnProperty.call(val, key)) properties.push(`${toSafeJsLiteral(key)}: ${valueToCode(val[key])}`);
725
996
  return `{${properties.join(", ")}}`;
726
997
  } finally {
727
998
  ancestors.delete(val);
728
999
  }
729
1000
  }
730
- return JSON.stringify(String(val));
1001
+ return toSafeJsLiteral(String(val));
731
1002
  }
732
1003
  const topLevelProps = [];
733
- for (const key in options) if (Object.prototype.hasOwnProperty.call(options, key)) topLevelProps.push(`${JSON.stringify(key)}: ${valueToCode(options[key])}`);
1004
+ for (const key in options) if (Object.prototype.hasOwnProperty.call(options, key)) topLevelProps.push(`${toSafeJsLiteral(key)}: ${valueToCode(options[key])}`);
734
1005
  return `{${topLevelProps.join(", ")}}`;
735
1006
  }
736
1007
  //#endregion
@@ -1177,7 +1448,7 @@ function getSsrNoopResolveCode(enableSsrInit, hostInitImportId, initResolveExpre
1177
1448
  if (!enableSsrInit) return "";
1178
1449
  return `if (${SERVER_ENV_GUARD}) {
1179
1450
  var _noop = { loadRemote: function() { return Promise.resolve(undefined); }, loadShare: function() { return Promise.resolve(undefined); } };
1180
- ${hostInitImportId ? `import(${JSON.stringify(hostInitImportId)})
1451
+ ${hostInitImportId ? `import(${toSafeJsLiteral(hostInitImportId)})
1181
1452
  .then(function(mod) { return mod.hostInitPromise; })
1182
1453
  .then(function(runtime) {
1183
1454
  ${initResolveExpression}(runtime);
@@ -1193,7 +1464,7 @@ function getSsrNoopResolveCode(enableSsrInit, hostInitImportId, initResolveExpre
1193
1464
  function() { return [runtimeMod, []]; }
1194
1465
  );
1195
1466
  }).then(function(pair) {
1196
- var runtime = pair[0].init({ name: '__mf_ssr_host__', remotes: ${JSON.stringify(ssrRemotes)}, shared: {}, plugins: pair[1] });
1467
+ var runtime = pair[0].init({ name: '__mf_ssr_host__', remotes: ${toSafeJsLiteral(ssrRemotes)}, shared: {}, plugins: pair[1] });
1197
1468
  ${initResolveExpression}(runtime);
1198
1469
  }, function() {
1199
1470
  ${initResolveExpression}(_noop);
@@ -1203,7 +1474,7 @@ function getSsrNoopResolveCode(enableSsrInit, hostInitImportId, initResolveExpre
1203
1474
  }
1204
1475
  function getRuntimeInitStateBootstrapCode(options) {
1205
1476
  return `
1206
- const ${options.globalKeyVar} = ${JSON.stringify(getRuntimeInitGlobalKey(options.ownerImportId))};
1477
+ const ${options.globalKeyVar} = ${toSafeJsLiteral(getRuntimeInitGlobalKey(options.ownerImportId))};
1207
1478
  let ${options.stateVar} = globalThis[${options.globalKeyVar}];
1208
1479
  if (!${options.stateVar}) {
1209
1480
  ${getDeferredInitPromiseCode()}
@@ -1219,8 +1490,8 @@ const ${options.exposedConst} = ${options.stateVar}.${options.exposedProperty};
1219
1490
  }
1220
1491
  function getRuntimeInitBootstrapCode(enableSsrInit = false, ownerImportId, ssrRemotes, hostInitImportId = ownerImportId, exportConditions) {
1221
1492
  return `
1222
- const globalKey = ${JSON.stringify(getRuntimeInitGlobalKey(ownerImportId))};
1223
- const moduleCacheGlobalKey = ${JSON.stringify(getModuleCacheGlobalKey(exportConditions))};
1493
+ const globalKey = ${toSafeJsLiteral(getRuntimeInitGlobalKey(ownerImportId))};
1494
+ const moduleCacheGlobalKey = ${toSafeJsLiteral(getModuleCacheGlobalKey(exportConditions))};
1224
1495
  globalThis[moduleCacheGlobalKey] ||= { share: {}, remote: {} };
1225
1496
  globalThis[moduleCacheGlobalKey].share ||= {};
1226
1497
  globalThis[moduleCacheGlobalKey].remote ||= {};
@@ -1245,7 +1516,7 @@ globalThis[globalKey].moduleCache.remote ||= {};
1245
1516
  }
1246
1517
  function getRuntimeModuleCacheBootstrapCode(exportConditions) {
1247
1518
  return `
1248
- const __mfCacheGlobalKey = ${JSON.stringify(getModuleCacheGlobalKey(exportConditions))};
1519
+ const __mfCacheGlobalKey = ${toSafeJsLiteral(getModuleCacheGlobalKey(exportConditions))};
1249
1520
  globalThis[__mfCacheGlobalKey] ||= { share: {}, remote: {} };
1250
1521
  globalThis[__mfCacheGlobalKey].share ||= {};
1251
1522
  globalThis[__mfCacheGlobalKey].remote ||= {};
@@ -2391,7 +2662,8 @@ const legacySharedVirtualModuleState = {
2391
2662
  preBuildShareItemMap: {},
2392
2663
  treeShakingProviderCacheMap: {},
2393
2664
  materializedTreeShakingProviders: /* @__PURE__ */ new Set(),
2394
- loadShareCacheMap: {}
2665
+ loadShareCacheMap: {},
2666
+ warnedMissingImportFalse: /* @__PURE__ */ new Set()
2395
2667
  };
2396
2668
  const sharedVirtualModuleStates = /* @__PURE__ */ new WeakMap();
2397
2669
  let nextSharedVirtualModuleOwnerId = 1;
@@ -2410,6 +2682,7 @@ function getSharedVirtualModuleState(options) {
2410
2682
  treeShakingProviderCacheMap: {},
2411
2683
  materializedTreeShakingProviders: /* @__PURE__ */ new Set(),
2412
2684
  loadShareCacheMap: {},
2685
+ warnedMissingImportFalse: /* @__PURE__ */ new Set(),
2413
2686
  ownerKey: `${options.internalName}${MF_OWNER_INFIX}${nextSharedVirtualModuleOwnerId++}`
2414
2687
  };
2415
2688
  sharedVirtualModuleStates.set(options, state);
@@ -2809,7 +3082,11 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
2809
3082
  let exportLine;
2810
3083
  if (namedExports.length > 0) exportLine = generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor, treeShakingConsumer);
2811
3084
  else {
2812
- if (detectedNamedExports === void 0) mfWarn(`Shared dependency "${pkg}" has import: false but is not installed locally.\n Named imports (e.g. import { ... } from '${pkg}') will not work in production builds.\n Install it as a devDependency to enable named export detection.`);
3085
+ const { warnedMissingImportFalse } = getSharedVirtualModuleState(resolvedOptions);
3086
+ if (detectedNamedExports === void 0 && !shareItem.shareConfig.suppressMissingImportWarning && !warnedMissingImportFalse.has(pkg)) {
3087
+ warnedMissingImportFalse.add(pkg);
3088
+ mfWarn(`Shared dependency "${pkg}" has import: false but is not installed locally.\n Named imports (e.g. import { ... } from '${pkg}') will not work in production builds.\n Install it as a devDependency to enable named export detection.`);
3089
+ }
2813
3090
  exportLine = generateDeferredHostProvidedExports([], pkg, cacheDescriptor, treeShakingConsumer);
2814
3091
  }
2815
3092
  loadShareCacheMap[pkg].writeSync(`
@@ -3028,15 +3305,15 @@ function generateLocalSharedImportMap(options) {
3028
3305
  ${orderedShares.map((pkg, index) => {
3029
3306
  const shareItem = getNormalizeShareItem(pkg, resolvedOptions);
3030
3307
  if (!shareItem?.shareConfig.eager || shareItem.shareConfig.import === false) return "";
3031
- return `import * as __mfEagerShare_${index} from ${JSON.stringify(getLocalSharedPackagePath(pkg, shareItem, options))};`;
3308
+ return `import * as __mfEagerShare_${index} from ${toSafeJsLiteral(getLocalSharedPackagePath(pkg, shareItem, options))};`;
3032
3309
  }).filter(Boolean).join("\n")}
3033
3310
  const importMap = {
3034
3311
  ${orderedShares.map((pkg, index) => {
3035
3312
  const shareItem = getNormalizeShareItem(pkg, resolvedOptions);
3036
3313
  return `
3037
- ${JSON.stringify(pkg)}: async () => {
3038
- ${shareItem?.shareConfig.import === false ? `throw new Error(\`[Module Federation] Shared module '\${${JSON.stringify(pkg)}}' must be provided by host\`);` : shareItem?.shareConfig.eager ? `let pkg = __mfEagerShare_${index};
3039
- return pkg;` : `let pkg = await import(${JSON.stringify(getLocalSharedPackagePath(pkg, shareItem, options))});
3314
+ ${toSafeJsLiteral(pkg)}: async () => {
3315
+ ${shareItem?.shareConfig.import === false ? `throw new Error(\`[Module Federation] Shared module '\${${toSafeJsLiteral(pkg)}}' must be provided by host\`);` : shareItem?.shareConfig.eager ? `let pkg = __mfEagerShare_${index};
3316
+ return pkg;` : `let pkg = await import(${toSafeJsLiteral(getLocalSharedPackagePath(pkg, shareItem, options))});
3040
3317
  return pkg;`}
3041
3318
  }
3042
3319
  `;
@@ -3056,23 +3333,23 @@ function generateLocalSharedImportMap(options) {
3056
3333
  const treeShakingProviderImportId = treeShakingConfig && !disableRuntimeInference && hasTreeShakingSharedProvider(key, shareItem, options) ? getTreeShakingSharedProviderImportId(key, options) : void 0;
3057
3334
  const treeShakingStatus = treeShakingUsage?.kind === "full" || disableRuntimeInference || treeShakingConfig?.mode === "runtime-infer" && !treeShakingProviderImportId && shareItem.shareConfig.import !== false ? 0 : 1;
3058
3335
  return `
3059
- ${JSON.stringify(key)}: {
3060
- name: ${JSON.stringify(key)},
3061
- version: ${JSON.stringify(shareItem.version)},
3062
- scope: [${JSON.stringify(shareItem.scope)}],
3336
+ ${toSafeJsLiteral(key)}: {
3337
+ name: ${toSafeJsLiteral(key)},
3338
+ version: ${toSafeJsLiteral(shareItem.version)},
3339
+ scope: [${toSafeJsLiteral(shareItem.scope)}],
3063
3340
  loaded: false,
3064
3341
  materialize: ${sharesToMaterialize.has(key)},
3065
3342
  eager: ${Boolean(shareItem.shareConfig.eager)},
3066
- from: ${JSON.stringify(resolvedOptions.name)},
3343
+ from: ${toSafeJsLiteral(resolvedOptions.name)},
3067
3344
  canLiveRebind: ${canLiveRebind},
3068
3345
  async get () {
3069
3346
  if (${shareItem.shareConfig.import === false}) {
3070
- throw new Error(\`[Module Federation] Shared module '\${${JSON.stringify(key)}}' must be provided by host\`);
3347
+ throw new Error(\`[Module Federation] Shared module '\${${toSafeJsLiteral(key)}}' must be provided by host\`);
3071
3348
  }
3072
- usedShared[${JSON.stringify(key)}].loaded = true
3073
- const {${JSON.stringify(key)}: pkgDynamicImport} = importMap
3349
+ usedShared[${toSafeJsLiteral(key)}].loaded = true
3350
+ const {${toSafeJsLiteral(key)}: pkgDynamicImport} = importMap
3074
3351
  const res = await pkgDynamicImport()
3075
- const exportModule = ${JSON.stringify(useDirectReactImport)} && ${JSON.stringify(key)} === "react"
3352
+ const exportModule = ${toSafeJsLiteral(useDirectReactImport)} && ${toSafeJsLiteral(key)} === "react"
3076
3353
  ? (res?.default ?? res)
3077
3354
  : {...res}
3078
3355
  // All npm packages pre-built by vite will be converted to esm
@@ -3088,18 +3365,18 @@ function generateLocalSharedImportMap(options) {
3088
3365
  },
3089
3366
  shareConfig: {
3090
3367
  singleton: ${shareItem.shareConfig.singleton},
3091
- requiredVersion: ${JSON.stringify(shareItem.shareConfig.requiredVersion)},
3368
+ requiredVersion: ${toSafeJsLiteral(shareItem.shareConfig.requiredVersion)},
3092
3369
  strictVersion: ${shareItem.shareConfig.strictVersion},
3093
3370
  eager: ${Boolean(shareItem.shareConfig.eager)},
3094
3371
  ${shareItem.shareConfig.import === false ? "import: false," : ""}
3095
3372
  },
3096
3373
  ${treeShakingConfig ? `treeShaking: {
3097
- mode: ${JSON.stringify(treeShakingConfig.mode)},
3098
- usedExports: ${JSON.stringify(treeShakingUsedExports)},
3099
- providedExports: ${JSON.stringify(treeShakingProviderExports)},
3374
+ mode: ${toSafeJsLiteral(treeShakingConfig.mode)},
3375
+ usedExports: ${toSafeJsLiteral(treeShakingUsedExports)},
3376
+ providedExports: ${toSafeJsLiteral(treeShakingProviderExports)},
3100
3377
  status: ${treeShakingStatus},
3101
3378
  ${treeShakingProviderImportId ? `async get() {
3102
- const container = await import(${JSON.stringify(treeShakingProviderImportId)});
3379
+ const container = await import(${toSafeJsLiteral(treeShakingProviderImportId)});
3103
3380
  if (typeof container.init === "function") await container.init();
3104
3381
  return container.get();
3105
3382
  },` : ""}
@@ -3113,12 +3390,12 @@ function generateLocalSharedImportMap(options) {
3113
3390
  if (!remote) return null;
3114
3391
  return `
3115
3392
  {
3116
- alias: ${JSON.stringify(key)},
3117
- entryGlobalName: ${JSON.stringify(remote.entryGlobalName)},
3118
- name: ${JSON.stringify(options ? getRuntimeRemoteAlias(key, options) : remote.name)},
3119
- type: ${JSON.stringify(remote.type)},
3120
- entry: ${JSON.stringify(remote.entry)},
3121
- shareScope: ${JSON.stringify(remote.shareScope ?? "default")},
3393
+ alias: ${toSafeJsLiteral(key)},
3394
+ entryGlobalName: ${toSafeJsLiteral(remote.entryGlobalName)},
3395
+ name: ${toSafeJsLiteral(options ? getRuntimeRemoteAlias(key, options) : remote.name)},
3396
+ type: ${toSafeJsLiteral(remote.type)},
3397
+ entry: ${toSafeJsLiteral(remote.entry)},
3398
+ shareScope: ${toSafeJsLiteral(remote.shareScope ?? "default")},
3122
3399
  }
3123
3400
  `;
3124
3401
  }).filter((x) => x !== null).join(",")}
@@ -3259,8 +3536,8 @@ function getShareItemForPreload(pkg, options = getNormalizeModuleFederationOptio
3259
3536
  function generateSharedCacheSeedItem(pkg, shareItem, importPath, options = getNormalizeModuleFederationOptions()) {
3260
3537
  const cacheDescriptor = getSharedCacheDescriptor(pkg, shareItem);
3261
3538
  const cacheOwner = options.name;
3262
- return `if (__mfReadSharedCache(__mfModuleCache.share, ${JSON.stringify(cacheDescriptor)}) === undefined) {
3263
- const mod = await import(${JSON.stringify(importPath)});
3539
+ return `if (__mfReadSharedCache(__mfModuleCache.share, ${toSafeJsLiteral(cacheDescriptor)}) === undefined) {
3540
+ const mod = await import(${toSafeJsLiteral(importPath)});
3264
3541
  ${normalizeRuntimeShareCode}
3265
3542
  const normalizedModule = __mfNormalizeRuntimeShare(mod);
3266
3543
  const exportModule = normalizedModule === mod ? {...mod} : normalizedModule;
@@ -3268,7 +3545,7 @@ function generateSharedCacheSeedItem(pkg, shareItem, importPath, options = getNo
3268
3545
  value: true,
3269
3546
  enumerable: false
3270
3547
  });
3271
- __mfWriteSharedCache(__mfModuleCache.share, ${JSON.stringify(cacheDescriptor)}, exportModule, ${JSON.stringify(cacheOwner)});
3548
+ __mfWriteSharedCache(__mfModuleCache.share, ${toSafeJsLiteral(cacheDescriptor)}, exportModule, ${toSafeJsLiteral(cacheOwner)});
3272
3549
  }`;
3273
3550
  }
3274
3551
  const normalizeRuntimeShareCode = `const __mfNormalizeRuntimeShare = (mod) => {
@@ -3430,9 +3707,13 @@ const externalSharedProviderSelectionHelperCode = `const __mfSelectExternalShare
3430
3707
  function generateRuntimeSharedCacheSeedCode(shareStrategy, options) {
3431
3708
  const seedBatches = getShareBatches(options, false);
3432
3709
  return `
3433
- const __mfSeedOrder = ${JSON.stringify(seedBatches.flat())};
3434
- const __mfSeedBatches = ${JSON.stringify(seedBatches)};
3435
- const __mfSeedKeys = __mfSeedOrder.filter((pkg) => usedShared[pkg] && usedShared[pkg].materialize !== false);
3710
+ const __mfSeedOrder = ${toSafeJsLiteral(seedBatches.flat())};
3711
+ const __mfSeedBatches = ${toSafeJsLiteral(seedBatches)};
3712
+ // A share is normally skipped here until the dev scanner has observed a real
3713
+ // import and set materialize. An import:false share has no local fallback
3714
+ // though, so on a cold request (materialize not set yet) it must still be
3715
+ // attempted here, or it is never seeded and its consumer reads it undefined.
3716
+ const __mfSeedKeys = __mfSeedOrder.filter((pkg) => usedShared[pkg] && (usedShared[pkg].materialize !== false || usedShared[pkg].shareConfig?.import === false));
3436
3717
  __mfModuleCache.providerInit ||= new Map();
3437
3718
  const __mfInitializeProviderOnce = (key, initialize) => {
3438
3719
  const existing = __mfModuleCache.providerInit.get(key);
@@ -3531,7 +3812,7 @@ function generateRuntimeSharedCacheSeedCode(shareStrategy, options) {
3531
3812
  initialShared[pkg],
3532
3813
  pkg,
3533
3814
  share,
3534
- ${JSON.stringify(shareStrategy)}
3815
+ ${toSafeJsLiteral(shareStrategy)}
3535
3816
  ));
3536
3817
  };
3537
3818
  const __mfFirstRuntimeSeedBarrierIndex = __mfSeedKeys.findIndex(
@@ -3738,7 +4019,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
3738
4019
  const needsSharedProviderSelectionHelper = Object.keys(options.shared ?? {}).length > 0;
3739
4020
  const hasTreeShakingShared = Object.values(options.shared ?? {}).some((share) => !!share?.shareConfig.treeShaking);
3740
4021
  const hasMultipleShareScopes = Array.isArray(options.shareScope);
3741
- const materializedShareBatches = JSON.stringify(getShareBatches(options, false));
4022
+ const materializedShareBatches = toSafeJsLiteral(getShareBatches(options, false));
3742
4023
  const runtimeImports = [
3743
4024
  "init as runtimeInit",
3744
4025
  "loadRemote",
@@ -3795,9 +4076,9 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
3795
4076
  ${command === "build" ? getRuntimeInitResolveBootstrapCode(false, getRuntimeInitStatusImportId(options)) : getRuntimeInitBootstrapCode(false, getRuntimeInitStatusImportId(options), void 0, void 0, exportConditions) + "\n const { initResolve } = globalThis[globalKey];"}
3796
4077
  ${getRuntimeModuleCacheBootstrapCode(exportConditions)}
3797
4078
  const initTokens = {}
3798
- const shareScopeNames = Array.isArray(${JSON.stringify(options.shareScope)}) ? ${JSON.stringify(options.shareScope)} : [${JSON.stringify(options.shareScope)}]
3799
- const shareScopeName = ${JSON.stringify(hasMultipleShareScopes ? options.shareScope[0] : options.shareScope)}
3800
- const mfName = ${JSON.stringify(options.name)}
4079
+ const shareScopeNames = Array.isArray(${toSafeJsLiteral(options.shareScope)}) ? ${toSafeJsLiteral(options.shareScope)} : [${toSafeJsLiteral(options.shareScope)}]
4080
+ const shareScopeName = ${toSafeJsLiteral(hasMultipleShareScopes ? options.shareScope[0] : options.shareScope)}
4081
+ const mfName = ${toSafeJsLiteral(options.name)}
3801
4082
  const __mfMaterializedShareBatches = ${materializedShareBatches}
3802
4083
  let localSharedImportMapPromise
3803
4084
  let exposesMapPromise
@@ -3927,7 +4208,12 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
3927
4208
  function isWebpackProvider(provider) {
3928
4209
  if (typeof provider?.get !== 'function') return false;
3929
4210
  const source = Function.prototype.toString.call(provider.get);
3930
- return source.includes('__webpack_require__');
4211
+ // Production minification renames __webpack_require__, but preserves
4212
+ // Webpack's lazy chunk-loading .e(...).then(...) shape.
4213
+ return (
4214
+ source.includes('__webpack_require__') ||
4215
+ /\\.\\s*e\\s*\\([^)]*\\)\\s*\\.then\\s*\\(/.test(source)
4216
+ );
3931
4217
  }
3932
4218
  const __mfUsesWebpackShareScope = Object.values(initialShared).some((versions) =>
3933
4219
  Object.values(versions || {}).some(isWebpackProvider)
@@ -3979,7 +4265,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
3979
4265
  ? await Promise.all([${pluginImportNames.filter((item) => isSsrOnlyPlugin(item[1])).map((item) => {
3980
4266
  const specifier = getSsrOnlyPluginSpecifier(item[1]);
3981
4267
  const opts = item[2];
3982
- return `import(${JSON.stringify(specifier)}).then(m => (m.default ?? m)(${opts}))`;
4268
+ return `import(${toSafeJsLiteral(specifier)}).then(m => (m.default ?? m)(${opts}))`;
3983
4269
  }).join(", ")}])
3984
4270
  : [];
3985
4271
  const __mfRuntimeShareLoadIdKey = "__mf_vite_runtime_share_load_id__";
@@ -3990,7 +4276,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
3990
4276
  name: mfName,
3991
4277
  remotes: ${options.shareStrategy === "loaded-first" ? "[]" : "usedRemotes"},
3992
4278
  shared: usedShared,
3993
- plugins: [__mfSharePinLifecyclePlugin(), ${hasTreeShakingShared ? "__mfTreeShakingSnapshotPlugin()," : ""} ...__browserPlugins, ...__ssrPlugins],
4279
+ plugins: [__mfSharePinLifecyclePlugin(), __mfRealNameSnapshotPlugin(), ${hasTreeShakingShared ? "__mfTreeShakingSnapshotPlugin()," : ""} ...__browserPlugins, ...__ssrPlugins],
3994
4280
  ${options.shareStrategy ? `shareStrategy: '${options.shareStrategy}'` : ""}
3995
4281
  });
3996
4282
  ${hasMultipleShareScopes ? `for (const shareScopeName of shareScopeNamesToInitialize) {
@@ -4022,6 +4308,33 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
4022
4308
  }
4023
4309
  };
4024
4310
  }
4311
+ function __mfRealNameSnapshotPlugin() {
4312
+ return {
4313
+ name: "vite-real-name-snapshot-plugin",
4314
+ afterLoadSnapshot(args) {
4315
+ // Remotes are registered under an owner-scoped runtime name, so the
4316
+ // global snapshot only ever holds that name. Containers built by other
4317
+ // bundlers ask for the same remote by its real container name, miss, and
4318
+ // fall back to that container's own entry, whose remoteEntry is empty
4319
+ // (RUNTIME-011). Mirroring the resolved snapshot under the real name
4320
+ // keeps the primary lookup off that fallback.
4321
+ const snapshot = args && args.remoteSnapshot;
4322
+ const globalName = snapshot && snapshot.globalName;
4323
+ const version = snapshot && snapshot.version;
4324
+ if (!globalName || !version || !snapshot.remoteEntry) return args;
4325
+ const moduleInfo = globalThis.__FEDERATION__ && globalThis.__FEDERATION__.moduleInfo;
4326
+ const realNameKey = globalName + ":" + version;
4327
+ // Stores the same object, not a copy, so a later mutation (e.g. runtime-core
4328
+ // normalizing fields) stays consistent across both keys. Never overwrites an
4329
+ // existing entry: a different owner may have already resolved this real name
4330
+ // to its own snapshot, and this mirror must not shadow that one.
4331
+ if (moduleInfo && !moduleInfo[realNameKey]) {
4332
+ moduleInfo[realNameKey] = snapshot;
4333
+ }
4334
+ return args;
4335
+ }
4336
+ };
4337
+ }
4025
4338
  const runtimeResolveShareHook = initRes.sharedHandler.hooks.lifecycle.resolveShare;
4026
4339
  const __mfRuntimeProviderOrigins = new WeakMap();
4027
4340
  runtimeResolveShareHook.on((args) => {
@@ -4050,7 +4363,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
4050
4363
  if (!versionMap || versionMap[version] !== currentProvider) return undefined;
4051
4364
  const pinnedProvider = Object.assign({}, provider, {
4052
4365
  version: provider.version ?? version,
4053
- scope: provider.scope ?? currentProvider?.scope ?? ${JSON.stringify(hasMultipleShareScopes ? options.shareScope : [options.shareScope])},
4366
+ scope: provider.scope ?? currentProvider?.scope ?? ${toSafeJsLiteral(hasMultipleShareScopes ? options.shareScope : [options.shareScope])},
4054
4367
  strategy: 'loaded-first'
4055
4368
  });
4056
4369
  const providerFrom = provider.from;
@@ -4322,7 +4635,6 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
4322
4635
  expectedSelection
4323
4636
  ) => {
4324
4637
  try {
4325
- if (__mfGetPendingExternalSharedProvider(pkg, usedShare)) return;
4326
4638
  const usedCacheDescriptor = __mfGetSharedCacheDescriptor(pkg, usedShare.shareConfig?.singleton, usedShare.version, usedShare.scope);
4327
4639
  const cachedShare = __mfReadSharedCache(__mfModuleCache.share, usedCacheDescriptor);
4328
4640
  const cachedShareOwner = __mfReadSharedCacheOwner(__mfModuleCache.share, usedCacheDescriptor);
@@ -4370,12 +4682,6 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
4370
4682
  !scopeRootProvider &&
4371
4683
  !__mfMatchesSharedProvider(liveProvider, provider)
4372
4684
  ) return;
4373
- if (
4374
- !selectedLocalProvider &&
4375
- isWebpackProvider(provider) &&
4376
- !provider.lib &&
4377
- !provider.loaded
4378
- ) return;
4379
4685
  const loadedShare = await __mfLoadPinnedRuntimeShare(
4380
4686
  pkg,
4381
4687
  usedShare.shareConfig,
@@ -4653,8 +4959,8 @@ function getHostAutoInitState(options) {
4653
4959
  function generateHostAutoInitCode(remoteEntryImport, _command = "build", options, exportConditions) {
4654
4960
  const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
4655
4961
  const shouldPreloadShares = resolvedOptions.shareStrategy !== "loaded-first";
4656
- const hostInitShareOrder = JSON.stringify(getOrderedUsedShares(options));
4657
- const cacheOwner = JSON.stringify(resolvedOptions.name);
4962
+ const hostInitShareBatches = toSafeJsLiteral(getShareBatches(options, false));
4963
+ const cacheOwner = toSafeJsLiteral(resolvedOptions.name);
4658
4964
  const preferLocalVinextReact = hasPackageDependency("vinext") && (!exportConditions?.includes("browser") || exportConditions.includes("worker"));
4659
4965
  return `
4660
4966
  ${getRuntimeModuleCacheBootstrapCode(exportConditions)}
@@ -4669,44 +4975,44 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build", options
4669
4975
  const {usedShared} = await import("${getLocalSharedImportMapPath(options)}");
4670
4976
  ${normalizeRuntimeShareCode}
4671
4977
  ${shouldPreloadShares ? `
4672
- const __mfHostInitShareOrder = ${hostInitShareOrder};
4673
- for (const pkg of __mfHostInitShareOrder) {
4674
- const share = usedShared[pkg];
4675
- if (!share || share.materialize === false) continue;
4676
- // remoteEntry.init resolves tree-enabled shares into the
4677
- // coverage-aware cache. Never republish that selected partial under
4678
- // a generic full-module key here.
4679
- if (share.treeShaking) continue;
4680
- const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, share.shareConfig?.singleton, share.version, share.scope);
4681
- if (
4682
- __mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined &&
4683
- __mfReadSharedCacheOwner(__mfModuleCache.share, cacheDescriptor) !== undefined
4684
- ) {
4685
- continue;
4686
- }
4687
- await runtime.loadShare(pkg, {
4688
- customShareInfo: { shareConfig: share.shareConfig }
4689
- }).then(async (factory) => {
4690
- const mod = typeof factory === "function" ? factory() : factory;
4691
- let resolved = __mfNormalizeRuntimeShare(await Promise.resolve(mod));
4692
- ${preferLocalVinextReact ? `if (
4693
- (pkg === "react" || pkg === "react-dom") &&
4694
- typeof share.get === "function" &&
4695
- share.shareConfig?.import !== false
4696
- ) {
4697
- try {
4698
- const localFactory = await share.get();
4699
- const localModule = typeof localFactory === "function" ? localFactory() : localFactory;
4700
- resolved = __mfNormalizeRuntimeShare(await Promise.resolve(localModule));
4701
- } catch {}
4702
- }` : ""}
4703
- __mfWriteSharedCache(
4704
- __mfModuleCache.share,
4705
- cacheDescriptor,
4706
- resolved,
4707
- ${cacheOwner}
4708
- );
4709
- });
4978
+ const __mfHostInitShareBatches = ${hostInitShareBatches};
4979
+ for (const __mfHostInitShareBatch of __mfHostInitShareBatches) {
4980
+ await Promise.all(__mfHostInitShareBatch.map(async (pkg) => {
4981
+ const share = usedShared[pkg];
4982
+ if (!share || share.materialize === false) return;
4983
+ // remoteEntry.init resolves tree-enabled shares into the
4984
+ // coverage-aware cache. Never republish that selected partial under
4985
+ // a generic full-module key here.
4986
+ if (share.treeShaking) return;
4987
+ const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, share.shareConfig?.singleton, share.version, share.scope);
4988
+ if (
4989
+ __mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined &&
4990
+ __mfReadSharedCacheOwner(__mfModuleCache.share, cacheDescriptor) ${_command === "serve" ? "!== undefined" : `=== ${cacheOwner}`}
4991
+ ) return;
4992
+ await runtime.loadShare(pkg, {
4993
+ customShareInfo: { shareConfig: share.shareConfig }
4994
+ }).then(async (factory) => {
4995
+ const mod = typeof factory === "function" ? factory() : factory;
4996
+ let resolved = __mfNormalizeRuntimeShare(await Promise.resolve(mod));
4997
+ ${preferLocalVinextReact ? `if (
4998
+ (pkg === "react" || pkg === "react-dom") &&
4999
+ typeof share.get === "function" &&
5000
+ share.shareConfig?.import !== false
5001
+ ) {
5002
+ try {
5003
+ const localFactory = await share.get();
5004
+ const localModule = typeof localFactory === "function" ? localFactory() : localFactory;
5005
+ resolved = __mfNormalizeRuntimeShare(await Promise.resolve(localModule));
5006
+ } catch {}
5007
+ }` : ""}
5008
+ __mfWriteSharedCache(
5009
+ __mfModuleCache.share,
5010
+ cacheDescriptor,
5011
+ resolved,
5012
+ ${cacheOwner}
5013
+ );
5014
+ });
5015
+ }));
4710
5016
  }
4711
5017
  ` : ""}
4712
5018
  return runtime;
@@ -4723,7 +5029,7 @@ function writeHostAutoInit(remoteEntryId = REMOTE_ENTRY_ID, command = "build", o
4723
5029
  state.remoteEntryId = remoteEntryId;
4724
5030
  state.command = command;
4725
5031
  if (exportConditions !== void 0) state.exportConditions = exportConditions;
4726
- state.module.writeSync(generateHostAutoInitCode(JSON.stringify(remoteEntryId), command, options, state.exportConditions), true);
5032
+ state.module.writeSync(generateHostAutoInitCode(toSafeJsLiteral(remoteEntryId), command, options, state.exportConditions), true);
4727
5033
  }
4728
5034
  function refreshHostAutoInit(options, exportConditions) {
4729
5035
  try {
@@ -4784,6 +5090,7 @@ const usedRemotesMap = {};
4784
5090
  const usedRemotesByOptions = /* @__PURE__ */ new WeakMap();
4785
5091
  const dynamicRemotesByOptions = /* @__PURE__ */ new WeakMap();
4786
5092
  const staticRemotesByOptions = /* @__PURE__ */ new WeakMap();
5093
+ const EMPTY_STATIC_REMOTES = /* @__PURE__ */ new Set();
4787
5094
  function getScopedUsedRemotesMap(options) {
4788
5095
  let scoped = usedRemotesByOptions.get(options);
4789
5096
  if (!scoped) {
@@ -4820,12 +5127,28 @@ function markStaticRemote(remote, options) {
4820
5127
  }
4821
5128
  remotes.add(remote);
4822
5129
  }
5130
+ function getStaticRemotes(options) {
5131
+ return staticRemotesByOptions.get(options) ?? EMPTY_STATIC_REMOTES;
5132
+ }
4823
5133
  function isDynamicOnlyRemote(remote, options) {
4824
5134
  return (dynamicRemotesByOptions.get(options)?.has(remote) ?? false) && !(staticRemotesByOptions.get(options)?.has(remote) ?? false);
4825
5135
  }
4826
5136
  function getRemoteAliasFromId(id, remotes) {
4827
5137
  return Object.keys(remotes).filter((name) => id === name || id.startsWith(name + "/")).sort((a, b) => b.length - a.length)[0];
4828
5138
  }
5139
+ function getRemoteRegistration(id, remotes, options) {
5140
+ const alias = getRemoteAliasFromId(id, remotes);
5141
+ if (!alias) return void 0;
5142
+ const remote = remotes[alias];
5143
+ return {
5144
+ entryGlobalName: remote.entryGlobalName,
5145
+ name: options ? getRuntimeRemoteAlias(alias, options) : remote.name,
5146
+ alias,
5147
+ type: remote.type,
5148
+ entry: remote.entry,
5149
+ shareScope: remote.shareScope ?? "default"
5150
+ };
5151
+ }
4829
5152
  function getRuntimeRemoteId(id, remotes, options) {
4830
5153
  const alias = getRemoteAliasFromId(id, remotes);
4831
5154
  if (!alias) return id;
@@ -5000,18 +5323,9 @@ function generateRemotes(id, command, enableSsrInit = false, consumer = "unified
5000
5323
  const isLoadedFirst = resolvedOptions.shareStrategy === "loaded-first";
5001
5324
  const initMode = resolveRemoteInitMode(resolvedOptions.shareStrategy, consumer);
5002
5325
  const deferRemoteLoad = shouldDeferRemoteLoad(initMode);
5003
- const remoteAlias = getRemoteAliasFromId(id, resolvedOptions.remotes);
5004
- const remote = remoteAlias ? resolvedOptions.remotes[remoteAlias] : void 0;
5005
- const runtimeRemoteAlias = remoteAlias ? getRuntimeRemoteAlias(remoteAlias, options) : void 0;
5006
5326
  const runtimeRemoteId = getRuntimeRemoteId(id, resolvedOptions.remotes, options);
5007
- const registerRemoteCode = isLoadedFirst && remote ? `runtime.registerRemotes([${JSON.stringify({
5008
- entryGlobalName: remote.entryGlobalName,
5009
- name: options ? runtimeRemoteAlias : remote.name,
5010
- alias: remoteAlias,
5011
- type: remote.type,
5012
- entry: remote.entry,
5013
- shareScope: remote.shareScope ?? "default"
5014
- })}]);` : "";
5327
+ const remoteRegistration = getRemoteRegistration(id, resolvedOptions.remotes, options);
5328
+ const registerRemoteCode = isLoadedFirst && remoteRegistration ? `runtime.registerRemotes([${JSON.stringify(remoteRegistration)}]);` : "";
5015
5329
  const hostAutoInitPath = getHostAutoInitPath(options);
5016
5330
  const ssrRemotes = Object.entries(resolvedOptions.remotes).map(([name, item]) => ({
5017
5331
  name: getRuntimeRemoteAlias(name, options),
@@ -5064,7 +5378,7 @@ function generateRemotes(id, command, enableSsrInit = false, consumer = "unified
5064
5378
  }`;
5065
5379
  const realRemoteInit = `__mfRemotePending = __mfStartRemoteLoad().then(__mfAssignRemoteModule);`;
5066
5380
  const deferredClientInit = `exportModule = __mfCreateDeferredRemoteProxy();`;
5067
- const eagerLoadClientRemote = shouldEagerLoadClientRemoteInDev(command, enableSsrInit);
5381
+ const eagerLoadClientRemote = id === remoteRegistration?.alias || shouldEagerLoadClientRemoteInDev(command, enableSsrInit);
5068
5382
  const eagerClientInit = eagerLoadClientRemote ? getEagerDeferredClientInit() : deferredClientInit;
5069
5383
  const loadedFirstClientInit = eagerLoadClientRemote ? getEagerDeferredClientInit() : deferredClientInit;
5070
5384
  const environmentSplitInit = (clientInit, serverInit) => consumer === "client" ? clientInit : consumer === "server" ? serverInit : `if (${SERVER_ENV_GUARD}) {
@@ -5090,28 +5404,57 @@ function generateRemotes(id, command, enableSsrInit = false, consumer = "unified
5090
5404
  }
5091
5405
  //#endregion
5092
5406
  //#region src/plugins/pluginAddEntry.ts
5407
+ const isPreloadableVirtualMfChunk = (name) => name.includes("virtual_mf") && !name.includes("__prebuild__");
5093
5408
  const HOST_INIT_PRELOAD_CHUNKS = [
5094
5409
  (name) => name === "hostInit",
5095
5410
  (name) => name === "remoteEntry",
5096
- (name) => name.startsWith("_virtual_mf") && !name.includes("__prebuild__"),
5411
+ (name) => name === "virtualExposes",
5412
+ isPreloadableVirtualMfChunk,
5097
5413
  (name) => name === "index"
5098
5414
  ];
5415
+ const isRemoteWarmupExcluded = (name) => name.includes("__prebuild__") || name.includes("__loadShare__");
5416
+ const REMOTE_ENTRY_WARMUP_CHUNKS = [
5417
+ (name) => name === "hostInit",
5418
+ (name) => name === "virtualExposes",
5419
+ (name) => isPreloadableVirtualMfChunk(name) && !isRemoteWarmupExcluded(name)
5420
+ ];
5421
+ function getChunksByFileName(bundle) {
5422
+ return new Map(Object.values(bundle).filter((chunk) => chunk.type === "chunk").map((chunk) => [chunk.fileName, chunk]));
5423
+ }
5424
+ function collectPreloadChunkFiles(chunksByFileName, seeds, excludeFromClosure = (name) => name.includes("__prebuild__")) {
5425
+ const seenFiles = /* @__PURE__ */ new Set();
5426
+ const files = [];
5427
+ const queue = [...seeds];
5428
+ while (queue.length > 0) {
5429
+ const chunk = queue.shift();
5430
+ if (seenFiles.has(chunk.fileName)) continue;
5431
+ seenFiles.add(chunk.fileName);
5432
+ for (const imported of chunk.imports ?? []) {
5433
+ const importedChunk = chunksByFileName.get(imported);
5434
+ if (importedChunk && !excludeFromClosure(importedChunk.name)) queue.push(importedChunk);
5435
+ }
5436
+ files.push(chunk.fileName);
5437
+ }
5438
+ return files;
5439
+ }
5099
5440
  function escapeHtmlAttr(value) {
5100
5441
  return value.replace(/&/g, "&amp;").replace(/"/g, "&quot;");
5101
5442
  }
5102
5443
  function getExistingHrefSet(html) {
5103
5444
  return new Set(Array.from(html.matchAll(/\bhref\s*=\s*["']([^"']+)["']/gi), (match) => match[1]));
5104
5445
  }
5105
- function injectHostInitPreloads(html, bundle, resolvePath) {
5446
+ function injectHostInitPreloads(html, bundle, resolvePath, externalHrefs = []) {
5106
5447
  const existingHrefs = getExistingHrefSet(html);
5107
- const seenFiles = /* @__PURE__ */ new Set();
5108
5448
  const hrefs = [];
5109
- for (const chunk of Object.values(bundle)) {
5110
- if (chunk.type !== "chunk") continue;
5111
- if (!HOST_INIT_PRELOAD_CHUNKS.some((match) => match(chunk.name))) continue;
5112
- if (seenFiles.has(chunk.fileName)) continue;
5113
- seenFiles.add(chunk.fileName);
5114
- const href = resolvePath(chunk.fileName);
5449
+ for (const href of externalHrefs) {
5450
+ if (existingHrefs.has(href)) continue;
5451
+ existingHrefs.add(href);
5452
+ hrefs.push(href);
5453
+ }
5454
+ const chunksByFileName = getChunksByFileName(bundle);
5455
+ const seeds = Array.from(chunksByFileName.values()).filter((chunk) => HOST_INIT_PRELOAD_CHUNKS.some((match) => match(chunk.name)));
5456
+ for (const fileName of collectPreloadChunkFiles(chunksByFileName, seeds)) {
5457
+ const href = resolvePath(fileName);
5115
5458
  if (existingHrefs.has(href)) continue;
5116
5459
  existingHrefs.add(href);
5117
5460
  hrefs.push(href);
@@ -5120,6 +5463,40 @@ function injectHostInitPreloads(html, bundle, resolvePath) {
5120
5463
  const tags = hrefs.map((href) => `<link rel="modulepreload" crossorigin href="${escapeHtmlAttr(href)}">`).join("");
5121
5464
  return html.includes("</head>") ? html.replace("</head>", `${tags}</head>`) : `${tags}${html}`;
5122
5465
  }
5466
+ function appendRemoteEntryWarmup(bundle, entryFileName) {
5467
+ const chunksByFileName = getChunksByFileName(bundle);
5468
+ const entryChunk = chunksByFileName.get(entryFileName);
5469
+ if (!entryChunk || entryChunk.code.includes("__mfWarmupPath")) return;
5470
+ const reachable = /* @__PURE__ */ new Set();
5471
+ const walk = [entryChunk];
5472
+ while (walk.length > 0) {
5473
+ const chunk = walk.pop();
5474
+ if (reachable.has(chunk.fileName)) continue;
5475
+ reachable.add(chunk.fileName);
5476
+ for (const imported of [...chunk.imports ?? [], ...chunk.dynamicImports ?? []]) {
5477
+ const importedChunk = chunksByFileName.get(imported);
5478
+ if (importedChunk) walk.push(importedChunk);
5479
+ }
5480
+ }
5481
+ const seeds = Array.from(reachable).map((file) => chunksByFileName.get(file)).filter((chunk) => chunk.fileName !== entryFileName && REMOTE_ENTRY_WARMUP_CHUNKS.some((match) => match(chunk.name)));
5482
+ const lastSlash = entryFileName.lastIndexOf("/");
5483
+ const entryDir = lastSlash !== -1 ? entryFileName.slice(0, lastSlash + 1) : "";
5484
+ const files = collectPreloadChunkFiles(chunksByFileName, seeds, isRemoteWarmupExcluded).filter((file) => file !== entryFileName).map((file) => rebaseImport(file, entryDir));
5485
+ if (files.length === 0) return;
5486
+ entryChunk.code += `
5487
+ if (typeof document !== 'undefined' && document.head) {
5488
+ try {
5489
+ for (const __mfWarmupPath of ${JSON.stringify(files)}) {
5490
+ const __mfWarmupLink = document.createElement('link');
5491
+ __mfWarmupLink.rel = 'modulepreload';
5492
+ __mfWarmupLink.crossOrigin = '';
5493
+ __mfWarmupLink.href = new URL(__mfWarmupPath, import.meta.url).href;
5494
+ document.head.appendChild(__mfWarmupLink);
5495
+ }
5496
+ } catch (__mfWarmupError) {}
5497
+ }
5498
+ `;
5499
+ }
5123
5500
  function getFirstHtmlEntryFile(entryFiles) {
5124
5501
  return entryFiles.find((file) => file.endsWith(".html"));
5125
5502
  }
@@ -5138,20 +5515,25 @@ function resolveDevHashEntryFileName$1(fileName) {
5138
5515
  function getBuildInput(config) {
5139
5516
  return config.build?.rollupOptions?.input ?? config.build?.rolldownOptions?.input;
5140
5517
  }
5141
- function patchHashEntryFileName(output, entryName, fileName) {
5142
- const originalEntryFileNames = output.entryFileNames;
5143
- output.entryFileNames = (chunkInfo, ...args) => {
5144
- if (chunkInfo?.name === entryName) return fileName;
5145
- if (typeof originalEntryFileNames === "function") return originalEntryFileNames(chunkInfo, ...args);
5146
- return originalEntryFileNames || "assets/[name]-[hash].js";
5147
- };
5518
+ function patchHashEntryFileName(output, entryName, fileName, defaultFileNames) {
5519
+ for (const option of ["entryFileNames", "chunkFileNames"]) {
5520
+ const originalFileNames = output[option];
5521
+ output[option] = (chunkInfo, ...args) => {
5522
+ if (chunkInfo?.name === entryName) return fileName;
5523
+ if (typeof originalFileNames === "function") return originalFileNames(chunkInfo, ...args);
5524
+ return originalFileNames || defaultFileNames;
5525
+ };
5526
+ }
5148
5527
  }
5149
5528
  function patchHashEntryFileNames(config, entryName, fileName) {
5150
5529
  if (!fileName?.includes?.("[hash")) return;
5530
+ fileName = fileName.replace(/(\[hash(?::\d+)?\])$/, "$1.js");
5151
5531
  config.build ??= {};
5152
5532
  config.build.rollupOptions ??= {};
5153
5533
  config.build.rolldownOptions ??= {};
5154
- const patchOutput = (output) => patchHashEntryFileName(output, entryName, fileName);
5534
+ const assetsDir = config.build.assetsDir ?? "assets";
5535
+ const defaultFileNames = `${assetsDir ? `${assetsDir}/` : ""}[name]-[hash].js`;
5536
+ const patchOutput = (output) => patchHashEntryFileName(output, entryName, fileName, defaultFileNames);
5155
5537
  const patchBundlerOutput = (bundlerOptions) => {
5156
5538
  const output = bundlerOptions.output;
5157
5539
  if (Array.isArray(output)) {
@@ -5162,6 +5544,7 @@ function patchHashEntryFileNames(config, entryName, fileName) {
5162
5544
  };
5163
5545
  patchBundlerOutput(config.build.rollupOptions);
5164
5546
  patchBundlerOutput(config.build.rolldownOptions);
5547
+ Object.values(config.environments ?? {}).forEach((environment) => patchHashEntryFileNames(environment, entryName, fileName));
5165
5548
  }
5166
5549
  const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClientInjected, skipTransformFor = [], federationOptions }) => {
5167
5550
  const DEV_HTML_PROXY_PREFIX = "virtual:mf-html-entry-proxy?";
@@ -5240,6 +5623,16 @@ const __mfCurrentScript = document.currentScript;
5240
5623
  }
5241
5624
  return patched;
5242
5625
  }
5626
+ function getRemoteEntryPreloadUrls() {
5627
+ const normalizedOptions = federationOptions ?? getNormalizeModuleFederationOptions();
5628
+ const isLoadedFirstClientBuild = (_command === "build" || viteConfig?.command === "build") && waitsForInit && !viteConfig?.build?.ssr && normalizedOptions.shareStrategy === "loaded-first";
5629
+ if (normalizedOptions.shareStrategy === "loaded-first" && !isLoadedFirstClientBuild) return [];
5630
+ const remoteSources = isLoadedFirstClientBuild ? Array.from(getStaticRemotes(normalizedOptions)) : Object.entries(getUsedRemotesMap(federationOptions)).flatMap(([, remotes]) => Array.from(remotes)).filter((remote) => !federationOptions || !isDynamicOnlyRemote(remote, federationOptions));
5631
+ return Array.from(new Set(remoteSources.flatMap((remote) => {
5632
+ const registration = getRemoteRegistration(remote, normalizedOptions.remotes, federationOptions);
5633
+ return registration && (registration.type === "module" || registration.type === "esm") && /^(?:https?:)?\/\//.test(registration.entry) ? [registration.entry] : [];
5634
+ })));
5635
+ }
5243
5636
  function getBootstrapSource(initSrc, entrySrc, useSystemImportFallback = false, options) {
5244
5637
  const importHelper = useSystemImportFallback ? `const __mfImport = (src) =>
5245
5638
  globalThis.System && typeof globalThis.System.import === 'function'
@@ -5251,11 +5644,35 @@ const __mfCurrentScript = document.currentScript;
5251
5644
  const entryImportDeclaration = isEncodedVirtualEntry ? `const __mfEntryUrl = ${JSON.stringify(entrySrc)};
5252
5645
  ` : "";
5253
5646
  const entryImportExpression = isEncodedVirtualEntry ? "import(/* @vite-ignore */ __mfEntryUrl)" : importExpression(entrySrc);
5254
- const remotePreloads = !options?.skipRemotePreload && (federationOptions ?? getNormalizeModuleFederationOptions())?.shareStrategy !== "loaded-first" ? Object.entries(getUsedRemotesMap(federationOptions)).flatMap(([, remotes]) => Array.from(remotes)).filter((remote) => !federationOptions || !isDynamicOnlyRemote(remote, federationOptions)).sort().map((remote) => `__mfPreloadRemote(${JSON.stringify(getRuntimeRemoteId(remote, (federationOptions ?? getNormalizeModuleFederationOptions()).remotes, federationOptions))}, ${JSON.stringify(remote)})`).join(",") : "";
5647
+ const normalizedOptions = federationOptions ?? getNormalizeModuleFederationOptions();
5648
+ const isLoadedFirstClientBuild = (_command === "build" || viteConfig?.command === "build") && waitsForInit && !viteConfig?.build?.ssr && normalizedOptions.shareStrategy === "loaded-first";
5649
+ const shouldPreloadRemotes = !options?.skipRemotePreload && (normalizedOptions.shareStrategy !== "loaded-first" || isLoadedFirstClientBuild);
5650
+ const remoteSources = isLoadedFirstClientBuild ? Array.from(getStaticRemotes(normalizedOptions)) : Object.entries(getUsedRemotesMap(federationOptions)).flatMap(([, remotes]) => Array.from(remotes)).filter((remote) => !federationOptions || !isDynamicOnlyRemote(remote, federationOptions));
5651
+ const remotePreloads = shouldPreloadRemotes ? remoteSources.sort().map((remote) => {
5652
+ const registration = isLoadedFirstClientBuild ? getRemoteRegistration(remote, normalizedOptions.remotes, federationOptions) : void 0;
5653
+ return `__mfPreloadRemote(${JSON.stringify(getRuntimeRemoteId(remote, normalizedOptions.remotes, federationOptions))}, ${JSON.stringify(remote)}${registration ? `, ${JSON.stringify(registration)}` : ""})`;
5654
+ }).join(",") : "";
5655
+ const remoteEntryPrefetchUrls = shouldPreloadRemotes ? getRemoteEntryPreloadUrls() : [];
5656
+ const remoteEntryPrefetchBlock = remoteEntryPrefetchUrls.length > 0 ? `const __mfRemoteEntryPrefetchUrls = ${JSON.stringify(remoteEntryPrefetchUrls)};
5657
+ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
5658
+ import(/* @vite-ignore */ __mfRemoteEntryPrefetchUrl).catch(() => {});
5659
+ }
5660
+ ` : "";
5661
+ const sharedPreloadSources = _command === "serve" && waitsForInit && Object.keys(normalizedOptions.exposes || {}).length > 0 && Object.keys(normalizedOptions.remotes || {}).length === 0 && federationOptions ? Array.from(getUsedShares(federationOptions)).filter((pkg) => !pkg.endsWith("/")).filter((pkg) => {
5662
+ const shareItem = federationOptions.shared[pkg] || Object.entries(federationOptions.shared).find(([key]) => key.endsWith("/") && pkg.startsWith(key))?.[1];
5663
+ const isExplicitShare = Object.prototype.hasOwnProperty.call(federationOptions.shared, pkg);
5664
+ return shareItem?.shareConfig?.singleton === true && shareItem?.shareConfig?.import !== false && !shareItem?.shareConfig?.treeShaking && (isExplicitShare || typeof shareItem?.shareConfig?.import === "string" || Boolean(getProjectResolvedImportPath(pkg)));
5665
+ }).map((pkg) => toViteEncodedId(getLoadShareModulePath(pkg, false, federationOptions))) : [];
5666
+ const sharedPreloadBlock = sharedPreloadSources.length > 0 ? `
5667
+ const __mfSharedPreloadUrls = ${JSON.stringify(sharedPreloadSources)};
5668
+ await Promise.all(__mfSharedPreloadUrls.map((src) => import(/* @vite-ignore */ src).catch((err) => console.warn("[module-federation] shared preload failed:", src, err))));` : "";
5255
5669
  const remoteCachePrefix = getRuntimeRemoteCachePrefix(federationOptions);
5256
5670
  const preloadBlock = remotePreloads ? `
5257
5671
  const runtime = await initHost();
5258
- const __mfPreloadRemote = (runtimeRemote, remote) => {
5672
+ const __mfPreloadRemote = (runtimeRemote, remote${isLoadedFirstClientBuild ? ", registration" : ""}) => {
5673
+ ${isLoadedFirstClientBuild ? `if (registration && typeof runtime.registerRemotes === "function") {
5674
+ runtime.registerRemotes([registration]);
5675
+ }` : ""}
5259
5676
  const remoteCacheKey = ${JSON.stringify(remoteCachePrefix)} + remote;
5260
5677
  const pendingKey = "__mf_pending__" + remoteCacheKey;
5261
5678
  if (!__mfModuleCache.remote[pendingKey]) {
@@ -5273,7 +5690,7 @@ const __mfCurrentScript = document.currentScript;
5273
5690
  return __mfModuleCache.remote[pendingKey];
5274
5691
  };
5275
5692
  const __mfRemotePreloads = [${remotePreloads}];
5276
- await Promise.allSettled(__mfRemotePreloads);` : `await initHost();`;
5693
+ await ${isLoadedFirstClientBuild ? "Promise.all" : "Promise.allSettled"}(__mfRemotePreloads);` : `await initHost();`;
5277
5694
  const pendingShareLoadsAwait = `
5278
5695
  if (__mfModuleCache.pendingShareLoads) {
5279
5696
  await Promise.all(__mfModuleCache.pendingShareLoads);
@@ -5287,13 +5704,14 @@ const __mfCurrentScript = document.currentScript;
5287
5704
  const __mfHostInit = await ${importExpression(initSrc)};
5288
5705
  await __mfHostInit.__tla;
5289
5706
  const { initHost } = __mfHostInit;
5290
- ${preloadBlock}${pendingShareLoadsAwait}
5707
+ ${preloadBlock}${sharedPreloadBlock}${pendingShareLoadsAwait}
5291
5708
  })().then(() => ${entryImportExpression});
5292
5709
  `;
5293
5710
  return [
5294
5711
  getRuntimeModuleCacheBootstrapCode(),
5295
5712
  importHelper,
5296
5713
  entryImportDeclaration,
5714
+ remoteEntryPrefetchBlock,
5297
5715
  importCode
5298
5716
  ].join("\n");
5299
5717
  }
@@ -5325,6 +5743,17 @@ const __mfCurrentScript = document.currentScript;
5325
5743
  const normalized = decodeViteId(id).replace(/^\0+/, "");
5326
5744
  return normalized.includes("virtual:mf:") || /__(?:loadShare|prebuild|loadRemote)__/.test(normalized);
5327
5745
  }
5746
+ function isWorkspaceSourceId(id) {
5747
+ const normalized = normalizeModuleId(decodeViteId(id));
5748
+ if (normalized.startsWith("\0") || normalized.startsWith("virtual:")) return false;
5749
+ const filePath = stripQueryAndHash$1(normalized);
5750
+ if (filePath.startsWith("/@fs/")) return true;
5751
+ if (!path$1.isAbsolute(filePath)) return false;
5752
+ const root = normalizePathForImport(path$1.resolve(viteConfig.root));
5753
+ const absolutePath = normalizePathForImport(path$1.resolve(filePath));
5754
+ const relativePath = normalizePathForImport(path$1.relative(root, absolutePath));
5755
+ return (relativePath === ".." || relativePath.startsWith("../") || path$1.isAbsolute(relativePath)) && fs$2.existsSync(absolutePath);
5756
+ }
5328
5757
  function addEntryFile(file) {
5329
5758
  const normalized = normalizeModuleId(file);
5330
5759
  if (!entryFiles.includes(normalized)) entryFiles.push(normalized);
@@ -5391,7 +5820,10 @@ const __mfCurrentScript = document.currentScript;
5391
5820
  }
5392
5821
  const devFileName = resolveDevHashEntryFileName$1(fileName);
5393
5822
  if (devFileName !== fileName && req.url?.startsWith((viteConfig.base + devFileName).replace(/^\/?/, "/"))) req.url = req.url.replace(devFileName, fileName);
5394
- if (req.url && req.url.startsWith((viteConfig.base + fileName).replace(/^\/?/, "/"))) req.url = devEntryPath;
5823
+ if (req.url && req.url.startsWith((viteConfig.base + fileName).replace(/^\/?/, "/"))) {
5824
+ req.url = devEntryPath;
5825
+ req.headers["sec-fetch-dest"] = "script";
5826
+ }
5395
5827
  next();
5396
5828
  });
5397
5829
  },
@@ -5472,6 +5904,10 @@ const __mfCurrentScript = document.currentScript;
5472
5904
  },
5473
5905
  generateBundle(_options, bundle) {
5474
5906
  if (skipSvelteKitSsrBuild()) return;
5907
+ if (entryName === "remoteEntry" && emitFileId && fileName && !viteConfig?.build?.ssr && _options?.format === "es" && viteConfig?.build?.modulePreload !== false) {
5908
+ const remoteEntryFile = findRemoteEntryFile(fileName, bundle);
5909
+ if (remoteEntryFile) appendRemoteEntryWarmup(bundle, remoteEntryFile);
5910
+ }
5475
5911
  if (!injectHtml()) return;
5476
5912
  if (!emitFileId) return;
5477
5913
  const htmlFileNames = Object.keys(bundle).filter((fileName) => fileName.endsWith(".html"));
@@ -5533,12 +5969,12 @@ const __mfCurrentScript = document.currentScript;
5533
5969
  htmlContent = htmlContent.replace("<head>", `<head>${scriptContent}`);
5534
5970
  }
5535
5971
  }
5536
- if (waitsForInit && viteConfig.build.modulePreload !== false) htmlContent = injectHostInitPreloads(htmlContent, bundle, (builtFileName) => resolvePath(builtFileName, fileName));
5972
+ if (waitsForInit && viteConfig.build.modulePreload !== false) htmlContent = injectHostInitPreloads(htmlContent, bundle, (builtFileName) => resolvePath(builtFileName, fileName), getRemoteEntryPreloadUrls());
5537
5973
  htmlAsset.source = htmlContent;
5538
5974
  }
5539
5975
  },
5540
5976
  closeBundle() {
5541
- if (_command === "serve" || skipSvelteKitSsrBuild()) return;
5977
+ if (_command === "serve" || !hasPackageDependency("@sveltejs/kit") || skipSvelteKitSsrBuild()) return;
5542
5978
  let attempts = 0;
5543
5979
  const retry = () => {
5544
5980
  attempts += 1;
@@ -5578,7 +6014,7 @@ const __mfCurrentScript = document.currentScript;
5578
6014
  return mapCodeToCodeWithSourcemap(code.replace("vueApp.mount(vueAppRootContainer);", `${injection}vueApp.mount(vueAppRootContainer);`));
5579
6015
  }
5580
6016
  const isReactRouterEntry = isReactRouterClientEntry(id);
5581
- const isHydrationEntryFallback = inject === "entry" && entryFiles.length === 0 && (!htmlFilePath || !fs$2.existsSync(htmlFilePath)) && !clientInjected && !isFederationInternalVirtualId(id) && !id.includes("node_modules") && (!code.includes("HydratedRouter") || isReactRouterEntry) && (id.startsWith("\0") || /\.(js|ts|mjs|vue|jsx|tsx)(\?|$)/.test(id)) && (/hydrateRoot|createRoot|ReactDOM\.render/.test(code) || /\.mount\s*\(\s*['"#]/.test(code) || /\.mount\s*\(/.test(code) && /createSSRApp|createApp/.test(code));
6017
+ const isHydrationEntryFallback = inject === "entry" && entryFiles.length === 0 && (!htmlFilePath || !fs$2.existsSync(htmlFilePath)) && !clientInjected && !isFederationInternalVirtualId(id) && !id.includes("node_modules") && (!code.includes("HydratedRouter") || isReactRouterEntry) && (id.startsWith("\0") || /\.(js|ts|mjs|vue|jsx|tsx)(\?|$)/.test(id)) && (/hydrateRoot|createRoot|ReactDOM\.render/.test(code) || /\.mount\s*\(\s*['"#]/.test(code) || /\.mount\s*\(/.test(code) && /createSSRApp|createApp/.test(code)) && !isWorkspaceSourceId(id);
5582
6018
  const isNuxtEntryAsyncModule = /(?:^|\/)nuxt\/dist\/app\/entry\.async\.js(?:\?|$)/.test(id) && code.includes("entry();");
5583
6019
  const isNuxtClientEntryFallback = _command === "serve" && inject === "entry" && (!htmlFilePath || !fs$2.existsSync(htmlFilePath)) && !clientInjected && !hasEntryBootstrapParam(id) && !id.includes("node_modules/.vite") && isNuxtEntryAsyncModule && !entryFiles.some((file) => projectId === file);
5584
6020
  if (!(_command === "serve" && isNuxtEntryAsyncModule) && (injectedTransformIds.has(projectId) || injectEntry() && entryFiles.some((file) => projectId === file) || _command === "serve" && inject === "html" && !isVinext && !clientInjected && !skipHtmlDevFallback && !id.startsWith("\0") && !id.includes("node_modules") && /\.(js|ts|mjs|vue|jsx|tsx)(\?|$)/.test(id) || isHydrationEntryFallback || inject === "entry" && waitsForInit && isReactRouterEntry || isNuxtClientEntryFallback)) {
@@ -5669,6 +6105,7 @@ const REACT_REFRESH_PROXY_MODULE = [
5669
6105
  `const __rt = await import(__target);`,
5670
6106
  `export const injectIntoGlobalHook = __rt.injectIntoGlobalHook;`,
5671
6107
  `export const register = __rt.register;`,
6108
+ `export const getRefreshReg = __rt.getRefreshReg;`,
5672
6109
  `export const createSignatureFunctionForTransform = __rt.createSignatureFunctionForTransform;`,
5673
6110
  `export const registerExportsForReactRefresh = __rt.registerExportsForReactRefresh;`,
5674
6111
  `export const validateRefreshBoundaryAndEnqueueUpdate = __rt.validateRefreshBoundaryAndEnqueueUpdate;`,
@@ -6332,200 +6769,6 @@ function initVirtualModules(command, remoteEntryId, enableSsrInit = false, optio
6332
6769
  })) : void 0);
6333
6770
  }
6334
6771
  //#endregion
6335
- //#region src/utils/bundleHelpers.ts
6336
- function isOutputChunk$1(chunk) {
6337
- return chunk.type === "chunk";
6338
- }
6339
- function escapeRegExp$1(value) {
6340
- return value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
6341
- }
6342
- function getProxyBaseName(fileName) {
6343
- return fileName.replace(/^.*\//, "").replace(/\.js$/, "").replace(/-[A-Za-z0-9_-]+$/, "");
6344
- }
6345
- function extractFunctionDeclaration(code, functionName) {
6346
- const funcRe = new RegExp(`function\\s+${functionName}\\s*\\([^)]*\\)\\s*\\{`);
6347
- const funcStart = code.search(funcRe);
6348
- if (funcStart < 0) return;
6349
- let depth = 0;
6350
- for (let i = code.indexOf("{", funcStart); i < code.length; i++) if (code[i] === "{") depth++;
6351
- else if (code[i] === "}") {
6352
- depth--;
6353
- if (depth === 0) return code.slice(funcStart, i + 1);
6354
- }
6355
- }
6356
- /**
6357
- * Resolve the local alias for a non-inlineable proxy binding.
6358
- * If Rollup's deconflict renamed the alias but didn't update references
6359
- * in the code body, fall back to proxyLocal so they stay in sync.
6360
- */
6361
- function resolveProxyAlias(binding, proxyLocal, code, fullImport, claimedLocals = /* @__PURE__ */ new Set()) {
6362
- const codeWithoutImport = code.replace(fullImport, "");
6363
- const escapedLocal = binding.local.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
6364
- const localUsedInCode = new RegExp(`\\b${escapedLocal}\\b`).test(codeWithoutImport);
6365
- const claimedImportLocals = /* @__PURE__ */ new Set();
6366
- const importRe = /import\s*\{([^}]+)\}\s*from\s*["'][^"']+["']\s*;?/g;
6367
- let match;
6368
- while ((match = importRe.exec(codeWithoutImport)) !== null) for (const spec of match[1].split(",")) {
6369
- const parts = spec.trim().split(/\s+as\s+/);
6370
- claimedImportLocals.add((parts[1] || parts[0]).trim());
6371
- }
6372
- const local = !localUsedInCode && !claimedLocals.has(proxyLocal) && !claimedImportLocals.has(proxyLocal) ? proxyLocal : binding.local;
6373
- return {
6374
- imported: binding.imported,
6375
- local
6376
- };
6377
- }
6378
- function collectLoadShareProxyChunks(bundle, loadShareTag) {
6379
- const proxyChunks = /* @__PURE__ */ new Map();
6380
- for (const [fileName, chunk] of Object.entries(bundle)) {
6381
- if (!isOutputChunk$1(chunk)) continue;
6382
- if (fileName.includes(loadShareTag) && fileName.includes("commonjs-proxy")) proxyChunks.set(fileName, {
6383
- code: chunk.code,
6384
- fileName
6385
- });
6386
- }
6387
- return proxyChunks;
6388
- }
6389
- function collectSystemProxyInfos(proxyChunks, loadShareTag) {
6390
- const systemProxyInfo = /* @__PURE__ */ new Map();
6391
- for (const [proxyFileName, proxyInfo] of Array.from(proxyChunks.entries())) {
6392
- const depsMatch = proxyInfo.code.match(/System\.register\(\[([\s\S]*?)\]/);
6393
- if (!depsMatch) continue;
6394
- const loadShareDep = Array.from(depsMatch[1].matchAll(/["']([^"']+)["']/g)).map((m) => m[1]).find((dep) => dep.includes(loadShareTag) && !dep.includes("commonjs-proxy"));
6395
- if (!loadShareDep) continue;
6396
- const loadShareBindings = {};
6397
- for (const m of proxyInfo.code.matchAll(/([A-Za-z_$][\w$]*)\s*=\s*module\d+\.([A-Za-z_$][\w$]*)/g)) loadShareBindings[m[1]] = m[2];
6398
- const exportMap = {};
6399
- const objectExportMatch = proxyInfo.code.match(/exports\(\s*\{([\s\S]*?)\}\s*\)/);
6400
- if (objectExportMatch) for (const m of objectExportMatch[1].matchAll(/([A-Za-z_$][\w$]*)\s*:\s*([A-Za-z_$][\w$]*)/g)) {
6401
- const [, exported, local] = m;
6402
- const funcBody = extractFunctionDeclaration(proxyInfo.code, local);
6403
- if (funcBody) exportMap[exported] = {
6404
- type: "helper",
6405
- code: funcBody
6406
- };
6407
- }
6408
- for (const m of proxyInfo.code.matchAll(/exports\(\s*["']([^"']+)["']\s*,([\s\S]*?)\);/g)) {
6409
- const exported = m[1];
6410
- const expression = m[2];
6411
- for (const [local, exportName] of Object.entries(loadShareBindings).reverse()) if (new RegExp(`\\b${local}\\b`).test(expression)) {
6412
- exportMap[exported] = {
6413
- type: "reexport",
6414
- exportName
6415
- };
6416
- break;
6417
- }
6418
- }
6419
- if (Object.keys(exportMap).length > 0) systemProxyInfo.set(proxyFileName, {
6420
- loadShareDep,
6421
- exportMap
6422
- });
6423
- }
6424
- return systemProxyInfo;
6425
- }
6426
- function rewriteEsmProxyConsumers(code, proxyChunks) {
6427
- let nextCode = code;
6428
- const claimedLocals = /* @__PURE__ */ new Set();
6429
- for (const [proxyFileName, proxyInfo] of Array.from(proxyChunks.entries())) {
6430
- const proxyBaseName = getProxyBaseName(proxyFileName);
6431
- const importMatch = new RegExp(`import\\s*\\{([^}]+)\\}\\s*from\\s*["']([^"']*${escapeRegExp$1(proxyBaseName)}[^"']*)["']\\s*;?`).exec(nextCode);
6432
- if (!importMatch) continue;
6433
- const fullImport = importMatch[0];
6434
- const bindings = importMatch[1].split(",").map((s) => {
6435
- const parts = s.trim().split(/\s+as\s+/);
6436
- return {
6437
- imported: parts[0].trim(),
6438
- local: (parts[1] || parts[0]).trim()
6439
- };
6440
- });
6441
- const exportMapMatch = proxyInfo.code.match(/export\s*\{([^}]+)\}/);
6442
- if (!exportMapMatch) continue;
6443
- const exportMap = {};
6444
- for (const entry of exportMapMatch[1].split(",")) {
6445
- const parts = entry.trim().split(/\s+as\s+/);
6446
- if (parts.length === 2) exportMap[parts[1].trim()] = parts[0].trim();
6447
- }
6448
- const inlineable = [];
6449
- const nonInlineable = [];
6450
- const pendingLocals = new Set(bindings.map((binding) => binding.local));
6451
- for (const b of bindings) {
6452
- pendingLocals.delete(b.local);
6453
- const proxyLocal = exportMap[b.imported];
6454
- if (!proxyLocal) {
6455
- claimedLocals.add(b.local);
6456
- nonInlineable.push(b);
6457
- continue;
6458
- }
6459
- const funcBody = extractFunctionDeclaration(proxyInfo.code, proxyLocal);
6460
- if (funcBody) {
6461
- inlineable.push({
6462
- local: b.local,
6463
- funcBody: funcBody.replace(new RegExp(`function\\s+${proxyLocal}\\s*\\(`), `function ${b.local}(`)
6464
- });
6465
- claimedLocals.add(b.local);
6466
- } else {
6467
- const unavailableLocals = new Set(claimedLocals);
6468
- pendingLocals.forEach((local) => unavailableLocals.add(local));
6469
- const resolvedBinding = resolveProxyAlias(b, proxyLocal, nextCode, fullImport, unavailableLocals);
6470
- claimedLocals.add(resolvedBinding.local);
6471
- nonInlineable.push(resolvedBinding);
6472
- }
6473
- }
6474
- const hasRenamedAlias = nonInlineable.some((b) => bindings.find((ob) => ob.imported === b.imported)?.local !== b.local);
6475
- if (inlineable.length === 0 && !hasRenamedAlias) continue;
6476
- let replacement = "";
6477
- if (nonInlineable.length > 0) replacement = `import{${nonInlineable.map((b) => b.imported === b.local ? b.imported : `${b.imported} as ${b.local}`).join(",")}}from"${importMatch[2]}";`;
6478
- replacement += inlineable.map((f) => f.funcBody).join("");
6479
- nextCode = nextCode.replace(fullImport, () => replacement);
6480
- }
6481
- return nextCode;
6482
- }
6483
- function rewriteSystemProxyConsumers(code, systemProxyInfo) {
6484
- if (!code.includes("System.register(")) return code;
6485
- let nextCode = code;
6486
- for (const [proxyFileName, proxyInfo] of Array.from(systemProxyInfo.entries())) {
6487
- const proxyBaseName = getProxyBaseName(proxyFileName);
6488
- const depMatch = new RegExp(`["']([^"']*${escapeRegExp$1(proxyBaseName)}[^"']*)["']`).exec(nextCode);
6489
- if (!depMatch) continue;
6490
- let setterIndex = 0;
6491
- const depListMatch = nextCode.match(/System\.register\(\[([\s\S]*?)\]/);
6492
- if (depListMatch) setterIndex = Array.from(depListMatch[1].matchAll(/["']([^"']+)["']/g)).map((m) => m[1]).findIndex((dep) => dep.includes(proxyBaseName));
6493
- if (setterIndex < 0) continue;
6494
- const settersStart = nextCode.indexOf("setters: [");
6495
- if (settersStart < 0) continue;
6496
- const setterMatch = Array.from(nextCode.slice(settersStart).matchAll(/\((module\d+)\)\s*=>\s*\{([\s\S]*?)\}/g))[setterIndex];
6497
- if (!setterMatch) continue;
6498
- const [fullSetter, moduleLocal, setterBody] = setterMatch;
6499
- const helpersToInline = [];
6500
- const nextSetterBody = setterBody.replace(new RegExp(`([A-Za-z_$][\\w$]*)\\s*=\\s*${moduleLocal}\\.([A-Za-z_$][\\w$]*);?`, "g"), (assignment, local, imported) => {
6501
- const mapped = proxyInfo.exportMap[imported];
6502
- if (!mapped) return assignment;
6503
- if (mapped.type === "helper") {
6504
- helpersToInline.push(mapped.code.replace(new RegExp(`function\\s+${imported}\\s*\\(`), `function ${local}(`));
6505
- return "";
6506
- }
6507
- return `${local} = ${moduleLocal}.${mapped.exportName};`;
6508
- });
6509
- if (nextSetterBody === setterBody && helpersToInline.length === 0) continue;
6510
- const nextSetter = fullSetter.replace(setterBody, () => nextSetterBody);
6511
- nextCode = nextCode.replace(fullSetter, () => nextSetter);
6512
- nextCode = nextCode.replace(depMatch[0], JSON.stringify(proxyInfo.loadShareDep));
6513
- if (helpersToInline.length > 0) nextCode = nextCode.replace("execute: (function() {", () => {
6514
- return `execute: (function() {${helpersToInline.join("")}`;
6515
- });
6516
- }
6517
- return nextCode;
6518
- }
6519
- function findRemoteEntryFile(filename, bundle) {
6520
- const strippedName = filename.replace(/[\[\]]/g, "_").replace(/\.[^/.]+$/, "");
6521
- let fallback;
6522
- for (const fileData of Object.values(bundle)) {
6523
- if (fileData.fileName === filename) return fileData.fileName;
6524
- if (fallback === void 0 && (strippedName === fileData.name || fileData.name === "remoteEntry")) fallback = fileData.fileName;
6525
- }
6526
- return fallback;
6527
- }
6528
- //#endregion
6529
6772
  //#region src/utils/cssModuleHelpers.ts
6530
6773
  const ASSET_TYPES = ["js", "css"];
6531
6774
  const LOAD_TIMINGS = ["sync", "async"];
@@ -6589,28 +6832,33 @@ const chunkContainsCssModules = (modules) => {
6589
6832
  for (const modulePath of Object.keys(modules)) if (isCSSFile(modulePath)) return true;
6590
6833
  return false;
6591
6834
  };
6835
+ const collectStaticChunks = (bundle, roots) => {
6836
+ const chunks = [];
6837
+ const visited = /* @__PURE__ */ new Set();
6838
+ const queue = [...roots];
6839
+ for (let queueIndex = 0; queueIndex < queue.length; queueIndex++) {
6840
+ const fileName = queue[queueIndex];
6841
+ if (visited.has(fileName)) continue;
6842
+ visited.add(fileName);
6843
+ const chunk = bundle[fileName];
6844
+ if (!chunk || chunk.type !== "chunk") continue;
6845
+ chunks.push(chunk);
6846
+ queue.push(...chunk.imports ?? []);
6847
+ }
6848
+ return chunks;
6849
+ };
6592
6850
  /**
6593
6851
  * Analyzes assets associated with a chunk without mutating the output map.
6594
6852
  * The static-import traversal is cycle-safe and ignores missing bundle entries.
6595
6853
  */
6596
6854
  const analyzeChunkAssets = (bundle, fileName, chunk) => {
6597
6855
  const dynamicAssets = [];
6598
- const visited = /* @__PURE__ */ new Set();
6599
- const queue = [fileName];
6600
- for (let queueIndex = 0; queueIndex < queue.length; queueIndex++) {
6601
- const currentFileName = queue[queueIndex];
6602
- if (visited.has(currentFileName)) continue;
6603
- visited.add(currentFileName);
6604
- const currentChunk = bundle[currentFileName];
6605
- if (!currentChunk || currentChunk.type !== "chunk") continue;
6606
- for (const dynamicImport of currentChunk.dynamicImports ?? []) {
6607
- if (!bundle[dynamicImport]) continue;
6608
- dynamicAssets.push({
6609
- fileName: dynamicImport,
6610
- type: isCSSFile(dynamicImport) ? "css" : "js"
6611
- });
6612
- }
6613
- for (const staticImport of currentChunk.imports ?? []) queue.push(staticImport);
6856
+ for (const currentChunk of collectStaticChunks(bundle, [fileName])) for (const dynamicImport of currentChunk.dynamicImports ?? []) {
6857
+ if (!bundle[dynamicImport]) continue;
6858
+ dynamicAssets.push({
6859
+ fileName: dynamicImport,
6860
+ type: isCSSFile(dynamicImport) ? "css" : "js"
6861
+ });
6614
6862
  }
6615
6863
  return {
6616
6864
  importedCss: Array.from(chunk.viteMetadata?.importedCss ?? []),
@@ -6927,6 +7175,54 @@ function isTreeShakingProviderChunk(file) {
6927
7175
  if (file.facadeModuleId?.includes("__treeShakingProvider__")) return true;
6928
7176
  return Object.keys(file.modules || {}).some((id) => id.includes("__treeShakingProvider__") || id.includes("__mf_tree_shaking_graph__"));
6929
7177
  }
7178
+ function isContainerBootstrapChunk(chunk, moduleIds) {
7179
+ return [chunk.facadeModuleId, ...chunk.moduleIds ?? []].some((id) => typeof id === "string" && moduleIds.has(normalizeVirtualModuleId(id)));
7180
+ }
7181
+ function collectImportedCss(chunks) {
7182
+ const css = /* @__PURE__ */ new Set();
7183
+ for (const chunk of chunks) for (const cssFile of chunk.viteMetadata?.importedCss ?? []) css.add(cssFile);
7184
+ return Array.from(css);
7185
+ }
7186
+ function expandExposeAssets(filesMap, exposeModules, bundle, remoteEntryFileName, options) {
7187
+ if (exposeModules.length === 0) return;
7188
+ const containerChunks = remoteEntryFileName ? collectStaticChunks(bundle, [remoteEntryFileName]) : [];
7189
+ const bootstrapChunks = containerChunks.slice(1);
7190
+ const seen = new Set(containerChunks.map((chunk) => chunk.fileName));
7191
+ if (containerChunks.length > 0) {
7192
+ const bootstrapModuleIds = /* @__PURE__ */ new Set([getLocalSharedImportMapPath(options), getVirtualExposesId(options)]);
7193
+ for (const containerChunk of containerChunks) for (const imported of containerChunk.dynamicImports ?? []) {
7194
+ const importedChunk = bundle[imported];
7195
+ if (!importedChunk || importedChunk.type !== "chunk" || !isContainerBootstrapChunk(importedChunk, bootstrapModuleIds)) continue;
7196
+ for (const chunk of collectStaticChunks(bundle, [imported])) {
7197
+ if (seen.has(chunk.fileName)) continue;
7198
+ seen.add(chunk.fileName);
7199
+ bootstrapChunks.push(chunk);
7200
+ }
7201
+ }
7202
+ }
7203
+ const bootstrapAssets = bootstrapChunks.map((chunk) => chunk.fileName);
7204
+ const bootstrapCss = collectImportedCss(bootstrapChunks);
7205
+ for (const exposeModule of exposeModules) {
7206
+ const assets = filesMap[exposeModule];
7207
+ if (!assets) continue;
7208
+ const syncChunks = collectStaticChunks(bundle, assets.js.sync);
7209
+ const sync = Array.from(/* @__PURE__ */ new Set([...bootstrapAssets, ...syncChunks.map((chunk) => chunk.fileName)]));
7210
+ const syncSet = new Set(sync);
7211
+ const asyncChunks = collectStaticChunks(bundle, assets.js.async);
7212
+ const async = asyncChunks.map((chunk) => chunk.fileName).filter((fileName) => !syncSet.has(fileName));
7213
+ assets.js.sync = sync;
7214
+ assets.js.async = async;
7215
+ const syncCss = Array.from(/* @__PURE__ */ new Set([
7216
+ ...assets.css.sync,
7217
+ ...bootstrapCss,
7218
+ ...collectImportedCss(syncChunks)
7219
+ ]));
7220
+ const syncCssSet = new Set(syncCss);
7221
+ const asyncCss = Array.from(/* @__PURE__ */ new Set([...assets.css.async, ...collectImportedCss(asyncChunks)])).filter((fileName) => !syncCssSet.has(fileName));
7222
+ assets.css.sync = syncCss;
7223
+ assets.css.async = asyncCss;
7224
+ }
7225
+ }
6930
7226
  function getTreeShakingBuildInfo(options) {
6931
7227
  if (!(Object.values(options.shared || {}).some((share) => !!share.shareConfig.treeShaking) || !!options.treeShakingSharedPlugins?.length || !!options.treeShakingSharedExcludePlugins?.length)) return {};
6932
7228
  return {
@@ -7089,6 +7385,7 @@ const Manifest = (providedOptions) => {
7089
7385
  root,
7090
7386
  stripKnownJsExtensions: true
7091
7387
  });
7388
+ expandExposeAssets(filesMap, exposesModules, bundle, foundRemoteEntryFile, mfOptions);
7092
7389
  const fileToShareKey = await buildFileToShareKeyMap(getUsedShares(mfOptions), this.resolve.bind(this), mfOptions);
7093
7390
  processModuleAssets(Object.fromEntries(Object.entries(bundle).filter(([, file]) => !isTreeShakingProviderChunk(file))), filesMap, (modulePath) => fileToShareKey.get(modulePath));
7094
7391
  if (mfOptions.bundleAllCSS) addCssAssetsToAllExports(filesMap, allCssAssets);
@@ -7452,12 +7749,18 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
7452
7749
  return Object.keys(options.remotes).some((name) => source === name || source.startsWith(name + "/"));
7453
7750
  }
7454
7751
  function collectImportSources(code) {
7455
- const sources = /* @__PURE__ */ new Set();
7752
+ const sources = /* @__PURE__ */ new Map();
7456
7753
  for (const match of code.matchAll(/(?:^|[;\n\r])\s*import\s+(?:[\s\S]*?\s+from\s+)?["']([^"']+)["']|import\(\s*["']([^"']+)["']\s*\)/g)) {
7457
7754
  const source = match[1] || match[2];
7458
- if (source) sources.add(source);
7755
+ if (source) {
7756
+ const dynamic = !match[1];
7757
+ sources.set(source, (sources.get(source) ?? true) && dynamic);
7758
+ }
7459
7759
  }
7460
- return Array.from(sources).sort();
7760
+ return Array.from(sources, ([source, dynamic]) => ({
7761
+ source,
7762
+ dynamic
7763
+ })).sort((a, b) => a.source.localeCompare(b.source));
7461
7764
  }
7462
7765
  function shouldScanResolvedImport(id) {
7463
7766
  if (!id || id.includes("\0")) return false;
@@ -7474,9 +7777,9 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
7474
7777
  return [];
7475
7778
  }
7476
7779
  const dependencies = /* @__PURE__ */ new Set();
7477
- for (const source of collectImportSources(code)) {
7780
+ for (const { source, dynamic } of collectImportSources(code)) {
7478
7781
  if (isRemoteImport(source)) {
7479
- dependencies.add(source);
7782
+ if (!dynamic) dependencies.add(source);
7480
7783
  continue;
7481
7784
  }
7482
7785
  const resolved = await ctx.resolve(source, id);
@@ -7859,6 +8162,7 @@ function excludeSharedSubDependencies(shared) {
7859
8162
  delete shared[depKey];
7860
8163
  sharedKeys.delete(depKey);
7861
8164
  sharedKeyByBase.delete(dep);
8165
+ sharedKeyMatcherCache.delete(shared);
7862
8166
  }
7863
8167
  }
7864
8168
  }
@@ -8083,15 +8387,6 @@ const JS_EXTENSIONS_RE = /\.(?:[mc]?[jt]sx?|vue|svelte)(?:\?|$)/;
8083
8387
  function isAstNode(value) {
8084
8388
  return !!value && typeof value === "object" && typeof value.type === "string";
8085
8389
  }
8086
- function findStaticRemoteSources(code, isRemoteImport) {
8087
- const codePositions = createCodePositionMap(code);
8088
- const sources = /* @__PURE__ */ new Set();
8089
- for (const pattern of [/\b(?:import|export)\s+[^;]*?\bfrom\s*["']([^"']+)["']/g, /\bimport\s*["']([^"']+)["']/g]) for (const match of code.matchAll(pattern)) {
8090
- const source = match[1];
8091
- if (codePositions[match.index] && isRemoteImport(source)) sources.add(source);
8092
- }
8093
- return sources;
8094
- }
8095
8390
  function walkAST(root, visitor) {
8096
8391
  const seen = /* @__PURE__ */ new WeakSet();
8097
8392
  function visit(node) {
@@ -8148,8 +8443,10 @@ function applyRewrites(code, imports, id) {
8148
8443
  importParts.push(`__mf_remote_pending as ${pendingId}`);
8149
8444
  let rewrite = `import { ${importParts.join(", ")} } from ${src};`;
8150
8445
  if (imp.named.length > 0) {
8151
- const destructParts = imp.named.map((s) => `${s.imported}: ${s.local}`);
8152
- rewrite += `\nconst { ${destructParts.join(", ")} } = ${nsId};`;
8446
+ const declarations = imp.named.map((s) => `let ${s.local};`).join("\n");
8447
+ const initializers = imp.named.map((s) => `if (${JSON.stringify(s.imported)} in ${nsId}) {\n${s.local} = ${nsId}[${JSON.stringify(s.imported)}];\n}`).join("\n");
8448
+ const assignments = imp.named.map((s) => `${s.local} = ${nsId}[${JSON.stringify(s.imported)}];`).join("\n");
8449
+ rewrite += `\n${declarations}\n${initializers}\n${pendingId}.then(() => {\n${assignments}\n});`;
8153
8450
  }
8154
8451
  ms.overwrite(imp.start, imp.end, rewrite);
8155
8452
  }
@@ -8169,10 +8466,11 @@ function applyRewrites(code, imports, id) {
8169
8466
  };
8170
8467
  });
8171
8468
  const importLine = `import { __moduleExports as ${nsId}, __mf_remote_pending as ${pendingId} } from ${src};`;
8172
- const varLines = vars.map((v) => `let ${v.tmp} = ${nsId}[${JSON.stringify(v.local)}];`).join("\n");
8469
+ const varLines = vars.map((v) => `let ${v.tmp};`).join("\n");
8470
+ const initializers = vars.map((v) => `if (${JSON.stringify(v.local)} in ${nsId}) {\n${v.tmp} = ${nsId}[${JSON.stringify(v.local)}];\n}`).join("\n");
8173
8471
  const syncLine = `${pendingId}.then(() => {\n${vars.map((v) => `${v.tmp} = ${nsId}[${JSON.stringify(v.local)}];`).join("\n")}\n});`;
8174
8472
  const exportLine = `export { ${vars.map((v) => `${v.tmp} as ${v.exported}`).join(", ")} };`;
8175
- ms.overwrite(imp.start, imp.end, `${importLine}\n${varLines}\n${syncLine}\n${exportLine}`);
8473
+ ms.overwrite(imp.start, imp.end, `${importLine}\n${varLines}\n${initializers}\n${syncLine}\n${exportLine}`);
8176
8474
  changed = true;
8177
8475
  break;
8178
8476
  }
@@ -8350,7 +8648,7 @@ function pluginRemoteNamedExports(options) {
8350
8648
  if (!JS_EXTENSIONS_RE.test(id)) return;
8351
8649
  if (!remoteNames.some((name) => code.includes(name))) return;
8352
8650
  const matchesRemoteImport = (source) => isRemoteImport(source, id);
8353
- for (const source of findStaticRemoteSources(code, matchesRemoteImport)) markStaticRemote(source, options);
8651
+ for (const { kind, source, typeOnly } of findModuleImportDescriptors(code)) if (kind === "static" && !typeOnly && matchesRemoteImport(source)) markStaticRemote(source, options);
8354
8652
  let imports;
8355
8653
  try {
8356
8654
  imports = await collectFromAST(this.parse(code), code, matchesRemoteImport);
@@ -8858,7 +9156,7 @@ const FEDERATION_CONTROL_CHUNK_HINTS = [
8858
9156
  "localSharedImportMap"
8859
9157
  ];
8860
9158
  function stripEmptyPreloadCalls(code) {
8861
- const helperImportRegex = /import\s*\{\s*_\s*as\s*(\w+)\s*\}\s*from\s*["'][^"']+["']\s*;?/g;
9159
+ const helperImportRegex = /import\s*\{\s*_\s*as\s*([A-Za-z_$][\w$]*)\s*\}\s*from\s*["'][^"']+["']\s*;?/g;
8862
9160
  const helperAliases = [];
8863
9161
  let helperImportMatch;
8864
9162
  while ((helperImportMatch = helperImportRegex.exec(code)) !== null) helperAliases.push(helperImportMatch[1]);
@@ -8894,7 +9192,7 @@ function stripEmptyPreloadCalls(code) {
8894
9192
  }
8895
9193
  nextCode = nextCode.replace(/import\s*["'][^"']*__loadShare__[^"']*["']\s*;?/g, "");
8896
9194
  nextCode = nextCode.replace(helperImportRegex, (statement, local) => {
8897
- return new RegExp(`\\b${local}\\b`).test(nextCode.replace(statement, "")) ? statement : "";
9195
+ return isIdentifierReferenced(local, nextCode.replace(statement, "")) ? statement : "";
8898
9196
  });
8899
9197
  return nextCode;
8900
9198
  }
@@ -9140,6 +9438,14 @@ function includeLinkedSharedEntries(optimizeDeps, shared, projectRoot, exposes,
9140
9438
  ]);
9141
9439
  for (const [packageName, share] of Object.entries(shared ?? {})) {
9142
9440
  if (share?.shareConfig?.import === false) continue;
9441
+ const configuredImport = share?.shareConfig?.import;
9442
+ if (typeof configuredImport === "string") {
9443
+ const entry = path$1.isAbsolute(configuredImport) ? configuredImport : path$1.resolve(projectRoot, configuredImport);
9444
+ if (existsSync(entry) && !entry.replaceAll("\\", "/").includes("/node_modules/")) {
9445
+ additions.add(entry);
9446
+ continue;
9447
+ }
9448
+ }
9143
9449
  const installed = getInstalledPackageJson(packageName, { cwd: projectRoot });
9144
9450
  if (!installed || installed.dir.replaceAll("\\", "/").includes("/node_modules/")) continue;
9145
9451
  const entry = getInstalledPackageEntry(packageName, { cwd: projectRoot });
@@ -9167,9 +9473,10 @@ function isFile(candidate) {
9167
9473
  return false;
9168
9474
  }
9169
9475
  }
9170
- function registerEntryImports(options, projectRoot) {
9171
- const staticImport = /\b(?:import|export)\s+(?:type\s+)?(?:[^'";]*?\s+from\s*)?(['"])([^'"]+)\1/g;
9172
- const dynamicImport = /\b(?:import|require)\s*\(\s*(['"])([^'"]+)\1/g;
9476
+ function isReactRouterBuildClientRouteInput(entry) {
9477
+ return /[?&]__react-router-build-client-route(?:[=&]|$)/.test(entry);
9478
+ }
9479
+ function registerEntryImports(options, projectRoot, recordShared = true, entryFiles = []) {
9173
9480
  const sourceExtensions = [
9174
9481
  ".mjs",
9175
9482
  ".js",
@@ -9199,10 +9506,15 @@ function registerEntryImports(options, projectRoot) {
9199
9506
  preloadRemotes
9200
9507
  });
9201
9508
  };
9202
- const htmlEntry = path$1.join(root, "index.html");
9203
- if (existsSync(htmlEntry)) {
9509
+ const htmlEntries = entryFiles.filter((file) => file.endsWith(".html"));
9510
+ const htmlEntryPaths = htmlEntries.length ? htmlEntries : entryFiles.length === 0 ? [path$1.join(root, "index.html")] : [];
9511
+ for (const htmlEntry of htmlEntryPaths) if (existsSync(htmlEntry)) {
9204
9512
  const html = readFileSync(htmlEntry, "utf8");
9205
- for (const match of html.matchAll(/<script\b[^>]*\bsrc=(['"])([^'"]+)\1[^>]*>/gi)) enqueue(match[2], htmlEntry, true);
9513
+ for (const match of html.matchAll(/<script\b(?=[^>]*\btype=["']module["'])(?=[^>]*\bsrc=(['"])([^'"]+)\1)[^>]*>/gi)) enqueue(match[2], htmlEntry, true);
9514
+ }
9515
+ for (const entry of entryFiles.filter((file) => !file.endsWith(".html"))) {
9516
+ const relativeEntry = path$1.relative(root, entry);
9517
+ enqueue(relativeEntry.startsWith(".") ? relativeEntry : `./${relativeEntry}`, path$1.join(root, "index.html"), true);
9206
9518
  }
9207
9519
  for (const expose of Object.values(options.exposes ?? {})) enqueue(expose.import);
9208
9520
  while (pending.length) {
@@ -9210,17 +9522,15 @@ function registerEntryImports(options, projectRoot) {
9210
9522
  if (visited.get(file) || visited.has(file) && !preloadRemotes) continue;
9211
9523
  visited.set(file, preloadRemotes);
9212
9524
  const code = readFileSync(file, "utf8");
9213
- for (const pattern of [staticImport, dynamicImport]) {
9214
- const isStatic = pattern === staticImport;
9215
- pattern.lastIndex = 0;
9216
- for (const match of code.matchAll(pattern)) {
9217
- const request = match[2];
9218
- const remoteKey = preloadRemotes && isStatic && request ? Object.keys(options.remotes).find((name) => request === name || request.startsWith(`${name}/`)) : void 0;
9219
- const sharedKey = request && findSharedKey(request, options.shared);
9220
- if (remoteKey) addUsedRemote(remoteKey, request, options);
9221
- else if (sharedKey) addUsedShares(request, options);
9222
- else if (request) enqueue(request, file, preloadRemotes && isStatic);
9223
- }
9525
+ for (const { source: request, kind, typeOnly } of findModuleImportDescriptors(code)) {
9526
+ const isStatic = kind === "static" && !typeOnly;
9527
+ const remoteKey = preloadRemotes && isStatic && request ? Object.keys(options.remotes).find((name) => request === name || request.startsWith(`${name}/`)) : void 0;
9528
+ const sharedKey = !typeOnly && request && findSharedKey(request, options.shared);
9529
+ if (remoteKey) {
9530
+ addUsedRemote(remoteKey, request, options);
9531
+ markStaticRemote(request, options);
9532
+ } else if (sharedKey && recordShared) addUsedShares(request, options);
9533
+ else if (request && !typeOnly) enqueue(request, file, preloadRemotes && isStatic);
9224
9534
  }
9225
9535
  }
9226
9536
  }
@@ -9238,6 +9548,8 @@ function createEarlyVirtualModulesPlugin(options) {
9238
9548
  config(config, { command: _command }) {
9239
9549
  if (_command === "serve") ignoreFederationGeneratedFiles(config, options);
9240
9550
  const root = config.root || process.cwd();
9551
+ const buildInput = getBuildInput(config);
9552
+ const resolvedConfiguredEntryFiles = (typeof buildInput === "string" ? [buildInput] : Array.isArray(buildInput) ? buildInput : buildInput && typeof buildInput === "object" ? Object.values(buildInput) : []).map((entry) => String(entry)).filter((entry) => !isReactRouterBuildClientRouteInput(entry)).map((entry) => entry.split(/[?#]/)[0]).map((entry) => path$1.isAbsolute(entry) ? entry : path$1.resolve(root, entry));
9241
9553
  resetConcreteSharedImportSourceCache();
9242
9554
  setPackageDetectionCwd(root);
9243
9555
  const isVinext = hasPackageDependency("vinext");
@@ -9252,7 +9564,7 @@ function createEarlyVirtualModulesPlugin(options) {
9252
9564
  config.optimizeDeps.exclude.push(...Object.keys(remotes || {}));
9253
9565
  }
9254
9566
  }
9255
- if (_command === "serve" && (Object.keys(shared ?? {}).length > 0 || Object.keys(remotes ?? {}).length > 0)) registerEntryImports(options, root);
9567
+ if (!config.build?.ssr && (Object.keys(shared ?? {}).length > 0 || Object.keys(remotes ?? {}).length > 0)) registerEntryImports(options, root, _command === "serve", resolvedConfiguredEntryFiles);
9256
9568
  if (shared && Object.keys(shared).length > 0) {
9257
9569
  if (_command === "serve") {
9258
9570
  excludeSharedSubDependencies(shared);
@@ -9316,9 +9628,20 @@ function createEarlyVirtualModulesPlugin(options) {
9316
9628
  if (args.kind === "entry-point") return;
9317
9629
  if (!args.importer || args.namespace === "mf-shared") return;
9318
9630
  if (isSharedResolverInternalImporter(args.importer)) return;
9319
- if (!findSharedKey(args.path, shared) || isAssetLikeImport(args.path)) return;
9631
+ const key = findSharedKey(args.path, shared);
9632
+ if (!key || isAssetLikeImport(args.path)) return;
9320
9633
  if (getPackageNameFromNodeModulePath(args.importer) === getPackageName(args.path) && !isReactDomSelfReference(args.path, args.importer)) return;
9321
9634
  addUsedShares(args.path, options);
9635
+ if (args.kind === "import-statement" || args.kind === "dynamic-import") {
9636
+ const shareItem = shared[key];
9637
+ const loadSharePath = getLoadShareModulePath(args.path, isRolldown, options);
9638
+ writeLoadShareModule(args.path, shareItem, _command, isRolldown, options);
9639
+ if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(args.path, shareItem, options);
9640
+ return {
9641
+ path: loadSharePath,
9642
+ external: true
9643
+ };
9644
+ }
9322
9645
  return {
9323
9646
  path: args.path,
9324
9647
  namespace: "mf-shared"
@@ -9375,7 +9698,7 @@ export default __mfShared.default ?? __mfShared;`
9375
9698
  optimizeDeps.exclude ??= [];
9376
9699
  const shouldBypassOptimizeDep = isLitShare(key) || !canResolveSharedSubpath(key, root);
9377
9700
  if (optimizeDeps.include.includes(key)) optimizeDeps.exclude = optimizeDeps.exclude.filter((dep) => dep !== key);
9378
- else if (shouldBypassOptimizeDep) optimizeDeps.exclude.push(key);
9701
+ else if (shouldBypassOptimizeDep || optimizeDeps.exclude.includes(key)) optimizeDeps.exclude.push(key);
9379
9702
  else optimizeDeps.include.push(key);
9380
9703
  for (const subpath of getCommonSharedSubpaths(key)) {
9381
9704
  const canResolveSubpath = canResolveSharedSubpath(subpath, root);
@@ -9580,7 +9903,10 @@ function federation(mfUserOptions) {
9580
9903
  },
9581
9904
  load(id, loadOptions) {
9582
9905
  if (id.includes("__loadRemote__") && !refreshLoadRemoteModuleForEnvironment(id, this, loadOptions)) return;
9583
- if (command !== "build" && id.includes("__loadShare__") && refreshLoadShareModuleForEnvironment(id, this, loadOptions) === "not-owned") return;
9906
+ if (command !== "build" && id.includes("__loadShare__")) {
9907
+ id = findCurrentLoadShareForStaleOwnerId(id, options.shared, findSharedKey, options)?.getResolvedId() ?? id;
9908
+ if (refreshLoadShareModuleForEnvironment(id, this, loadOptions) === "not-owned") return;
9909
+ }
9584
9910
  if (id.includes("__prebuild__") && refreshPreBuildModuleForEnvironment(id, this, loadOptions) === "not-owned") return;
9585
9911
  if (id.includes("__H_A_I__") && isOwnedHostAutoInitId(id, options)) refreshHostAutoInit(options, getLoadHookExportConditions(this, loadOptions));
9586
9912
  const virtualModule = VirtualModule.findById(id);