@module-federation/vite 1.20.7 → 1.20.8

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),
@@ -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
  }
@@ -5240,6 +5617,16 @@ const __mfCurrentScript = document.currentScript;
5240
5617
  }
5241
5618
  return patched;
5242
5619
  }
5620
+ function getRemoteEntryPreloadUrls() {
5621
+ const normalizedOptions = federationOptions ?? getNormalizeModuleFederationOptions();
5622
+ const isLoadedFirstClientBuild = (_command === "build" || viteConfig?.command === "build") && waitsForInit && !viteConfig?.build?.ssr && normalizedOptions.shareStrategy === "loaded-first";
5623
+ if (normalizedOptions.shareStrategy === "loaded-first" && !isLoadedFirstClientBuild) return [];
5624
+ const remoteSources = isLoadedFirstClientBuild ? Array.from(getStaticRemotes(normalizedOptions)) : Object.entries(getUsedRemotesMap(federationOptions)).flatMap(([, remotes]) => Array.from(remotes)).filter((remote) => !federationOptions || !isDynamicOnlyRemote(remote, federationOptions));
5625
+ return Array.from(new Set(remoteSources.flatMap((remote) => {
5626
+ const registration = getRemoteRegistration(remote, normalizedOptions.remotes, federationOptions);
5627
+ return registration && (registration.type === "module" || registration.type === "esm") && /^(?:https?:)?\/\//.test(registration.entry) ? [registration.entry] : [];
5628
+ })));
5629
+ }
5243
5630
  function getBootstrapSource(initSrc, entrySrc, useSystemImportFallback = false, options) {
5244
5631
  const importHelper = useSystemImportFallback ? `const __mfImport = (src) =>
5245
5632
  globalThis.System && typeof globalThis.System.import === 'function'
@@ -5251,11 +5638,35 @@ const __mfCurrentScript = document.currentScript;
5251
5638
  const entryImportDeclaration = isEncodedVirtualEntry ? `const __mfEntryUrl = ${JSON.stringify(entrySrc)};
5252
5639
  ` : "";
5253
5640
  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(",") : "";
5641
+ const normalizedOptions = federationOptions ?? getNormalizeModuleFederationOptions();
5642
+ const isLoadedFirstClientBuild = (_command === "build" || viteConfig?.command === "build") && waitsForInit && !viteConfig?.build?.ssr && normalizedOptions.shareStrategy === "loaded-first";
5643
+ const shouldPreloadRemotes = !options?.skipRemotePreload && (normalizedOptions.shareStrategy !== "loaded-first" || isLoadedFirstClientBuild);
5644
+ const remoteSources = isLoadedFirstClientBuild ? Array.from(getStaticRemotes(normalizedOptions)) : Object.entries(getUsedRemotesMap(federationOptions)).flatMap(([, remotes]) => Array.from(remotes)).filter((remote) => !federationOptions || !isDynamicOnlyRemote(remote, federationOptions));
5645
+ const remotePreloads = shouldPreloadRemotes ? remoteSources.sort().map((remote) => {
5646
+ const registration = isLoadedFirstClientBuild ? getRemoteRegistration(remote, normalizedOptions.remotes, federationOptions) : void 0;
5647
+ return `__mfPreloadRemote(${JSON.stringify(getRuntimeRemoteId(remote, normalizedOptions.remotes, federationOptions))}, ${JSON.stringify(remote)}${registration ? `, ${JSON.stringify(registration)}` : ""})`;
5648
+ }).join(",") : "";
5649
+ const remoteEntryPrefetchUrls = shouldPreloadRemotes ? getRemoteEntryPreloadUrls() : [];
5650
+ const remoteEntryPrefetchBlock = remoteEntryPrefetchUrls.length > 0 ? `const __mfRemoteEntryPrefetchUrls = ${JSON.stringify(remoteEntryPrefetchUrls)};
5651
+ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
5652
+ import(/* @vite-ignore */ __mfRemoteEntryPrefetchUrl).catch(() => {});
5653
+ }
5654
+ ` : "";
5655
+ 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) => {
5656
+ const shareItem = federationOptions.shared[pkg] || Object.entries(federationOptions.shared).find(([key]) => key.endsWith("/") && pkg.startsWith(key))?.[1];
5657
+ const isExplicitShare = Object.prototype.hasOwnProperty.call(federationOptions.shared, pkg);
5658
+ return shareItem?.shareConfig?.singleton === true && shareItem?.shareConfig?.import !== false && !shareItem?.shareConfig?.treeShaking && (isExplicitShare || typeof shareItem?.shareConfig?.import === "string" || Boolean(getProjectResolvedImportPath(pkg)));
5659
+ }).map((pkg) => toViteEncodedId(getLoadShareModulePath(pkg, false, federationOptions))) : [];
5660
+ const sharedPreloadBlock = sharedPreloadSources.length > 0 ? `
5661
+ const __mfSharedPreloadUrls = ${JSON.stringify(sharedPreloadSources)};
5662
+ await Promise.all(__mfSharedPreloadUrls.map((src) => import(/* @vite-ignore */ src).catch((err) => console.warn("[module-federation] shared preload failed:", src, err))));` : "";
5255
5663
  const remoteCachePrefix = getRuntimeRemoteCachePrefix(federationOptions);
5256
5664
  const preloadBlock = remotePreloads ? `
5257
5665
  const runtime = await initHost();
5258
- const __mfPreloadRemote = (runtimeRemote, remote) => {
5666
+ const __mfPreloadRemote = (runtimeRemote, remote${isLoadedFirstClientBuild ? ", registration" : ""}) => {
5667
+ ${isLoadedFirstClientBuild ? `if (registration && typeof runtime.registerRemotes === "function") {
5668
+ runtime.registerRemotes([registration]);
5669
+ }` : ""}
5259
5670
  const remoteCacheKey = ${JSON.stringify(remoteCachePrefix)} + remote;
5260
5671
  const pendingKey = "__mf_pending__" + remoteCacheKey;
5261
5672
  if (!__mfModuleCache.remote[pendingKey]) {
@@ -5273,7 +5684,7 @@ const __mfCurrentScript = document.currentScript;
5273
5684
  return __mfModuleCache.remote[pendingKey];
5274
5685
  };
5275
5686
  const __mfRemotePreloads = [${remotePreloads}];
5276
- await Promise.allSettled(__mfRemotePreloads);` : `await initHost();`;
5687
+ await ${isLoadedFirstClientBuild ? "Promise.all" : "Promise.allSettled"}(__mfRemotePreloads);` : `await initHost();`;
5277
5688
  const pendingShareLoadsAwait = `
5278
5689
  if (__mfModuleCache.pendingShareLoads) {
5279
5690
  await Promise.all(__mfModuleCache.pendingShareLoads);
@@ -5287,13 +5698,14 @@ const __mfCurrentScript = document.currentScript;
5287
5698
  const __mfHostInit = await ${importExpression(initSrc)};
5288
5699
  await __mfHostInit.__tla;
5289
5700
  const { initHost } = __mfHostInit;
5290
- ${preloadBlock}${pendingShareLoadsAwait}
5701
+ ${preloadBlock}${sharedPreloadBlock}${pendingShareLoadsAwait}
5291
5702
  })().then(() => ${entryImportExpression});
5292
5703
  `;
5293
5704
  return [
5294
5705
  getRuntimeModuleCacheBootstrapCode(),
5295
5706
  importHelper,
5296
5707
  entryImportDeclaration,
5708
+ remoteEntryPrefetchBlock,
5297
5709
  importCode
5298
5710
  ].join("\n");
5299
5711
  }
@@ -5325,6 +5737,17 @@ const __mfCurrentScript = document.currentScript;
5325
5737
  const normalized = decodeViteId(id).replace(/^\0+/, "");
5326
5738
  return normalized.includes("virtual:mf:") || /__(?:loadShare|prebuild|loadRemote)__/.test(normalized);
5327
5739
  }
5740
+ function isWorkspaceSourceId(id) {
5741
+ const normalized = normalizeModuleId(decodeViteId(id));
5742
+ if (normalized.startsWith("\0") || normalized.startsWith("virtual:")) return false;
5743
+ const filePath = stripQueryAndHash$1(normalized);
5744
+ if (filePath.startsWith("/@fs/")) return true;
5745
+ if (!path$1.isAbsolute(filePath)) return false;
5746
+ const root = normalizePathForImport(path$1.resolve(viteConfig.root));
5747
+ const absolutePath = normalizePathForImport(path$1.resolve(filePath));
5748
+ const relativePath = normalizePathForImport(path$1.relative(root, absolutePath));
5749
+ return (relativePath === ".." || relativePath.startsWith("../") || path$1.isAbsolute(relativePath)) && fs$2.existsSync(absolutePath);
5750
+ }
5328
5751
  function addEntryFile(file) {
5329
5752
  const normalized = normalizeModuleId(file);
5330
5753
  if (!entryFiles.includes(normalized)) entryFiles.push(normalized);
@@ -5391,7 +5814,10 @@ const __mfCurrentScript = document.currentScript;
5391
5814
  }
5392
5815
  const devFileName = resolveDevHashEntryFileName$1(fileName);
5393
5816
  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;
5817
+ if (req.url && req.url.startsWith((viteConfig.base + fileName).replace(/^\/?/, "/"))) {
5818
+ req.url = devEntryPath;
5819
+ req.headers["sec-fetch-dest"] = "script";
5820
+ }
5395
5821
  next();
5396
5822
  });
5397
5823
  },
@@ -5472,6 +5898,10 @@ const __mfCurrentScript = document.currentScript;
5472
5898
  },
5473
5899
  generateBundle(_options, bundle) {
5474
5900
  if (skipSvelteKitSsrBuild()) return;
5901
+ if (entryName === "remoteEntry" && emitFileId && fileName && !viteConfig?.build?.ssr && _options?.format === "es" && viteConfig?.build?.modulePreload !== false) {
5902
+ const remoteEntryFile = findRemoteEntryFile(fileName, bundle);
5903
+ if (remoteEntryFile) appendRemoteEntryWarmup(bundle, remoteEntryFile);
5904
+ }
5475
5905
  if (!injectHtml()) return;
5476
5906
  if (!emitFileId) return;
5477
5907
  const htmlFileNames = Object.keys(bundle).filter((fileName) => fileName.endsWith(".html"));
@@ -5533,12 +5963,12 @@ const __mfCurrentScript = document.currentScript;
5533
5963
  htmlContent = htmlContent.replace("<head>", `<head>${scriptContent}`);
5534
5964
  }
5535
5965
  }
5536
- if (waitsForInit && viteConfig.build.modulePreload !== false) htmlContent = injectHostInitPreloads(htmlContent, bundle, (builtFileName) => resolvePath(builtFileName, fileName));
5966
+ if (waitsForInit && viteConfig.build.modulePreload !== false) htmlContent = injectHostInitPreloads(htmlContent, bundle, (builtFileName) => resolvePath(builtFileName, fileName), getRemoteEntryPreloadUrls());
5537
5967
  htmlAsset.source = htmlContent;
5538
5968
  }
5539
5969
  },
5540
5970
  closeBundle() {
5541
- if (_command === "serve" || skipSvelteKitSsrBuild()) return;
5971
+ if (_command === "serve" || !hasPackageDependency("@sveltejs/kit") || skipSvelteKitSsrBuild()) return;
5542
5972
  let attempts = 0;
5543
5973
  const retry = () => {
5544
5974
  attempts += 1;
@@ -5578,7 +6008,7 @@ const __mfCurrentScript = document.currentScript;
5578
6008
  return mapCodeToCodeWithSourcemap(code.replace("vueApp.mount(vueAppRootContainer);", `${injection}vueApp.mount(vueAppRootContainer);`));
5579
6009
  }
5580
6010
  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));
6011
+ 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
6012
  const isNuxtEntryAsyncModule = /(?:^|\/)nuxt\/dist\/app\/entry\.async\.js(?:\?|$)/.test(id) && code.includes("entry();");
5583
6013
  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
6014
  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)) {
@@ -6332,200 +6762,6 @@ function initVirtualModules(command, remoteEntryId, enableSsrInit = false, optio
6332
6762
  })) : void 0);
6333
6763
  }
6334
6764
  //#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
6765
  //#region src/utils/cssModuleHelpers.ts
6530
6766
  const ASSET_TYPES = ["js", "css"];
6531
6767
  const LOAD_TIMINGS = ["sync", "async"];
@@ -6589,28 +6825,33 @@ const chunkContainsCssModules = (modules) => {
6589
6825
  for (const modulePath of Object.keys(modules)) if (isCSSFile(modulePath)) return true;
6590
6826
  return false;
6591
6827
  };
6828
+ const collectStaticChunks = (bundle, roots) => {
6829
+ const chunks = [];
6830
+ const visited = /* @__PURE__ */ new Set();
6831
+ const queue = [...roots];
6832
+ for (let queueIndex = 0; queueIndex < queue.length; queueIndex++) {
6833
+ const fileName = queue[queueIndex];
6834
+ if (visited.has(fileName)) continue;
6835
+ visited.add(fileName);
6836
+ const chunk = bundle[fileName];
6837
+ if (!chunk || chunk.type !== "chunk") continue;
6838
+ chunks.push(chunk);
6839
+ queue.push(...chunk.imports ?? []);
6840
+ }
6841
+ return chunks;
6842
+ };
6592
6843
  /**
6593
6844
  * Analyzes assets associated with a chunk without mutating the output map.
6594
6845
  * The static-import traversal is cycle-safe and ignores missing bundle entries.
6595
6846
  */
6596
6847
  const analyzeChunkAssets = (bundle, fileName, chunk) => {
6597
6848
  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);
6849
+ for (const currentChunk of collectStaticChunks(bundle, [fileName])) for (const dynamicImport of currentChunk.dynamicImports ?? []) {
6850
+ if (!bundle[dynamicImport]) continue;
6851
+ dynamicAssets.push({
6852
+ fileName: dynamicImport,
6853
+ type: isCSSFile(dynamicImport) ? "css" : "js"
6854
+ });
6614
6855
  }
6615
6856
  return {
6616
6857
  importedCss: Array.from(chunk.viteMetadata?.importedCss ?? []),
@@ -6927,6 +7168,54 @@ function isTreeShakingProviderChunk(file) {
6927
7168
  if (file.facadeModuleId?.includes("__treeShakingProvider__")) return true;
6928
7169
  return Object.keys(file.modules || {}).some((id) => id.includes("__treeShakingProvider__") || id.includes("__mf_tree_shaking_graph__"));
6929
7170
  }
7171
+ function isContainerBootstrapChunk(chunk, moduleIds) {
7172
+ return [chunk.facadeModuleId, ...chunk.moduleIds ?? []].some((id) => typeof id === "string" && moduleIds.has(normalizeVirtualModuleId(id)));
7173
+ }
7174
+ function collectImportedCss(chunks) {
7175
+ const css = /* @__PURE__ */ new Set();
7176
+ for (const chunk of chunks) for (const cssFile of chunk.viteMetadata?.importedCss ?? []) css.add(cssFile);
7177
+ return Array.from(css);
7178
+ }
7179
+ function expandExposeAssets(filesMap, exposeModules, bundle, remoteEntryFileName, options) {
7180
+ if (exposeModules.length === 0) return;
7181
+ const containerChunks = remoteEntryFileName ? collectStaticChunks(bundle, [remoteEntryFileName]) : [];
7182
+ const bootstrapChunks = containerChunks.slice(1);
7183
+ const seen = new Set(containerChunks.map((chunk) => chunk.fileName));
7184
+ if (containerChunks.length > 0) {
7185
+ const bootstrapModuleIds = /* @__PURE__ */ new Set([getLocalSharedImportMapPath(options), getVirtualExposesId(options)]);
7186
+ for (const containerChunk of containerChunks) for (const imported of containerChunk.dynamicImports ?? []) {
7187
+ const importedChunk = bundle[imported];
7188
+ if (!importedChunk || importedChunk.type !== "chunk" || !isContainerBootstrapChunk(importedChunk, bootstrapModuleIds)) continue;
7189
+ for (const chunk of collectStaticChunks(bundle, [imported])) {
7190
+ if (seen.has(chunk.fileName)) continue;
7191
+ seen.add(chunk.fileName);
7192
+ bootstrapChunks.push(chunk);
7193
+ }
7194
+ }
7195
+ }
7196
+ const bootstrapAssets = bootstrapChunks.map((chunk) => chunk.fileName);
7197
+ const bootstrapCss = collectImportedCss(bootstrapChunks);
7198
+ for (const exposeModule of exposeModules) {
7199
+ const assets = filesMap[exposeModule];
7200
+ if (!assets) continue;
7201
+ const syncChunks = collectStaticChunks(bundle, assets.js.sync);
7202
+ const sync = Array.from(/* @__PURE__ */ new Set([...bootstrapAssets, ...syncChunks.map((chunk) => chunk.fileName)]));
7203
+ const syncSet = new Set(sync);
7204
+ const asyncChunks = collectStaticChunks(bundle, assets.js.async);
7205
+ const async = asyncChunks.map((chunk) => chunk.fileName).filter((fileName) => !syncSet.has(fileName));
7206
+ assets.js.sync = sync;
7207
+ assets.js.async = async;
7208
+ const syncCss = Array.from(/* @__PURE__ */ new Set([
7209
+ ...assets.css.sync,
7210
+ ...bootstrapCss,
7211
+ ...collectImportedCss(syncChunks)
7212
+ ]));
7213
+ const syncCssSet = new Set(syncCss);
7214
+ const asyncCss = Array.from(/* @__PURE__ */ new Set([...assets.css.async, ...collectImportedCss(asyncChunks)])).filter((fileName) => !syncCssSet.has(fileName));
7215
+ assets.css.sync = syncCss;
7216
+ assets.css.async = asyncCss;
7217
+ }
7218
+ }
6930
7219
  function getTreeShakingBuildInfo(options) {
6931
7220
  if (!(Object.values(options.shared || {}).some((share) => !!share.shareConfig.treeShaking) || !!options.treeShakingSharedPlugins?.length || !!options.treeShakingSharedExcludePlugins?.length)) return {};
6932
7221
  return {
@@ -7089,6 +7378,7 @@ const Manifest = (providedOptions) => {
7089
7378
  root,
7090
7379
  stripKnownJsExtensions: true
7091
7380
  });
7381
+ expandExposeAssets(filesMap, exposesModules, bundle, foundRemoteEntryFile, mfOptions);
7092
7382
  const fileToShareKey = await buildFileToShareKeyMap(getUsedShares(mfOptions), this.resolve.bind(this), mfOptions);
7093
7383
  processModuleAssets(Object.fromEntries(Object.entries(bundle).filter(([, file]) => !isTreeShakingProviderChunk(file))), filesMap, (modulePath) => fileToShareKey.get(modulePath));
7094
7384
  if (mfOptions.bundleAllCSS) addCssAssetsToAllExports(filesMap, allCssAssets);
@@ -7859,6 +8149,7 @@ function excludeSharedSubDependencies(shared) {
7859
8149
  delete shared[depKey];
7860
8150
  sharedKeys.delete(depKey);
7861
8151
  sharedKeyByBase.delete(dep);
8152
+ sharedKeyMatcherCache.delete(shared);
7862
8153
  }
7863
8154
  }
7864
8155
  }
@@ -8083,15 +8374,6 @@ const JS_EXTENSIONS_RE = /\.(?:[mc]?[jt]sx?|vue|svelte)(?:\?|$)/;
8083
8374
  function isAstNode(value) {
8084
8375
  return !!value && typeof value === "object" && typeof value.type === "string";
8085
8376
  }
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
8377
  function walkAST(root, visitor) {
8096
8378
  const seen = /* @__PURE__ */ new WeakSet();
8097
8379
  function visit(node) {
@@ -8350,7 +8632,7 @@ function pluginRemoteNamedExports(options) {
8350
8632
  if (!JS_EXTENSIONS_RE.test(id)) return;
8351
8633
  if (!remoteNames.some((name) => code.includes(name))) return;
8352
8634
  const matchesRemoteImport = (source) => isRemoteImport(source, id);
8353
- for (const source of findStaticRemoteSources(code, matchesRemoteImport)) markStaticRemote(source, options);
8635
+ for (const { kind, source, typeOnly } of findModuleImportDescriptors(code)) if (kind === "static" && !typeOnly && matchesRemoteImport(source)) markStaticRemote(source, options);
8354
8636
  let imports;
8355
8637
  try {
8356
8638
  imports = await collectFromAST(this.parse(code), code, matchesRemoteImport);
@@ -8858,7 +9140,7 @@ const FEDERATION_CONTROL_CHUNK_HINTS = [
8858
9140
  "localSharedImportMap"
8859
9141
  ];
8860
9142
  function stripEmptyPreloadCalls(code) {
8861
- const helperImportRegex = /import\s*\{\s*_\s*as\s*(\w+)\s*\}\s*from\s*["'][^"']+["']\s*;?/g;
9143
+ const helperImportRegex = /import\s*\{\s*_\s*as\s*([A-Za-z_$][\w$]*)\s*\}\s*from\s*["'][^"']+["']\s*;?/g;
8862
9144
  const helperAliases = [];
8863
9145
  let helperImportMatch;
8864
9146
  while ((helperImportMatch = helperImportRegex.exec(code)) !== null) helperAliases.push(helperImportMatch[1]);
@@ -8894,7 +9176,7 @@ function stripEmptyPreloadCalls(code) {
8894
9176
  }
8895
9177
  nextCode = nextCode.replace(/import\s*["'][^"']*__loadShare__[^"']*["']\s*;?/g, "");
8896
9178
  nextCode = nextCode.replace(helperImportRegex, (statement, local) => {
8897
- return new RegExp(`\\b${local}\\b`).test(nextCode.replace(statement, "")) ? statement : "";
9179
+ return isIdentifierReferenced(local, nextCode.replace(statement, "")) ? statement : "";
8898
9180
  });
8899
9181
  return nextCode;
8900
9182
  }
@@ -9167,9 +9449,10 @@ function isFile(candidate) {
9167
9449
  return false;
9168
9450
  }
9169
9451
  }
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;
9452
+ function isReactRouterBuildClientRouteInput(entry) {
9453
+ return /[?&]__react-router-build-client-route(?:[=&]|$)/.test(entry);
9454
+ }
9455
+ function registerEntryImports(options, projectRoot, recordShared = true, entryFiles = []) {
9173
9456
  const sourceExtensions = [
9174
9457
  ".mjs",
9175
9458
  ".js",
@@ -9199,10 +9482,15 @@ function registerEntryImports(options, projectRoot) {
9199
9482
  preloadRemotes
9200
9483
  });
9201
9484
  };
9202
- const htmlEntry = path$1.join(root, "index.html");
9203
- if (existsSync(htmlEntry)) {
9485
+ const htmlEntries = entryFiles.filter((file) => file.endsWith(".html"));
9486
+ const htmlEntryPaths = htmlEntries.length ? htmlEntries : entryFiles.length === 0 ? [path$1.join(root, "index.html")] : [];
9487
+ for (const htmlEntry of htmlEntryPaths) if (existsSync(htmlEntry)) {
9204
9488
  const html = readFileSync(htmlEntry, "utf8");
9205
- for (const match of html.matchAll(/<script\b[^>]*\bsrc=(['"])([^'"]+)\1[^>]*>/gi)) enqueue(match[2], htmlEntry, true);
9489
+ for (const match of html.matchAll(/<script\b(?=[^>]*\btype=["']module["'])(?=[^>]*\bsrc=(['"])([^'"]+)\1)[^>]*>/gi)) enqueue(match[2], htmlEntry, true);
9490
+ }
9491
+ for (const entry of entryFiles.filter((file) => !file.endsWith(".html"))) {
9492
+ const relativeEntry = path$1.relative(root, entry);
9493
+ enqueue(relativeEntry.startsWith(".") ? relativeEntry : `./${relativeEntry}`, path$1.join(root, "index.html"), true);
9206
9494
  }
9207
9495
  for (const expose of Object.values(options.exposes ?? {})) enqueue(expose.import);
9208
9496
  while (pending.length) {
@@ -9210,17 +9498,15 @@ function registerEntryImports(options, projectRoot) {
9210
9498
  if (visited.get(file) || visited.has(file) && !preloadRemotes) continue;
9211
9499
  visited.set(file, preloadRemotes);
9212
9500
  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
- }
9501
+ for (const { source: request, kind, typeOnly } of findModuleImportDescriptors(code)) {
9502
+ const isStatic = kind === "static" && !typeOnly;
9503
+ const remoteKey = preloadRemotes && isStatic && request ? Object.keys(options.remotes).find((name) => request === name || request.startsWith(`${name}/`)) : void 0;
9504
+ const sharedKey = !typeOnly && request && findSharedKey(request, options.shared);
9505
+ if (remoteKey) {
9506
+ addUsedRemote(remoteKey, request, options);
9507
+ markStaticRemote(request, options);
9508
+ } else if (sharedKey && recordShared) addUsedShares(request, options);
9509
+ else if (request && !typeOnly) enqueue(request, file, preloadRemotes && isStatic);
9224
9510
  }
9225
9511
  }
9226
9512
  }
@@ -9238,6 +9524,8 @@ function createEarlyVirtualModulesPlugin(options) {
9238
9524
  config(config, { command: _command }) {
9239
9525
  if (_command === "serve") ignoreFederationGeneratedFiles(config, options);
9240
9526
  const root = config.root || process.cwd();
9527
+ const buildInput = getBuildInput(config);
9528
+ 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
9529
  resetConcreteSharedImportSourceCache();
9242
9530
  setPackageDetectionCwd(root);
9243
9531
  const isVinext = hasPackageDependency("vinext");
@@ -9252,7 +9540,7 @@ function createEarlyVirtualModulesPlugin(options) {
9252
9540
  config.optimizeDeps.exclude.push(...Object.keys(remotes || {}));
9253
9541
  }
9254
9542
  }
9255
- if (_command === "serve" && (Object.keys(shared ?? {}).length > 0 || Object.keys(remotes ?? {}).length > 0)) registerEntryImports(options, root);
9543
+ if (!config.build?.ssr && (Object.keys(shared ?? {}).length > 0 || Object.keys(remotes ?? {}).length > 0)) registerEntryImports(options, root, _command === "serve", resolvedConfiguredEntryFiles);
9256
9544
  if (shared && Object.keys(shared).length > 0) {
9257
9545
  if (_command === "serve") {
9258
9546
  excludeSharedSubDependencies(shared);
@@ -9580,7 +9868,10 @@ function federation(mfUserOptions) {
9580
9868
  },
9581
9869
  load(id, loadOptions) {
9582
9870
  if (id.includes("__loadRemote__") && !refreshLoadRemoteModuleForEnvironment(id, this, loadOptions)) return;
9583
- if (command !== "build" && id.includes("__loadShare__") && refreshLoadShareModuleForEnvironment(id, this, loadOptions) === "not-owned") return;
9871
+ if (command !== "build" && id.includes("__loadShare__")) {
9872
+ id = findCurrentLoadShareForStaleOwnerId(id, options.shared, findSharedKey, options)?.getResolvedId() ?? id;
9873
+ if (refreshLoadShareModuleForEnvironment(id, this, loadOptions) === "not-owned") return;
9874
+ }
9584
9875
  if (id.includes("__prebuild__") && refreshPreBuildModuleForEnvironment(id, this, loadOptions) === "not-owned") return;
9585
9876
  if (id.includes("__H_A_I__") && isOwnedHostAutoInitId(id, options)) refreshHostAutoInit(options, getLoadHookExportConditions(this, loadOptions));
9586
9877
  const virtualModule = VirtualModule.findById(id);