@module-federation/vite 1.22.1 → 1.23.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.js CHANGED
@@ -1,6 +1,6 @@
1
- import { _ as stripViteFsPrefix, a as ensureTrailingSlash, c as getCommonSharedSubpaths, d as isNodeModulePath, f as isNuxtClientBase, g as stripQueryAndHash, h as resolvePublicPath, l as getNodeModulesSuffix, m as normalizeNodeModulePath, n as invalidateSharedKeyMatcher, o as filterId, p as isViteOptimizableEntry, r as matchesSharedSource, s as getBasePath$1, t as findSharedKey, u as isAssetLikeImport } from "./sharedKeyMatcher-BRzBCbuR.js";
2
- import { i as resolveHashPlaceholderFileName, n as normalizePathForImport, r as rebaseImport } from "./buildPaths-BoaQTkxt.js";
3
- import { _ as sharedCacheHelperCode, a as getPackageDetectionCwd, b as mfWarn, c as getSharedCacheDescriptor, d as isPackageExportAvailable, f as isPackageInstalled, g as setPackageDetectionCwd, h as resolveImportPath, i as getIsRolldown, l as hasPackageDependency, m as packageNameEncode, n as getInstalledPackageEntry, o as getPackageName, p as packageNameDecode, r as getInstalledPackageJson, s as getPackageNameFromNodeModulePath, u as isNuxtProjectRoot, v as createModuleFederationError } from "./dtsConstants-dDsHZFC1.js";
1
+ import { _ as resolvePublicPath, a as matchesSharedSource, c as filterId, d as getNodeModulesSuffix, f as isAssetLikeImport, g as normalizeNodeModulePath, h as isViteOptimizableEntry, i as invalidateSharedKeyMatcher, l as getBasePath$1, m as isNuxtClientBase, n as getSharedRequest, p as isNodeModulePath, r as getSharedRuntimeKey, s as ensureTrailingSlash, t as findSharedKey, u as getCommonSharedSubpaths, v as stripQueryAndHash, y as stripViteFsPrefix } from "./sharedKeyMatcher-Od_nYxJA.js";
2
+ import { a as CodeRewriter, c as normalizePathForImport, i as createCodePositionMap, l as rebaseImport, o as createSourceMap, r as mfWarn, t as createModuleFederationError, u as resolveHashPlaceholderFileName } from "./logger--uKHOVjR.js";
3
+ import { C as isReactCoreShare, S as REACT_DOM_CLIENT_SHARE, _ as resolveModulePath, a as getIsRolldown, b as supportsCodeSplittingGroupDebugName, c as getPackageNameFromNodeModulePath, d as isNuxtProjectRoot, f as isPackageExportAvailable, g as resolveImportPath, h as packageNameEncode, i as getInstalledPackageJson, l as getSharedCacheDescriptor, m as packageNameDecode, n as getDependencyNames, o as getPackageDetectionCwd, p as isPackageInstalled, r as getInstalledPackageEntry, s as getPackageName, u as hasPackageDependency, v as setPackageDetectionCwd, x as REACT_CLIENT_INTERNALS_KEY, y as sharedCacheHelperCode } from "./dtsConstants-Bs4FukGL.js";
4
4
  import { createRequire } from "node:module";
5
5
  import * as fs$2 from "fs";
6
6
  import { existsSync, readFileSync, readdirSync, realpathSync, statSync, writeFileSync } from "fs";
@@ -8,6 +8,7 @@ import { createRequire as createRequire$1, isBuiltin } from "module";
8
8
  import * as path$1 from "node:path";
9
9
  import path, { basename } from "node:path";
10
10
  import { fileURLToPath, pathToFileURL } from "url";
11
+ import * as vite from "vite";
11
12
  import { parseAst, version } from "vite";
12
13
  import { createHash } from "node:crypto";
13
14
  import * as fs$1 from "node:fs";
@@ -235,134 +236,6 @@ function findRemoteEntryFile(filename, bundle) {
235
236
  return fallback;
236
237
  }
237
238
  //#endregion
238
- //#region src/utils/codeRewriter.ts
239
- const BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
240
- var CodeRewriter = class {
241
- original;
242
- replacements = [];
243
- constructor(original) {
244
- this.original = original;
245
- }
246
- overwrite(start, end, content) {
247
- if (start < 0 || end < start || end > this.original.length) throw new Error(`Invalid overwrite range: ${start}-${end}`);
248
- this.replacements.push({
249
- start,
250
- end,
251
- content
252
- });
253
- }
254
- toString() {
255
- return applyReplacements(this.original, this.getSortedReplacements()).code;
256
- }
257
- generateMap(source = "") {
258
- const { code, replacements } = applyReplacements(this.original, this.getSortedReplacements());
259
- return {
260
- version: 3,
261
- sources: [source],
262
- sourcesContent: [this.original],
263
- names: [],
264
- mappings: generateLineMappings(code, this.original, replacements)
265
- };
266
- }
267
- getSortedReplacements() {
268
- return [...this.replacements].sort((a, b) => a.start - b.start || a.end - b.end);
269
- }
270
- };
271
- function createSourceMap(code, source = "") {
272
- return {
273
- version: 3,
274
- sources: [source],
275
- sourcesContent: [code],
276
- names: [],
277
- mappings: generateLineMappings(code, code, [])
278
- };
279
- }
280
- function applyReplacements(original, replacements) {
281
- let code = "";
282
- let cursor = 0;
283
- let delta = 0;
284
- const applied = [];
285
- for (const replacement of replacements) {
286
- if (replacement.start < cursor) throw new Error("Overlapping overwrite ranges are not supported");
287
- code += original.slice(cursor, replacement.start);
288
- const generatedStart = replacement.start + delta;
289
- code += replacement.content;
290
- const generatedEnd = generatedStart + replacement.content.length;
291
- applied.push({
292
- ...replacement,
293
- generatedStart,
294
- generatedEnd
295
- });
296
- cursor = replacement.end;
297
- delta += replacement.content.length - (replacement.end - replacement.start);
298
- }
299
- code += original.slice(cursor);
300
- return {
301
- code,
302
- replacements: applied
303
- };
304
- }
305
- function generateLineMappings(generated, original, replacements) {
306
- const generatedLineStarts = getLineStarts(generated);
307
- const originalLineStarts = getLineStarts(original);
308
- let previousOriginalLine = 0;
309
- let previousOriginalColumn = 0;
310
- let mappings = "";
311
- generatedLineStarts.forEach((generatedOffset, lineIndex) => {
312
- if (lineIndex > 0) mappings += ";";
313
- const originalOffset = generatedOffsetToOriginalOffset(generatedOffset, replacements);
314
- const originalLine = findLine(originalLineStarts, originalOffset);
315
- const originalColumn = originalOffset - originalLineStarts[originalLine];
316
- mappings += encodeSegment([
317
- 0,
318
- 0,
319
- originalLine - previousOriginalLine,
320
- originalColumn - previousOriginalColumn
321
- ]);
322
- previousOriginalLine = originalLine;
323
- previousOriginalColumn = originalColumn;
324
- });
325
- return mappings;
326
- }
327
- function generatedOffsetToOriginalOffset(offset, replacements) {
328
- let delta = 0;
329
- for (const replacement of replacements) {
330
- if (offset < replacement.generatedStart) break;
331
- if (offset < replacement.generatedEnd) return replacement.start;
332
- delta += replacement.content.length - (replacement.end - replacement.start);
333
- }
334
- return offset - delta;
335
- }
336
- function getLineStarts(code) {
337
- const starts = [0];
338
- for (let i = 0; i < code.length; i++) if (code.charCodeAt(i) === 10) starts.push(i + 1);
339
- return starts;
340
- }
341
- function findLine(lineStarts, offset) {
342
- let low = 0;
343
- let high = lineStarts.length - 1;
344
- while (low <= high) {
345
- const mid = low + high >> 1;
346
- if (lineStarts[mid] <= offset) low = mid + 1;
347
- else high = mid - 1;
348
- }
349
- return Math.max(0, high);
350
- }
351
- function encodeSegment(values) {
352
- return values.map(encodeVlq).join("");
353
- }
354
- function encodeVlq(value) {
355
- let vlq = value < 0 ? (-value << 1) + 1 : value << 1;
356
- let encoded = "";
357
- do {
358
- let digit = vlq & 31;
359
- vlq >>>= 5;
360
- if (vlq > 0) digit |= 32;
361
- encoded += BASE64_CHARS[digit];
362
- } while (vlq > 0);
363
- return encoded;
364
- }
365
- //#endregion
366
239
  //#region src/utils/mapCodeToCodeWithSourcemap.ts
367
240
  async function mapCodeToCodeWithSourcemap(code) {
368
241
  const resolvedCode = await code;
@@ -400,152 +273,21 @@ function resolveEnvironmentConsumerTarget(ctx) {
400
273
  function isClientEnvironment(ctx) {
401
274
  return resolveEnvironmentConsumerTarget(ctx) !== "server";
402
275
  }
276
+ /**
277
+ * Whether a build hook runs for a server graph. Vite 6+ hooks carry an
278
+ * environment; Vite 5 (and hooks invoked before `configResolved`) fall back to
279
+ * the legacy root `build.ssr` flag.
280
+ */
281
+ function isServerBuildContext(ctx, config) {
282
+ const target = resolveEnvironmentConsumerTarget(ctx);
283
+ if (target) return target === "server";
284
+ return Boolean(config?.build?.ssr);
285
+ }
403
286
  function resolveRemoteConsumer(ctx, hasMultiEnvironment) {
404
287
  if (!hasMultiEnvironment) return "unified";
405
288
  return resolveEnvironmentConsumerTarget(ctx) ?? "client";
406
289
  }
407
290
  //#endregion
408
- //#region src/utils/codePositionMap.ts
409
- const REGEX_PREFIX_KEYWORDS = /* @__PURE__ */ new Set([
410
- "await",
411
- "case",
412
- "delete",
413
- "in",
414
- "instanceof",
415
- "new",
416
- "return",
417
- "throw",
418
- "typeof",
419
- "void",
420
- "yield"
421
- ]);
422
- function isJsxClosingTagSlash(code, slashIndex) {
423
- if (code[slashIndex - 1] !== "<") return false;
424
- let cursor = slashIndex + 1;
425
- while (/\s/.test(code[cursor] || "")) cursor++;
426
- if (code[cursor] === ">") return true;
427
- const tagStart = cursor;
428
- while (/[-:.$_\u200C\u200D\p{ID_Continue}]/u.test(code[cursor] || "")) cursor++;
429
- if (cursor === tagStart) return false;
430
- while (/\s/.test(code[cursor] || "")) cursor++;
431
- return code[cursor] === ">";
432
- }
433
- /** Mark comments, string/template literals, and regular expressions as non-code. */
434
- function createCodePositionMap(code, onComment) {
435
- const positions = Array(code.length).fill(true);
436
- const mask = (start, end) => {
437
- for (let index = start; index < end; index++) positions[index] = false;
438
- };
439
- let canStartRegex = true;
440
- for (let index = 0; index < code.length;) {
441
- const char = code[index];
442
- const next = code[index + 1];
443
- if (/\s/.test(char)) {
444
- index++;
445
- continue;
446
- }
447
- if (char === "/" && next === "/") {
448
- const start = index;
449
- index += 2;
450
- while (index < code.length && code[index] !== "\n" && code[index] !== "\r") index++;
451
- mask(start, index);
452
- onComment?.(start, index);
453
- continue;
454
- }
455
- if (char === "/" && next === "*") {
456
- const start = index;
457
- index += 2;
458
- while (index < code.length && !(code[index] === "*" && code[index + 1] === "/")) index++;
459
- index = Math.min(code.length, index + 2);
460
- mask(start, index);
461
- onComment?.(start, index);
462
- continue;
463
- }
464
- if (char === "\"" || char === "'" || char === "`") {
465
- const quote = char;
466
- const start = index++;
467
- while (index < code.length) {
468
- if (code[index] === "\\") {
469
- index += 2;
470
- continue;
471
- }
472
- if (code[index] === quote) {
473
- index++;
474
- break;
475
- }
476
- index++;
477
- }
478
- mask(start, index);
479
- canStartRegex = false;
480
- continue;
481
- }
482
- const closesJsxTag = isJsxClosingTagSlash(code, index);
483
- if (char === "/" && canStartRegex && !closesJsxTag) {
484
- const start = index;
485
- let cursor = index + 1;
486
- let escaped = false;
487
- let inCharacterClass = false;
488
- let closed = false;
489
- for (; cursor < code.length; cursor++) {
490
- const regexChar = code[cursor];
491
- if (regexChar === "\n" || regexChar === "\r") break;
492
- if (escaped) {
493
- escaped = false;
494
- continue;
495
- }
496
- if (regexChar === "\\") {
497
- escaped = true;
498
- continue;
499
- }
500
- if (regexChar === "[") {
501
- inCharacterClass = true;
502
- continue;
503
- }
504
- if (regexChar === "]" && inCharacterClass) {
505
- inCharacterClass = false;
506
- continue;
507
- }
508
- if (regexChar === "/" && !inCharacterClass) {
509
- cursor++;
510
- while (/[$_\p{ID_Continue}]/u.test(code[cursor] || "")) cursor++;
511
- closed = true;
512
- break;
513
- }
514
- }
515
- if (closed) {
516
- mask(start, cursor);
517
- index = cursor;
518
- canStartRegex = false;
519
- continue;
520
- }
521
- }
522
- if (/[$_\p{ID_Start}]/u.test(char)) {
523
- const start = index++;
524
- while (/[$_\u200C\u200D\p{ID_Continue}]/u.test(code[index] || "")) index++;
525
- canStartRegex = REGEX_PREFIX_KEYWORDS.has(code.slice(start, index));
526
- continue;
527
- }
528
- if (/\d/.test(char)) {
529
- index++;
530
- while (/[\w.]/.test(code[index] || "")) index++;
531
- canStartRegex = false;
532
- continue;
533
- }
534
- if ((char === "+" || char === "-") && next === char) {
535
- index += 2;
536
- continue;
537
- }
538
- if (char === "!" && next !== "=") {
539
- index++;
540
- continue;
541
- }
542
- if (char === ")" || char === "]" || char === "}") canStartRegex = false;
543
- else if (char !== ".") canStartRegex = true;
544
- index++;
545
- }
546
- return positions;
547
- }
548
- //#endregion
549
291
  //#region src/utils/htmlEntryUtils.ts
550
292
  const IDENTIFIER = String.raw`[$_\p{ID_Start}][$_\u200C\u200D\p{ID_Continue}]*`;
551
293
  const NAMED_SPECIFIERS = String.raw`\{[^{}]*\}`;
@@ -711,18 +453,18 @@ function normalizeExposes(exposes) {
711
453
  });
712
454
  return res;
713
455
  }
714
- function normalizeRemotes(remotes) {
456
+ function normalizeRemotes(remotes, defaultShareScope = "default") {
715
457
  if (!remotes) return {};
716
458
  const result = {};
717
459
  if (typeof remotes === "object") Object.keys(remotes).forEach((key) => {
718
- result[key] = normalizeRemoteItem(key, remotes[key]);
460
+ result[key] = normalizeRemoteItem(key, remotes[key], defaultShareScope);
719
461
  });
720
462
  return result;
721
463
  }
722
464
  function warnOmittedObjectRemoteType(remoteKey) {
723
465
  mfWarn(`Remote "${remoteKey}" omits type and defaults to 'var'. Set type: 'module' for Vite ESM remotes, or type: 'var' explicitly to silence this warning.`);
724
466
  }
725
- function normalizeRemoteItem(key, remote) {
467
+ function normalizeRemoteItem(key, remote, defaultShareScope) {
726
468
  warnOnReservedInternalNamePrefix(key, "remoteAlias");
727
469
  if (typeof remote === "string") {
728
470
  const separatorIndex = remote.startsWith("@") ? remote.indexOf("@", 1) : remote.indexOf("@");
@@ -741,7 +483,7 @@ function normalizeRemoteItem(key, remote) {
741
483
  internalName: toInternalModuleFederationName(key),
742
484
  entry,
743
485
  entryGlobalName,
744
- shareScope: "default"
486
+ shareScope: defaultShareScope
745
487
  };
746
488
  }
747
489
  const typeOmitted = remote.type === void 0 || remote.type === null || remote.type === "";
@@ -750,7 +492,7 @@ function normalizeRemoteItem(key, remote) {
750
492
  type: "var",
751
493
  name: key,
752
494
  internalName: toInternalModuleFederationName(key),
753
- shareScope: "default",
495
+ shareScope: defaultShareScope,
754
496
  entryGlobalName: key
755
497
  }, {
756
498
  ...remote,
@@ -858,10 +600,15 @@ function resolveSharedVersions(shared, root) {
858
600
  item.shareConfig.requiredVersion = requiredVersion;
859
601
  }
860
602
  }
861
- function normalizeShareItem(key, shareItem) {
603
+ function normalizeShareItem(key, shareItem, defaultShareScope) {
862
604
  const treeShaking = typeof shareItem === "object" ? shareItem.treeShaking : void 0;
863
605
  if (treeShaking && treeShaking.mode !== "server-calc" && treeShaking.mode !== "runtime-infer") throw createModuleFederationError(`Invalid shared config for "${key}": treeShaking.mode must be either "server-calc" or "runtime-infer".`);
864
606
  if (treeShaking && typeof shareItem === "object" && shareItem.eager) throw createModuleFederationError(`Invalid shared config for "${key}": cannot use both "eager: true" and "treeShaking.mode" simultaneously. Choose one strategy.`);
607
+ if (typeof shareItem === "object") {
608
+ const request = typeof shareItem.request === "string" ? shareItem.request : key;
609
+ const shareKey = typeof shareItem.shareKey === "string" ? shareItem.shareKey : key;
610
+ if (request.endsWith("/") !== shareKey.endsWith("/")) throw createModuleFederationError(`Invalid shared config for "${key}": "request" and "shareKey" must both end with "/" for a prefix share, or neither. Got request "${request}" and shareKey "${shareKey}".`);
611
+ }
865
612
  if (treeShaking?.mode === "runtime-infer" && typeof shareItem === "object" && shareItem.singleton) mfWarn(`Shared singleton "${key}" uses runtime-infer tree shaking, which may load both a tree-shaken bundle and a full bundle when consumers require different exports. Prefer server-calc for singleton dependencies. If runtime-infer is required, expand usedExports to reduce this risk.`);
866
613
  const config = typeof shareItem === "object" ? shareItem : {};
867
614
  const { version, requiredVersion } = resolveSharedVersion(key, config, getPackageDetectionCwd());
@@ -869,7 +616,7 @@ function normalizeShareItem(key, shareItem) {
869
616
  const result = {
870
617
  name: shareItem,
871
618
  version,
872
- scope: "default",
619
+ scope: defaultShareScope,
873
620
  from: "",
874
621
  shareConfig: {
875
622
  import: void 0,
@@ -885,13 +632,16 @@ function normalizeShareItem(key, shareItem) {
885
632
  name: key,
886
633
  from: "",
887
634
  version,
888
- scope: shareItem.shareScope || "default",
635
+ scope: shareItem.shareScope || defaultShareScope,
889
636
  shareConfig: {
890
637
  import: shareItem.import,
891
638
  singleton: shareItem.singleton || false,
892
639
  eager: shareItem.eager || false,
893
640
  requiredVersion,
894
641
  strictVersion: !!shareItem.strictVersion,
642
+ ...shareItem.request !== void 0 ? { request: shareItem.request } : {},
643
+ ...shareItem.shareKey !== void 0 ? { shareKey: shareItem.shareKey } : {},
644
+ ...shareItem.allowNodeModulesSuffixMatch !== void 0 ? { allowNodeModulesSuffixMatch: shareItem.allowNodeModulesSuffixMatch } : {},
895
645
  ...shareItem.suppressMissingImportWarning ? { suppressMissingImportWarning: true } : {},
896
646
  ...treeShaking ? { treeShaking: { ...treeShaking } } : {}
897
647
  }
@@ -921,7 +671,7 @@ function normalizeSharedKey(key) {
921
671
  if (baseKey === "react") return key;
922
672
  return getCommonSharedSubpaths(baseKey).length > 0 ? baseKey : key;
923
673
  }
924
- function normalizeShared(shared) {
674
+ function normalizeShared(shared, defaultShareScope = "default") {
925
675
  explicitSharedKeys = /* @__PURE__ */ new Set();
926
676
  if (!shared) return {};
927
677
  const result = {};
@@ -930,7 +680,7 @@ function normalizeShared(shared) {
930
680
  if (isModuleFederationRuntimePackage(key)) return;
931
681
  const normalizedKey = normalizeSharedKey(key);
932
682
  const hadConfiguredPackageSubpath = (result[normalizedKey]?.shareConfig)?.__mfConfiguredPackageSubpath === true;
933
- result[normalizedKey] = normalizeShareItem(normalizedKey, normalizedKey);
683
+ result[normalizedKey] = normalizeShareItem(normalizedKey, normalizedKey, defaultShareScope);
934
684
  if (key.endsWith("/") || hadConfiguredPackageSubpath) result[normalizedKey].shareConfig.__mfConfiguredPackageSubpath = true;
935
685
  explicitSharedKeys.add(normalizedKey);
936
686
  sourceEntries.push([normalizedKey, normalizedKey]);
@@ -940,15 +690,16 @@ function normalizeShared(shared) {
940
690
  const normalizedKey = normalizeSharedKey(key);
941
691
  const value = shared[key];
942
692
  const hadConfiguredPackageSubpath = (result[normalizedKey]?.shareConfig)?.__mfConfiguredPackageSubpath === true;
943
- result[normalizedKey] = normalizeShareItem(normalizedKey, value);
944
- if (key.endsWith("/") || hadConfiguredPackageSubpath) result[normalizedKey].shareConfig.__mfConfiguredPackageSubpath = true;
693
+ result[normalizedKey] = normalizeShareItem(normalizedKey, value, defaultShareScope);
694
+ const requestIsPrefix = typeof value?.request === "string" && value.request.endsWith("/");
695
+ if (key.endsWith("/") || requestIsPrefix || hadConfiguredPackageSubpath) result[normalizedKey].shareConfig.__mfConfiguredPackageSubpath = true;
945
696
  explicitSharedKeys.add(normalizedKey);
946
697
  sourceEntries.push([normalizedKey, value]);
947
698
  });
948
699
  sourceEntries.forEach(([key, value]) => {
949
700
  for (const subpathShare of getLitExportSubpathShares(key)) {
950
701
  if (result[subpathShare]) continue;
951
- result[subpathShare] = normalizeShareItem(subpathShare, value);
702
+ result[subpathShare] = normalizeShareItem(subpathShare, value, defaultShareScope);
952
703
  }
953
704
  });
954
705
  return result;
@@ -1018,21 +769,28 @@ function isExplicitSharedKey(key, options) {
1018
769
  }
1019
770
  function getNormalizeShareItem(key, options = getNormalizeModuleFederationOptions()) {
1020
771
  const matchedKey = findSharedKey(key, options.shared);
1021
- return options.shared[key] || (matchedKey ? options.shared[matchedKey] : void 0) || options.shared[getPackageName(key)] || options.shared[getPackageName(key) + "/"];
772
+ const shareItem = options.shared[key] || (matchedKey ? options.shared[matchedKey] : void 0) || options.shared[getPackageName(key)] || options.shared[getPackageName(key) + "/"];
773
+ if (shareItem) return shareItem;
774
+ return Object.entries(options.shared).find(([sharedKey, item]) => {
775
+ const runtimeKey = typeof item.shareConfig.shareKey === "string" ? item.shareConfig.shareKey : sharedKey;
776
+ return runtimeKey.endsWith("/") ? key === runtimeKey.slice(0, -1) || key.startsWith(runtimeKey) : runtimeKey === key;
777
+ })?.[1];
1022
778
  }
1023
779
  function normalizeModuleFederationOptions(options) {
1024
780
  warnOnReservedInternalNamePrefix(options.name, "containerName");
1025
781
  if (options.virtualModuleDir && options.virtualModuleDir.includes("/")) throw createModuleFederationError(`Invalid virtualModuleDir: "${options.virtualModuleDir}". The virtualModuleDir option cannot contain slashes (/). Please use a single directory name like '__mf__virtual__your_app_name'.`);
782
+ const defaultShareScope = typeof options.shareScope === "string" ? options.shareScope : "default";
1026
783
  const normalized = {
1027
784
  exposes: normalizeExposes(options.exposes),
1028
785
  filename: options.filename || "remoteEntry-[hash]",
786
+ ssrFilename: options.ssrFilename || void 0,
1029
787
  internalName: toInternalModuleFederationName(options.name),
1030
788
  library: normalizeLibrary(options.library),
1031
789
  name: options.name,
1032
- remotes: normalizeRemotes(options.remotes),
790
+ remotes: normalizeRemotes(options.remotes, defaultShareScope),
1033
791
  runtime: options.runtime,
1034
792
  shareScope: options.shareScope || "default",
1035
- shared: normalizeShared(options.shared),
793
+ shared: normalizeShared(options.shared, defaultShareScope),
1036
794
  runtimePlugins: options.runtimePlugins || [],
1037
795
  implementation: normalizePathForImport(options.implementation || resolveRuntimeImplementation()),
1038
796
  manifest: normalizeManifest(options.manifest),
@@ -1131,6 +889,10 @@ var VirtualModule = class VirtualModule {
1131
889
  if (!cacheMap[this.tag]) cacheMap[this.tag] = {};
1132
890
  cacheMap[this.tag][this.name] = this;
1133
891
  }
892
+ /** The federation scope this module was created under, if it was scoped. */
893
+ getScopeName() {
894
+ return this.scopeName;
895
+ }
1134
896
  getImportId() {
1135
897
  const mfName = this.scopeName ?? getNormalizeModuleFederationOptions().internalName;
1136
898
  const importIdKey = `${mfName}${this.tag}${this.name}${this.tag}`;
@@ -1162,17 +924,38 @@ const SERVER_ENV_GUARD = "import.meta.env.SSR";
1162
924
  const SSR_ENTRY_LOADER_SPECIFIER = "@module-federation/vite/ssrEntryLoader";
1163
925
  const SSR_ONLY_RUNTIME_PLUGINS = /* @__PURE__ */ new Set([SSR_ENTRY_LOADER_SPECIFIER]);
1164
926
  /**
927
+ * Whether a Vite environment builds a server graph.
928
+ *
929
+ * Vite 6+ sets `consumer` on the environment config; `build.ssr` covers the
930
+ * legacy `vite build --ssr` flag. Environment names are user-defined, so `ssr`
931
+ * and `server` are only a fallback for configs that carry neither field.
932
+ */
933
+ function isServerEnvironment(name, config) {
934
+ return config?.consumer === "server" || Boolean(config?.build?.ssr) || name === "ssr" || name === "server";
935
+ }
936
+ /**
937
+ * Whether a resolved Vite config includes a server graph: the legacy
938
+ * `build.ssr` flag, or any server environment. Vite always registers an `ssr`
939
+ * environment for `serve`, so this only gates builds.
940
+ */
941
+ function isSsrConfig(config) {
942
+ if (Boolean(config.build?.ssr)) return true;
943
+ return Object.entries(config.environments ?? {}).some(([name, environment]) => isServerEnvironment(name, environment));
944
+ }
945
+ /**
1165
946
  * Single source of truth for SSR-related feature gates.
1166
947
  *
1167
- * - Vite 8+ dev: ModuleRunner + FetchableDevEnvironment for `/__mf_ssr__/` entries.
1168
- * - Any Vite major on build/preview: HTTP fetch + temp-file import via ssrEntryLoader.
948
+ * - Vite 8+ server environments: ModuleRunner + FetchableDevEnvironment for
949
+ * `/__mf_ssr__/` entries.
950
+ * - SSR builds on any Vite major: HTTP fetch + temp-file import via
951
+ * ssrEntryLoader.
1169
952
  */
1170
- function getSsrCapabilities(viteMajor, command, hasRemotes) {
953
+ function getSsrCapabilities(viteMajor, command, hasRemotes, isSsr = false) {
1171
954
  if (!hasRemotes) return {
1172
955
  enableSsrInitBootstrap: false,
1173
956
  injectSsrEntryLoader: false
1174
957
  };
1175
- const supported = command === "build" || command === "serve" && viteMajor >= 8;
958
+ const supported = isSsr && (command === "build" || command === "serve" && viteMajor >= 8);
1176
959
  return {
1177
960
  enableSsrInitBootstrap: supported,
1178
961
  injectSsrEntryLoader: supported
@@ -1276,106 +1059,48 @@ function isParsableExpression(source) {
1276
1059
  }
1277
1060
  }
1278
1061
  //#endregion
1279
- //#region src/utils/treeShaking.ts
1280
- function shouldAnalyzeSharedExports(shareItem) {
1281
- return !!(shareItem && (shareItem.shareConfig.treeShaking || shareItem.shareConfig.import === false));
1062
+ //#region src/utils/runtimePluginSpecifier.ts
1063
+ function getRuntimePluginSpecifier(plugin) {
1064
+ return typeof plugin === "string" ? plugin : plugin[0];
1282
1065
  }
1283
- const legacyTreeShakingState = {
1284
- inferredUsage: /* @__PURE__ */ new Map(),
1285
- buildMode: false
1286
- };
1287
- const treeShakingStates = /* @__PURE__ */ new WeakMap();
1288
- function getTreeShakingState(options) {
1289
- if (!options) return legacyTreeShakingState;
1290
- let state = treeShakingStates.get(options);
1291
- if (!state) {
1292
- state = {
1293
- inferredUsage: /* @__PURE__ */ new Map(),
1294
- buildMode: false
1295
- };
1296
- treeShakingStates.set(options, state);
1297
- }
1298
- return state;
1299
- }
1300
- function setTreeShakingBuildMode(enabled, options) {
1301
- getTreeShakingState(options).buildMode = enabled;
1302
- }
1303
- function resetTreeShakingExports(options) {
1304
- getTreeShakingState(options).inferredUsage.clear();
1305
- }
1306
- function getOrCreateExportRecord(sharedKey, request, options) {
1307
- const inferredUsage = getTreeShakingState(options).inferredUsage;
1308
- let byRequest = inferredUsage.get(sharedKey);
1309
- if (!byRequest) {
1310
- byRequest = /* @__PURE__ */ new Map();
1311
- inferredUsage.set(sharedKey, byRequest);
1312
- }
1313
- let record = byRequest.get(request);
1314
- if (!record) {
1315
- record = {
1316
- requiresFullBundle: false,
1317
- usedExports: /* @__PURE__ */ new Set()
1318
- };
1319
- byRequest.set(request, record);
1320
- }
1321
- return record;
1322
- }
1323
- function recordTreeShakingExports(sharedKey, exports, request = sharedKey, options) {
1324
- const record = getOrCreateExportRecord(sharedKey, request, options);
1325
- exports.forEach((name) => record.usedExports.add(name));
1326
- }
1327
- function markTreeShakingPackageUnsafe(sharedKey, request = sharedKey, options) {
1328
- getOrCreateExportRecord(sharedKey, request, options).requiresFullBundle = true;
1329
- }
1330
- function getExportRecords(sharedKey, request, options) {
1331
- const inferredUsage = getTreeShakingState(options).inferredUsage;
1332
- if (sharedKey) {
1333
- const records = inferredUsage.get(sharedKey);
1334
- const wildcard = records?.get("*");
1335
- const exact = records?.get(request);
1336
- return [wildcard, exact === wildcard ? void 0 : exact].filter((record) => !!record);
1337
- }
1338
- const records = [];
1339
- inferredUsage.forEach((byRequest, configuredKey) => {
1340
- const wildcard = byRequest.get("*");
1341
- const exact = byRequest.get(request);
1342
- const keyBase = configuredKey.endsWith("/") ? configuredKey.slice(0, -1) : configuredKey;
1343
- const requestMatchesConfiguredKey = request === keyBase || request.startsWith(`${keyBase}/`);
1344
- if (wildcard && requestMatchesConfiguredKey) records.push(wildcard);
1345
- if (exact && exact !== wildcard) records.push(exact);
1346
- });
1347
- return records;
1066
+ /** Drop SSR-only plugins from a client graph; a server graph keeps them all. */
1067
+ function filterRuntimePluginsForTarget(runtimePlugins, ssrOnlySpecifiers, isServer) {
1068
+ if (isServer) return [...runtimePlugins];
1069
+ return runtimePlugins.filter((plugin) => !ssrOnlySpecifiers.has(getRuntimePluginSpecifier(plugin)));
1348
1070
  }
1071
+ //#endregion
1072
+ //#region src/utils/importAnalysis.ts
1073
+ const analysisByBuild = /* @__PURE__ */ new WeakMap();
1349
1074
  /**
1350
- * Return the analyzed requirement for one concrete shared request.
1351
- *
1352
- * Callers that know the configured share key should pass it explicitly. The
1353
- * fallback lookup across keys keeps aliases/backwards-compatible callers
1354
- * working, while still keeping each concrete request's exports isolated.
1075
+ * Share source analysis within one build environment. Callers still resolve
1076
+ * requests and apply their own sharing configuration. Clear at buildStart and
1077
+ * buildEnd so watch rebuilds start fresh and completed builds release source.
1355
1078
  */
1356
- function getSharedExportUsage(request, shareItem, sharedKey, options) {
1357
- const treeShaking = shareItem?.shareConfig.treeShaking;
1358
- if (!shouldAnalyzeSharedExports(shareItem) || !getTreeShakingState(options).buildMode) return;
1359
- const records = getExportRecords(sharedKey, request, options);
1360
- if (records.some((record) => record.requiresFullBundle)) return { kind: "full" };
1361
- const configured = treeShaking?.usedExports ?? [];
1362
- const result = new Set(configured);
1363
- records.forEach((record) => record.usedExports.forEach((name) => result.add(name)));
1364
- if (result.size > 0) return {
1365
- kind: "exports",
1366
- usedExports: [...result].sort()
1367
- };
1368
- return records.length > 0 ? {
1369
- kind: "exports",
1370
- usedExports: []
1371
- } : { kind: "unknown" };
1079
+ function getImportAnalysis(build) {
1080
+ let analysis = analysisByBuild.get(build);
1081
+ if (!analysis) {
1082
+ const importsByCode = /* @__PURE__ */ new Map();
1083
+ analysis = {
1084
+ analyze(code) {
1085
+ const cached = importsByCode.get(code);
1086
+ if (cached !== void 0) return cached;
1087
+ const imports = analyzeImports(code);
1088
+ importsByCode.set(code, imports);
1089
+ return imports;
1090
+ },
1091
+ clear() {
1092
+ importsByCode.clear();
1093
+ }
1094
+ };
1095
+ analysisByBuild.set(build, analysis);
1096
+ }
1097
+ return analysis;
1372
1098
  }
1373
- function getTreeShakingExportUsage(request, shareItem, sharedKey, options) {
1374
- if (!shareItem?.shareConfig.treeShaking) return void 0;
1375
- return getSharedExportUsage(request, shareItem, sharedKey, options);
1099
+ function isRecord(value) {
1100
+ return value !== null && typeof value === "object";
1376
1101
  }
1377
1102
  function getModuleSource(node) {
1378
- if (!node || typeof node !== "object") return void 0;
1103
+ if (!isRecord(node)) return void 0;
1379
1104
  const source = node;
1380
1105
  if (source.type === "Literal" && typeof source.value === "string") return source.value;
1381
1106
  if (source.type === "StringLiteral" && typeof source.value === "string") return source.value;
@@ -1383,11 +1108,13 @@ function getModuleSource(node) {
1383
1108
  const expressions = Array.isArray(source.expressions) ? source.expressions : [];
1384
1109
  const quasis = Array.isArray(source.quasis) ? source.quasis : [];
1385
1110
  if (expressions.length > 0 || quasis.length !== 1) return void 0;
1386
- const value = quasis[0]?.value;
1387
- return typeof value?.cooked === "string" ? value.cooked : typeof value?.raw === "string" ? value.raw : void 0;
1111
+ const quasi = quasis[0];
1112
+ if (!isRecord(quasi) || !isRecord(quasi.value)) return void 0;
1113
+ const value = quasi.value;
1114
+ return typeof value.cooked === "string" ? value.cooked : typeof value.raw === "string" ? value.raw : void 0;
1388
1115
  }
1389
1116
  function getExportedName(node) {
1390
- if (!node || typeof node !== "object") return void 0;
1117
+ if (!isRecord(node)) return void 0;
1391
1118
  const exported = node;
1392
1119
  if (exported.type === "Identifier" && typeof exported.name === "string") return exported.name;
1393
1120
  if ((exported.type === "Literal" || exported.type === "StringLiteral") && typeof exported.value === "string") return exported.value;
@@ -1400,7 +1127,7 @@ function forEachAstNode(root, visit) {
1400
1127
  const seen = /* @__PURE__ */ new Set();
1401
1128
  while (stack.length > 0) {
1402
1129
  const value = stack.pop();
1403
- if (!value || typeof value !== "object") continue;
1130
+ if (!isRecord(value)) continue;
1404
1131
  if (seen.has(value)) continue;
1405
1132
  seen.add(value);
1406
1133
  if (Array.isArray(value)) {
@@ -1414,18 +1141,22 @@ function forEachAstNode(root, visit) {
1414
1141
  });
1415
1142
  }
1416
1143
  }
1417
- function collectImportDeclaration(node, source, record, markUnsafe) {
1144
+ function collectImportDeclaration(node, source, record, requireAllExports) {
1418
1145
  if (isTypeOnly(node)) return;
1419
1146
  const specifiers = Array.isArray(node.specifiers) ? node.specifiers : [];
1420
1147
  if (specifiers.length === 0) {
1421
- markUnsafe(source);
1148
+ requireAllExports(source);
1422
1149
  return;
1423
1150
  }
1424
1151
  const names = [];
1425
1152
  for (const specifier of specifiers) {
1153
+ if (!isRecord(specifier)) {
1154
+ requireAllExports(source);
1155
+ return;
1156
+ }
1426
1157
  if (isTypeOnly(specifier)) continue;
1427
1158
  if (specifier.type === "ImportNamespaceSpecifier") {
1428
- markUnsafe(source);
1159
+ requireAllExports(source);
1429
1160
  return;
1430
1161
  }
1431
1162
  if (specifier.type === "ImportDefaultSpecifier") {
@@ -1434,118 +1165,246 @@ function collectImportDeclaration(node, source, record, markUnsafe) {
1434
1165
  }
1435
1166
  if (specifier.type === "ImportSpecifier") {
1436
1167
  const imported = specifier.imported;
1437
- if (imported?.type === "Literal" || imported?.type === "StringLiteral") {
1438
- markUnsafe(source);
1168
+ if (isRecord(imported) && (imported.type === "Literal" || imported.type === "StringLiteral")) {
1169
+ requireAllExports(source);
1439
1170
  return;
1440
1171
  }
1441
1172
  const name = getExportedName(specifier.imported);
1442
1173
  if (!name) {
1443
- markUnsafe(source);
1174
+ requireAllExports(source);
1444
1175
  return;
1445
1176
  }
1446
1177
  names.push(name);
1447
1178
  continue;
1448
1179
  }
1449
- markUnsafe(source);
1180
+ requireAllExports(source);
1450
1181
  return;
1451
1182
  }
1452
1183
  record(names, source);
1453
1184
  }
1454
- function collectReExport(node, source, record, markUnsafe) {
1185
+ function collectReExport(node, source, record, requireAllExports) {
1455
1186
  if (isTypeOnly(node)) return;
1456
1187
  if (node.type === "ExportAllDeclaration") {
1457
- markUnsafe(source);
1188
+ requireAllExports(source);
1458
1189
  return;
1459
1190
  }
1460
1191
  const specifiers = Array.isArray(node.specifiers) ? node.specifiers : [];
1461
1192
  if (specifiers.length === 0) {
1462
- markUnsafe(source);
1193
+ requireAllExports(source);
1463
1194
  return;
1464
1195
  }
1465
1196
  const names = [];
1466
1197
  for (const specifier of specifiers) {
1198
+ if (!isRecord(specifier)) {
1199
+ requireAllExports(source);
1200
+ return;
1201
+ }
1467
1202
  if (isTypeOnly(specifier)) continue;
1468
1203
  if (specifier.type !== "ExportSpecifier") {
1469
- markUnsafe(source);
1204
+ requireAllExports(source);
1470
1205
  return;
1471
1206
  }
1472
1207
  const local = specifier.local;
1473
- if (local?.type === "Literal" || local?.type === "StringLiteral") {
1474
- markUnsafe(source);
1208
+ if (isRecord(local) && (local.type === "Literal" || local.type === "StringLiteral")) {
1209
+ requireAllExports(source);
1475
1210
  return;
1476
1211
  }
1477
1212
  const name = getExportedName(specifier.local);
1478
1213
  if (!name) {
1479
- markUnsafe(source);
1214
+ requireAllExports(source);
1480
1215
  return;
1481
1216
  }
1482
1217
  names.push(name);
1483
1218
  }
1484
1219
  record(names, source);
1485
1220
  }
1221
+ function analyzeImports(code) {
1222
+ let ast;
1223
+ try {
1224
+ ast = vite.parseAst(code);
1225
+ } catch {
1226
+ return null;
1227
+ }
1228
+ const imports = [];
1229
+ const recordSource = (names, source) => imports.push({
1230
+ source,
1231
+ usedExports: names
1232
+ });
1233
+ const requireAllExports = (source) => imports.push({
1234
+ source,
1235
+ usedExports: null
1236
+ });
1237
+ const collectImport = (node) => {
1238
+ if (node.type === "ImportDeclaration") {
1239
+ const source = getModuleSource(node.source);
1240
+ if (source) collectImportDeclaration(node, source, recordSource, requireAllExports);
1241
+ return;
1242
+ }
1243
+ if ((node.type === "ExportNamedDeclaration" || node.type === "ExportAllDeclaration") && node.source) {
1244
+ const source = getModuleSource(node.source);
1245
+ if (source) collectReExport(node, source, recordSource, requireAllExports);
1246
+ return;
1247
+ }
1248
+ if (node.type === "ImportExpression") {
1249
+ const source = getModuleSource(node.source);
1250
+ if (source) requireAllExports(source);
1251
+ return;
1252
+ }
1253
+ if (node.type === "CallExpression") {
1254
+ const callee = node.callee;
1255
+ const args = Array.isArray(node.arguments) ? node.arguments : [];
1256
+ if (isRecord(callee) && callee.type === "Identifier" && callee.name === "require" && args.length > 0) {
1257
+ const source = getModuleSource(args[0]);
1258
+ if (source) requireAllExports(source);
1259
+ }
1260
+ }
1261
+ };
1262
+ if ("Visitor" in vite && typeof vite.Visitor === "function") {
1263
+ const visit = (node) => {
1264
+ if (isRecord(node)) collectImport(node);
1265
+ };
1266
+ try {
1267
+ new vite.Visitor({
1268
+ ImportDeclaration: visit,
1269
+ ExportNamedDeclaration: visit,
1270
+ ExportAllDeclaration: visit,
1271
+ ImportExpression: visit,
1272
+ CallExpression: visit
1273
+ }).visit(ast);
1274
+ return imports;
1275
+ } catch {
1276
+ imports.length = 0;
1277
+ }
1278
+ }
1279
+ forEachAstNode(ast, collectImport);
1280
+ return imports;
1281
+ }
1282
+ //#endregion
1283
+ //#region src/utils/treeShaking.ts
1284
+ function shouldAnalyzeSharedExports(shareItem) {
1285
+ return !!(shareItem && (shareItem.shareConfig.treeShaking || shareItem.shareConfig.import === false));
1286
+ }
1287
+ const legacyTreeShakingState = {
1288
+ inferredUsage: /* @__PURE__ */ new Map(),
1289
+ buildMode: false
1290
+ };
1291
+ const treeShakingStates = /* @__PURE__ */ new WeakMap();
1292
+ function getTreeShakingState(options) {
1293
+ if (!options) return legacyTreeShakingState;
1294
+ let state = treeShakingStates.get(options);
1295
+ if (!state) {
1296
+ state = {
1297
+ inferredUsage: /* @__PURE__ */ new Map(),
1298
+ buildMode: false
1299
+ };
1300
+ treeShakingStates.set(options, state);
1301
+ }
1302
+ return state;
1303
+ }
1304
+ function setTreeShakingBuildMode(enabled, options) {
1305
+ getTreeShakingState(options).buildMode = enabled;
1306
+ }
1307
+ function resetTreeShakingExports(options) {
1308
+ getTreeShakingState(options).inferredUsage.clear();
1309
+ }
1310
+ function getOrCreateExportRecord(sharedKey, request, options) {
1311
+ const inferredUsage = getTreeShakingState(options).inferredUsage;
1312
+ let byRequest = inferredUsage.get(sharedKey);
1313
+ if (!byRequest) {
1314
+ byRequest = /* @__PURE__ */ new Map();
1315
+ inferredUsage.set(sharedKey, byRequest);
1316
+ }
1317
+ let record = byRequest.get(request);
1318
+ if (!record) {
1319
+ record = {
1320
+ requiresFullBundle: false,
1321
+ usedExports: /* @__PURE__ */ new Set()
1322
+ };
1323
+ byRequest.set(request, record);
1324
+ }
1325
+ return record;
1326
+ }
1327
+ function recordTreeShakingExports(sharedKey, exports, request = sharedKey, options) {
1328
+ const record = getOrCreateExportRecord(sharedKey, request, options);
1329
+ exports.forEach((name) => record.usedExports.add(name));
1330
+ }
1331
+ function markTreeShakingPackageUnsafe(sharedKey, request = sharedKey, options) {
1332
+ getOrCreateExportRecord(sharedKey, request, options).requiresFullBundle = true;
1333
+ }
1334
+ function getExportRecords(sharedKey, request, options) {
1335
+ const inferredUsage = getTreeShakingState(options).inferredUsage;
1336
+ if (sharedKey) {
1337
+ const records = inferredUsage.get(sharedKey);
1338
+ const wildcard = records?.get("*");
1339
+ const exact = records?.get(request);
1340
+ return [wildcard, exact === wildcard ? void 0 : exact].filter((record) => !!record);
1341
+ }
1342
+ const records = [];
1343
+ inferredUsage.forEach((byRequest, configuredKey) => {
1344
+ const wildcard = byRequest.get("*");
1345
+ const exact = byRequest.get(request);
1346
+ const configuredRequest = getSharedRequest(configuredKey, options?.shared?.[configuredKey]);
1347
+ const keyBase = configuredRequest.endsWith("/") ? configuredRequest.slice(0, -1) : configuredRequest;
1348
+ const requestMatchesConfiguredKey = request === keyBase || request.startsWith(`${keyBase}/`);
1349
+ if (wildcard && requestMatchesConfiguredKey) records.push(wildcard);
1350
+ if (exact && exact !== wildcard) records.push(exact);
1351
+ });
1352
+ return records;
1353
+ }
1354
+ /**
1355
+ * Return the analyzed requirement for one concrete shared request.
1356
+ *
1357
+ * Callers that know the configured share key should pass it explicitly. The
1358
+ * fallback lookup across keys keeps aliases/backwards-compatible callers
1359
+ * working, while still keeping each concrete request's exports isolated.
1360
+ */
1361
+ function getSharedExportUsage(request, shareItem, sharedKey, options) {
1362
+ const treeShaking = shareItem?.shareConfig.treeShaking;
1363
+ if (!shouldAnalyzeSharedExports(shareItem) || !getTreeShakingState(options).buildMode) return;
1364
+ const records = getExportRecords(sharedKey, request, options);
1365
+ if (records.some((record) => record.requiresFullBundle)) return { kind: "full" };
1366
+ const configured = treeShaking?.usedExports ?? [];
1367
+ const result = new Set(configured);
1368
+ records.forEach((record) => record.usedExports.forEach((name) => result.add(name)));
1369
+ if (result.size > 0) return {
1370
+ kind: "exports",
1371
+ usedExports: [...result].sort()
1372
+ };
1373
+ return records.length > 0 ? {
1374
+ kind: "exports",
1375
+ usedExports: []
1376
+ } : { kind: "unknown" };
1377
+ }
1378
+ function getTreeShakingExportUsage(request, shareItem, sharedKey, options) {
1379
+ if (!shareItem?.shareConfig.treeShaking) return void 0;
1380
+ return getSharedExportUsage(request, shareItem, sharedKey, options);
1381
+ }
1486
1382
  /**
1487
- * Collect the exports required by a consumer's ESM graph.
1488
- *
1489
- * Parsing the module avoids treating import-looking text in comments, strings,
1490
- * templates, or regular expressions as real dependencies. If parsing fails,
1491
- * every configured share whose exports are analyzed is conservatively marked
1492
- * as requiring its full export surface instead of guessing from source text.
1493
- *
1494
- * Generated federation wrappers are excluded because their imports describe
1495
- * the wrapper implementation, not the consumer's requirements.
1383
+ * Record consumer imports against this instance's sharing configuration.
1384
+ * Generated wrappers do not contribute consumer usage. If parsing fails,
1385
+ * every share enabled for analysis requires all of its exports.
1496
1386
  */
1497
- async function collectTreeShakingImports(code, id, shared, findSharedKey, record, markUnsafe) {
1387
+ async function collectTreeShakingImports(code, id, shared, findSharedKey, record, markUnsafe, analysis = getImportAnalysis(shared)) {
1498
1388
  const normalizedId = normalizePathForImport(id);
1499
1389
  if (normalizedId.includes("__prebuild__") || normalizedId.includes("__loadShare__") || normalizedId.includes("__mf_tree_shaking_graph__")) return;
1500
- let ast;
1501
- try {
1502
- ast = parseAst(code);
1503
- } catch {
1390
+ const imports = analysis.analyze(code);
1391
+ if (imports === null) {
1504
1392
  Object.entries(shared).forEach(([sharedKey, shareItem]) => {
1505
1393
  if (shouldAnalyzeSharedExports(shareItem)) markUnsafe(sharedKey, "*");
1506
1394
  });
1507
1395
  return;
1508
1396
  }
1509
1397
  const pending = [];
1510
- const withSharedSource = (source, use) => {
1398
+ for (const { source, usedExports } of imports) {
1511
1399
  const apply = (key) => {
1512
- if (key && shouldAnalyzeSharedExports(shared[key])) use(key);
1400
+ if (!key || !shouldAnalyzeSharedExports(shared[key])) return;
1401
+ if (usedExports === null) markUnsafe(key, source);
1402
+ else record(key, usedExports, source);
1513
1403
  };
1514
1404
  const key = findSharedKey(source, shared);
1515
1405
  if (key instanceof Promise) pending.push(key.then(apply));
1516
1406
  else apply(key);
1517
- };
1518
- const recordSource = (names, source) => {
1519
- withSharedSource(source, (key) => record(key, names, source));
1520
- };
1521
- const markSourceUnsafe = (source) => {
1522
- withSharedSource(source, (key) => markUnsafe(key, source));
1523
- };
1524
- forEachAstNode(ast, (node) => {
1525
- if (node.type === "ImportDeclaration") {
1526
- const source = getModuleSource(node.source);
1527
- if (source) collectImportDeclaration(node, source, recordSource, markSourceUnsafe);
1528
- return;
1529
- }
1530
- if ((node.type === "ExportNamedDeclaration" || node.type === "ExportAllDeclaration") && node.source) {
1531
- const source = getModuleSource(node.source);
1532
- if (source) collectReExport(node, source, recordSource, markSourceUnsafe);
1533
- return;
1534
- }
1535
- if (node.type === "ImportExpression") {
1536
- const source = getModuleSource(node.source);
1537
- if (source) markSourceUnsafe(source);
1538
- return;
1539
- }
1540
- if (node.type === "CallExpression") {
1541
- const callee = node.callee;
1542
- const args = Array.isArray(node.arguments) ? node.arguments : [];
1543
- if (callee?.type === "Identifier" && callee.name === "require" && args.length > 0) {
1544
- const source = getModuleSource(args[0]);
1545
- if (source) markSourceUnsafe(source);
1546
- }
1547
- }
1548
- });
1407
+ }
1549
1408
  await Promise.all(pending);
1550
1409
  }
1551
1410
  //#endregion
@@ -2162,7 +2021,7 @@ ${exportStatement}
2162
2021
  //#endregion
2163
2022
  //#region src/plugins/pluginReactMixedModeGuard.ts
2164
2023
  function createReactMixedModeRuntimeGuard() {
2165
- return `const __mfReactInternals = mod["__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE"];
2024
+ return `const __mfReactInternals = mod[${JSON.stringify(REACT_CLIENT_INTERNALS_KEY)}];
2166
2025
  if (__mfReactInternals && "A" in __mfReactInternals) {
2167
2026
  let __mfReactDispatcher = __mfReactInternals.A;
2168
2027
  Object.defineProperty(__mfReactInternals, "A", {
@@ -2252,6 +2111,77 @@ function findLikelyTypeArgumentEnd(source, start, codePositions) {
2252
2111
  }
2253
2112
  }
2254
2113
  //#endregion
2114
+ //#region src/virtualModules/shareTags.ts
2115
+ const LOAD_SHARE_TAG = "__loadShare__";
2116
+ /** A share's local copy. Reachable only through `import()`, so it stays lazy. */
2117
+ const PREBUILD_TAG = "__prebuild__";
2118
+ //#endregion
2119
+ //#region src/virtualModules/loadShareSharedChunk.ts
2120
+ const HELPERS_MODULE_NAME = "loadShareHelpers";
2121
+ const HELPERS_MODULE_TAG = "__mf_v__";
2122
+ const HELPERS_MODULE_MARKER = `${HELPERS_MODULE_TAG}${HELPERS_MODULE_NAME}${HELPERS_MODULE_TAG}`;
2123
+ const SHARED_CHUNK_SUFFIX = `${LOAD_SHARE_TAG}shared`;
2124
+ const HELPER_EXPORT_LIST = [
2125
+ "__mfGetSharedCacheDescriptor",
2126
+ "__mfReadSharedCache",
2127
+ "__mfSharedCacheListenersKey",
2128
+ "__mfGetSharedCacheListeners",
2129
+ "__mfSubscribeSharedCache",
2130
+ "__mfSharedCacheOwnersKey",
2131
+ "__mfGetSharedCacheOwners",
2132
+ "__mfReadSharedCacheOwner",
2133
+ "__mfGetSharedModuleIdentity",
2134
+ "__mfIsSameSharedModule",
2135
+ "__mfWriteSharedCache",
2136
+ "__mfTreeShakingSharedCacheKey",
2137
+ "__mfGetTreeShakingSharedCache",
2138
+ "__mfReadTreeShakingSharedCache",
2139
+ "__mfWriteTreeShakingSharedCache",
2140
+ "__mfTreeShakingSelectionCacheKey",
2141
+ "__mfGetTreeShakingSelectionCache",
2142
+ "__mfReadTreeShakingSharedSelection",
2143
+ "__mfWriteTreeShakingSharedSelection"
2144
+ ].join(", ");
2145
+ const helperModules = /* @__PURE__ */ new WeakMap();
2146
+ function getSharedCacheHelpersModule(options) {
2147
+ let module = helperModules.get(options);
2148
+ if (!module) {
2149
+ module = new VirtualModule(HELPERS_MODULE_NAME, HELPERS_MODULE_TAG, "", getFederationScopeKey(options));
2150
+ module.writeSync(`${sharedCacheHelperCode}\nexport { ${HELPER_EXPORT_LIST} };`);
2151
+ helperModules.set(options, module);
2152
+ }
2153
+ return module;
2154
+ }
2155
+ function getSharedCacheHelpersImportCode(options) {
2156
+ const importId = getSharedCacheHelpersModule(options).getImportId();
2157
+ return `import { ${HELPER_EXPORT_LIST} } from ${JSON.stringify(importId)};`;
2158
+ }
2159
+ function isSharedCacheHelpersId(id) {
2160
+ return id.includes(HELPERS_MODULE_MARKER);
2161
+ }
2162
+ function getSharedChunkName(id) {
2163
+ const ownerTag = isSharedCacheHelpersId(id) ? HELPERS_MODULE_MARKER : LOAD_SHARE_TAG;
2164
+ return `${id.slice(0, id.indexOf(ownerTag))}${SHARED_CHUNK_SUFFIX}`;
2165
+ }
2166
+ function isSharedChunk(chunk) {
2167
+ return chunk.name?.endsWith(SHARED_CHUNK_SUFFIX) ?? false;
2168
+ }
2169
+ /**
2170
+ * Fallbacks inlined into a shared chunk, which means they are no longer lazy.
2171
+ * Only inlined modules count: a shared chunk also imports fallback chunks with
2172
+ * the experiment off, because Rolldown hoists its runtime helpers into whichever
2173
+ * chunk first uses them.
2174
+ */
2175
+ function findEagerFallbacksInSharedChunk(bundle) {
2176
+ const offenders = /* @__PURE__ */ new Map();
2177
+ for (const [fileName, chunk] of Object.entries(bundle)) {
2178
+ if (chunk.type !== "chunk" || !isSharedChunk(chunk)) continue;
2179
+ const inlined = Object.keys(chunk.modules ?? {}).filter((id) => id.includes(PREBUILD_TAG));
2180
+ if (inlined.length > 0) offenders.set(fileName, inlined);
2181
+ }
2182
+ return offenders;
2183
+ }
2184
+ //#endregion
2255
2185
  //#region src/virtualModules/virtualShared_preBuild.ts
2256
2186
  /**
2257
2187
  * Even the resolveId hook cannot interfere with vite pre-build,
@@ -2287,7 +2217,7 @@ function isValidEsmExportName(name) {
2287
2217
  const JS_IDENTIFIER_PATTERN = `[\$_\\p{ID_Start}][\$_\\u200C\\u200D\\p{ID_Continue}]*`;
2288
2218
  function resolvePackageEntryFromProjectRoot(pkg) {
2289
2219
  try {
2290
- return createRequire$1(pathToFileURL(path$1.join(getPackageDetectionCwd(), "package.json"))).resolve(pkg);
2220
+ return resolveModulePath(pkg, path$1.join(getPackageDetectionCwd(), "package.json"));
2291
2221
  } catch {
2292
2222
  return;
2293
2223
  }
@@ -2445,7 +2375,7 @@ function resolveConfiguredImportPath(importSource, exportConditions = DEFAULT_SH
2445
2375
  });
2446
2376
  if (esmEntry) return esmEntry;
2447
2377
  try {
2448
- return createRequire$1(pathToFileURL(path$1.join(projectRoot, "package.json"))).resolve(importSource);
2378
+ return resolveModulePath(importSource, path$1.join(projectRoot, "package.json"));
2449
2379
  } catch {
2450
2380
  return;
2451
2381
  }
@@ -2473,6 +2403,11 @@ function resolveRelativeModule(filePath, specifier) {
2473
2403
  const dir = path$1.dirname(filePath);
2474
2404
  const exact = path$1.resolve(dir, specifier);
2475
2405
  if (existsSync(exact) && !statSync(exact).isDirectory()) return exact;
2406
+ const sourceExtensions = specifier.endsWith(".mjs") ? [".mts"] : specifier.endsWith(".cjs") ? [".cts"] : /\.jsx?$/.test(specifier) ? [".ts", ".tsx"] : [];
2407
+ for (const ext of sourceExtensions) {
2408
+ const candidate = exact.replace(/\.[cm]?jsx?$/, ext);
2409
+ if (existsSync(candidate) && !statSync(candidate).isDirectory()) return candidate;
2410
+ }
2476
2411
  const extensions = [
2477
2412
  ".ts",
2478
2413
  ".tsx",
@@ -2500,7 +2435,7 @@ function resolveReExportModule(filePath, specifier, exportConditions) {
2500
2435
  });
2501
2436
  if (esmEntry) return esmEntry;
2502
2437
  try {
2503
- return resolveFileLikeModule(createRequire$1(pathToFileURL(filePath)).resolve(specifier));
2438
+ return resolveFileLikeModule(resolveModulePath(specifier, filePath));
2504
2439
  } catch {
2505
2440
  return;
2506
2441
  }
@@ -2828,7 +2763,8 @@ function getRequiredNamedExports(specifier) {
2828
2763
  const getActiveHandles = process._getActiveHandles;
2829
2764
  const handlesBeforeRequire = typeof getActiveHandles === "function" ? new Set(getActiveHandles.call(process)) : void 0;
2830
2765
  try {
2831
- const mod = createRequire$1(pathToFileURL(path$1.join(getPackageDetectionCwd(), "package.json")))(specifier);
2766
+ const projectPackageJson = path$1.join(getPackageDetectionCwd(), "package.json");
2767
+ const mod = createRequire$1(pathToFileURL(projectPackageJson))(resolveModulePath(specifier, projectPackageJson));
2832
2768
  const runtimeNamedKeys = Object.keys(mod).filter((key) => key !== "default" && key !== "__esModule");
2833
2769
  if (runtimeNamedKeys.some((key) => !isValidEsmExportName(key))) return void 0;
2834
2770
  return runtimeNamedKeys;
@@ -2871,7 +2807,7 @@ function getSharedNamedExports(pkg, shareItem, exportConditions = DEFAULT_SHARED
2871
2807
  }
2872
2808
  function getLocalProviderImportPath(pkg) {
2873
2809
  try {
2874
- const resolved = resolveWorkspaceEsmEntry(pkg, createRequire$1(pathToFileURL(path$1.join(getPackageDetectionCwd(), "package.json"))).resolve(pkg));
2810
+ const resolved = resolveWorkspaceEsmEntry(pkg, resolveModulePath(pkg, path$1.join(getPackageDetectionCwd(), "package.json")));
2875
2811
  return isWorkspaceFilePath(resolved) ? resolved : void 0;
2876
2812
  } catch {
2877
2813
  const resolved = getInstalledPackageEntry(pkg, {
@@ -2892,7 +2828,7 @@ function getProjectResolvedImportPath(pkg) {
2892
2828
  if (esmEntry) return esmEntry;
2893
2829
  }
2894
2830
  try {
2895
- return resolveWorkspaceEsmEntry(pkg, createRequire$1(pathToFileURL(path$1.join(getPackageDetectionCwd(), "package.json"))).resolve(pkg));
2831
+ return resolveWorkspaceEsmEntry(pkg, resolveModulePath(pkg, path$1.join(getPackageDetectionCwd(), "package.json")));
2896
2832
  } catch {
2897
2833
  return;
2898
2834
  }
@@ -2948,25 +2884,11 @@ function getSharedDependencyGraphPackageJson(pkg) {
2948
2884
  const installedPackageJson = getInstalledPackageJson(pkg, { packageName: getPackageName(pkg) })?.packageJson;
2949
2885
  if (installedPackageJson) return installedPackageJson;
2950
2886
  try {
2951
- const packageJsonPath = createRequire$1(pathToFileURL(path$1.join(getPackageDetectionCwd(), "package.json"))).resolve(`${getPackageName(pkg)}/package.json`);
2887
+ const packageJsonPath = resolveModulePath(`${getPackageName(pkg)}/package.json`, path$1.join(getPackageDetectionCwd(), "package.json"));
2952
2888
  return JSON.parse(readFileSync(packageJsonPath, "utf-8"));
2953
2889
  } catch {}
2954
2890
  return getWorkspacePackageJson(pkg);
2955
2891
  }
2956
- function getDependencyNames(packageJson) {
2957
- if (!packageJson) return [];
2958
- const names = /* @__PURE__ */ new Set();
2959
- for (const field of [
2960
- "dependencies",
2961
- "peerDependencies",
2962
- "optionalDependencies"
2963
- ]) {
2964
- const deps = packageJson[field];
2965
- if (!deps || typeof deps !== "object") continue;
2966
- for (const dep of Object.keys(deps)) names.add(dep);
2967
- }
2968
- return Array.from(names);
2969
- }
2970
2892
  function isSharedSingletonConsumedByPeer(pkg, options = getNormalizeModuleFederationOptions(), requireFederationRuntimeDependency = false) {
2971
2893
  const shared = options?.shared || {};
2972
2894
  if (!requireFederationRuntimeDependency && Object.entries(shared).some(([key, item]) => key !== pkg && key.startsWith(`${pkg}/`) && item.shareConfig.singleton === true)) return true;
@@ -2975,25 +2897,39 @@ function isSharedSingletonConsumedByPeer(pkg, options = getNormalizeModuleFedera
2975
2897
  const packageName = getPackageName(key);
2976
2898
  if (!sharedKeyByPackageName.get(packageName) || key === packageName) sharedKeyByPackageName.set(packageName, key);
2977
2899
  });
2978
- const reachesPkg = (current, seen, hasFederationRuntimeDependency = false) => {
2900
+ const runtimeDependencyCache = /* @__PURE__ */ new Map();
2901
+ const reachesFederationRuntime = (current, seen) => {
2902
+ if (runtimeDependencyCache.has(current)) return runtimeDependencyCache.get(current);
2903
+ const result = getDependencyNames(getSharedDependencyGraphPackageJson(current)).some((dependency) => {
2904
+ if (dependency === "@module-federation/enhanced" || dependency === "@module-federation/runtime" || dependency === "@module-federation/runtime-core") return true;
2905
+ if (seen.has(dependency)) return false;
2906
+ seen.add(dependency);
2907
+ const reachable = reachesFederationRuntime(dependency, seen);
2908
+ seen.delete(dependency);
2909
+ return reachable;
2910
+ });
2911
+ runtimeDependencyCache.set(current, result);
2912
+ return result;
2913
+ };
2914
+ const reachesPkg = (current, seen) => {
2979
2915
  const dependencies = getDependencyNames(getSharedDependencyGraphPackageJson(current));
2980
- const usesFederationRuntime = dependencies.some((dependency) => dependency === "@module-federation/enhanced" || dependency === "@module-federation/runtime" || dependency === "@module-federation/runtime-core");
2981
- const runtimeIsReachable = hasFederationRuntimeDependency || usesFederationRuntime;
2982
2916
  for (const dependency of dependencies) {
2983
2917
  const sharedDependency = sharedKeyByPackageName.get(dependency);
2984
- if (!sharedDependency) continue;
2985
- if (sharedDependency === pkg) return !requireFederationRuntimeDependency || runtimeIsReachable;
2986
- if (seen.has(sharedDependency)) continue;
2987
- seen.add(sharedDependency);
2988
- if (reachesPkg(sharedDependency, seen, runtimeIsReachable)) return true;
2918
+ if (sharedDependency === pkg) return true;
2919
+ if (!sharedDependency && !requireFederationRuntimeDependency) continue;
2920
+ const next = sharedDependency || dependency;
2921
+ if (seen.has(next)) continue;
2922
+ seen.add(next);
2923
+ if (reachesPkg(next, seen)) return true;
2924
+ seen.delete(next);
2989
2925
  }
2990
2926
  return false;
2991
2927
  };
2992
- return Array.from(sharedKeyByPackageName.values()).some((sharedPkg) => sharedPkg !== pkg && reachesPkg(sharedPkg, /* @__PURE__ */ new Set([sharedPkg])));
2928
+ return Array.from(sharedKeyByPackageName.values()).some((sharedPkg) => sharedPkg !== pkg && (!requireFederationRuntimeDependency || reachesFederationRuntime(sharedPkg, /* @__PURE__ */ new Set([sharedPkg]))) && reachesPkg(sharedPkg, /* @__PURE__ */ new Set([sharedPkg])));
2993
2929
  }
2994
2930
  function tryResolveImportFromPackageRoot(pkg, root) {
2995
2931
  try {
2996
- return resolveWorkspaceEsmEntry(pkg, createRequire$1(pathToFileURL(path$1.join(root, "package.json"))).resolve(pkg), root);
2932
+ return resolveWorkspaceEsmEntry(pkg, resolveModulePath(pkg, path$1.join(root, "package.json")), root);
2997
2933
  } catch {
2998
2934
  return;
2999
2935
  }
@@ -3026,9 +2962,11 @@ function resolveConcreteSharedImportSource(pkg, projectRoot) {
3026
2962
  if (resolved) return resolved;
3027
2963
  currentDir = path$1.dirname(currentDir);
3028
2964
  }
3029
- return tryResolveImportFromPackageRoot(pkg, currentDir);
2965
+ return tryResolveImportFromPackageRoot(pkg, currentDir) ?? getInstalledPackageEntry(pkg, {
2966
+ conditions: DEFAULT_SHARED_EXPORT_CONDITIONS,
2967
+ resolveSubpathWithRequire: false
2968
+ });
3030
2969
  }
3031
- const PREBUILD_TAG = "__prebuild__";
3032
2970
  const TREE_SHAKING_PROVIDER_TAG = "__treeShakingProvider__";
3033
2971
  const TREE_SHAKING_GRAPH_QUERY = "__mf_tree_shaking_graph__";
3034
2972
  const legacySharedVirtualModuleState = {
@@ -3037,9 +2975,11 @@ const legacySharedVirtualModuleState = {
3037
2975
  treeShakingProviderCacheMap: {},
3038
2976
  materializedTreeShakingProviders: /* @__PURE__ */ new Set(),
3039
2977
  loadShareCacheMap: {},
3040
- warnedMissingImportFalse: /* @__PURE__ */ new Set()
2978
+ warnedMissingImportFalse: /* @__PURE__ */ new Set(),
2979
+ coalescableLoadShares: /* @__PURE__ */ new Set()
3041
2980
  };
3042
2981
  const sharedVirtualModuleStates = /* @__PURE__ */ new WeakMap();
2982
+ const sharedVirtualModuleStatesByOwner = /* @__PURE__ */ new Map();
3043
2983
  function getSharedVirtualModuleState(options) {
3044
2984
  if (!options) try {
3045
2985
  const currentOptions = getNormalizeModuleFederationOptions();
@@ -3056,12 +2996,19 @@ function getSharedVirtualModuleState(options) {
3056
2996
  materializedTreeShakingProviders: /* @__PURE__ */ new Set(),
3057
2997
  loadShareCacheMap: {},
3058
2998
  warnedMissingImportFalse: /* @__PURE__ */ new Set(),
2999
+ coalescableLoadShares: /* @__PURE__ */ new Set(),
3059
3000
  ownerKey: getFederationScopeKey(options)
3060
3001
  };
3061
3002
  sharedVirtualModuleStates.set(options, state);
3003
+ if (state.ownerKey !== void 0) sharedVirtualModuleStatesByOwner.set(state.ownerKey, state);
3062
3004
  }
3063
3005
  return state;
3064
3006
  }
3007
+ /** State of the instance that owns a scoped virtual id; `options` covers unscoped ids. */
3008
+ function getSharedVirtualModuleStateForId(id, options) {
3009
+ const ownerKey = id === void 0 ? void 0 : VirtualModule.findById(id)?.getScopeName();
3010
+ return (ownerKey !== void 0 ? sharedVirtualModuleStatesByOwner.get(ownerKey) : void 0) ?? getSharedVirtualModuleState(options);
3011
+ }
3065
3012
  function createScopedSharedVirtualModule(pkg, tag, options) {
3066
3013
  return new VirtualModule(pkg, tag, ".js", getSharedVirtualModuleState(options).ownerKey);
3067
3014
  }
@@ -3178,7 +3125,7 @@ function writePreBuildLibPath(pkg, shareItem, options, exportConditions) {
3178
3125
  const cache = globalThis[__mfCacheGlobalKey]?.share;
3179
3126
  const sharedReact = cache && __mfReadSharedCache(cache, ${reactCacheDescriptor});
3180
3127
  const reactExports = sharedReact?.default ?? sharedReact;
3181
- const internals = reactExports?.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;
3128
+ const internals = reactExports?.[${JSON.stringify(REACT_CLIENT_INTERNALS_KEY)}];
3182
3129
  return internals?.H?.useMemoCache(size);
3183
3130
  };
3184
3131
  export default { c };
@@ -3256,7 +3203,6 @@ function getPreBuildShareItem(pkg, options) {
3256
3203
  function getSharedImportSource(pkg, shareItem, options) {
3257
3204
  return getConcreteSharedImportSource(pkg, shareItem) || getPreBuildLibImportId(pkg, options);
3258
3205
  }
3259
- const LOAD_SHARE_TAG = "__loadShare__";
3260
3206
  function getLoadShareImportId(pkg, _isRolldown, options) {
3261
3207
  const { loadShareCacheMap } = getSharedVirtualModuleState(options);
3262
3208
  if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = createScopedSharedVirtualModule(pkg, LOAD_SHARE_TAG, options);
@@ -3316,14 +3262,14 @@ function getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer) {
3316
3262
  * a merged chunk, TDZ bindings otherwise), so the exports stay unassigned until the deferred cache write
3317
3263
  * re-applies them; a host-provided copy re-applies them through the cache subscription as before.
3318
3264
  */
3319
- function generateEagerWorkspaceSingletonExports(namedExports, importSource, cacheDescriptor, cacheOwner, treeShakingConsumer, mutableExports = []) {
3265
+ function generateEagerWorkspaceSingletonExports(edges, namedExports, importSource, cacheDescriptor, cacheOwner, treeShakingConsumer, mutableExports = []) {
3320
3266
  const copiedExports = namedExports.filter((name) => !mutableExports.includes(name));
3321
3267
  const namedExportVars = copiedExports.map((_name, i) => `__mf_${i}`);
3322
3268
  const declarations = namedExports.length > 0 ? ["let __mf_default;", ...namedExportVars.map((name) => `let ${name};`)].join("\n ") : "let __mf_default;";
3323
3269
  const assignments = [...copiedExports.map((name, i) => `${namedExportVars[i]} = mod[${escapeGeneratedStringLiteral(name)}];`), "__mf_default = mod.default ?? mod;"].join("\n ");
3324
3270
  const namedExportLine = copiedExports.length > 0 ? `\n export { ${copiedExports.map((name, i) => `${namedExportVars[i]} as ${name}`).join(", ")} };` : "";
3325
- const mutableExportLine = mutableExports.length ? `\n export { ${mutableExports.join(", ")} } from ${escapeGeneratedStringLiteral(importSource)};` : "";
3326
- return `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(importSource)};
3271
+ const mutableExportLine = mutableExports.length ? `\n ${edges.reExportNames(mutableExports, importSource)}` : "";
3272
+ return `${edges.importNamespace(importSource)}
3327
3273
  let exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
3328
3274
  if (exportModule === undefined) {
3329
3275
  Promise.resolve().then(() => {
@@ -3351,28 +3297,26 @@ function generateEagerWorkspaceSingletonExports(namedExports, importSource, cach
3351
3297
  __mfApplyEagerShareExportsWhenReady(exportModule);
3352
3298
  export { __mf_default as default };${namedExportLine}${mutableExportLine}`;
3353
3299
  }
3354
- function generateLazyWorkspaceSingletonExports(namedExports, importSource, cacheDescriptor, cacheOwner, treeShakingConsumer, serveLocalFallback = false, mutableExports = []) {
3300
+ function generateLazyWorkspaceSingletonExports(edges, namedExports, importSource, cacheDescriptor, cacheOwner, treeShakingConsumer, serveLocalFallback = false, mutableExports = [], deferredEntryFallback = false) {
3355
3301
  const copiedExports = namedExports.filter((name) => !mutableExports.includes(name));
3356
3302
  const namedExportVars = copiedExports.map((_name, i) => `__mf_${i}`);
3357
3303
  const declarations = namedExports.length > 0 ? ["let __mf_default;", ...namedExportVars.map((name) => `let ${name};`)].join("\n ") : "let __mf_default;";
3358
3304
  const assignments = copiedExports.length > 0 ? [...copiedExports.map((name, i) => `${namedExportVars[i]} = mod[${escapeGeneratedStringLiteral(name)}];`), "__mf_default = mod.default ?? mod;"].join("\n ") : "__mf_default = mod.default ?? mod;";
3359
3305
  const namedExportLine = copiedExports.length > 0 ? `\n export { ${copiedExports.map((name, i) => `${namedExportVars[i]} as ${name}`).join(", ")} };` : "";
3360
- const mutableExportLine = mutableExports.length ? `\n export { ${mutableExports.join(", ")} } from ${escapeGeneratedStringLiteral(importSource)};` : "";
3306
+ const mutableExportLine = mutableExports.length ? `\n ${edges.reExportNames(mutableExports, importSource)}` : "";
3361
3307
  const applyLocalFallback = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
3362
3308
  __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});
3363
3309
  __mfApplyLazyShareExports(exportModule);`;
3364
- return `${declarations}
3365
- const __mfApplyLazyShareExports = (mod) => {
3366
- ${assignments}
3367
- };
3368
- __mfSubscribeSharedCache(__mfModuleCache.share, ${cacheDescriptor}, __mfApplyLazyShareExports);
3369
- let exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
3370
- if (exportModule === undefined) {
3371
- if (import.meta.env.SSR${serveLocalFallback ? " || (import.meta.env.DEV && typeof __mfLocalShare !== 'undefined')" : ""}) {
3372
- ${applyLocalFallback}
3373
- } else {
3374
- __mfTrackPendingShareLoad(initPromise.then(() => {
3375
- exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
3310
+ const readDeferredShare = getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer);
3311
+ const deferredEntryLoad = `Promise.race([
3312
+ initPromise.then(() => ${readDeferredShare}),
3313
+ new Promise((resolve) => {
3314
+ const current = ${readDeferredShare};
3315
+ if (current !== undefined) resolve(current);
3316
+ else __mfSubscribeSharedCache(__mfModuleCache.share, ${cacheDescriptor}, resolve);
3317
+ })
3318
+ ]).then((cached) => {
3319
+ exportModule = cached;
3376
3320
  if (exportModule !== undefined) {
3377
3321
  __mfApplyLazyShareExports(exportModule);
3378
3322
  return;
@@ -3381,8 +3325,32 @@ function generateLazyWorkspaceSingletonExports(namedExports, importSource, cache
3381
3325
  exportModule = __mfNormalizeShareModule(mod);
3382
3326
  __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});
3383
3327
  });
3384
- }));
3385
- }
3328
+ })`;
3329
+ const deferredInitLoad = `initPromise.then(() => {
3330
+ exportModule = ${readDeferredShare};
3331
+ if (exportModule !== undefined) {
3332
+ __mfApplyLazyShareExports(exportModule);
3333
+ return;
3334
+ }
3335
+ return import(${escapeGeneratedStringLiteral(importSource)}).then((mod) => {
3336
+ exportModule = __mfNormalizeShareModule(mod);
3337
+ __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});
3338
+ });
3339
+ })`;
3340
+ const synchronousFallbackConditions = [...deferredEntryFallback ? [] : ["import.meta.env.SSR"], ...serveLocalFallback ? ["(import.meta.env.DEV && typeof __mfLocalShare !== 'undefined')"] : []];
3341
+ const trackPendingLoad = `__mfTrackPendingShareLoad(${deferredEntryFallback ? deferredEntryLoad : deferredInitLoad});`;
3342
+ return `${declarations}
3343
+ const __mfApplyLazyShareExports = (mod) => {
3344
+ ${assignments}
3345
+ };
3346
+ __mfSubscribeSharedCache(__mfModuleCache.share, ${cacheDescriptor}, __mfApplyLazyShareExports);
3347
+ let exportModule = ${readDeferredShare};
3348
+ if (exportModule === undefined) {
3349
+ ${synchronousFallbackConditions.length > 0 ? `if (${synchronousFallbackConditions.join(" || ")}) {
3350
+ ${applyLocalFallback}
3351
+ } else {
3352
+ ${trackPendingLoad}
3353
+ }` : trackPendingLoad}
3386
3354
  } else {
3387
3355
  __mfApplyLazyShareExports(exportModule);
3388
3356
  }
@@ -3418,6 +3386,14 @@ function generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor,
3418
3386
  if (exportModule === undefined) {
3419
3387
  __mfTrackPendingShareLoad(initPromise.then(() => {
3420
3388
  exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
3389
+ // A share init() left to its dynamic import is normally bridged before that import runs;
3390
+ // bridge it here when this wrapper is reached another way.
3391
+ if (exportModule === undefined && typeof __mfPromiseState.loadLazyShares === "function") {
3392
+ return __mfPromiseState.loadLazyShares([${escapeGeneratedStringLiteral(pkg)}]).then(() => {
3393
+ exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
3394
+ });
3395
+ }
3396
+ }).then(() => {
3421
3397
  if (exportModule === undefined) {
3422
3398
  throw new Error("[Module Federation] Shared module ${pkg} was imported before federation bootstrap finished.");
3423
3399
  }
@@ -3426,7 +3402,7 @@ function generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor,
3426
3402
  } else {
3427
3403
  __mfApplyHostProvidedExports(exportModule);
3428
3404
  }
3429
- export { __mf_default as default };${namedExportLine}`;
3405
+ export { __mf_default as default, exportModule as __moduleExports };${namedExportLine}`;
3430
3406
  }
3431
3407
  function selectImportFalseNamedExports(detectedNamedExports, usage) {
3432
3408
  if (!detectedNamedExports || usage?.kind !== "exports") return detectedNamedExports ?? [];
@@ -3465,9 +3441,49 @@ const initializedLocalShareModuleCode = `const __mfInitializedLocalShare = (mod)
3465
3441
  throw error;
3466
3442
  }
3467
3443
  };`;
3444
+ function createLocalPayloadEdges() {
3445
+ let edges = 0;
3446
+ return {
3447
+ importNamespace(source) {
3448
+ edges++;
3449
+ return `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(source)};`;
3450
+ },
3451
+ reExportAll(source) {
3452
+ edges++;
3453
+ return `export * from ${escapeGeneratedStringLiteral(source)}`;
3454
+ },
3455
+ reExportNames(names, source) {
3456
+ if (names.length === 0) return "";
3457
+ edges++;
3458
+ return `export { ${names.join(", ")} } from ${escapeGeneratedStringLiteral(source)};`;
3459
+ },
3460
+ get none() {
3461
+ return edges === 0;
3462
+ }
3463
+ };
3464
+ }
3465
+ function recordCoalescability(pkg, hasNoLocalPayloadEdge, command, shareConfig, coalescableLoadShares) {
3466
+ const coalescable = command === "build" && shareConfig.eager !== true && shareConfig.import !== false && hasNoLocalPayloadEdge;
3467
+ if (coalescable) coalescableLoadShares.add(pkg);
3468
+ else coalescableLoadShares.delete(pkg);
3469
+ return coalescable;
3470
+ }
3471
+ /**
3472
+ * `prependWorkspaceSingletonSsrImport` adds a local-payload edge in the server
3473
+ * build's load hook, after this module has generated the wrapper. `id` names
3474
+ * the owning instance when the hook belongs to a different one.
3475
+ */
3476
+ function markLoadShareWrapperNotCoalescable(pkg, options, id) {
3477
+ getSharedVirtualModuleStateForId(id, options).coalescableLoadShares.delete(pkg);
3478
+ }
3479
+ /** With `id`, answers from the owning instance's state, whichever instance asks. */
3480
+ function isCoalescableLoadShareWrapper(pkg, options, id) {
3481
+ return getSharedVirtualModuleStateForId(id, options).coalescableLoadShares.has(pkg);
3482
+ }
3468
3483
  function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exportConditions, importFalseExportUsage) {
3469
3484
  const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
3470
- const { loadShareCacheMap } = getSharedVirtualModuleState(options);
3485
+ const { loadShareCacheMap, coalescableLoadShares } = getSharedVirtualModuleState(options);
3486
+ const edges = createLocalPayloadEdges();
3471
3487
  if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = createScopedSharedVirtualModule(pkg, LOAD_SHARE_TAG, options);
3472
3488
  let importLine = getRuntimeModuleCacheBootstrapCode(exportConditions);
3473
3489
  const cacheDescriptor = getSharedCacheDescriptorLiteral(pkg, shareItem);
@@ -3487,6 +3503,7 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3487
3503
  }
3488
3504
  exportLine = generateDeferredHostProvidedExports([], pkg, cacheDescriptor, treeShakingConsumer);
3489
3505
  }
3506
+ recordCoalescability(pkg, edges.none, command, shareItem.shareConfig, coalescableLoadShares);
3490
3507
  loadShareCacheMap[pkg].writeSync(`
3491
3508
  ${getRuntimeInitPromiseBootstrapCode(false, runtimeInitOwnerImportId)}
3492
3509
  ${importLine}
@@ -3508,13 +3525,14 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3508
3525
  const mutableExports = new Set(isLocalOnlyContainer(resolvedOptions) ? getSharedMutableExports(pkg, shareItem, exportConditions) : []);
3509
3526
  const copiedNamedExports = namedExports.filter((name) => !mutableExports.has(name));
3510
3527
  const liveNamedExports = namedExports.filter((name) => mutableExports.has(name));
3511
- const liveNamedExportLine = liveNamedExports.length ? `export { ${liveNamedExports.join(", ")} } from ${escapeGeneratedStringLiteral(sharedImportSource)};` : "";
3528
+ const liveNamedExportLine = edges.reExportNames(liveNamedExports, sharedImportSource);
3512
3529
  const hasCompleteExportCoverage = detectedNamedExports !== void 0;
3513
3530
  const isWorkspaceSingleton = isWorkspacePackage && shareItem.shareConfig.singleton === true;
3514
3531
  const usesDeferredSingletonFallback = hasCompleteExportCoverage && shareItem.shareConfig.eager !== true && (isWorkspacePackage || command !== "build" && isRemoteOnlyContainer(resolvedOptions) && shareItem.shareConfig.singleton === true || command === "build" && isRemoteContainer(resolvedOptions) && !isSharedSingletonConsumedByPeer(pkg, resolvedOptions, true));
3515
3532
  const servesRemoteSingletonFallback = command !== "build" && isRemoteOnlyContainer(resolvedOptions) && shareItem.shareConfig.singleton === true;
3516
3533
  const isConsumedByPeerSingleton = isSharedSingletonConsumedByPeer(pkg, resolvedOptions);
3517
3534
  const usesEntryInjectedRemoteFallback = hasCompleteExportCoverage && !isWorkspaceSingleton && isRemoteContainer(resolvedOptions) && shareItem.shareConfig.singleton === true && resolvedOptions.hostInitInjectLocation === "entry" && (command === "build" || isConsumedByPeerSingleton);
3535
+ const usesDeferredEntryInjectedSingletonFallback = usesEntryInjectedRemoteFallback && !isReactCoreShare(pkg) && (pkg === "react-dom/client" || shareItem.shareConfig.eager !== true && !isSharedSingletonConsumedByPeer(pkg, resolvedOptions, true));
3518
3536
  const usesEagerWorkspaceFallback = hasCompleteExportCoverage && isWorkspaceSingleton && !servesRemoteSingletonFallback && (isConsumedByPeerSingleton || shareItem.shareConfig.eager === true);
3519
3537
  const usesDeferredTreeShakingFallback = hasCompleteExportCoverage && Boolean(treeShakingConsumer);
3520
3538
  const reactMixedModeGuard = pkg === "react" ? createReactMixedModeRuntimeGuard() : "";
@@ -3522,11 +3540,14 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3522
3540
  let initBlock = "";
3523
3541
  if (usesDeferredTreeShakingFallback) {
3524
3542
  importLine = `${getRuntimeInitPromiseBootstrapCode(false, runtimeInitOwnerImportId)}\n ${importLine}`;
3525
- exportLine = generateLazyWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor, cacheOwner, treeShakingConsumer, command !== "build" && !servesRemoteSingletonFallback && (isWorkspaceSingleton || isWorkspacePackage), liveNamedExports);
3526
- } else if (usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback) exportLine = generateEagerWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor, cacheOwner, treeShakingConsumer, liveNamedExports);
3543
+ exportLine = generateLazyWorkspaceSingletonExports(edges, namedExports, lazyLocalFallbackSource, cacheDescriptor, cacheOwner, treeShakingConsumer, command !== "build" && !servesRemoteSingletonFallback && (isWorkspaceSingleton || isWorkspacePackage), liveNamedExports);
3544
+ } else if (usesDeferredEntryInjectedSingletonFallback) {
3545
+ importLine = `${getRuntimeInitPromiseBootstrapCode(false, runtimeInitOwnerImportId)}\n ${importLine}`;
3546
+ exportLine = generateLazyWorkspaceSingletonExports(edges, namedExports, lazyLocalFallbackSource, cacheDescriptor, cacheOwner, treeShakingConsumer, false, liveNamedExports, true);
3547
+ } else if (usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback) exportLine = generateEagerWorkspaceSingletonExports(edges, namedExports, lazyLocalFallbackSource, cacheDescriptor, cacheOwner, treeShakingConsumer, liveNamedExports);
3527
3548
  else if (usesDeferredSingletonFallback) {
3528
3549
  importLine = `${getRuntimeInitPromiseBootstrapCode(false, runtimeInitOwnerImportId)}\n ${importLine}`;
3529
- exportLine = generateLazyWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor, cacheOwner, treeShakingConsumer, command !== "build" && !servesRemoteSingletonFallback && (isWorkspaceSingleton || isWorkspacePackage), liveNamedExports);
3550
+ exportLine = generateLazyWorkspaceSingletonExports(edges, namedExports, lazyLocalFallbackSource, cacheDescriptor, cacheOwner, treeShakingConsumer, command !== "build" && !servesRemoteSingletonFallback && (isWorkspaceSingleton || isWorkspacePackage), liveNamedExports);
3530
3551
  } else if (detectedNamedExports === void 0) {
3531
3552
  exportLine = `const __mfDefaultExport = (() => {
3532
3553
  ${generateShareModuleUnwrapCode({
@@ -3536,7 +3557,7 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3536
3557
  })}
3537
3558
  })();
3538
3559
  export default __mfDefaultExport;
3539
- export * from ${escapeGeneratedStringLiteral(coherentLocalSource)}`;
3560
+ ${edges.reExportAll(coherentLocalSource)}`;
3540
3561
  initBlock = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
3541
3562
  __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});`;
3542
3563
  } else if (namedExports.length > 0 && shareItem.shareConfig.singleton === true) {
@@ -3587,21 +3608,23 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3587
3608
  __mfSubscribeSharedCache(__mfModuleCache.share, ${cacheDescriptor}, __mfApplySharedDefaultExport);
3588
3609
  __mfApplySharedDefaultExport(exportModule);
3589
3610
  export { __mfDefaultExport as default };
3590
- export * from ${escapeGeneratedStringLiteral(sharedImportSource)}`;
3611
+ ${edges.reExportAll(sharedImportSource)}`;
3591
3612
  initBlock = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
3592
3613
  __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});`;
3593
3614
  } else {
3594
- exportLine = `export default exportModule.default ?? exportModule\n export * from ${escapeGeneratedStringLiteral(sharedImportSource)}`;
3615
+ exportLine = `export default exportModule.default ?? exportModule\n ${edges.reExportAll(sharedImportSource)}`;
3595
3616
  initBlock = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
3596
3617
  __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});`;
3597
3618
  }
3598
- const prebuildImportLine = usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback ? "" : usesDeferredSingletonFallback || usesDeferredTreeShakingFallback ? !servesRemoteSingletonFallback && usesDeferredSingletonFallback && command !== "build" && (isWorkspaceSingleton || isWorkspacePackage) ? `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(lazyLocalFallbackSource)};` : "" : `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(detectedNamedExports === void 0 ? coherentLocalSource : skipServePrebuildWarmup ? devImportSource : sharedImportSource)};`;
3599
- const devDynamicImportLine = isWorkspacePackage ? "" : usesDeferredSingletonFallback || usesDeferredTreeShakingFallback ? "" : command !== "build" && !skipServePrebuildWarmup ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
3600
- const moduleBody = usesDeferredSingletonFallback || usesDeferredTreeShakingFallback || usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback ? `
3601
- ${prebuildImportLine}
3619
+ const staticLocalShareSource = detectedNamedExports === void 0 ? coherentLocalSource : skipServePrebuildWarmup ? devImportSource : sharedImportSource;
3620
+ const prebuildImportLine = usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback ? "" : usesDeferredSingletonFallback || usesDeferredTreeShakingFallback ? !servesRemoteSingletonFallback && usesDeferredSingletonFallback && command !== "build" && (isWorkspaceSingleton || isWorkspacePackage) ? edges.importNamespace(lazyLocalFallbackSource) : "" : edges.importNamespace(staticLocalShareSource);
3621
+ const devDynamicImportLine = isWorkspacePackage ? "" : usesDeferredSingletonFallback || usesDeferredTreeShakingFallback || usesDeferredEntryInjectedSingletonFallback ? "" : command !== "build" && !skipServePrebuildWarmup ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
3622
+ const cacheHelpers = recordCoalescability(pkg, edges.none, command, shareItem.shareConfig, coalescableLoadShares) ? getSharedCacheHelpersImportCode(resolvedOptions) : sharedCacheHelperCode;
3623
+ const moduleBody = usesDeferredSingletonFallback || usesDeferredTreeShakingFallback || usesDeferredEntryInjectedSingletonFallback || usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback ? `
3624
+ ${usesDeferredEntryInjectedSingletonFallback ? "" : prebuildImportLine}
3602
3625
  ${devDynamicImportLine}
3603
3626
  ${importLine}
3604
- ${sharedCacheHelperCode}
3627
+ ${cacheHelpers}
3605
3628
  ${normalizeLocalShareModuleCode}
3606
3629
  ${initializedLocalShareModuleCode}
3607
3630
  ${exportLine}
@@ -3609,7 +3632,7 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3609
3632
  ${prebuildImportLine}
3610
3633
  ${devDynamicImportLine}
3611
3634
  ${importLine}
3612
- ${sharedCacheHelperCode}
3635
+ ${cacheHelpers}
3613
3636
  ${normalizeLocalShareModuleCode}
3614
3637
  let exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)}
3615
3638
  if (exportModule === undefined) {
@@ -3653,6 +3676,7 @@ function addConfiguredShare(pkg, options) {
3653
3676
  if (options) getScopedUsedShares(options).add(pkg);
3654
3677
  }
3655
3678
  const LOCAL_SHARED_IMPORT_MAP_ID = "virtual:mf-localSharedImportMap";
3679
+ const LAZY_CONSUME_ONLY_SHARES_PLACEHOLDER = "__MF_LAZY_CONSUME_ONLY_SHARES__";
3656
3680
  const localOwnerIds = /* @__PURE__ */ new WeakMap();
3657
3681
  let nextLocalOwnerId = 1;
3658
3682
  function getLocalOwnerKey(options) {
@@ -3690,6 +3714,10 @@ function getLocalSharedPackagePath(pkg, shareItem, options) {
3690
3714
  if (shouldUseDirectReactImport() && pkg === "react") return "react";
3691
3715
  return getConcreteSharedImportSource(pkg, shareItem) || getLocalProviderImportPath(pkg) || getSharedImportSource(pkg, shareItem, options);
3692
3716
  }
3717
+ function getCanonicalSharedKey(pkg, shareItem) {
3718
+ const { request, shareKey } = shareItem.shareConfig;
3719
+ return request !== void 0 || shareKey !== void 0 ? getSharedRuntimeKey(pkg, shareItem) : pkg;
3720
+ }
3693
3721
  function getDirectSharedCacheSeedImportPath(pkg, shareItem) {
3694
3722
  return getConcreteSharedImportSource(pkg, shareItem) || getProjectResolvedImportPath(pkg) || getLocalProviderImportPath(pkg) || pkg;
3695
3723
  }
@@ -3703,7 +3731,7 @@ function generateLocalSharedImportMap(options) {
3703
3731
  import {loadShare} from "@module-federation/runtime";
3704
3732
  ${orderedShares.map((pkg, index) => {
3705
3733
  const shareItem = getNormalizeShareItem(pkg, resolvedOptions);
3706
- if (!shareItem?.shareConfig.eager || shareItem.shareConfig.import === false) return "";
3734
+ if (!shareItem || !shareItem.shareConfig.eager || shareItem.shareConfig.import === false) return "";
3707
3735
  return `import * as __mfEagerShare_${index} from ${toSafeJsLiteral(getLocalSharedPackagePath(pkg, shareItem, options))};`;
3708
3736
  }).filter(Boolean).join("\n")}
3709
3737
  ${normalizeRuntimeShareCode}
@@ -3728,12 +3756,17 @@ function generateLocalSharedImportMap(options) {
3728
3756
  const __mfHostOnly = (name) => async () => {
3729
3757
  throw new Error(\`[Module Federation] Shared module '\${name}' must be provided by host\`);
3730
3758
  };
3759
+ // Replaced by the lazy consume-only share plugin with the keys that only a dynamic
3760
+ // import() reaches, so init() leaves them to that import; an unreplaced string matches no key.
3761
+ const __mfLazyShares = ${JSON.stringify(LAZY_CONSUME_ONLY_SHARES_PLACEHOLDER)};
3762
+ const __mfIsLazyShare = (name) => Array.isArray(__mfLazyShares) && __mfLazyShares.includes(name);
3731
3763
  const __mfConsumeOnly = (name, version, scope, materialize, shareConfig) => ({
3732
3764
  name,
3733
3765
  version,
3734
3766
  scope: [scope],
3735
3767
  loaded: false,
3736
- materialize,
3768
+ materialize: materialize && !__mfIsLazyShare(name),
3769
+ lazy: __mfIsLazyShare(name),
3737
3770
  eager: shareConfig.eager,
3738
3771
  from: ${toSafeJsLiteral(resolvedOptions.name)},
3739
3772
  canLiveRebind: true,
@@ -3743,7 +3776,8 @@ function generateLocalSharedImportMap(options) {
3743
3776
  const importMap = {
3744
3777
  ${orderedShares.map((pkg, index) => {
3745
3778
  const shareItem = getNormalizeShareItem(pkg, resolvedOptions);
3746
- if (shareItem?.shareConfig.import === false) return `
3779
+ if (!shareItem) return "";
3780
+ if (shareItem.shareConfig.import === false) return `
3747
3781
  ${toSafeJsLiteral(pkg)}: __mfHostOnly(${toSafeJsLiteral(pkg)})`;
3748
3782
  return `
3749
3783
  ${toSafeJsLiteral(pkg)}: async () => {
@@ -3759,7 +3793,7 @@ function generateLocalSharedImportMap(options) {
3759
3793
  const shareItem = getNormalizeShareItem(key, resolvedOptions);
3760
3794
  if (!shareItem) return null;
3761
3795
  const isReactFamily = key.startsWith("react/") || key === "react-dom/client";
3762
- const cacheKeys = [key, ...key === "react-dom/client" ? ["react-dom"] : []].flatMap((pkg) => {
3796
+ const cacheKeys = [key, ...key === "react-dom/client" ? [getPackageName(REACT_DOM_CLIENT_SHARE)] : []].flatMap((pkg) => {
3763
3797
  const descriptor = getSharedCacheDescriptor(pkg, shareItem);
3764
3798
  return [descriptor.canonical, ...descriptor.aliases ?? []];
3765
3799
  });
@@ -3771,7 +3805,7 @@ function generateLocalSharedImportMap(options) {
3771
3805
  const canLiveRebind = shareItem.shareConfig.import === false || detectedNamedExports !== void 0;
3772
3806
  const treeShakingConfig = canLiveRebind ? shareItem.shareConfig.treeShaking : void 0;
3773
3807
  if (shareItem.shareConfig.import === false && !treeShakingConfig) return `
3774
- ${toSafeJsLiteral(key)}: __mfConsumeOnly(${toSafeJsLiteral(key)}, ${toSafeJsLiteral(shareItem.version)}, ${toSafeJsLiteral(shareItem.scope)}, ${sharesToMaterialize.has(key)}, {singleton: ${shareItem.shareConfig.singleton}, requiredVersion: ${toSafeJsLiteral(shareItem.shareConfig.requiredVersion)}, strictVersion: ${shareItem.shareConfig.strictVersion}, eager: ${Boolean(shareItem.shareConfig.eager)}})`;
3808
+ ${toSafeJsLiteral(key)}: __mfConsumeOnly(${toSafeJsLiteral(key)}, ${toSafeJsLiteral(shareItem.version)}, ${toSafeJsLiteral(shareItem.scope)}, ${sharesToMaterialize.has(key)}, {singleton: ${shareItem.shareConfig.singleton}, requiredVersion: ${toSafeJsLiteral(shareItem.shareConfig.requiredVersion)}, strictVersion: ${shareItem.shareConfig.strictVersion}, eager: ${Boolean(shareItem.shareConfig.eager)}, ${shareItem.shareConfig.request !== void 0 ? `request: ${toSafeJsLiteral(shareItem.shareConfig.request)},` : ""} ${shareItem.shareConfig.shareKey !== void 0 ? `shareKey: ${toSafeJsLiteral(shareItem.shareConfig.shareKey)},` : ""}})`;
3775
3809
  const treeShakingUsage = treeShakingConfig ? getTreeShakingExportUsage(key, shareItem, shareItem.name, options) : void 0;
3776
3810
  const treeShakingProviderExports = treeShakingUsage?.kind === "exports" ? treeShakingUsage.usedExports : [];
3777
3811
  const treeShakingUsedExports = resolvedOptions.injectTreeShakingUsedExports === false ? treeShakingConfig?.usedExports || [] : treeShakingProviderExports;
@@ -3842,6 +3876,8 @@ function generateLocalSharedImportMap(options) {
3842
3876
  requiredVersion: ${toSafeJsLiteral(shareItem.shareConfig.requiredVersion)},
3843
3877
  strictVersion: ${shareItem.shareConfig.strictVersion},
3844
3878
  eager: ${Boolean(shareItem.shareConfig.eager)},
3879
+ ${shareItem.shareConfig.request !== void 0 ? `request: ${toSafeJsLiteral(shareItem.shareConfig.request)},` : ""}
3880
+ ${shareItem.shareConfig.shareKey !== void 0 ? `shareKey: ${toSafeJsLiteral(shareItem.shareConfig.shareKey)},` : ""}
3845
3881
  ${shareItem.shareConfig.import === false ? "import: false," : ""}
3846
3882
  },
3847
3883
  ${treeShakingConfig ? `treeShaking: {
@@ -3894,11 +3930,17 @@ function expandSharedPrefixKey(prefixKey, used) {
3894
3930
  function getOrderedUsedShares(options) {
3895
3931
  const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
3896
3932
  const used = getUsedShares(options);
3897
- const shares = new Set(used);
3933
+ const shares = /* @__PURE__ */ new Set();
3934
+ const addShare = (pkg) => {
3935
+ const shareItem = getNormalizeShareItem(pkg, resolvedOptions);
3936
+ shares.add(shareItem ? getCanonicalSharedKey(pkg, shareItem) : pkg);
3937
+ };
3938
+ used.forEach(addShare);
3898
3939
  Object.keys(resolvedOptions.shared ?? {}).forEach((pkg) => {
3899
- if (!pkg.endsWith("/")) shares.add(pkg);
3940
+ const share = resolvedOptions.shared?.[pkg];
3941
+ if (share && !getSharedRequest(pkg, share).endsWith("/")) addShare(pkg);
3900
3942
  });
3901
- for (const [pkg, share] of Object.entries(resolvedOptions.shared ?? {})) if (pkg.endsWith("/") && share.shareConfig?.eager) for (const concrete of expandSharedPrefixKey(pkg, used)) shares.add(concrete);
3943
+ for (const [pkg, share] of Object.entries(resolvedOptions.shared ?? {})) if (share.shareConfig?.eager && getSharedRequest(pkg, share).endsWith("/")) for (const concrete of expandSharedPrefixKey(getSharedRequest(pkg, share), used)) addShare(concrete);
3902
3944
  return orderSharedDependenciesFirst(Array.from(shares).sort((a, b) => {
3903
3945
  const priority = (pkg) => pkg === "react" ? 0 : pkg === "react-dom" ? 1 : pkg.startsWith("react/") ? 2 : 3;
3904
3946
  return priority(a) - priority(b) || a.localeCompare(b);
@@ -3911,7 +3953,8 @@ function getMaterializedShares(options) {
3911
3953
  const usedForEager = options ? usedSharesByOptions.get(options) ?? [] : usedShares;
3912
3954
  for (const [pkg, share] of Object.entries(resolvedOptions.shared ?? {})) {
3913
3955
  if (!share.shareConfig?.eager) continue;
3914
- if (pkg.endsWith("/")) for (const concrete of expandSharedPrefixKey(pkg, usedForEager)) shares.add(concrete);
3956
+ const request = getSharedRequest(pkg, share);
3957
+ if (request.endsWith("/")) for (const concrete of expandSharedPrefixKey(request, usedForEager)) shares.add(concrete);
3915
3958
  else shares.add(pkg);
3916
3959
  }
3917
3960
  const configured = /* @__PURE__ */ new Map();
@@ -3939,10 +3982,14 @@ function getMaterializedShares(options) {
3939
3982
  }
3940
3983
  }
3941
3984
  }
3942
- return orderSharedDependenciesFirst([...shares].sort((a, b) => {
3985
+ const sorted = [...shares].sort((a, b) => {
3943
3986
  const priority = (pkg) => pkg === "react" ? 0 : pkg === "react-dom" ? 1 : pkg.startsWith("react/") ? 2 : 3;
3944
3987
  return priority(a) - priority(b) || a.localeCompare(b);
3945
- }));
3988
+ });
3989
+ return orderSharedDependenciesFirst([...new Set(sorted.map((pkg) => {
3990
+ const shareItem = getNormalizeShareItem(pkg, resolvedOptions);
3991
+ return shareItem ? getCanonicalSharedKey(pkg, shareItem) : pkg;
3992
+ }))]);
3946
3993
  }
3947
3994
  /** Shared keys a share's package.json depends on (roots stand in for their subpaths, subpaths for their root), keyed by share. */
3948
3995
  function getSharePrerequisites(ordered) {
@@ -4030,9 +4077,30 @@ function orderSharedDependenciesFirst(sharedPackages) {
4030
4077
  }
4031
4078
  function getShareItemForPreload(pkg, options = getNormalizeModuleFederationOptions()) {
4032
4079
  const shared = options.shared;
4033
- const wildcardKey = `${getPackageName(pkg)}/`;
4080
+ const packageName = getPackageName(pkg);
4081
+ const wildcardKey = `${packageName}/`;
4034
4082
  if (isExplicitSharedKey(pkg, options)) return shared[pkg];
4035
4083
  if (isExplicitSharedKey(wildcardKey, options)) return shared[wildcardKey];
4084
+ if (pkg !== packageName && isExplicitSharedKey(packageName, options) && shared[packageName]?.shareConfig.import !== false && getCommonSharedSubpaths(packageName).includes(pkg)) return shared[packageName];
4085
+ const shareItem = getNormalizeShareItem(pkg, options);
4086
+ if (!shareItem) return void 0;
4087
+ if (shareItem.shareConfig.request === void 0 && shareItem.shareConfig.shareKey === void 0) return;
4088
+ const runtimeKey = getSharedRuntimeKey(pkg, shareItem);
4089
+ if (runtimeKey === pkg || runtimeKey.endsWith("/") && (pkg === runtimeKey.slice(0, -1) || pkg.startsWith(runtimeKey))) return shareItem;
4090
+ }
4091
+ /**
4092
+ * Entry-injected renderer wrappers (see `REACT_DOM_CLIENT_SHARE`) assign
4093
+ * `createRoot` only after `initPromise` and a dynamic import, so a standalone
4094
+ * remote must evaluate that wrapper before the app entry. The subpath is often
4095
+ * absent from `getMaterializedShares()` when pending shares is emitted:
4096
+ * `react-dom/` collapses to `react-dom`, and the entry import may not be
4097
+ * recorded yet.
4098
+ */
4099
+ function shouldPreloadEntryDeferredReactDomClient(options) {
4100
+ if (options.hostInitInjectLocation !== "entry" || !isRemoteContainer(options)) return false;
4101
+ const shareItem = getShareItemForPreload(REACT_DOM_CLIENT_SHARE, options);
4102
+ if (!shareItem || shareItem.shareConfig.singleton !== true) return false;
4103
+ return shareItem.shareConfig.import !== false && !shareItem.shareConfig.treeShaking;
4036
4104
  }
4037
4105
  function generateSharedCacheSeedItem(pkg, shareItem, importPath, options = getNormalizeModuleFederationOptions()) {
4038
4106
  const cacheDescriptor = getSharedCacheDescriptor(pkg, shareItem);
@@ -4054,6 +4122,9 @@ const normalizeRuntimeShareCode = `const __mfNormalizeRuntimeShare = (mod) => {
4054
4122
  for (let i = 0; i < 5; i++) {
4055
4123
  const defaultExport = current?.default;
4056
4124
  if (!defaultExport || typeof defaultExport !== "object" || Object.keys(defaultExport).length === 0) break;
4125
+ // Only unwrap plain CJS namespaces; spreading a class instance would drop its prototype.
4126
+ const proto = Object.getPrototypeOf(defaultExport);
4127
+ if (proto !== null && proto !== Object.prototype) break;
4057
4128
  const namedValues = Object.keys(current).filter((key) => key !== "default").map((key) => current[key]);
4058
4129
  if (namedValues.length > 0 && namedValues.some((value) => value !== undefined)) break;
4059
4130
  current = defaultExport;
@@ -4217,7 +4288,28 @@ const externalSharedProviderSelectionHelperCode = `const __mfSelectExternalShare
4217
4288
  ) return undefined;
4218
4289
  return { provider, scopeRootProvider };
4219
4290
  };`;
4220
- function generateRuntimeSharedCacheSeedCode(shareStrategy, options) {
4291
+ /**
4292
+ * A consume-only stub never outranks a provider: when registering this container's
4293
+ * `import: false` share replaces an unloaded provider of the same version (#1311),
4294
+ * the `afterRegisterShare` hook restores the provider. Registered once per instance.
4295
+ */
4296
+ function generateKeepProvidersOverStubsCode(runtimeVar) {
4297
+ return `if (!${runtimeVar}.__mfKeepAdoptedProviders) {
4298
+ ${runtimeVar}.__mfKeepAdoptedProviders = true;
4299
+ ${runtimeVar}.sharedHandler?.hooks?.lifecycle?.afterRegisterShare?.on?.((args) => {
4300
+ const { shared, previousShared, registeredShared } = args || {};
4301
+ if (
4302
+ shared?.shareConfig?.import !== false ||
4303
+ registeredShared !== shared ||
4304
+ !previousShared ||
4305
+ previousShared.shareConfig?.import === false
4306
+ ) return;
4307
+ const versions = ${runtimeVar}.shareScopeMap?.[args.scope]?.[args.pkgName];
4308
+ if (versions && versions[shared.version] === shared) versions[shared.version] = previousShared;
4309
+ });
4310
+ }`;
4311
+ }
4312
+ function generateRuntimeSharedCacheSeedCode(shareStrategy, options, command = "build") {
4221
4313
  const seedBatches = getShareBatches(options, false);
4222
4314
  const seedOrder = seedBatches.flat();
4223
4315
  const seedIndex = new Map(seedOrder.map((pkg, index) => [pkg, index]));
@@ -4231,7 +4323,7 @@ function generateRuntimeSharedCacheSeedCode(shareStrategy, options) {
4231
4323
  // import and set materialize. An import:false share has no local fallback
4232
4324
  // though, so on a cold request (materialize not set yet) it must still be
4233
4325
  // attempted here, or it is never seeded and its consumer reads it undefined.
4234
- const __mfSeedKeys = __mfSeedOrder.filter((pkg) => usedShared[pkg] && (usedShared[pkg].materialize !== false || usedShared[pkg].shareConfig?.import === false));
4326
+ const __mfSeedKeys = __mfSeedOrder.filter((pkg) => usedShared[pkg] && (usedShared[pkg].materialize !== false || (usedShared[pkg].shareConfig?.import === false && !usedShared[pkg].lazy)));
4235
4327
  __mfModuleCache.providerInit ||= new Map();
4236
4328
  const __mfInitializeProviderOnce = (key, initialize) => {
4237
4329
  const existing = __mfModuleCache.providerInit.get(key);
@@ -4264,6 +4356,16 @@ function generateRuntimeSharedCacheSeedCode(shareStrategy, options) {
4264
4356
  );
4265
4357
  return;
4266
4358
  }
4359
+ ${command === "serve" ? `// A pending webpack provider for this share, or for its package when this
4360
+ // is a subpath, is only bridged after init(). Seeding the local fallback now
4361
+ // would evaluate the package's dev proxy, which snapshots its exports, before
4362
+ // the bridge runs and pin a second copy. The proxy seeds itself on first import.
4363
+ if (
4364
+ typeof __mfGetPendingExternalSharedProvider === 'function' &&
4365
+ __mfGetPendingExternalSharedProvider(pkg, share)
4366
+ ) {
4367
+ return;
4368
+ }` : ""}
4267
4369
  const externalProvider = typeof __mfGetExternalSharedProvider === 'function'
4268
4370
  ? __mfGetExternalSharedProvider(pkg, share)
4269
4371
  : undefined;
@@ -4283,8 +4385,9 @@ function generateRuntimeSharedCacheSeedCode(shareStrategy, options) {
4283
4385
  __mfNormalizeRuntimeShare(externalResolved),
4284
4386
  externalProvider.from
4285
4387
  );
4388
+ return;
4286
4389
  }
4287
- return;
4390
+ if (typeof isWebpackProvider === 'function' && isWebpackProvider(externalProvider)) return;
4288
4391
  }
4289
4392
  const providerKey = cacheDescriptor.canonical;
4290
4393
  const resolved = await __mfInitializeProviderOnce(providerKey, async () => {
@@ -4292,6 +4395,12 @@ function generateRuntimeSharedCacheSeedCode(shareStrategy, options) {
4292
4395
  const mod = typeof factory === "function" ? factory() : factory;
4293
4396
  return Promise.resolve(mod);
4294
4397
  });
4398
+ // The seeded local copy is what this container's consumers are bound to.
4399
+ // Flag the Runtime's provider as eager so a same-version sibling cannot
4400
+ // take over the share scope slot via the Runtime's name tie-break.
4401
+ for (const provider of initRes.options.shared?.[pkg] || []) {
4402
+ if (provider.get === share.get) provider.eager = true;
4403
+ }
4295
4404
  ${normalizeRuntimeShareCode}
4296
4405
  const normalizedModule = __mfNormalizeRuntimeShare(resolved);
4297
4406
  const exportModule = normalizedModule === resolved ? {...resolved} : normalizedModule;
@@ -4564,7 +4673,7 @@ function generateTreeShakingSnapshotPluginCode(enabled) {
4564
4673
  },
4565
4674
  });`;
4566
4675
  }
4567
- function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(options), command = "build", exportConditions) {
4676
+ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(options), command = "build", exportConditions, isSsrBuild = false) {
4568
4677
  const needsSharedProviderSelectionHelper = hasShared(options);
4569
4678
  const hasTreeShakingShared = Object.values(options.shared ?? {}).some((share) => !!share?.shareConfig.treeShaking);
4570
4679
  const hasMultipleShareScopes = Array.isArray(options.shareScope);
@@ -4576,7 +4685,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
4576
4685
  ...hasTreeShakingShared ? ["getRemoteEntry"] : []
4577
4686
  ].join(", ");
4578
4687
  const runtimeHelperImports = [...hasTreeShakingShared ? ["global as runtimeGlobal"] : [], ...needsSharedProviderSelectionHelper ? ["share as runtimeShare"] : []];
4579
- const pluginImportNames = options.runtimePlugins.map((p, i) => {
4688
+ const pluginImportNames = filterRuntimePluginsForTarget(options.runtimePlugins, SSR_ONLY_RUNTIME_PLUGINS, isSsrBuild).map((p, i) => {
4580
4689
  if (typeof p === "string") return [
4581
4690
  `$runtimePlugin_${i}`,
4582
4691
  `import $runtimePlugin_${i} from "${p}";`,
@@ -4899,13 +5008,36 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
4899
5008
  };
4900
5009
  }
4901
5010
  const runtimeResolveShareHook = initRes.sharedHandler.hooks.lifecycle.resolveShare;
5011
+ // Registering this container's shares lets its consume-only stub displace the parent's
5012
+ // unloaded same-version provider whenever this container's name sorts after the parent's
5013
+ // (the Runtime keeps the higher name). Nothing can be loaded from a stub, so put the
5014
+ // provider back; a share bridged later, e.g. from a lazy import(), still finds it.
5015
+ ${generateKeepProvidersOverStubsCode("initRes")}
4902
5016
  const __mfRuntimeProviderOrigins = new WeakMap();
4903
5017
  runtimeResolveShareHook.on((args) => {
4904
5018
  const loadId = args.shareInfo?.[__mfRuntimeShareLoadIdKey];
4905
5019
  const resolver = args.resolver;
4906
5020
  if (typeof resolver !== "function") return args;
4907
5021
  const instrumentedResolver = (...resolverArgs) => {
4908
- const resolved = resolver(...resolverArgs);
5022
+ let resolved = resolver(...resolverArgs);
5023
+ // A consume-only stub can never be loaded. The Runtime still settles on one when
5024
+ // it carries the highest version, e.g. a parent that registers its provider under
5025
+ // "0.0.0"; hand back the provider this container selects for itself instead.
5026
+ if (
5027
+ resolved?.shared?.shareConfig?.import === false &&
5028
+ typeof __mfSelectSharedProvider === "function" &&
5029
+ usedShared[args.pkgName]
5030
+ ) {
5031
+ const provider = __mfSelectSharedProvider(
5032
+ args.shareScopeMap?.[args.scope]?.[args.pkgName],
5033
+ args.pkgName,
5034
+ usedShared[args.pkgName],
5035
+ '${options.shareStrategy}'
5036
+ );
5037
+ if (provider && provider.shareConfig?.import !== false) {
5038
+ resolved = { shared: provider, useTreesShaking: resolved.useTreesShaking };
5039
+ }
5040
+ }
4909
5041
  const selectedProvider = resolved?.shared;
4910
5042
  if (
4911
5043
  selectedProvider &&
@@ -5318,7 +5450,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
5318
5450
  );
5319
5451
  }
5320
5452
  }
5321
- ${generateRuntimeSharedCacheSeedCode(options.shareStrategy, options)}
5453
+ ${generateRuntimeSharedCacheSeedCode(options.shareStrategy, options, command)}
5322
5454
  ${initializeSharingCode}
5323
5455
  __mfRestoreForeignSharedProviders();
5324
5456
  // Calling provider.get() marks a provider as loaded. Wait until the Runtime has
@@ -5336,9 +5468,13 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
5336
5468
  );
5337
5469
  }));
5338
5470
  };
5339
- await __mfBridgeSharedProviders();
5340
5471
  if (__mfUsesWebpackShareScope) {
5472
+ // A webpack host's loadShare() awaits initializeSharing(), which awaits this
5473
+ // init(). Bridging here would call the host's provider.get() and re-enter
5474
+ // loadShare(), so both promises wait on each other forever (#1326).
5341
5475
  __mfLateBridgeShared = __mfBridgeSharedProviders;
5476
+ } else {
5477
+ await __mfBridgeSharedProviders();
5342
5478
  }
5343
5479
  try {
5344
5480
  const allInstances = globalThis.__FEDERATION__?.__SHARE__;
@@ -5492,6 +5628,29 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
5492
5628
  (pkg) => !__mfBlockedSeedKeys.has(__mfSeedIndex.get(pkg))
5493
5629
  ));
5494
5630
  await __mfSeedLocalShared(__mfReadyDeferredSeedKeys);
5631
+ ${command === "build" ? `// A consume-only share reached only through import() is bridged when that import runs
5632
+ // (see pluginLazyConsumeOnlyShares), through the same provider selection init() uses.
5633
+ const __mfLazyShareLoads = new Map();
5634
+ __mfResolveState.loadLazyShares = async (names) => {
5635
+ const requested = new Set(names);
5636
+ for (const batch of __mfMaterializedShareBatches) await Promise.all(batch.filter((pkg) => requested.has(pkg)).map((pkg) => {
5637
+ const share = usedShared[pkg];
5638
+ if (!share || !share.lazy || !__mfIsRuntimeOnlySharePending(pkg)) return;
5639
+ let load = __mfLazyShareLoads.get(pkg);
5640
+ if (!load) {
5641
+ load = __mfBridgeExternalSharedProvider(
5642
+ pkg,
5643
+ share,
5644
+ ${hasMultipleShareScopes ? "getShareVersions(pkg, share)" : "shared[pkg]"},
5645
+ initialShared[pkg],
5646
+ undefined
5647
+ ).then(() => __mfIsRuntimeOnlySharePending(pkg) ? __mfResolveImportFalseShared(pkg, share) : undefined);
5648
+ load.catch(() => __mfLazyShareLoads.delete(pkg));
5649
+ __mfLazyShareLoads.set(pkg, load);
5650
+ }
5651
+ return load;
5652
+ }));
5653
+ };` : ""}
5495
5654
  initResolve(initRes)
5496
5655
  return initRes
5497
5656
  }
@@ -5508,8 +5667,13 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
5508
5667
  ${guardHostAutoInit ? `let __mfInitPromise;
5509
5668
  function __mfGuardedInit(shared, initScope, remoteEntryInitOptions) {
5510
5669
  if (shared === undefined && __mfInitPromise) return __mfInitPromise;
5511
- __mfInitPromise = init(shared, initScope, remoteEntryInitOptions);
5512
- return __mfInitPromise;
5670
+ // A call skipped by the circular-init guard resolves to undefined and must not
5671
+ // replace the cached result of the call that actually initialized the container.
5672
+ const prev = __mfInitPromise;
5673
+ const next = init(shared, initScope, remoteEntryInitOptions);
5674
+ __mfInitPromise = prev ? next.then((res) => (res === undefined ? prev : res)) : next;
5675
+ if (prev) __mfInitPromise.catch(() => {});
5676
+ return next;
5513
5677
  }
5514
5678
  export { __mfGuardedInit as init, getExposes as get }` : `export { init, getExposes as get }`}
5515
5679
  `;
@@ -5590,7 +5754,8 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build", options
5590
5754
  for (const __mfHostInitShareBatch of __mfHostInitShareBatches) {
5591
5755
  await Promise.all(__mfHostInitShareBatch.map(async (pkg) => {
5592
5756
  const share = usedShared[pkg];
5593
- if (!share || share.materialize === false) return;
5757
+ // A standalone container has no dynamic-import boundary to load a lazy share behind.
5758
+ if (!share || (share.materialize === false && !share.lazy)) return;
5594
5759
  // remoteEntry.init resolves tree-enabled shares into the
5595
5760
  // coverage-aware cache. Never republish that selected partial under
5596
5761
  // a generic full-module key here.
@@ -5621,20 +5786,7 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build", options
5621
5786
  // container's own stub and lets it displace an unloaded adopted
5622
5787
  // provider whenever this container's name sorts after the provider's
5623
5788
  // (#1311). Put the provider back: a stub never outranks a provider.
5624
- if (!runtime.__mfKeepAdoptedProviders) {
5625
- runtime.__mfKeepAdoptedProviders = true;
5626
- runtime.sharedHandler?.hooks?.lifecycle?.afterRegisterShare?.on?.((args) => {
5627
- const { shared, previousShared, registeredShared } = args || {};
5628
- if (
5629
- shared?.shareConfig?.import !== false ||
5630
- registeredShared !== shared ||
5631
- !previousShared ||
5632
- previousShared.shareConfig?.import === false
5633
- ) return;
5634
- const versions = runtime.shareScopeMap?.[args.scope]?.[args.pkgName];
5635
- if (versions && versions[shared.version] === shared) versions[shared.version] = previousShared;
5636
- });
5637
- }
5789
+ ${generateKeepProvidersOverStubsCode("runtime")}
5638
5790
  for (const instance of globalThis.__FEDERATION__?.__INSTANCES__ || []) {
5639
5791
  for (const scopeName of __mfScopeNames) {
5640
5792
  const versions = instance?.shareScopeMap?.[scopeName]?.[pkg];
@@ -5734,22 +5886,32 @@ function getPendingSharesState(options) {
5734
5886
  }
5735
5887
  function generatePendingSharesCode(command = "build", options) {
5736
5888
  const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
5737
- const pendingShareImports = command === "build" ? getMaterializedShares(options).filter((pkg) => {
5889
+ const pendingSharePkgs = command === "build" ? getMaterializedShares(options).filter((pkg) => {
5738
5890
  const shareItem = getShareItemForPreload(pkg, resolvedOptions);
5739
5891
  if (!shareItem || pkg.endsWith("/")) return false;
5740
5892
  if (shareItem.shareConfig.eager) return false;
5741
5893
  return shareItem.shareConfig.import !== false && !shareItem.shareConfig.treeShaking;
5742
- }).map((pkg) => `[${toSafeJsLiteral(pkg)}, () => import(${toSafeJsLiteral(getLoadShareModulePath(pkg, false, options))})]`) : [];
5894
+ }) : [];
5895
+ if (command === "build" && shouldPreloadEntryDeferredReactDomClient(resolvedOptions) && !pendingSharePkgs.includes("react-dom/client")) pendingSharePkgs.push(REACT_DOM_CLIENT_SHARE);
5896
+ const pendingShareImports = pendingSharePkgs.map((pkg) => `[${toSafeJsLiteral(pkg)}, () => import(${toSafeJsLiteral(getLoadShareModulePath(pkg, false, options))})]`);
5743
5897
  return `
5744
5898
  ${getRuntimeModuleCacheBootstrapCode()}
5745
5899
  ${sharedCacheHelperCode}
5746
5900
  const __mfPendingShareImports = [${pendingShareImports.join(", ")}];
5747
5901
  export async function preloadPendingShares() {
5748
5902
  if (__mfPendingShareImports.length === 0) return;
5903
+ const __mfRendererShare = ${toSafeJsLiteral(REACT_DOM_CLIENT_SHARE)};
5904
+ const __mfRendererParent = ${toSafeJsLiteral(getPackageName(REACT_DOM_CLIENT_SHARE))};
5749
5905
  const {usedShared} = await import("${getLocalSharedImportMapPath(options)}");
5750
5906
  await Promise.all(__mfPendingShareImports.map(async ([pkg, load]) => {
5751
- const share = usedShared[pkg];
5752
- if (!share || share.materialize === false || share.treeShaking || share.shareConfig?.import === false) return;
5907
+ const exactShare = usedShared[pkg];
5908
+ const share = exactShare ?? (pkg === __mfRendererShare ? usedShared[__mfRendererParent] : undefined);
5909
+ if (!share || share.treeShaking || share.shareConfig?.import === false) return;
5910
+ // The collapsed parent does not mark the renderer subpath materialized until the entry
5911
+ // imports it, and that import map can be emitted first. The deferred renderer wrapper
5912
+ // still has to run before a standalone entry reads createRoot. A cache hit (the host
5913
+ // renderer) skips load(), so a nested leaf does not import its own client.
5914
+ if (exactShare && exactShare.materialize === false && pkg !== __mfRendererShare) return;
5753
5915
  const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, share.shareConfig?.singleton, share.version, share.scope);
5754
5916
  if (__mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined) return;
5755
5917
  await load().catch((err) => console.warn("[module-federation] shared preload failed:", pkg, err));
@@ -6413,7 +6575,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
6413
6575
  }
6414
6576
  ` : "";
6415
6577
  const sharedPreloadSources = _command === "serve" && waitsForInit && isRemoteOnlyContainer(normalizedOptions) && federationOptions ? Array.from(getUsedShares(federationOptions)).filter((pkg) => !pkg.endsWith("/")).filter((pkg) => {
6416
- const shareItem = federationOptions.shared[pkg] || Object.entries(federationOptions.shared).find(([key]) => key.endsWith("/") && pkg.startsWith(key))?.[1];
6578
+ const shareItem = getNormalizeShareItem(pkg, federationOptions);
6417
6579
  const isExplicitShare = Object.hasOwn(federationOptions.shared, pkg);
6418
6580
  return shareItem?.shareConfig?.singleton === true && shareItem?.shareConfig?.import !== false && !shareItem?.shareConfig?.treeShaking && (isExplicitShare || typeof shareItem?.shareConfig?.import === "string" || Boolean(getProjectResolvedImportPath(pkg)));
6419
6581
  }).map((pkg) => toViteEncodedId(getLoadShareModulePath(pkg, false, federationOptions))) : [];
@@ -6546,6 +6708,19 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
6546
6708
  apply: "serve",
6547
6709
  config(_config, { command }) {
6548
6710
  _command = command;
6711
+ const isRemoteEntry = entryName === "remoteEntry" && federationOptions !== void 0 && isRemoteContainer(federationOptions);
6712
+ if (command === "serve" && _config.experimental?.bundledDev && isRemoteEntry) {
6713
+ _config.experimental = {
6714
+ ..._config.experimental,
6715
+ bundledDev: false
6716
+ };
6717
+ _config.environments ??= {};
6718
+ _config.environments.client ??= {};
6719
+ if (_config.environments.client.isBundled !== false) {
6720
+ _config.environments.client.isBundled = false;
6721
+ mfWarn("Vite bundledDev is disabled for the client environment of a Module Federation remote container so its remoteEntry keeps the standard init/get contract.");
6722
+ }
6723
+ }
6549
6724
  },
6550
6725
  configResolved(config) {
6551
6726
  viteConfig = config;
@@ -6842,17 +7017,20 @@ function checkAliasConflicts(options) {
6842
7017
  }
6843
7018
  return false;
6844
7019
  };
6845
- for (const sharedKey of sharedKeys) for (const aliasEntry of userAliases) {
6846
- const replacement = aliasEntry.replacement;
6847
- if (!matchesSharedKey(aliasEntry, sharedKey)) continue;
6848
- if (replacement === "$1") break;
6849
- if (typeof replacement === "string") {
6850
- if (getPackageNameFromNodeModulePath(replacement) === (sharedKey.endsWith("/") ? sharedKey.slice(0, -1) : sharedKey)) continue;
6851
- conflicts.push({
6852
- sharedModule: sharedKey,
6853
- alias: String(aliasEntry.find),
6854
- target: replacement
6855
- });
7020
+ for (const sharedKey of sharedKeys) {
7021
+ const request = getSharedRequest(sharedKey, shared[sharedKey]);
7022
+ for (const aliasEntry of userAliases) {
7023
+ const replacement = aliasEntry.replacement;
7024
+ if (!matchesSharedKey(aliasEntry, request)) continue;
7025
+ if (replacement === "$1") break;
7026
+ if (typeof replacement === "string") {
7027
+ if (getPackageNameFromNodeModulePath(replacement) === (request.endsWith("/") ? request.slice(0, -1) : request)) continue;
7028
+ conflicts.push({
7029
+ sharedModule: sharedKey,
7030
+ alias: String(aliasEntry.find),
7031
+ target: replacement
7032
+ });
7033
+ }
6856
7034
  }
6857
7035
  }
6858
7036
  if (conflicts.length > 0) {
@@ -7567,9 +7745,6 @@ function pluginExternalRuntimeCore() {
7567
7745
  };
7568
7746
  }
7569
7747
  //#endregion
7570
- //#region package.json
7571
- var version$1 = "1.22.1";
7572
- //#endregion
7573
7748
  //#region src/virtualModules/index.ts
7574
7749
  function initVirtualModules(command, remoteEntryId, enableSsrInit = false, options) {
7575
7750
  writeLocalSharedImportMap(options);
@@ -7587,6 +7762,11 @@ const JS_EXTENSIONS = [
7587
7762
  ".mjs",
7588
7763
  ".cjs"
7589
7764
  ];
7765
+ /** A module path without its JS extension, so `./src/App` matches `/root/src/App.tsx`. */
7766
+ const stripKnownJsExtension = (file) => {
7767
+ const ext = path$1.extname(file);
7768
+ return JS_EXTENSIONS.includes(ext) ? path$1.join(path$1.dirname(file), path$1.basename(file, ext)) : file;
7769
+ };
7590
7770
  /**
7591
7771
  * Creates an empty asset map structure for tracking JS and CSS assets
7592
7772
  * @returns Initialized asset map with sync/async arrays for JS and CSS
@@ -7705,8 +7885,8 @@ const processModuleAssets = (bundle, filesMap, moduleMatcher, options = {}) => {
7705
7885
  const comparableModulePath = options.root ? path$1.resolve(options.root, modulePath) : modulePath;
7706
7886
  const comparableModulePaths = [comparableModulePath];
7707
7887
  if (options.stripKnownJsExtensions) {
7708
- const ext = path$1.extname(comparableModulePath);
7709
- if (JS_EXTENSIONS.includes(ext)) comparableModulePaths.push(path$1.join(path$1.dirname(comparableModulePath), path$1.basename(comparableModulePath, ext)));
7888
+ const stripped = stripKnownJsExtension(comparableModulePath);
7889
+ if (stripped !== comparableModulePath) comparableModulePaths.push(stripped);
7710
7890
  }
7711
7891
  const matchKey = comparableModulePaths.map(moduleMatcher).find(Boolean);
7712
7892
  if (!matchKey) continue;
@@ -7767,6 +7947,119 @@ const buildFileToShareKeyMap = async (shareKeys, resolveFn, options) => {
7767
7947
  return fileToShareKey;
7768
7948
  };
7769
7949
  //#endregion
7950
+ //#region src/plugins/pluginLazyConsumeOnlyShares.ts
7951
+ const chunkModuleIds = (chunk) => [...chunk.facadeModuleId ? [chunk.facadeModuleId] : [], ...chunk.moduleIds ?? Object.keys(chunk.modules ?? {})];
7952
+ function buildLazyShareGraph(chunks, wrapperShares, exposeModules) {
7953
+ const sharesInChunk = /* @__PURE__ */ new Map();
7954
+ const startupRoots = [];
7955
+ for (const [fileName, chunk] of Object.entries(chunks)) {
7956
+ if (chunk.type !== "chunk") continue;
7957
+ const moduleIds = chunkModuleIds(chunk);
7958
+ sharesInChunk.set(fileName, new Set(moduleIds.map((id) => wrapperShares.get(normalizeVirtualModuleId(id))).filter((share) => share !== void 0)));
7959
+ if (chunk.isEntry || moduleIds.some((id) => exposeModules.has(stripKnownJsExtension(id)))) startupRoots.push(fileName);
7960
+ }
7961
+ const sharesInClosure = (roots) => new Set(collectStaticChunks(chunks, roots).flatMap((chunk) => [...sharesInChunk.get(chunk.fileName) ?? []]));
7962
+ const lazyShares = new Set([...sharesInChunk.values()].flatMap((shares) => [...shares]));
7963
+ for (const share of sharesInClosure(startupRoots)) lazyShares.delete(share);
7964
+ const sharesByChunk = /* @__PURE__ */ new Map();
7965
+ if (lazyShares.size > 0) for (const fileName of sharesInChunk.keys()) {
7966
+ const shares = [...sharesInClosure([fileName])].filter((share) => lazyShares.has(share));
7967
+ if (shares.length > 0) sharesByChunk.set(fileName, shares.sort());
7968
+ }
7969
+ return {
7970
+ lazyShares,
7971
+ sharesByChunk
7972
+ };
7973
+ }
7974
+ const COMMENTS = String.raw`(?:\s|\/\*[\s\S]*?\*\/|\/\/[^\n]*\n)*`;
7975
+ const DYNAMIC_IMPORT_REGEX = new RegExp(String.raw`\bimport\(${COMMENTS}(["'` + "`" + String.raw`])([^"'` + "`" + String.raw`\n]+)\1${COMMENTS}\)`, "g");
7976
+ const QUOTES = [
7977
+ "\"",
7978
+ "'",
7979
+ "`"
7980
+ ];
7981
+ /**
7982
+ * A consume-only (`import: false`) share that only a dynamic `import()` reaches is
7983
+ * left out of `init()` and bridged when that import runs: the import expression is
7984
+ * wrapped so the share is in the cache before the chunk evaluates. There is no
7985
+ * other async boundary in an ESM graph without top-level await, so a wrapper
7986
+ * reached statically from an entry or an expose keeps loading during `init()`.
7987
+ */
7988
+ function pluginLazyConsumeOnlyShares(options) {
7989
+ let viteConfig;
7990
+ const graphs = /* @__PURE__ */ new WeakMap();
7991
+ const helperName = `__mfLoadLazyShares_${options.internalName.replace(/[^A-Za-z0-9_$]/g, "_")}`;
7992
+ return {
7993
+ name: "module-federation:lazy-consume-only-shares",
7994
+ apply: "build",
7995
+ configResolved(config) {
7996
+ viteConfig = config;
7997
+ },
7998
+ renderChunk(code, chunk, _outputOptions, meta) {
7999
+ const renderedChunk = chunk;
8000
+ const chunks = meta?.chunks;
8001
+ if (!chunks || Object.keys(options.exposes).length === 0) return null;
8002
+ if (isServerBuildContext(this, viteConfig)) return null;
8003
+ let graph = graphs.get(chunks);
8004
+ if (!graph) {
8005
+ const isRolldown = getIsRolldown(this);
8006
+ const wrapperShares = /* @__PURE__ */ new Map();
8007
+ for (const shareKey of getUsedShares(options)) {
8008
+ const shareConfig = getNormalizeShareItem(shareKey, options)?.shareConfig;
8009
+ if (shareConfig?.import !== false || shareConfig.eager || shareConfig.treeShaking) continue;
8010
+ wrapperShares.set(normalizeVirtualModuleId(getLoadShareModulePath(shareKey, isRolldown, options)), shareKey);
8011
+ }
8012
+ const root = viteConfig?.root ?? process.cwd();
8013
+ graph = buildLazyShareGraph(chunks, wrapperShares, new Set(Object.values(options.exposes).map((expose) => stripKnownJsExtension(path$1.resolve(root, expose.import)))));
8014
+ graphs.set(chunks, graph);
8015
+ }
8016
+ if (graph.lazyShares.size === 0) return null;
8017
+ const rewriter = new CodeRewriter(code);
8018
+ let edited = false;
8019
+ const importMapId = normalizeVirtualModuleId(getLocalSharedImportMapPath(options));
8020
+ const isImportMapChunk = chunkModuleIds(renderedChunk).some((id) => normalizeVirtualModuleId(id) === importMapId);
8021
+ if (isImportMapChunk) for (const quote of QUOTES) {
8022
+ const literal = `${quote}${LAZY_CONSUME_ONLY_SHARES_PLACEHOLDER}${quote}`;
8023
+ const start = code.indexOf(literal);
8024
+ if (start === -1) continue;
8025
+ rewriter.overwrite(start, start + literal.length, JSON.stringify([...graph.lazyShares].sort()));
8026
+ edited = true;
8027
+ break;
8028
+ }
8029
+ const chunkDir = path$1.posix.dirname(renderedChunk.fileName);
8030
+ const codePositions = createCodePositionMap(code);
8031
+ let usesHelper = false;
8032
+ for (const match of isImportMapChunk ? [] : code.matchAll(DYNAMIC_IMPORT_REGEX)) {
8033
+ const [expression, , specifier] = match;
8034
+ const start = match.index;
8035
+ if (!codePositions[start]) continue;
8036
+ const target = path$1.posix.normalize(path$1.posix.join(chunkDir, specifier));
8037
+ const shares = graph.sharesByChunk.get(target);
8038
+ if (!shares || !renderedChunk.dynamicImports.includes(target)) continue;
8039
+ rewriter.overwrite(start, start + expression.length, `${helperName}(${JSON.stringify(shares)}).then(() => ${expression})`);
8040
+ usesHelper = edited = true;
8041
+ }
8042
+ if (!edited) return null;
8043
+ if (usesHelper) {
8044
+ const stateKey = JSON.stringify(getRuntimeInitGlobalKey(getRuntimeInitStatusImportId(options)));
8045
+ rewriter.overwrite(code.length, code.length, `
8046
+ function ${helperName}(names) {
8047
+ const state = globalThis[${stateKey}];
8048
+ return state ? state.initPromise.then(() => (typeof state.loadLazyShares === "function" ? state.loadLazyShares(names) : undefined)) : Promise.resolve();
8049
+ }
8050
+ `);
8051
+ }
8052
+ return {
8053
+ code: rewriter.toString(),
8054
+ map: rewriter.generateMap(renderedChunk.fileName)
8055
+ };
8056
+ }
8057
+ };
8058
+ }
8059
+ //#endregion
8060
+ //#region package.json
8061
+ var version$1 = "1.23.1";
8062
+ //#endregion
7770
8063
  //#region src/virtualModules/virtualExposesSSR.ts
7771
8064
  /**
7772
8065
  * Virtual module ID for the SSR exposes map.
@@ -7821,7 +8114,8 @@ function getSsrFileNameParts(browserFilename) {
7821
8114
  ext
7822
8115
  };
7823
8116
  }
7824
- function getSsrRemoteEntryFileName(browserFilename) {
8117
+ function getSsrRemoteEntryFileName(options, browserFilename = options.filename) {
8118
+ if (options.ssrFilename) return options.ssrFilename;
7825
8119
  const { base, ext } = getSsrFileNameParts(browserFilename);
7826
8120
  return `${base}.ssr${ext ?? ".js"}`;
7827
8121
  }
@@ -7835,14 +8129,15 @@ function getSsrSharedSingletons(options) {
7835
8129
  const result = {};
7836
8130
  for (const [pkg, share] of Object.entries(options.shared)) {
7837
8131
  if (!share.shareConfig.singleton) continue;
7838
- if (pkg.endsWith("/")) {
7839
- for (const concrete of expandSharedPrefixKey(pkg, used)) result[concrete] = {
8132
+ const request = getSharedRequest(pkg, share);
8133
+ if (request.endsWith("/")) {
8134
+ for (const concrete of expandSharedPrefixKey(request, used)) result[getSharedRuntimeKey(concrete, share)] = {
7840
8135
  ...share,
7841
8136
  name: concrete
7842
8137
  };
7843
8138
  continue;
7844
8139
  }
7845
- result[pkg] = share;
8140
+ result[getSharedRuntimeKey(pkg, share)] = share;
7846
8141
  }
7847
8142
  return result;
7848
8143
  }
@@ -8187,7 +8482,7 @@ const Manifest = (providedOptions) => {
8187
8482
  type: "module"
8188
8483
  },
8189
8484
  ssrRemoteEntry: {
8190
- name: getSsrRemoteEntryFileName(devRemoteEntryFile),
8485
+ name: getSsrRemoteEntryFileName(mfOptions, devRemoteEntryFile),
8191
8486
  path: "/__mf_ssr__/",
8192
8487
  type: "module"
8193
8488
  },
@@ -8230,6 +8525,33 @@ const Manifest = (providedOptions) => {
8230
8525
  publicPath = mfOptions.publicPath === "auto" ? "auto" : resolvePublicPath(mfOptions, base, _originalConfigBase);
8231
8526
  },
8232
8527
  /**
8528
+ * A standalone `vite build --ssr` may run with its own `filename`, e.g.
8529
+ * `defineConfig(({ isSsrBuild }) => ...)`. The manifest written by the
8530
+ * earlier client build then advertises an SSR entry derived from the
8531
+ * browser filename, which is not the file this build emitted. Point the
8532
+ * manifest and stats on disk at the emitted SSR entry.
8533
+ */
8534
+ writeBundle(outputOptions) {
8535
+ if (!mfManifestName || _command !== "build" || isConsumerProject) return;
8536
+ const environment = this.environment;
8537
+ if (!(environment ? environment.name === "ssr" : Boolean(viteConfig?.build?.ssr))) return;
8538
+ const ssrEntryName = getSsrRemoteEntryFileName(mfOptions);
8539
+ const outDirs = [...new Set([outputOptions.dir, viteConfig?.environments?.client?.build?.outDir].filter((dir) => typeof dir === "string").map((dir) => path$1.resolve(root, dir)))];
8540
+ if (!outDirs.some((dir) => fs$1.existsSync(path$1.resolve(dir, ssrEntryName)))) return;
8541
+ for (const dir of outDirs) for (const fileName of [mfManifestName, mfManifestStatsName]) {
8542
+ if (!fileName) continue;
8543
+ const file = path$1.resolve(dir, fileName);
8544
+ if (!fs$1.existsSync(file)) continue;
8545
+ try {
8546
+ const data = JSON.parse(fs$1.readFileSync(file, "utf8"));
8547
+ const entry = data?.metaData?.ssrRemoteEntry;
8548
+ if (!entry || typeof entry !== "object" || entry.name === ssrEntryName) continue;
8549
+ entry.name = ssrEntryName;
8550
+ fs$1.writeFileSync(file, JSON.stringify(data));
8551
+ } catch {}
8552
+ }
8553
+ },
8554
+ /**
8233
8555
  * Generates the module federation manifest file
8234
8556
  * @param options - Rollup output options
8235
8557
  * @param bundle - Generated bundle assets
@@ -8239,10 +8561,10 @@ const Manifest = (providedOptions) => {
8239
8561
  if (this.environment?.name === "ssr") return;
8240
8562
  let filesMap = {};
8241
8563
  const foundRemoteEntryFile = findRemoteEntryFile(mfOptions.filename, bundle);
8242
- const expectedSsrRemoteEntryFile = getSsrRemoteEntryFileName(mfOptions.filename);
8564
+ const expectedSsrRemoteEntryFile = getSsrRemoteEntryFileName(mfOptions);
8243
8565
  const foundSsrRemoteEntryFile = Object.values(bundle).find((file) => file.fileName === expectedSsrRemoteEntryFile)?.fileName;
8244
8566
  if (foundRemoteEntryFile) remoteEntryFile = foundRemoteEntryFile;
8245
- ssrRemoteEntryFile = foundSsrRemoteEntryFile || (_command === "serve" ? getSsrRemoteEntryFileName(resolveHashPlaceholderFileName(mfOptions.filename)) : expectedSsrRemoteEntryFile);
8567
+ ssrRemoteEntryFile = foundSsrRemoteEntryFile || (_command === "serve" ? getSsrRemoteEntryFileName(mfOptions, resolveHashPlaceholderFileName(mfOptions.filename)) : expectedSsrRemoteEntryFile);
8246
8568
  const allCssAssets = mfOptions.bundleAllCSS && !disableAssetsAnalyze ? collectCssAssets(bundle) : /* @__PURE__ */ new Set();
8247
8569
  if (allCssAssets.size > 0) {
8248
8570
  const secondaryCss = /* @__PURE__ */ new Set();
@@ -8319,7 +8641,7 @@ const Manifest = (providedOptions) => {
8319
8641
  type: "module"
8320
8642
  };
8321
8643
  const ssrRemoteEntry = {
8322
- name: ssrRemoteEntryFile || getSsrRemoteEntryFileName(_command === "serve" ? resolveHashPlaceholderFileName(filename) : filename),
8644
+ name: ssrRemoteEntryFile || getSsrRemoteEntryFileName(mfOptions, _command === "serve" ? resolveHashPlaceholderFileName(filename) : filename),
8323
8645
  path: _command === "serve" ? "/__mf_ssr__/" : "",
8324
8646
  type: "module"
8325
8647
  };
@@ -8636,6 +8958,7 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
8636
8958
  return cleanId.includes(getHostAutoInitPath(options)) || cleanId.includes(getHostAutoInitPath());
8637
8959
  };
8638
8960
  const getEnvironmentConditions = (context) => context.environment?.config?.resolve?.conditions;
8961
+ const isSsrBuild = (context) => isServerBuildContext(context, viteConfig);
8639
8962
  function isRemoteImport(source) {
8640
8963
  return Object.keys(options.remotes).some((name) => source === name || source.startsWith(name + "/"));
8641
8964
  }
@@ -8671,7 +8994,12 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
8671
8994
  if (!dynamic) dependencies.add(source);
8672
8995
  continue;
8673
8996
  }
8674
- const resolved = await ctx.resolve(source, id);
8997
+ let resolved;
8998
+ try {
8999
+ resolved = await ctx.resolve(source, id);
9000
+ } catch {
9001
+ continue;
9002
+ }
8675
9003
  if (!resolved?.id || !shouldScanResolvedImport(resolved.id)) continue;
8676
9004
  for (const dependency of await collectRemoteDependencies(ctx, resolved.id, seen)) dependencies.add(dependency);
8677
9005
  }
@@ -8739,7 +9067,7 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
8739
9067
  }
8740
9068
  },
8741
9069
  async load(id) {
8742
- if (id === remoteEntryId) return getParsePromise().then((_) => generateRemoteEntry(options, virtualExposesId, _command, getEnvironmentConditions(this)));
9070
+ if (id === remoteEntryId) return getParsePromise().then((_) => generateRemoteEntry(options, virtualExposesId, _command, getEnvironmentConditions(this), isSsrBuild(this)));
8743
9071
  if (id === virtualExposesId) {
8744
9072
  await refreshExposeRemoteDependencies(this);
8745
9073
  return generateExposes(options, exposeRemoteDependencies, _command, reactIslandExposes);
@@ -8749,7 +9077,7 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
8749
9077
  async transform(code, id) {
8750
9078
  return mapCodeToCodeWithSourcemap(await (async () => {
8751
9079
  if (!filterId(id)) return;
8752
- if (id.includes(remoteEntryId)) return getParsePromise().then((_) => generateRemoteEntry(options, virtualExposesId, _command, getEnvironmentConditions(this)));
9080
+ if (id.includes(remoteEntryId)) return getParsePromise().then((_) => generateRemoteEntry(options, virtualExposesId, _command, getEnvironmentConditions(this), isSsrBuild(this)));
8753
9081
  if (id === virtualExposesId) {
8754
9082
  await refreshExposeRemoteDependencies(this);
8755
9083
  return generateExposes(options, exposeRemoteDependencies, _command, reactIslandExposes);
@@ -8847,7 +9175,7 @@ function pluginProxyRemotes_default(options) {
8847
9175
  const remoteModule = getRemoteVirtualModule(source, command, enableSsrInit, consumer, options);
8848
9176
  addUsedRemote(remoteName, source, options);
8849
9177
  refreshHostAutoInit(options);
8850
- return remoteModule.getImportId();
9178
+ return remoteModule.getResolvedId();
8851
9179
  }
8852
9180
  return {
8853
9181
  name: "proxyRemotes",
@@ -8867,7 +9195,7 @@ function pluginProxyRemotes_default(options) {
8867
9195
  },
8868
9196
  configResolved(config) {
8869
9197
  hasMultiEnvironment = Boolean(config.environments?.ssr);
8870
- enableSsrInit = getSsrCapabilities(parseInt(version, 10), command, Object.keys(remotes).length > 0).enableSsrInitBootstrap;
9198
+ enableSsrInit = getSsrCapabilities(parseInt(version, 10), command, Object.keys(remotes).length > 0, isSsrConfig(config)).enableSsrInitBootstrap;
8871
9199
  },
8872
9200
  resolveId(source, importer) {
8873
9201
  const resolvedIslandConsumerId = resolveReactIslandConsumerId(source);
@@ -8892,6 +9220,12 @@ function pluginProxyRemotes_default(options) {
8892
9220
  }
8893
9221
  //#endregion
8894
9222
  //#region src/utils/sharedSource.ts
9223
+ const pendingEntryLookups = /* @__PURE__ */ new Map();
9224
+ const getEntryLookupKey = (source, importer) => `${source}\0${importer}`;
9225
+ /** Whether a resolveId call is one of the shared source resolver's own entry lookups. */
9226
+ function isSharedEntryLookup(source, importer, options) {
9227
+ return options.custom?.__mfSharedEntryLookup === true || pendingEntryLookups.has(getEntryLookupKey(source, importer));
9228
+ }
8895
9229
  /** Identify shared entries through Vite, with a cache scoped to this federation instance. */
8896
9230
  function createSharedSourceResolver(shared, getResolutionConfig) {
8897
9231
  const caches = /* @__PURE__ */ new Map();
@@ -8902,9 +9236,10 @@ function createSharedSourceResolver(shared, getResolutionConfig) {
8902
9236
  if (findSharedKey(packageName, shared)) candidates.add(packageName);
8903
9237
  if (findSharedKey(suffix, shared)) candidates.add(suffix);
8904
9238
  for (const key of Object.keys(shared)) {
8905
- if (getPackageName(key) !== packageName) continue;
8906
- if (!key.endsWith("/")) candidates.add(key);
8907
- for (const subpath of getCommonSharedSubpaths(key)) if (findSharedKey(subpath, shared)) candidates.add(subpath);
9239
+ const request = getSharedRequest(key, shared[key]);
9240
+ if (getPackageName(request) !== packageName) continue;
9241
+ if (!request.endsWith("/")) candidates.add(request);
9242
+ for (const subpath of getCommonSharedSubpaths(request)) if (findSharedKey(subpath, shared)) candidates.add(subpath);
8908
9243
  }
8909
9244
  if (candidates.size === 0) return;
8910
9245
  const resolvedSource = await resolveEntry(source);
@@ -8912,7 +9247,8 @@ function createSharedSourceResolver(shared, getResolutionConfig) {
8912
9247
  for (const candidate of candidates) {
8913
9248
  const entry = await resolveEntry(candidate);
8914
9249
  if (!entry) continue;
8915
- if (normalizeNodeModulePath(entry) === normalizeNodeModulePath(resolvedSource) || getNodeModulesSuffix(entry) === suffix) return candidate;
9250
+ const allowNodeModulesSuffixMatch = shared[findSharedKey(candidate, shared) ?? candidate]?.shareConfig?.allowNodeModulesSuffixMatch === true;
9251
+ if (normalizeNodeModulePath(entry) === normalizeNodeModulePath(resolvedSource) || allowNodeModulesSuffixMatch && getNodeModulesSuffix(entry) === suffix) return candidate;
8916
9252
  }
8917
9253
  }
8918
9254
  return {
@@ -8946,8 +9282,11 @@ function createSharedSourceResolver(shared, getResolutionConfig) {
8946
9282
  cwd: root,
8947
9283
  conditions
8948
9284
  })) return void 0;
9285
+ const importer = path$1.join(root, "package.json");
9286
+ const lookupKey = getEntryLookupKey(request, importer);
9287
+ pendingEntryLookups.set(lookupKey, (pendingEntryLookups.get(lookupKey) ?? 0) + 1);
8949
9288
  try {
8950
- const resolved = await context.resolve(request, path$1.join(root, "package.json"), {
9289
+ const resolved = await context.resolve(request, importer, {
8951
9290
  ...options,
8952
9291
  skipSelf: true,
8953
9292
  custom: {
@@ -8958,6 +9297,10 @@ function createSharedSourceResolver(shared, getResolutionConfig) {
8958
9297
  return resolved && !resolved.external ? resolved.id : void 0;
8959
9298
  } catch {
8960
9299
  return;
9300
+ } finally {
9301
+ const remaining = pendingEntryLookups.get(lookupKey) - 1;
9302
+ if (remaining) pendingEntryLookups.set(lookupKey, remaining);
9303
+ else pendingEntryLookups.delete(lookupKey);
8961
9304
  }
8962
9305
  });
8963
9306
  cache?.set(normalizedSource, result);
@@ -9006,7 +9349,7 @@ function tryResolveFromProjectRoot(source) {
9006
9349
  const browserEntry = getInstalledPackageEntry(source, { cwd: getPackageDetectionCwd() });
9007
9350
  if (browserEntry) return browserEntry;
9008
9351
  try {
9009
- return createRequire$1(pathToFileURL(path$1.join(getPackageDetectionCwd(), "package.json"))).resolve(source);
9352
+ return resolveModulePath(source, path$1.join(getPackageDetectionCwd(), "package.json"));
9010
9353
  } catch {
9011
9354
  return;
9012
9355
  }
@@ -9032,9 +9375,13 @@ function getPackageDependencies(pkg) {
9032
9375
  */
9033
9376
  function excludeSharedSubDependencies(shared) {
9034
9377
  const sharedKeys = new Set(Object.keys(shared));
9035
- const sharedKeyByBase = new Map(Object.keys(shared).map((key) => [key.endsWith("/") ? key.slice(0, -1) : key, key]));
9378
+ const requestBase = (key) => {
9379
+ const request = getSharedRequest(key, shared[key]);
9380
+ return request.endsWith("/") ? request.slice(0, -1) : request;
9381
+ };
9382
+ const sharedKeyByBase = new Map(Object.keys(shared).map((key) => [requestBase(key), key]));
9036
9383
  for (const parentKey of sharedKeys) {
9037
- const deps = getPackageDependencies(parentKey);
9384
+ const deps = getPackageDependencies(requestBase(parentKey));
9038
9385
  for (const dep of deps) {
9039
9386
  const depKey = sharedKeyByBase.get(dep);
9040
9387
  if (depKey && depKey !== parentKey) {
@@ -9361,6 +9708,7 @@ function isSharedPackageRuntimeDependency(sharedKey, dependency, conditions) {
9361
9708
  function proxySharedModule(options) {
9362
9709
  const { shared = {}, federationOptions, getParsePromise = () => Promise.resolve() } = options;
9363
9710
  let _config;
9711
+ const getBuildImportAnalysis = (environment) => getImportAnalysis(environment ?? _config ?? options);
9364
9712
  let _command = "serve";
9365
9713
  let useDirectReactImport = false;
9366
9714
  let useRolldown = false;
@@ -9378,7 +9726,7 @@ function proxySharedModule(options) {
9378
9726
  const getRuntimeDependencyConditions = (context, resolveOptions) => {
9379
9727
  const environment = context.environment;
9380
9728
  const environmentConfig = environment?.config;
9381
- const isSsr = resolveOptions.ssr === true || Boolean(_config?.build?.ssr) || environmentConfig?.consumer === "server" || Boolean(environmentConfig?.build?.ssr) || environment?.name === "ssr" || environment?.name === "server";
9729
+ const isSsr = resolveOptions.ssr === true || Boolean(_config?.build?.ssr) || isServerEnvironment(environment?.name, environmentConfig);
9382
9730
  return getSharedExportConditions({
9383
9731
  environmentConditions: environmentConfig?.resolve?.conditions,
9384
9732
  isProduction: environmentConfig?.isProduction ?? isProduction,
@@ -9434,12 +9782,13 @@ function proxySharedModule(options) {
9434
9782
  }, federationOptions);
9435
9783
  },
9436
9784
  resolveId(source) {
9437
- if (source === getLocalSharedImportMapPath(federationOptions)) return getResolvedLocalSharedImportMapId(federationOptions);
9785
+ const resolvedId = getResolvedLocalSharedImportMapId(federationOptions);
9786
+ if (source === getLocalSharedImportMapPath(federationOptions) || source === resolvedId) return resolvedId;
9438
9787
  },
9439
9788
  load(id) {
9440
9789
  if (id === getResolvedLocalSharedImportMapId(federationOptions)) return getParsePromise().then((_) => {
9441
9790
  refreshTreeShakingForEnvironment(this);
9442
- const providerPackages = /* @__PURE__ */ new Set([...Object.keys(shared).filter((pkg) => !pkg.endsWith("/")), ...getUsedShares(federationOptions)]);
9791
+ const providerPackages = /* @__PURE__ */ new Set([...Object.keys(shared).filter((pkg) => !getSharedRequest(pkg, shared[pkg]).endsWith("/")), ...getUsedShares(federationOptions)]);
9443
9792
  for (const pkg of providerPackages) {
9444
9793
  const sharedKey = findSharedKey(pkg, shared);
9445
9794
  const shareItem = shared[pkg] || (sharedKey ? shared[sharedKey] : void 0);
@@ -9484,14 +9833,15 @@ function proxySharedModule(options) {
9484
9833
  const resolvedOptions = federationOptions ?? getNormalizeModuleFederationOptions();
9485
9834
  const registerConfiguredShare = _command === "build" && Object.keys(resolvedOptions.exposes).length > 0 ? addUsedShares : addConfiguredShare;
9486
9835
  Object.keys(shared).forEach((key) => {
9487
- if (key.endsWith("/")) return;
9488
- if (useDirectReactImport && key === "react") {
9489
- registerConfiguredShare(key, federationOptions);
9836
+ if (key.endsWith("/") || getSharedRequest(key, shared[key]).endsWith("/")) return;
9837
+ const runtimeKey = getSharedRuntimeKey(key, shared[key]);
9838
+ if (useDirectReactImport && runtimeKey === "react") {
9839
+ registerConfiguredShare(runtimeKey, federationOptions);
9490
9840
  return;
9491
9841
  }
9492
- writeLoadShareModule(key, shared[key], _command, isRolldown, federationOptions);
9493
- if (shared[key].shareConfig.import !== false) writePreBuildLibPath(key, shared[key], federationOptions);
9494
- registerConfiguredShare(key, federationOptions);
9842
+ writeLoadShareModule(runtimeKey, shared[key], _command, isRolldown, federationOptions);
9843
+ if (shared[key].shareConfig.import !== false) writePreBuildLibPath(runtimeKey, shared[key], federationOptions);
9844
+ registerConfiguredShare(runtimeKey, federationOptions);
9495
9845
  });
9496
9846
  writeLocalSharedImportMap(federationOptions);
9497
9847
  refreshHostAutoInit(federationOptions);
@@ -9502,10 +9852,14 @@ function proxySharedModule(options) {
9502
9852
  buildStart() {
9503
9853
  sharedSourceResolver.clear();
9504
9854
  if (_command !== "build") return;
9855
+ if (hasAnalyzableShares) getBuildImportAnalysis(this.environment).clear();
9505
9856
  resetTreeShakingExports(federationOptions);
9506
9857
  emittedTreeShakingProviders.clear();
9507
9858
  refreshTreeShakingForEnvironment(this);
9508
9859
  },
9860
+ buildEnd() {
9861
+ if (_command === "build" && hasAnalyzableShares) getBuildImportAnalysis(this.environment).clear();
9862
+ },
9509
9863
  shouldTransformCachedModule() {
9510
9864
  return _command === "build" && hasAnalyzableShares;
9511
9865
  },
@@ -9514,7 +9868,7 @@ function proxySharedModule(options) {
9514
9868
  await collectTreeShakingImports(code, id, shared, async (source, shares) => {
9515
9869
  const request = await sharedSourceResolver.resolve(this, source, transformOptions);
9516
9870
  return request ? findSharedKey(request, shares) : void 0;
9517
- }, (sharedKey, exports, request) => recordTreeShakingExports(sharedKey, exports, request, federationOptions), (sharedKey, request) => markTreeShakingPackageUnsafe(sharedKey, request, federationOptions));
9871
+ }, (sharedKey, exports, request) => recordTreeShakingExports(sharedKey, exports, request, federationOptions), (sharedKey, request) => markTreeShakingPackageUnsafe(sharedKey, request, federationOptions), getBuildImportAnalysis(this.environment));
9518
9872
  refreshTreeShakingForEnvironment(this);
9519
9873
  }
9520
9874
  },
@@ -9523,7 +9877,7 @@ function proxySharedModule(options) {
9523
9877
  enforce: "pre",
9524
9878
  apply: "build",
9525
9879
  async resolveId(source, importer, resolveOptions) {
9526
- if (resolveOptions.custom?.__mfSharedEntryLookup) return;
9880
+ if (isSharedEntryLookup(source, importer, resolveOptions)) return;
9527
9881
  const sourceToken = getTreeShakingGraphToken(source);
9528
9882
  const importerToken = getTreeShakingGraphToken(importer);
9529
9883
  const token = sourceToken || importerToken;
@@ -9559,7 +9913,7 @@ function proxySharedModule(options) {
9559
9913
  name: "proxyPreBuildShared:resolve-shared-loadShare",
9560
9914
  enforce: "pre",
9561
9915
  async resolveId(source, importer, resolveOptions) {
9562
- if (resolveOptions.custom?.__mfSharedEntryLookup || resolveOptions.custom?.__mfTreeShakingGraph) return;
9916
+ if (isSharedEntryLookup(source, importer, resolveOptions) || resolveOptions.custom?.__mfTreeShakingGraph) return;
9563
9917
  const sharedSource = await sharedSourceResolver.resolve(this, source, resolveOptions);
9564
9918
  if (!sharedSource) return;
9565
9919
  const key = findSharedKey(sharedSource, shared);
@@ -9574,8 +9928,9 @@ function proxySharedModule(options) {
9574
9928
  if (importerPackage === getPackageName(key)) return;
9575
9929
  if (importerPackage && shared[key].shareConfig.import !== false) {
9576
9930
  const importerIsUnsharedWorkspacePackage = !isNodeModulePath(importer) && !Object.keys(shared).some((sharedKey) => getPackageName(sharedKey) === importerPackage);
9577
- const runtimeDependencyRequest = key.endsWith("/") && matchesSharedSource(sharedSource, key) ? sharedSource : key;
9578
- if (importerIsUnsharedWorkspacePackage ? isSharedPackageRuntimeDependency(runtimeDependencyRequest, importerPackage, getRuntimeDependencyConditions(this, resolveOptions)) : isSharedPackageDependency(key, importerPackage)) return;
9931
+ const request = getSharedRequest(key, shared[key]);
9932
+ const runtimeDependencyRequest = request.endsWith("/") && matchesSharedSource(sharedSource, key, shared[key]) ? sharedSource : request;
9933
+ if (importerIsUnsharedWorkspacePackage ? isSharedPackageRuntimeDependency(runtimeDependencyRequest, importerPackage, getRuntimeDependencyConditions(this, resolveOptions)) : isSharedPackageDependency(request, importerPackage)) return;
9579
9934
  }
9580
9935
  if (useDirectReactImport && key === "react") return;
9581
9936
  if (isAssetLikeImport(source)) return;
@@ -9876,17 +10231,21 @@ function collectFromRegex(code, isRemoteImport) {
9876
10231
  }
9877
10232
  function pluginRemoteNamedExports(options) {
9878
10233
  const remoteNames = Object.keys(options.remotes);
10234
+ let root = process.cwd();
9879
10235
  const isNodeModulesId = (id) => id.includes("/node_modules/") || id.includes("\\node_modules\\");
9880
10236
  function isRemoteImport(source, importerId) {
9881
10237
  return remoteNames.some((name) => {
9882
10238
  if (source.startsWith(name + "/")) return true;
9883
10239
  if (source !== name) return false;
9884
- return !isNodeModulesId(importerId);
10240
+ return !isNodeModulesId(importerId) || !getInstalledPackageEntry(source, { cwd: root });
9885
10241
  }) || source.includes("__loadRemote__");
9886
10242
  }
9887
10243
  return {
9888
10244
  name: "module-federation-remote-named-exports",
9889
10245
  enforce: "post",
10246
+ configResolved(config) {
10247
+ root = config.root || process.cwd();
10248
+ },
9890
10249
  async transform(code, id) {
9891
10250
  if (remoteNames.length === 0) return;
9892
10251
  if (id.includes("__loadRemote__") || id.includes("__loadShare__")) return;
@@ -10038,18 +10397,25 @@ function pluginSSRRemoteEntry(options) {
10038
10397
  const remoteEntrySSRId = getRemoteEntrySSRId(options);
10039
10398
  const virtualExposesSSRId = getVirtualExposesSSRId(options);
10040
10399
  let cachedSsrRemoteEntrySource;
10041
- const ssrOutputFilename = getSsrRemoteEntryFileName(options.filename);
10400
+ const ssrOutputFilename = getSsrRemoteEntryFileName(options);
10042
10401
  const ssrExposesFileName = getSsrExposesFileName(options.filename);
10043
10402
  let ssrOutputFiles = /* @__PURE__ */ new Set();
10044
10403
  let ssrOutputDir = "";
10045
10404
  let clientOutputDir = "";
10046
- const ssrOnlyExternals = [
10405
+ const mfRuntimePackages = [
10047
10406
  "@module-federation/runtime",
10048
10407
  "@module-federation/runtime-core",
10049
- "@module-federation/sdk",
10050
- ...options.ssrExternals ?? []
10408
+ "@module-federation/sdk"
10051
10409
  ];
10410
+ const ssrOnlyExternals = [...mfRuntimePackages, ...options.ssrExternals ?? []];
10052
10411
  const ssrOnlyExternalPattern = new RegExp(`^(${ssrOnlyExternals.map((e) => e.replace(/[/\\^$*+?.()|[\]{}]/g, "\\$&")).join("|")})(\\/.*)?$`);
10412
+ let noExternal;
10413
+ const isNoExternal = (id) => {
10414
+ const pkg = ssrOnlyExternalPattern.exec(id)?.[1] ?? id;
10415
+ if (!noExternal || !mfRuntimePackages.includes(pkg)) return false;
10416
+ if (noExternal === true) return true;
10417
+ return (Array.isArray(noExternal) ? noExternal : [noExternal]).some((rule) => typeof rule === "string" ? rule === pkg : rule.test(pkg));
10418
+ };
10053
10419
  const ssrModuleIds = /* @__PURE__ */ new Set([remoteEntrySSRId, virtualExposesSSRId]);
10054
10420
  const resolvedAbsToPackage = /* @__PURE__ */ new Map();
10055
10421
  let isServe = false;
@@ -10080,7 +10446,9 @@ function pluginSSRRemoteEntry(options) {
10080
10446
  enforce: "pre",
10081
10447
  configResolved(config) {
10082
10448
  isServe = config.command === "serve";
10449
+ noExternal = config.environments?.ssr?.resolve?.noExternal ?? config.ssr?.noExternal;
10083
10450
  for (const pkg of ssrOnlyExternals) {
10451
+ if (isNoExternal(pkg)) continue;
10084
10452
  const aliasEntry = (config.resolve?.alias)?.find((a) => a.find === pkg || a.find instanceof RegExp && a.find.test(pkg));
10085
10453
  if (aliasEntry?.replacement) resolvedAbsToPackage.set(aliasEntry.replacement, pkg);
10086
10454
  }
@@ -10089,7 +10457,7 @@ function pluginSSRRemoteEntry(options) {
10089
10457
  if (id === remoteEntrySSRId || id.startsWith(remoteEntrySSRId)) return id;
10090
10458
  if (id === virtualExposesSSRId || id.startsWith(virtualExposesSSRId)) return id;
10091
10459
  if (!importer || !ssrModuleIds.has(importer)) return;
10092
- if (ssrOnlyExternalPattern.test(id)) return {
10460
+ if (ssrOnlyExternalPattern.test(id) && !isNoExternal(id)) return {
10093
10461
  id,
10094
10462
  external: true
10095
10463
  };
@@ -10114,7 +10482,7 @@ function pluginSSRRemoteEntry(options) {
10114
10482
  configureServer(server) {
10115
10483
  const base = "/__mf_ssr__";
10116
10484
  const basePath = getBasePath$1(viteConfig?.base);
10117
- const ssrEntryFileName = getSsrRemoteEntryFileName(options.filename);
10485
+ const ssrEntryFileName = getSsrRemoteEntryFileName(options);
10118
10486
  if (isNuxtProject || isNuxtClientBase(basePath)) server.middlewares.use((req, _res, next) => {
10119
10487
  if (req.url?.replace(/\?.*/, "") === `${basePath}/${ssrEntryFileName}`) req.url = `${basePath}/__mf_ssr__/${ssrEntryFileName}`;
10120
10488
  next();
@@ -10183,7 +10551,7 @@ function pluginSSRRemoteEntry(options) {
10183
10551
  resolveId(id) {
10184
10552
  if (id === remoteEntrySSRId || id.startsWith(remoteEntrySSRId)) return id;
10185
10553
  if (id === virtualExposesSSRId || id.startsWith(virtualExposesSSRId)) return id;
10186
- if (id === `/__mf_ssr__/${getSsrRemoteEntryFileName(options.filename)}`) return remoteEntrySSRId;
10554
+ if (id === `/__mf_ssr__/${getSsrRemoteEntryFileName(options)}`) return remoteEntrySSRId;
10187
10555
  if (id === `/__mf_ssr__/${ssrExposesFileName}`) return virtualExposesSSRId;
10188
10556
  },
10189
10557
  load(id) {
@@ -10388,6 +10756,85 @@ var aliasToArrayPlugin_default = {
10388
10756
  }
10389
10757
  };
10390
10758
  //#endregion
10759
+ //#region src/utils/deferredPrebuildHelper.ts
10760
+ function isExportAllHelper(code, exportName) {
10761
+ try {
10762
+ const ast = parseAst(code);
10763
+ let localName;
10764
+ for (const node of ast.body) {
10765
+ if (node.type !== "ExportNamedDeclaration") continue;
10766
+ for (const specifier of node.specifiers) if (specifier.type === "ExportSpecifier" && specifier.exported.type === "Identifier" && specifier.exported.name === exportName && specifier.local.type === "Identifier") localName = specifier.local.name;
10767
+ }
10768
+ if (!localName) return false;
10769
+ for (const node of ast.body) {
10770
+ if (node.type !== "VariableDeclaration") continue;
10771
+ for (const declaration of node.declarations) {
10772
+ if (declaration.id.type !== "Identifier" || declaration.id.name !== localName) continue;
10773
+ const initializer = declaration.init;
10774
+ if (!initializer) return false;
10775
+ const source = code.slice(initializer.start, initializer.end);
10776
+ return source.includes("Symbol.toStringTag") && source.includes("Module");
10777
+ }
10778
+ }
10779
+ } catch {}
10780
+ return false;
10781
+ }
10782
+ /**
10783
+ * Rolldown sometimes places its shared namespace helper in a local prebuild
10784
+ * chunk. A loadShare wrapper then imports that helper statically, evaluating the
10785
+ * fallback even when a host provider is already in the cache. Inline only the
10786
+ * recognized Rolldown helper; leave every other prebuild import untouched.
10787
+ */
10788
+ function inlineDeferredPrebuildNamespaceHelper(bundle) {
10789
+ for (const chunk of Object.values(bundle)) {
10790
+ if (chunk.type !== "chunk" || !chunk.fileName.includes("__loadShare__")) continue;
10791
+ let ast;
10792
+ try {
10793
+ ast = parseAst(chunk.code);
10794
+ } catch {
10795
+ continue;
10796
+ }
10797
+ const edits = [];
10798
+ const deferredSources = /* @__PURE__ */ new Set();
10799
+ forEachAstNode(ast, (node) => {
10800
+ if (node.type !== "ImportExpression") return;
10801
+ const source = getModuleSource(node.source);
10802
+ if (source) deferredSources.add(source);
10803
+ });
10804
+ const retainedImports = /* @__PURE__ */ new Set();
10805
+ const removedImports = /* @__PURE__ */ new Set();
10806
+ for (const node of ast.body) {
10807
+ if (node.type !== "ImportDeclaration") continue;
10808
+ const source = getModuleSource(node.source);
10809
+ if (!source) continue;
10810
+ const targetName = path.posix.normalize(path.posix.join(path.posix.dirname(chunk.fileName), source));
10811
+ const [specifier] = node.specifiers;
10812
+ const exported = specifier?.type === "ImportSpecifier" && specifier.imported;
10813
+ const target = bundle[targetName];
10814
+ if (!source.includes("__prebuild__") || node.specifiers.length !== 1 || !exported || exported.type !== "Identifier" || target?.type !== "chunk" || !deferredSources.has(source) || !Object.keys(target.modules ?? {}).some((id) => id.includes("rolldown/runtime.js")) || !isExportAllHelper(target.code, exported.name)) {
10815
+ retainedImports.add(targetName);
10816
+ continue;
10817
+ }
10818
+ removedImports.add(targetName);
10819
+ edits.push({
10820
+ start: node.start,
10821
+ end: node.end,
10822
+ replacement: `const ${specifier.local.name} = (all, noSymbols) => {
10823
+ const namespace = {};
10824
+ for (const name in all) Object.defineProperty(namespace, name, {
10825
+ get: all[name], enumerable: true,
10826
+ });
10827
+ if (!noSymbols) Object.defineProperty(namespace, Symbol.toStringTag, { value: 'Module' });
10828
+ return namespace;
10829
+ };`
10830
+ });
10831
+ }
10832
+ if (edits.length === 0) continue;
10833
+ for (const edit of edits.reverse()) chunk.code = chunk.code.slice(0, edit.start) + edit.replacement + chunk.code.slice(edit.end);
10834
+ if (chunk.imports) chunk.imports = chunk.imports.filter((imported) => !removedImports.has(imported) || retainedImports.has(imported));
10835
+ }
10836
+ }
10837
+ //#endregion
10391
10838
  //#region src/utils/controlChunkSanitizer.ts
10392
10839
  const FEDERATION_CONTROL_CHUNK_HINTS = ["hostInit", "localSharedImportMap"];
10393
10840
  function stripEmptyPreloadCalls(code) {
@@ -10605,7 +11052,7 @@ function isFederationHtmlPreloadDependency(dep, includeSharedRuntime = false) {
10605
11052
  }
10606
11053
  function canResolveSharedSubpath(subpath, projectRoot) {
10607
11054
  try {
10608
- return isViteOptimizableEntry(createRequire$1(pathToFileURL(path$1.join(projectRoot, "package.json"))).resolve(subpath));
11055
+ return isViteOptimizableEntry(resolveModulePath(subpath, path$1.join(projectRoot, "package.json")));
10609
11056
  } catch (error) {
10610
11057
  if (error?.code === "ERR_PACKAGE_PATH_NOT_EXPORTED" && !isBarePackageSubpath(subpath)) {
10611
11058
  const entry = resolveViteImportPackageEntry(subpath, projectRoot);
@@ -10788,17 +11235,20 @@ function registerEntryImports(options, projectRoot, recordShared = true, entryFi
10788
11235
  addUsedRemote(remoteKey, request, options);
10789
11236
  markStaticRemote(request, options);
10790
11237
  markPreloadRemote(request, options);
10791
- } else if (sharedKey && recordShared) addUsedShares(request, options);
11238
+ } else if (sharedKey && recordShared) materializeSharedRequest(options, request);
10792
11239
  else if (request && !typeOnly) enqueue(request, file, preloadRemotes && isStatic);
10793
11240
  }
10794
11241
  }
10795
11242
  return hasJsxSource;
10796
11243
  }
11244
+ function materializeSharedRequest(options, request) {
11245
+ addUsedShares(request, options);
11246
+ const packageName = getPackageName(request);
11247
+ if (packageName !== request && findSharedKey(packageName, options.shared)) addUsedShares(packageName, options);
11248
+ }
10797
11249
  function materializeAutomaticJsxRuntime(options, runtime) {
10798
11250
  if (!findSharedKey(runtime, options.shared)) return false;
10799
- addUsedShares(runtime, options);
10800
- const packageName = getPackageName(runtime);
10801
- if (packageName !== runtime && findSharedKey(packageName, options.shared)) addUsedShares(packageName, options);
11251
+ materializeSharedRequest(options, runtime);
10802
11252
  return true;
10803
11253
  }
10804
11254
  /**
@@ -10843,11 +11293,21 @@ function createEarlyVirtualModulesPlugin(options) {
10843
11293
  config.optimizeDeps = config.optimizeDeps || {};
10844
11294
  config.optimizeDeps.include = config.optimizeDeps.include || [];
10845
11295
  const optimizeDeps = config.optimizeDeps;
11296
+ const preparedShares = /* @__PURE__ */ new Map();
11297
+ const writeSharedModules = (source, shareItem) => {
11298
+ if (preparedShares.get(source) === shareItem) return;
11299
+ writeLoadShareModule(source, shareItem, _command, isRolldown, options);
11300
+ if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(source, shareItem, options);
11301
+ preparedShares.set(source, shareItem);
11302
+ };
10846
11303
  if (isRolldown) {
10847
11304
  optimizeDeps.rolldownOptions ??= {};
10848
11305
  optimizeDeps.rolldownOptions.plugins ??= [];
10849
11306
  optimizeDeps.rolldownOptions.plugins.push({
10850
11307
  name: "module-federation:optimize-shared-resolver",
11308
+ buildStart() {
11309
+ preparedShares.clear();
11310
+ },
10851
11311
  load(id) {
10852
11312
  if (!id.startsWith("module-federation:optimized-require-")) return;
10853
11313
  const sourcePackage = id.slice(36);
@@ -10875,13 +11335,11 @@ function createEarlyVirtualModulesPlugin(options) {
10875
11335
  if (isCommonJsImporter(importer) && !isReactSingleton && !isReactDomRequire) return;
10876
11336
  if (resolveOptions?.kind !== "entry-point") addUsedShares(source, options);
10877
11337
  if (isReactRequire || isReactDomRequire) {
10878
- writeLoadShareModule(source, shareItem, _command, isRolldown, options);
10879
- if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(source, shareItem, options);
11338
+ writeSharedModules(source, shareItem);
10880
11339
  return { id: `module-federation:optimized-require-${source}` };
10881
11340
  }
10882
11341
  const loadSharePath = getLoadShareModulePath(source, isRolldown, options);
10883
- writeLoadShareModule(source, shareItem, _command, isRolldown, options);
10884
- if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(source, shareItem, options);
11342
+ writeSharedModules(source, shareItem);
10885
11343
  return {
10886
11344
  id: loadSharePath,
10887
11345
  external: true
@@ -10894,6 +11352,9 @@ function createEarlyVirtualModulesPlugin(options) {
10894
11352
  optimizeDeps.esbuildOptions.plugins.push({
10895
11353
  name: "module-federation:optimize-shared-proxy",
10896
11354
  setup(build) {
11355
+ build.onStart(() => {
11356
+ preparedShares.clear();
11357
+ });
10897
11358
  build.onResolve({ filter: createViteEncodedIdPrefixRegExp("virtual:mf:") }, (args) => ({
10898
11359
  path: args.path,
10899
11360
  external: true
@@ -10911,8 +11372,7 @@ function createEarlyVirtualModulesPlugin(options) {
10911
11372
  if (args.kind === "import-statement" || args.kind === "dynamic-import") {
10912
11373
  const shareItem = shared[key];
10913
11374
  const loadSharePath = getLoadShareModulePath(args.path, isRolldown, options);
10914
- writeLoadShareModule(args.path, shareItem, _command, isRolldown, options);
10915
- if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(args.path, shareItem, options);
11375
+ writeSharedModules(args.path, shareItem);
10916
11376
  return {
10917
11377
  path: loadSharePath,
10918
11378
  external: true
@@ -10931,8 +11391,7 @@ function createEarlyVirtualModulesPlugin(options) {
10931
11391
  if (!key) return;
10932
11392
  const shareItem = shared[key];
10933
11393
  const loadSharePath = getLoadShareModulePath(args.path, isRolldown, options);
10934
- writeLoadShareModule(args.path, shareItem, _command, isRolldown, options);
10935
- if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(args.path, shareItem, options);
11394
+ writeSharedModules(args.path, shareItem);
10936
11395
  return {
10937
11396
  loader: "js",
10938
11397
  resolveDir: root,
@@ -10947,12 +11406,14 @@ export default __mfShared.default ?? __mfShared;`
10947
11406
  }
10948
11407
  for (const key of Object.keys(shared)) {
10949
11408
  const shareItem = shared[key];
10950
- if (key.endsWith("/")) {
11409
+ const request = getSharedRequest(key, shareItem);
11410
+ const runtimeKey = getSharedRuntimeKey(key, shareItem);
11411
+ if (key.endsWith("/") || request.endsWith("/") || runtimeKey.endsWith("/")) {
10951
11412
  if (_command === "serve" && shareItem.shareConfig?.import !== false) {
10952
11413
  const optimizeDeps = config.optimizeDeps ??= {};
10953
11414
  optimizeDeps.include ??= [];
10954
11415
  optimizeDeps.exclude ??= [];
10955
- for (const subpath of getCommonSharedSubpaths(key)) {
11416
+ for (const subpath of getCommonSharedSubpaths(request)) {
10956
11417
  writePreBuildLibPath(subpath, shareItem, options);
10957
11418
  if (canResolveSharedSubpath(subpath, root)) optimizeDeps.include.push(subpath);
10958
11419
  else optimizeDeps.exclude.push(subpath);
@@ -10960,23 +11421,24 @@ export default __mfShared.default ?? __mfShared;`
10960
11421
  }
10961
11422
  continue;
10962
11423
  }
10963
- if (isVinext && key === "react") {
10964
- addConfiguredShare(key, options);
11424
+ if (isVinext && runtimeKey === "react") {
11425
+ addConfiguredShare(runtimeKey, options);
10965
11426
  continue;
10966
11427
  }
10967
- getLoadShareModulePath(key, isRolldown, options);
10968
- writeLoadShareModule(key, shareItem, _command, isRolldown, options);
10969
- if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(key, shareItem, options);
10970
- addConfiguredShare(key, options);
11428
+ getLoadShareModulePath(runtimeKey, isRolldown, options);
11429
+ writeLoadShareModule(runtimeKey, shareItem, _command, isRolldown, options);
11430
+ if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(runtimeKey, shareItem, options);
11431
+ addConfiguredShare(runtimeKey, options);
10971
11432
  if (_command === "serve" && shareItem.shareConfig?.import !== false) {
10972
11433
  const optimizeDeps = config.optimizeDeps ??= {};
10973
11434
  optimizeDeps.include ??= [];
10974
11435
  optimizeDeps.exclude ??= [];
10975
- const shouldBypassOptimizeDep = isLitShare(key) || !canResolveSharedSubpath(key, root);
10976
- if (optimizeDeps.include.includes(key)) optimizeDeps.exclude = optimizeDeps.exclude.filter((dep) => dep !== key);
10977
- else if (shouldBypassOptimizeDep || optimizeDeps.exclude.includes(key)) optimizeDeps.exclude.push(key);
10978
- else optimizeDeps.include.push(key);
10979
- for (const subpath of getCommonSharedSubpaths(key)) {
11436
+ const shouldBypassOptimizeDep = isLitShare(runtimeKey) || !canResolveSharedSubpath(runtimeKey, root);
11437
+ if (optimizeDeps.include.includes(runtimeKey)) optimizeDeps.exclude = optimizeDeps.exclude.filter((dep) => dep !== runtimeKey);
11438
+ else if (shouldBypassOptimizeDep || optimizeDeps.exclude.includes(runtimeKey)) optimizeDeps.exclude.push(runtimeKey);
11439
+ else optimizeDeps.include.push(runtimeKey);
11440
+ const commonSubpaths = shareItem.shareConfig.request === void 0 && shareItem.shareConfig.shareKey === void 0 ? getCommonSharedSubpaths(runtimeKey) : [];
11441
+ for (const subpath of commonSubpaths) {
10980
11442
  const canResolveSubpath = canResolveSharedSubpath(subpath, root);
10981
11443
  if ([
10982
11444
  "react/compiler-runtime",
@@ -10992,7 +11454,7 @@ export default __mfShared.default ?? __mfShared;`
10992
11454
  addConfiguredShare(subpath, options);
10993
11455
  if (canResolveSubpath) {
10994
11456
  optimizeDeps.include.push(subpath);
10995
- if (key === "react-dom") optimizeDeps.include.push(`${key} > ${subpath}`);
11457
+ if (runtimeKey === "react-dom") optimizeDeps.include.push(`${runtimeKey} > ${subpath}`);
10996
11458
  } else optimizeDeps.exclude.push(subpath);
10997
11459
  }
10998
11460
  }
@@ -11010,10 +11472,8 @@ export default __mfShared.default ?? __mfShared;`
11010
11472
  const automaticJsxRuntime = getAutomaticJsxRuntime(config);
11011
11473
  if (automaticJsxRuntime && materializeAutomaticJsxRuntime(options, automaticJsxRuntime)) writeLocalSharedImportMap(options);
11012
11474
  }
11013
- if (!getSsrCapabilities(parseInt(version, 10), config.command, hasRemotes(options)).injectSsrEntryLoader) return;
11014
- if (options.runtimePlugins.some((p) => {
11015
- return (typeof p === "string" ? p : p[0]) === "@module-federation/vite/ssrEntryLoader";
11016
- })) return;
11475
+ if (!getSsrCapabilities(parseInt(version, 10), config.command, hasRemotes(options), isSsrConfig(config)).injectSsrEntryLoader) return;
11476
+ if (options.runtimePlugins.some((p) => getRuntimePluginSpecifier(p) === "@module-federation/vite/ssrEntryLoader")) return;
11017
11477
  const projectRequire = createRequire$1(pathToFileURL(path$1.join(config.root, "package.json")));
11018
11478
  const sharedKeys = Object.keys(options.shared ?? {});
11019
11479
  const commonSharedPkgs = [
@@ -11056,16 +11516,14 @@ function applyBuildTimeRuntimeDefines(define, options, { target, isAstro, defaul
11056
11516
  }
11057
11517
  function loadPluginDts(options) {
11058
11518
  if (options.dts === false) return [];
11059
- return [import("./pluginDts-CQ088qGF.js").then(({ default: pluginDts }) => pluginDts(options))];
11519
+ return [import("./pluginDts-DxgS2FEd.js").then(({ default: pluginDts }) => pluginDts(options))];
11060
11520
  }
11061
11521
  const INJECT_EXTERNAL_RUNTIME_CORE_PLUGIN = "@module-federation/vite/injectExternalRuntimeCorePlugin";
11062
11522
  function isInjectExternalRuntimeCorePlugin(specifier) {
11063
11523
  return specifier === INJECT_EXTERNAL_RUNTIME_CORE_PLUGIN || specifier.includes("injectExternalRuntimeCorePlugin") || specifier.includes("inject-external-runtime-core-plugin");
11064
11524
  }
11065
11525
  function hasInjectExternalRuntimeCorePlugin(runtimePlugins) {
11066
- return runtimePlugins.some((plugin) => {
11067
- return isInjectExternalRuntimeCorePlugin(typeof plugin === "string" ? plugin : plugin[0]);
11068
- });
11526
+ return runtimePlugins.some((plugin) => isInjectExternalRuntimeCorePlugin(getRuntimePluginSpecifier(plugin)));
11069
11527
  }
11070
11528
  function resolveInjectExternalRuntimeCorePlugin() {
11071
11529
  try {
@@ -11112,7 +11570,7 @@ function federation(mfUserOptions) {
11112
11570
  const emittedRuntimeCapabilityWarnings = /* @__PURE__ */ new Set();
11113
11571
  const getLoadHookExportConditions = (context, loadOptions) => {
11114
11572
  const environment = context.environment;
11115
- const isSsr = loadOptions?.ssr === true || isSsrBuild || environment?.config?.consumer === "server" || Boolean(environment?.config?.build?.ssr) || environment?.name === "ssr" || environment?.name === "server";
11573
+ const isSsr = loadOptions?.ssr === true || isSsrBuild || isServerEnvironment(environment?.name, environment?.config);
11116
11574
  return getSharedExportConditions({
11117
11575
  environmentConditions: environment?.config?.resolve?.conditions,
11118
11576
  isProduction: environment?.config?.isProduction ?? isProduction,
@@ -11236,7 +11694,7 @@ function federation(mfUserOptions) {
11236
11694
  ssrResolveConditions = config.ssr?.resolve?.conditions ? [...config.ssr.resolve.conditions] : void 0;
11237
11695
  ssrTarget = config.ssr?.target ?? "node";
11238
11696
  isProduction = config.isProduction;
11239
- const ssrCapabilities = getSsrCapabilities(parseInt(version, 10), command, Object.keys(options.remotes).length > 0);
11697
+ const ssrCapabilities = getSsrCapabilities(parseInt(version, 10), command, Object.keys(options.remotes).length > 0, isSsrConfig(config));
11240
11698
  resolveSharedVersions(shared, config.root);
11241
11699
  initVirtualModules(command, remoteEntryId, ssrCapabilities.enableSsrInitBootstrap, options);
11242
11700
  }
@@ -11286,6 +11744,7 @@ function federation(mfUserOptions) {
11286
11744
  federationOptions: options,
11287
11745
  getParsePromise: () => moduleParseController.parsePromise
11288
11746
  }),
11747
+ pluginLazyConsumeOnlyShares(options),
11289
11748
  {
11290
11749
  name: "module-federation-esm-shims",
11291
11750
  enforce: "pre",
@@ -11337,6 +11796,7 @@ function federation(mfUserOptions) {
11337
11796
  priority: USER_GROUP_MAX_PRIORITY
11338
11797
  };
11339
11798
  };
11799
+ const federationGroupDebugName = supportsCodeSplittingGroupDebugName(this) ? { debugName: "module-federation" } : {};
11340
11800
  let warnedAboutManualChunks = false;
11341
11801
  let warnedAboutObjectManualChunks = false;
11342
11802
  const applyManualChunks = (output, useCodeSplitting) => {
@@ -11344,11 +11804,13 @@ function federation(mfUserOptions) {
11344
11804
  const isPatchedByPlugin = typeof output.manualChunks === "function" && patchedManualChunks.has(output.manualChunks);
11345
11805
  const mfChunkName = function(id) {
11346
11806
  if (id.includes(runtimeInitId) || id.includes("__mf_v__runtimeInit__mf_v__")) return "runtimeInit";
11807
+ if (isSharedCacheHelpersId(id)) return getSharedChunkName(id);
11347
11808
  if (id.includes("__loadShare__")) {
11348
11809
  const pkg = getCachedLoadSharePkg(id);
11349
11810
  const key = pkg && findSharedKey(pkg, shared);
11350
11811
  if (key && shared[key].shareConfig.eager === true) return "loadShare-eager";
11351
11812
  if (key && shared[key].shareConfig.import === false) return null;
11813
+ if (pkg && !id.includes("commonjs-proxy") && isCoalescableLoadShareWrapper(pkg, options, id)) return getSharedChunkName(id);
11352
11814
  const match = id.match(/([^/\\]+__loadShare__[^/\\]+)/);
11353
11815
  return match ? match[1] : "loadShare";
11354
11816
  }
@@ -11385,7 +11847,8 @@ function federation(mfUserOptions) {
11385
11847
  };
11386
11848
  const mfNameGroup = {
11387
11849
  name: mfChunkName,
11388
- priority: MF_GROUP_PRIORITY
11850
+ priority: MF_GROUP_PRIORITY,
11851
+ ...federationGroupDebugName
11389
11852
  };
11390
11853
  federationGroups.add(mfPreloadGroup);
11391
11854
  federationGroups.add(mfNameGroup);
@@ -11458,7 +11921,14 @@ function federation(mfUserOptions) {
11458
11921
  if (!virtualModule?.code) return null;
11459
11922
  let code = virtualModule.code;
11460
11923
  const consumerTarget = resolveEnvironmentConsumerTarget(this);
11461
- if (consumerTarget === "server" || !consumerTarget && isSsrBuild) code = prependWorkspaceSingletonSsrImport(code);
11924
+ if (consumerTarget === "server" || !consumerTarget && isSsrBuild) {
11925
+ const withSsrImport = prependWorkspaceSingletonSsrImport(code);
11926
+ if (withSsrImport !== code) {
11927
+ const pkg = getCachedLoadSharePkg(id);
11928
+ if (pkg) markLoadShareWrapperNotCoalescable(pkg, options, id);
11929
+ code = withSsrImport;
11930
+ }
11931
+ }
11462
11932
  code = code.replace(/import\s+["'][^"']*__prebuild__[^"']*["']\s*;?/g, "");
11463
11933
  code = code.replace(/export\s+\*\s+from\s+["'][^"']*__prebuild__[^"']*["']\s*;?/g, "");
11464
11934
  if (!(/\b(?:var|let|const)\s+__moduleExports\b/.test(code) || /\bexport\s+const\s+__moduleExports\b/.test(code) || /\bexport\s*\{[^}]*__moduleExports/.test(code))) {
@@ -11476,6 +11946,9 @@ function federation(mfUserOptions) {
11476
11946
  return loadVirtualModule();
11477
11947
  },
11478
11948
  generateBundle(_outputOptions, bundle, _isWrite) {
11949
+ inlineDeferredPrebuildNamespaceHelper(bundle);
11950
+ for (const [fileName, fallbacks] of findEagerFallbacksInSharedChunk(bundle)) mfWarn(`A shared-dependency fallback was merged into the loadShare chunk ${fileName}: ${fallbacks.join(", ")}.\n That fallback is no longer lazy, so consumers download their local copy even when a peer provides the share, and the container can deadlock.
11951
+ Stop the shared module from statically importing another share.`);
11479
11952
  for (const [fileName, chunk] of Object.entries(bundle)) {
11480
11953
  if (!isOutputChunk(chunk)) continue;
11481
11954
  if (!isFederationControlChunk(fileName, filename)) continue;
@@ -11541,7 +12014,7 @@ function federation(mfUserOptions) {
11541
12014
  config.optimizeDeps.include.push("@module-federation/runtime");
11542
12015
  if (needsRuntimeHelpers) config.optimizeDeps.include.push("@module-federation/runtime/helpers");
11543
12016
  options.runtimePlugins.forEach((p) => {
11544
- const pluginPath = typeof p === "string" ? p : p[0];
12017
+ const pluginPath = getRuntimePluginSpecifier(p);
11545
12018
  if (SSR_ONLY_RUNTIME_PLUGINS.has(pluginPath)) return;
11546
12019
  if (pluginPath && !pluginPath.startsWith(".") && !pluginPath.startsWith("/") && !pluginPath.startsWith("\0") && !pluginPath.startsWith("virtual:")) {
11547
12020
  let optimizeDep = pluginPath;
@@ -11557,6 +12030,14 @@ function federation(mfUserOptions) {
11557
12030
  config.build ??= {};
11558
12031
  config.build.target ??= "esnext";
11559
12032
  }
12033
+ const isBundledDev = Boolean(config.experimental?.bundledDev);
12034
+ if (isRolldown && _command === "serve" && isBundledDev) {
12035
+ config.build.rolldownOptions ??= {};
12036
+ config.build.rolldownOptions.experimental ??= {};
12037
+ const devMode = config.build.rolldownOptions.experimental.devMode;
12038
+ if (typeof devMode === "object") devMode.lazy ??= false;
12039
+ else if (devMode === void 0) config.build.rolldownOptions.experimental.devMode = { lazy: false };
12040
+ }
11560
12041
  const isAstro = hasPackageDependency("astro");
11561
12042
  const resolvedTarget = options.target ?? (config.build?.ssr ? "node" : "web");
11562
12043
  if (!config.define) config.define = {};
@@ -11577,7 +12058,7 @@ function federation(mfUserOptions) {
11577
12058
  if (prematureExit) prematureExit.closeBundle = void 0;
11578
12059
  },
11579
12060
  configEnvironment(name, config) {
11580
- if (!(config.consumer === "server" || name === "ssr" || name === "server" || config.build?.ssr === true)) return;
12061
+ if (!isServerEnvironment(name, config)) return;
11581
12062
  const isAstro = hasPackageDependency("astro");
11582
12063
  config.define = { ...config.define ?? {} };
11583
12064
  applyBuildTimeRuntimeDefines(config.define, options, {