@module-federation/vite 1.22.1 → 1.23.0

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";
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
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";
3
+ import { C as isReactCoreShare, E as mfWarn, 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, w as createModuleFederationError, x as REACT_CLIENT_INTERNALS_KEY, y as sharedCacheHelperCode } from "./dtsConstants-DEMpRfBz.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";
@@ -400,6 +401,16 @@ function resolveEnvironmentConsumerTarget(ctx) {
400
401
  function isClientEnvironment(ctx) {
401
402
  return resolveEnvironmentConsumerTarget(ctx) !== "server";
402
403
  }
404
+ /**
405
+ * Whether a build hook runs for a server graph. Vite 6+ hooks carry an
406
+ * environment; Vite 5 (and hooks invoked before `configResolved`) fall back to
407
+ * the legacy root `build.ssr` flag.
408
+ */
409
+ function isServerBuildContext(ctx, config) {
410
+ const target = resolveEnvironmentConsumerTarget(ctx);
411
+ if (target) return target === "server";
412
+ return Boolean(config?.build?.ssr);
413
+ }
403
414
  function resolveRemoteConsumer(ctx, hasMultiEnvironment) {
404
415
  if (!hasMultiEnvironment) return "unified";
405
416
  return resolveEnvironmentConsumerTarget(ctx) ?? "client";
@@ -862,6 +873,11 @@ function normalizeShareItem(key, shareItem) {
862
873
  const treeShaking = typeof shareItem === "object" ? shareItem.treeShaking : void 0;
863
874
  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
875
  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.`);
876
+ if (typeof shareItem === "object") {
877
+ const request = typeof shareItem.request === "string" ? shareItem.request : key;
878
+ const shareKey = typeof shareItem.shareKey === "string" ? shareItem.shareKey : key;
879
+ 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}".`);
880
+ }
865
881
  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
882
  const config = typeof shareItem === "object" ? shareItem : {};
867
883
  const { version, requiredVersion } = resolveSharedVersion(key, config, getPackageDetectionCwd());
@@ -892,6 +908,9 @@ function normalizeShareItem(key, shareItem) {
892
908
  eager: shareItem.eager || false,
893
909
  requiredVersion,
894
910
  strictVersion: !!shareItem.strictVersion,
911
+ ...shareItem.request !== void 0 ? { request: shareItem.request } : {},
912
+ ...shareItem.shareKey !== void 0 ? { shareKey: shareItem.shareKey } : {},
913
+ ...shareItem.allowNodeModulesSuffixMatch !== void 0 ? { allowNodeModulesSuffixMatch: shareItem.allowNodeModulesSuffixMatch } : {},
895
914
  ...shareItem.suppressMissingImportWarning ? { suppressMissingImportWarning: true } : {},
896
915
  ...treeShaking ? { treeShaking: { ...treeShaking } } : {}
897
916
  }
@@ -941,7 +960,8 @@ function normalizeShared(shared) {
941
960
  const value = shared[key];
942
961
  const hadConfiguredPackageSubpath = (result[normalizedKey]?.shareConfig)?.__mfConfiguredPackageSubpath === true;
943
962
  result[normalizedKey] = normalizeShareItem(normalizedKey, value);
944
- if (key.endsWith("/") || hadConfiguredPackageSubpath) result[normalizedKey].shareConfig.__mfConfiguredPackageSubpath = true;
963
+ const requestIsPrefix = typeof value?.request === "string" && value.request.endsWith("/");
964
+ if (key.endsWith("/") || requestIsPrefix || hadConfiguredPackageSubpath) result[normalizedKey].shareConfig.__mfConfiguredPackageSubpath = true;
945
965
  explicitSharedKeys.add(normalizedKey);
946
966
  sourceEntries.push([normalizedKey, value]);
947
967
  });
@@ -1018,7 +1038,12 @@ function isExplicitSharedKey(key, options) {
1018
1038
  }
1019
1039
  function getNormalizeShareItem(key, options = getNormalizeModuleFederationOptions()) {
1020
1040
  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) + "/"];
1041
+ const shareItem = options.shared[key] || (matchedKey ? options.shared[matchedKey] : void 0) || options.shared[getPackageName(key)] || options.shared[getPackageName(key) + "/"];
1042
+ if (shareItem) return shareItem;
1043
+ return Object.entries(options.shared).find(([sharedKey, item]) => {
1044
+ const runtimeKey = typeof item.shareConfig.shareKey === "string" ? item.shareConfig.shareKey : sharedKey;
1045
+ return runtimeKey.endsWith("/") ? key === runtimeKey.slice(0, -1) || key.startsWith(runtimeKey) : runtimeKey === key;
1046
+ })?.[1];
1022
1047
  }
1023
1048
  function normalizeModuleFederationOptions(options) {
1024
1049
  warnOnReservedInternalNamePrefix(options.name, "containerName");
@@ -1026,6 +1051,7 @@ function normalizeModuleFederationOptions(options) {
1026
1051
  const normalized = {
1027
1052
  exposes: normalizeExposes(options.exposes),
1028
1053
  filename: options.filename || "remoteEntry-[hash]",
1054
+ ssrFilename: options.ssrFilename || void 0,
1029
1055
  internalName: toInternalModuleFederationName(options.name),
1030
1056
  library: normalizeLibrary(options.library),
1031
1057
  name: options.name,
@@ -1131,6 +1157,10 @@ var VirtualModule = class VirtualModule {
1131
1157
  if (!cacheMap[this.tag]) cacheMap[this.tag] = {};
1132
1158
  cacheMap[this.tag][this.name] = this;
1133
1159
  }
1160
+ /** The federation scope this module was created under, if it was scoped. */
1161
+ getScopeName() {
1162
+ return this.scopeName;
1163
+ }
1134
1164
  getImportId() {
1135
1165
  const mfName = this.scopeName ?? getNormalizeModuleFederationOptions().internalName;
1136
1166
  const importIdKey = `${mfName}${this.tag}${this.name}${this.tag}`;
@@ -1162,17 +1192,38 @@ const SERVER_ENV_GUARD = "import.meta.env.SSR";
1162
1192
  const SSR_ENTRY_LOADER_SPECIFIER = "@module-federation/vite/ssrEntryLoader";
1163
1193
  const SSR_ONLY_RUNTIME_PLUGINS = /* @__PURE__ */ new Set([SSR_ENTRY_LOADER_SPECIFIER]);
1164
1194
  /**
1195
+ * Whether a Vite environment builds a server graph.
1196
+ *
1197
+ * Vite 6+ sets `consumer` on the environment config; `build.ssr` covers the
1198
+ * legacy `vite build --ssr` flag. Environment names are user-defined, so `ssr`
1199
+ * and `server` are only a fallback for configs that carry neither field.
1200
+ */
1201
+ function isServerEnvironment(name, config) {
1202
+ return config?.consumer === "server" || Boolean(config?.build?.ssr) || name === "ssr" || name === "server";
1203
+ }
1204
+ /**
1205
+ * Whether a resolved Vite config includes a server graph: the legacy
1206
+ * `build.ssr` flag, or any server environment. Vite always registers an `ssr`
1207
+ * environment for `serve`, so this only gates builds.
1208
+ */
1209
+ function isSsrConfig(config) {
1210
+ if (Boolean(config.build?.ssr)) return true;
1211
+ return Object.entries(config.environments ?? {}).some(([name, environment]) => isServerEnvironment(name, environment));
1212
+ }
1213
+ /**
1165
1214
  * Single source of truth for SSR-related feature gates.
1166
1215
  *
1167
- * - Vite 8+ dev: ModuleRunner + FetchableDevEnvironment for `/__mf_ssr__/` entries.
1168
- * - Any Vite major on build/preview: HTTP fetch + temp-file import via ssrEntryLoader.
1216
+ * - Vite 8+ server environments: ModuleRunner + FetchableDevEnvironment for
1217
+ * `/__mf_ssr__/` entries.
1218
+ * - SSR builds on any Vite major: HTTP fetch + temp-file import via
1219
+ * ssrEntryLoader.
1169
1220
  */
1170
- function getSsrCapabilities(viteMajor, command, hasRemotes) {
1221
+ function getSsrCapabilities(viteMajor, command, hasRemotes, isSsr = false) {
1171
1222
  if (!hasRemotes) return {
1172
1223
  enableSsrInitBootstrap: false,
1173
1224
  injectSsrEntryLoader: false
1174
1225
  };
1175
- const supported = command === "build" || command === "serve" && viteMajor >= 8;
1226
+ const supported = isSsr && (command === "build" || command === "serve" && viteMajor >= 8);
1176
1227
  return {
1177
1228
  enableSsrInitBootstrap: supported,
1178
1229
  injectSsrEntryLoader: supported
@@ -1276,106 +1327,48 @@ function isParsableExpression(source) {
1276
1327
  }
1277
1328
  }
1278
1329
  //#endregion
1279
- //#region src/utils/treeShaking.ts
1280
- function shouldAnalyzeSharedExports(shareItem) {
1281
- return !!(shareItem && (shareItem.shareConfig.treeShaking || shareItem.shareConfig.import === false));
1330
+ //#region src/utils/runtimePluginSpecifier.ts
1331
+ function getRuntimePluginSpecifier(plugin) {
1332
+ return typeof plugin === "string" ? plugin : plugin[0];
1282
1333
  }
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;
1334
+ /** Drop SSR-only plugins from a client graph; a server graph keeps them all. */
1335
+ function filterRuntimePluginsForTarget(runtimePlugins, ssrOnlySpecifiers, isServer) {
1336
+ if (isServer) return [...runtimePlugins];
1337
+ return runtimePlugins.filter((plugin) => !ssrOnlySpecifiers.has(getRuntimePluginSpecifier(plugin)));
1348
1338
  }
1339
+ //#endregion
1340
+ //#region src/utils/importAnalysis.ts
1341
+ const analysisByBuild = /* @__PURE__ */ new WeakMap();
1349
1342
  /**
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.
1343
+ * Share source analysis within one build environment. Callers still resolve
1344
+ * requests and apply their own sharing configuration. Clear at buildStart and
1345
+ * buildEnd so watch rebuilds start fresh and completed builds release source.
1355
1346
  */
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" };
1347
+ function getImportAnalysis(build) {
1348
+ let analysis = analysisByBuild.get(build);
1349
+ if (!analysis) {
1350
+ const importsByCode = /* @__PURE__ */ new Map();
1351
+ analysis = {
1352
+ analyze(code) {
1353
+ const cached = importsByCode.get(code);
1354
+ if (cached !== void 0) return cached;
1355
+ const imports = analyzeImports(code);
1356
+ importsByCode.set(code, imports);
1357
+ return imports;
1358
+ },
1359
+ clear() {
1360
+ importsByCode.clear();
1361
+ }
1362
+ };
1363
+ analysisByBuild.set(build, analysis);
1364
+ }
1365
+ return analysis;
1372
1366
  }
1373
- function getTreeShakingExportUsage(request, shareItem, sharedKey, options) {
1374
- if (!shareItem?.shareConfig.treeShaking) return void 0;
1375
- return getSharedExportUsage(request, shareItem, sharedKey, options);
1367
+ function isRecord(value) {
1368
+ return value !== null && typeof value === "object";
1376
1369
  }
1377
1370
  function getModuleSource(node) {
1378
- if (!node || typeof node !== "object") return void 0;
1371
+ if (!isRecord(node)) return void 0;
1379
1372
  const source = node;
1380
1373
  if (source.type === "Literal" && typeof source.value === "string") return source.value;
1381
1374
  if (source.type === "StringLiteral" && typeof source.value === "string") return source.value;
@@ -1383,11 +1376,13 @@ function getModuleSource(node) {
1383
1376
  const expressions = Array.isArray(source.expressions) ? source.expressions : [];
1384
1377
  const quasis = Array.isArray(source.quasis) ? source.quasis : [];
1385
1378
  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;
1379
+ const quasi = quasis[0];
1380
+ if (!isRecord(quasi) || !isRecord(quasi.value)) return void 0;
1381
+ const value = quasi.value;
1382
+ return typeof value.cooked === "string" ? value.cooked : typeof value.raw === "string" ? value.raw : void 0;
1388
1383
  }
1389
1384
  function getExportedName(node) {
1390
- if (!node || typeof node !== "object") return void 0;
1385
+ if (!isRecord(node)) return void 0;
1391
1386
  const exported = node;
1392
1387
  if (exported.type === "Identifier" && typeof exported.name === "string") return exported.name;
1393
1388
  if ((exported.type === "Literal" || exported.type === "StringLiteral") && typeof exported.value === "string") return exported.value;
@@ -1400,7 +1395,7 @@ function forEachAstNode(root, visit) {
1400
1395
  const seen = /* @__PURE__ */ new Set();
1401
1396
  while (stack.length > 0) {
1402
1397
  const value = stack.pop();
1403
- if (!value || typeof value !== "object") continue;
1398
+ if (!isRecord(value)) continue;
1404
1399
  if (seen.has(value)) continue;
1405
1400
  seen.add(value);
1406
1401
  if (Array.isArray(value)) {
@@ -1414,18 +1409,22 @@ function forEachAstNode(root, visit) {
1414
1409
  });
1415
1410
  }
1416
1411
  }
1417
- function collectImportDeclaration(node, source, record, markUnsafe) {
1412
+ function collectImportDeclaration(node, source, record, requireAllExports) {
1418
1413
  if (isTypeOnly(node)) return;
1419
1414
  const specifiers = Array.isArray(node.specifiers) ? node.specifiers : [];
1420
1415
  if (specifiers.length === 0) {
1421
- markUnsafe(source);
1416
+ requireAllExports(source);
1422
1417
  return;
1423
1418
  }
1424
1419
  const names = [];
1425
1420
  for (const specifier of specifiers) {
1421
+ if (!isRecord(specifier)) {
1422
+ requireAllExports(source);
1423
+ return;
1424
+ }
1426
1425
  if (isTypeOnly(specifier)) continue;
1427
1426
  if (specifier.type === "ImportNamespaceSpecifier") {
1428
- markUnsafe(source);
1427
+ requireAllExports(source);
1429
1428
  return;
1430
1429
  }
1431
1430
  if (specifier.type === "ImportDefaultSpecifier") {
@@ -1434,118 +1433,246 @@ function collectImportDeclaration(node, source, record, markUnsafe) {
1434
1433
  }
1435
1434
  if (specifier.type === "ImportSpecifier") {
1436
1435
  const imported = specifier.imported;
1437
- if (imported?.type === "Literal" || imported?.type === "StringLiteral") {
1438
- markUnsafe(source);
1436
+ if (isRecord(imported) && (imported.type === "Literal" || imported.type === "StringLiteral")) {
1437
+ requireAllExports(source);
1439
1438
  return;
1440
1439
  }
1441
1440
  const name = getExportedName(specifier.imported);
1442
1441
  if (!name) {
1443
- markUnsafe(source);
1442
+ requireAllExports(source);
1444
1443
  return;
1445
1444
  }
1446
1445
  names.push(name);
1447
1446
  continue;
1448
1447
  }
1449
- markUnsafe(source);
1448
+ requireAllExports(source);
1450
1449
  return;
1451
1450
  }
1452
1451
  record(names, source);
1453
1452
  }
1454
- function collectReExport(node, source, record, markUnsafe) {
1453
+ function collectReExport(node, source, record, requireAllExports) {
1455
1454
  if (isTypeOnly(node)) return;
1456
1455
  if (node.type === "ExportAllDeclaration") {
1457
- markUnsafe(source);
1456
+ requireAllExports(source);
1458
1457
  return;
1459
1458
  }
1460
1459
  const specifiers = Array.isArray(node.specifiers) ? node.specifiers : [];
1461
1460
  if (specifiers.length === 0) {
1462
- markUnsafe(source);
1461
+ requireAllExports(source);
1463
1462
  return;
1464
1463
  }
1465
1464
  const names = [];
1466
1465
  for (const specifier of specifiers) {
1466
+ if (!isRecord(specifier)) {
1467
+ requireAllExports(source);
1468
+ return;
1469
+ }
1467
1470
  if (isTypeOnly(specifier)) continue;
1468
1471
  if (specifier.type !== "ExportSpecifier") {
1469
- markUnsafe(source);
1472
+ requireAllExports(source);
1470
1473
  return;
1471
1474
  }
1472
1475
  const local = specifier.local;
1473
- if (local?.type === "Literal" || local?.type === "StringLiteral") {
1474
- markUnsafe(source);
1476
+ if (isRecord(local) && (local.type === "Literal" || local.type === "StringLiteral")) {
1477
+ requireAllExports(source);
1475
1478
  return;
1476
1479
  }
1477
1480
  const name = getExportedName(specifier.local);
1478
1481
  if (!name) {
1479
- markUnsafe(source);
1482
+ requireAllExports(source);
1480
1483
  return;
1481
1484
  }
1482
1485
  names.push(name);
1483
1486
  }
1484
1487
  record(names, source);
1485
1488
  }
1486
- /**
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.
1496
- */
1497
- async function collectTreeShakingImports(code, id, shared, findSharedKey, record, markUnsafe) {
1498
- const normalizedId = normalizePathForImport(id);
1499
- if (normalizedId.includes("__prebuild__") || normalizedId.includes("__loadShare__") || normalizedId.includes("__mf_tree_shaking_graph__")) return;
1489
+ function analyzeImports(code) {
1500
1490
  let ast;
1501
1491
  try {
1502
- ast = parseAst(code);
1492
+ ast = vite.parseAst(code);
1503
1493
  } catch {
1504
- Object.entries(shared).forEach(([sharedKey, shareItem]) => {
1505
- if (shouldAnalyzeSharedExports(shareItem)) markUnsafe(sharedKey, "*");
1506
- });
1507
- return;
1494
+ return null;
1508
1495
  }
1509
- const pending = [];
1510
- const withSharedSource = (source, use) => {
1511
- const apply = (key) => {
1512
- if (key && shouldAnalyzeSharedExports(shared[key])) use(key);
1513
- };
1514
- const key = findSharedKey(source, shared);
1515
- if (key instanceof Promise) pending.push(key.then(apply));
1516
- 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) => {
1496
+ const imports = [];
1497
+ const recordSource = (names, source) => imports.push({
1498
+ source,
1499
+ usedExports: names
1500
+ });
1501
+ const requireAllExports = (source) => imports.push({
1502
+ source,
1503
+ usedExports: null
1504
+ });
1505
+ const collectImport = (node) => {
1525
1506
  if (node.type === "ImportDeclaration") {
1526
1507
  const source = getModuleSource(node.source);
1527
- if (source) collectImportDeclaration(node, source, recordSource, markSourceUnsafe);
1508
+ if (source) collectImportDeclaration(node, source, recordSource, requireAllExports);
1528
1509
  return;
1529
1510
  }
1530
1511
  if ((node.type === "ExportNamedDeclaration" || node.type === "ExportAllDeclaration") && node.source) {
1531
1512
  const source = getModuleSource(node.source);
1532
- if (source) collectReExport(node, source, recordSource, markSourceUnsafe);
1513
+ if (source) collectReExport(node, source, recordSource, requireAllExports);
1533
1514
  return;
1534
1515
  }
1535
1516
  if (node.type === "ImportExpression") {
1536
1517
  const source = getModuleSource(node.source);
1537
- if (source) markSourceUnsafe(source);
1518
+ if (source) requireAllExports(source);
1538
1519
  return;
1539
1520
  }
1540
1521
  if (node.type === "CallExpression") {
1541
1522
  const callee = node.callee;
1542
1523
  const args = Array.isArray(node.arguments) ? node.arguments : [];
1543
- if (callee?.type === "Identifier" && callee.name === "require" && args.length > 0) {
1524
+ if (isRecord(callee) && callee.type === "Identifier" && callee.name === "require" && args.length > 0) {
1544
1525
  const source = getModuleSource(args[0]);
1545
- if (source) markSourceUnsafe(source);
1526
+ if (source) requireAllExports(source);
1546
1527
  }
1547
1528
  }
1529
+ };
1530
+ if ("Visitor" in vite && typeof vite.Visitor === "function") {
1531
+ const visit = (node) => {
1532
+ if (isRecord(node)) collectImport(node);
1533
+ };
1534
+ try {
1535
+ new vite.Visitor({
1536
+ ImportDeclaration: visit,
1537
+ ExportNamedDeclaration: visit,
1538
+ ExportAllDeclaration: visit,
1539
+ ImportExpression: visit,
1540
+ CallExpression: visit
1541
+ }).visit(ast);
1542
+ return imports;
1543
+ } catch {
1544
+ imports.length = 0;
1545
+ }
1546
+ }
1547
+ forEachAstNode(ast, collectImport);
1548
+ return imports;
1549
+ }
1550
+ //#endregion
1551
+ //#region src/utils/treeShaking.ts
1552
+ function shouldAnalyzeSharedExports(shareItem) {
1553
+ return !!(shareItem && (shareItem.shareConfig.treeShaking || shareItem.shareConfig.import === false));
1554
+ }
1555
+ const legacyTreeShakingState = {
1556
+ inferredUsage: /* @__PURE__ */ new Map(),
1557
+ buildMode: false
1558
+ };
1559
+ const treeShakingStates = /* @__PURE__ */ new WeakMap();
1560
+ function getTreeShakingState(options) {
1561
+ if (!options) return legacyTreeShakingState;
1562
+ let state = treeShakingStates.get(options);
1563
+ if (!state) {
1564
+ state = {
1565
+ inferredUsage: /* @__PURE__ */ new Map(),
1566
+ buildMode: false
1567
+ };
1568
+ treeShakingStates.set(options, state);
1569
+ }
1570
+ return state;
1571
+ }
1572
+ function setTreeShakingBuildMode(enabled, options) {
1573
+ getTreeShakingState(options).buildMode = enabled;
1574
+ }
1575
+ function resetTreeShakingExports(options) {
1576
+ getTreeShakingState(options).inferredUsage.clear();
1577
+ }
1578
+ function getOrCreateExportRecord(sharedKey, request, options) {
1579
+ const inferredUsage = getTreeShakingState(options).inferredUsage;
1580
+ let byRequest = inferredUsage.get(sharedKey);
1581
+ if (!byRequest) {
1582
+ byRequest = /* @__PURE__ */ new Map();
1583
+ inferredUsage.set(sharedKey, byRequest);
1584
+ }
1585
+ let record = byRequest.get(request);
1586
+ if (!record) {
1587
+ record = {
1588
+ requiresFullBundle: false,
1589
+ usedExports: /* @__PURE__ */ new Set()
1590
+ };
1591
+ byRequest.set(request, record);
1592
+ }
1593
+ return record;
1594
+ }
1595
+ function recordTreeShakingExports(sharedKey, exports, request = sharedKey, options) {
1596
+ const record = getOrCreateExportRecord(sharedKey, request, options);
1597
+ exports.forEach((name) => record.usedExports.add(name));
1598
+ }
1599
+ function markTreeShakingPackageUnsafe(sharedKey, request = sharedKey, options) {
1600
+ getOrCreateExportRecord(sharedKey, request, options).requiresFullBundle = true;
1601
+ }
1602
+ function getExportRecords(sharedKey, request, options) {
1603
+ const inferredUsage = getTreeShakingState(options).inferredUsage;
1604
+ if (sharedKey) {
1605
+ const records = inferredUsage.get(sharedKey);
1606
+ const wildcard = records?.get("*");
1607
+ const exact = records?.get(request);
1608
+ return [wildcard, exact === wildcard ? void 0 : exact].filter((record) => !!record);
1609
+ }
1610
+ const records = [];
1611
+ inferredUsage.forEach((byRequest, configuredKey) => {
1612
+ const wildcard = byRequest.get("*");
1613
+ const exact = byRequest.get(request);
1614
+ const configuredRequest = getSharedRequest(configuredKey, options?.shared?.[configuredKey]);
1615
+ const keyBase = configuredRequest.endsWith("/") ? configuredRequest.slice(0, -1) : configuredRequest;
1616
+ const requestMatchesConfiguredKey = request === keyBase || request.startsWith(`${keyBase}/`);
1617
+ if (wildcard && requestMatchesConfiguredKey) records.push(wildcard);
1618
+ if (exact && exact !== wildcard) records.push(exact);
1548
1619
  });
1620
+ return records;
1621
+ }
1622
+ /**
1623
+ * Return the analyzed requirement for one concrete shared request.
1624
+ *
1625
+ * Callers that know the configured share key should pass it explicitly. The
1626
+ * fallback lookup across keys keeps aliases/backwards-compatible callers
1627
+ * working, while still keeping each concrete request's exports isolated.
1628
+ */
1629
+ function getSharedExportUsage(request, shareItem, sharedKey, options) {
1630
+ const treeShaking = shareItem?.shareConfig.treeShaking;
1631
+ if (!shouldAnalyzeSharedExports(shareItem) || !getTreeShakingState(options).buildMode) return;
1632
+ const records = getExportRecords(sharedKey, request, options);
1633
+ if (records.some((record) => record.requiresFullBundle)) return { kind: "full" };
1634
+ const configured = treeShaking?.usedExports ?? [];
1635
+ const result = new Set(configured);
1636
+ records.forEach((record) => record.usedExports.forEach((name) => result.add(name)));
1637
+ if (result.size > 0) return {
1638
+ kind: "exports",
1639
+ usedExports: [...result].sort()
1640
+ };
1641
+ return records.length > 0 ? {
1642
+ kind: "exports",
1643
+ usedExports: []
1644
+ } : { kind: "unknown" };
1645
+ }
1646
+ function getTreeShakingExportUsage(request, shareItem, sharedKey, options) {
1647
+ if (!shareItem?.shareConfig.treeShaking) return void 0;
1648
+ return getSharedExportUsage(request, shareItem, sharedKey, options);
1649
+ }
1650
+ /**
1651
+ * Record consumer imports against this instance's sharing configuration.
1652
+ * Generated wrappers do not contribute consumer usage. If parsing fails,
1653
+ * every share enabled for analysis requires all of its exports.
1654
+ */
1655
+ async function collectTreeShakingImports(code, id, shared, findSharedKey, record, markUnsafe, analysis = getImportAnalysis(shared)) {
1656
+ const normalizedId = normalizePathForImport(id);
1657
+ if (normalizedId.includes("__prebuild__") || normalizedId.includes("__loadShare__") || normalizedId.includes("__mf_tree_shaking_graph__")) return;
1658
+ const imports = analysis.analyze(code);
1659
+ if (imports === null) {
1660
+ Object.entries(shared).forEach(([sharedKey, shareItem]) => {
1661
+ if (shouldAnalyzeSharedExports(shareItem)) markUnsafe(sharedKey, "*");
1662
+ });
1663
+ return;
1664
+ }
1665
+ const pending = [];
1666
+ for (const { source, usedExports } of imports) {
1667
+ const apply = (key) => {
1668
+ if (!key || !shouldAnalyzeSharedExports(shared[key])) return;
1669
+ if (usedExports === null) markUnsafe(key, source);
1670
+ else record(key, usedExports, source);
1671
+ };
1672
+ const key = findSharedKey(source, shared);
1673
+ if (key instanceof Promise) pending.push(key.then(apply));
1674
+ else apply(key);
1675
+ }
1549
1676
  await Promise.all(pending);
1550
1677
  }
1551
1678
  //#endregion
@@ -2162,7 +2289,7 @@ ${exportStatement}
2162
2289
  //#endregion
2163
2290
  //#region src/plugins/pluginReactMixedModeGuard.ts
2164
2291
  function createReactMixedModeRuntimeGuard() {
2165
- return `const __mfReactInternals = mod["__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE"];
2292
+ return `const __mfReactInternals = mod[${JSON.stringify(REACT_CLIENT_INTERNALS_KEY)}];
2166
2293
  if (__mfReactInternals && "A" in __mfReactInternals) {
2167
2294
  let __mfReactDispatcher = __mfReactInternals.A;
2168
2295
  Object.defineProperty(__mfReactInternals, "A", {
@@ -2252,6 +2379,77 @@ function findLikelyTypeArgumentEnd(source, start, codePositions) {
2252
2379
  }
2253
2380
  }
2254
2381
  //#endregion
2382
+ //#region src/virtualModules/shareTags.ts
2383
+ const LOAD_SHARE_TAG = "__loadShare__";
2384
+ /** A share's local copy. Reachable only through `import()`, so it stays lazy. */
2385
+ const PREBUILD_TAG = "__prebuild__";
2386
+ //#endregion
2387
+ //#region src/virtualModules/loadShareSharedChunk.ts
2388
+ const HELPERS_MODULE_NAME = "loadShareHelpers";
2389
+ const HELPERS_MODULE_TAG = "__mf_v__";
2390
+ const HELPERS_MODULE_MARKER = `${HELPERS_MODULE_TAG}${HELPERS_MODULE_NAME}${HELPERS_MODULE_TAG}`;
2391
+ const SHARED_CHUNK_SUFFIX = `${LOAD_SHARE_TAG}shared`;
2392
+ const HELPER_EXPORT_LIST = [
2393
+ "__mfGetSharedCacheDescriptor",
2394
+ "__mfReadSharedCache",
2395
+ "__mfSharedCacheListenersKey",
2396
+ "__mfGetSharedCacheListeners",
2397
+ "__mfSubscribeSharedCache",
2398
+ "__mfSharedCacheOwnersKey",
2399
+ "__mfGetSharedCacheOwners",
2400
+ "__mfReadSharedCacheOwner",
2401
+ "__mfGetSharedModuleIdentity",
2402
+ "__mfIsSameSharedModule",
2403
+ "__mfWriteSharedCache",
2404
+ "__mfTreeShakingSharedCacheKey",
2405
+ "__mfGetTreeShakingSharedCache",
2406
+ "__mfReadTreeShakingSharedCache",
2407
+ "__mfWriteTreeShakingSharedCache",
2408
+ "__mfTreeShakingSelectionCacheKey",
2409
+ "__mfGetTreeShakingSelectionCache",
2410
+ "__mfReadTreeShakingSharedSelection",
2411
+ "__mfWriteTreeShakingSharedSelection"
2412
+ ].join(", ");
2413
+ const helperModules = /* @__PURE__ */ new WeakMap();
2414
+ function getSharedCacheHelpersModule(options) {
2415
+ let module = helperModules.get(options);
2416
+ if (!module) {
2417
+ module = new VirtualModule(HELPERS_MODULE_NAME, HELPERS_MODULE_TAG, "", getFederationScopeKey(options));
2418
+ module.writeSync(`${sharedCacheHelperCode}\nexport { ${HELPER_EXPORT_LIST} };`);
2419
+ helperModules.set(options, module);
2420
+ }
2421
+ return module;
2422
+ }
2423
+ function getSharedCacheHelpersImportCode(options) {
2424
+ const importId = getSharedCacheHelpersModule(options).getImportId();
2425
+ return `import { ${HELPER_EXPORT_LIST} } from ${JSON.stringify(importId)};`;
2426
+ }
2427
+ function isSharedCacheHelpersId(id) {
2428
+ return id.includes(HELPERS_MODULE_MARKER);
2429
+ }
2430
+ function getSharedChunkName(id) {
2431
+ const ownerTag = isSharedCacheHelpersId(id) ? HELPERS_MODULE_MARKER : LOAD_SHARE_TAG;
2432
+ return `${id.slice(0, id.indexOf(ownerTag))}${SHARED_CHUNK_SUFFIX}`;
2433
+ }
2434
+ function isSharedChunk(chunk) {
2435
+ return chunk.name?.endsWith(SHARED_CHUNK_SUFFIX) ?? false;
2436
+ }
2437
+ /**
2438
+ * Fallbacks inlined into a shared chunk, which means they are no longer lazy.
2439
+ * Only inlined modules count: a shared chunk also imports fallback chunks with
2440
+ * the experiment off, because Rolldown hoists its runtime helpers into whichever
2441
+ * chunk first uses them.
2442
+ */
2443
+ function findEagerFallbacksInSharedChunk(bundle) {
2444
+ const offenders = /* @__PURE__ */ new Map();
2445
+ for (const [fileName, chunk] of Object.entries(bundle)) {
2446
+ if (chunk.type !== "chunk" || !isSharedChunk(chunk)) continue;
2447
+ const inlined = Object.keys(chunk.modules ?? {}).filter((id) => id.includes(PREBUILD_TAG));
2448
+ if (inlined.length > 0) offenders.set(fileName, inlined);
2449
+ }
2450
+ return offenders;
2451
+ }
2452
+ //#endregion
2255
2453
  //#region src/virtualModules/virtualShared_preBuild.ts
2256
2454
  /**
2257
2455
  * Even the resolveId hook cannot interfere with vite pre-build,
@@ -2287,7 +2485,7 @@ function isValidEsmExportName(name) {
2287
2485
  const JS_IDENTIFIER_PATTERN = `[\$_\\p{ID_Start}][\$_\\u200C\\u200D\\p{ID_Continue}]*`;
2288
2486
  function resolvePackageEntryFromProjectRoot(pkg) {
2289
2487
  try {
2290
- return createRequire$1(pathToFileURL(path$1.join(getPackageDetectionCwd(), "package.json"))).resolve(pkg);
2488
+ return resolveModulePath(pkg, path$1.join(getPackageDetectionCwd(), "package.json"));
2291
2489
  } catch {
2292
2490
  return;
2293
2491
  }
@@ -2445,7 +2643,7 @@ function resolveConfiguredImportPath(importSource, exportConditions = DEFAULT_SH
2445
2643
  });
2446
2644
  if (esmEntry) return esmEntry;
2447
2645
  try {
2448
- return createRequire$1(pathToFileURL(path$1.join(projectRoot, "package.json"))).resolve(importSource);
2646
+ return resolveModulePath(importSource, path$1.join(projectRoot, "package.json"));
2449
2647
  } catch {
2450
2648
  return;
2451
2649
  }
@@ -2500,7 +2698,7 @@ function resolveReExportModule(filePath, specifier, exportConditions) {
2500
2698
  });
2501
2699
  if (esmEntry) return esmEntry;
2502
2700
  try {
2503
- return resolveFileLikeModule(createRequire$1(pathToFileURL(filePath)).resolve(specifier));
2701
+ return resolveFileLikeModule(resolveModulePath(specifier, filePath));
2504
2702
  } catch {
2505
2703
  return;
2506
2704
  }
@@ -2828,7 +3026,8 @@ function getRequiredNamedExports(specifier) {
2828
3026
  const getActiveHandles = process._getActiveHandles;
2829
3027
  const handlesBeforeRequire = typeof getActiveHandles === "function" ? new Set(getActiveHandles.call(process)) : void 0;
2830
3028
  try {
2831
- const mod = createRequire$1(pathToFileURL(path$1.join(getPackageDetectionCwd(), "package.json")))(specifier);
3029
+ const projectPackageJson = path$1.join(getPackageDetectionCwd(), "package.json");
3030
+ const mod = createRequire$1(pathToFileURL(projectPackageJson))(resolveModulePath(specifier, projectPackageJson));
2832
3031
  const runtimeNamedKeys = Object.keys(mod).filter((key) => key !== "default" && key !== "__esModule");
2833
3032
  if (runtimeNamedKeys.some((key) => !isValidEsmExportName(key))) return void 0;
2834
3033
  return runtimeNamedKeys;
@@ -2871,7 +3070,7 @@ function getSharedNamedExports(pkg, shareItem, exportConditions = DEFAULT_SHARED
2871
3070
  }
2872
3071
  function getLocalProviderImportPath(pkg) {
2873
3072
  try {
2874
- const resolved = resolveWorkspaceEsmEntry(pkg, createRequire$1(pathToFileURL(path$1.join(getPackageDetectionCwd(), "package.json"))).resolve(pkg));
3073
+ const resolved = resolveWorkspaceEsmEntry(pkg, resolveModulePath(pkg, path$1.join(getPackageDetectionCwd(), "package.json")));
2875
3074
  return isWorkspaceFilePath(resolved) ? resolved : void 0;
2876
3075
  } catch {
2877
3076
  const resolved = getInstalledPackageEntry(pkg, {
@@ -2892,7 +3091,7 @@ function getProjectResolvedImportPath(pkg) {
2892
3091
  if (esmEntry) return esmEntry;
2893
3092
  }
2894
3093
  try {
2895
- return resolveWorkspaceEsmEntry(pkg, createRequire$1(pathToFileURL(path$1.join(getPackageDetectionCwd(), "package.json"))).resolve(pkg));
3094
+ return resolveWorkspaceEsmEntry(pkg, resolveModulePath(pkg, path$1.join(getPackageDetectionCwd(), "package.json")));
2896
3095
  } catch {
2897
3096
  return;
2898
3097
  }
@@ -2948,25 +3147,11 @@ function getSharedDependencyGraphPackageJson(pkg) {
2948
3147
  const installedPackageJson = getInstalledPackageJson(pkg, { packageName: getPackageName(pkg) })?.packageJson;
2949
3148
  if (installedPackageJson) return installedPackageJson;
2950
3149
  try {
2951
- const packageJsonPath = createRequire$1(pathToFileURL(path$1.join(getPackageDetectionCwd(), "package.json"))).resolve(`${getPackageName(pkg)}/package.json`);
3150
+ const packageJsonPath = resolveModulePath(`${getPackageName(pkg)}/package.json`, path$1.join(getPackageDetectionCwd(), "package.json"));
2952
3151
  return JSON.parse(readFileSync(packageJsonPath, "utf-8"));
2953
3152
  } catch {}
2954
3153
  return getWorkspacePackageJson(pkg);
2955
3154
  }
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
3155
  function isSharedSingletonConsumedByPeer(pkg, options = getNormalizeModuleFederationOptions(), requireFederationRuntimeDependency = false) {
2971
3156
  const shared = options?.shared || {};
2972
3157
  if (!requireFederationRuntimeDependency && Object.entries(shared).some(([key, item]) => key !== pkg && key.startsWith(`${pkg}/`) && item.shareConfig.singleton === true)) return true;
@@ -2975,25 +3160,39 @@ function isSharedSingletonConsumedByPeer(pkg, options = getNormalizeModuleFedera
2975
3160
  const packageName = getPackageName(key);
2976
3161
  if (!sharedKeyByPackageName.get(packageName) || key === packageName) sharedKeyByPackageName.set(packageName, key);
2977
3162
  });
2978
- const reachesPkg = (current, seen, hasFederationRuntimeDependency = false) => {
3163
+ const runtimeDependencyCache = /* @__PURE__ */ new Map();
3164
+ const reachesFederationRuntime = (current, seen) => {
3165
+ if (runtimeDependencyCache.has(current)) return runtimeDependencyCache.get(current);
3166
+ const result = getDependencyNames(getSharedDependencyGraphPackageJson(current)).some((dependency) => {
3167
+ if (dependency === "@module-federation/enhanced" || dependency === "@module-federation/runtime" || dependency === "@module-federation/runtime-core") return true;
3168
+ if (seen.has(dependency)) return false;
3169
+ seen.add(dependency);
3170
+ const reachable = reachesFederationRuntime(dependency, seen);
3171
+ seen.delete(dependency);
3172
+ return reachable;
3173
+ });
3174
+ runtimeDependencyCache.set(current, result);
3175
+ return result;
3176
+ };
3177
+ const reachesPkg = (current, seen) => {
2979
3178
  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
3179
  for (const dependency of dependencies) {
2983
3180
  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;
3181
+ if (sharedDependency === pkg) return true;
3182
+ if (!sharedDependency && !requireFederationRuntimeDependency) continue;
3183
+ const next = sharedDependency || dependency;
3184
+ if (seen.has(next)) continue;
3185
+ seen.add(next);
3186
+ if (reachesPkg(next, seen)) return true;
3187
+ seen.delete(next);
2989
3188
  }
2990
3189
  return false;
2991
3190
  };
2992
- return Array.from(sharedKeyByPackageName.values()).some((sharedPkg) => sharedPkg !== pkg && reachesPkg(sharedPkg, /* @__PURE__ */ new Set([sharedPkg])));
3191
+ return Array.from(sharedKeyByPackageName.values()).some((sharedPkg) => sharedPkg !== pkg && (!requireFederationRuntimeDependency || reachesFederationRuntime(sharedPkg, /* @__PURE__ */ new Set([sharedPkg]))) && reachesPkg(sharedPkg, /* @__PURE__ */ new Set([sharedPkg])));
2993
3192
  }
2994
3193
  function tryResolveImportFromPackageRoot(pkg, root) {
2995
3194
  try {
2996
- return resolveWorkspaceEsmEntry(pkg, createRequire$1(pathToFileURL(path$1.join(root, "package.json"))).resolve(pkg), root);
3195
+ return resolveWorkspaceEsmEntry(pkg, resolveModulePath(pkg, path$1.join(root, "package.json")), root);
2997
3196
  } catch {
2998
3197
  return;
2999
3198
  }
@@ -3026,9 +3225,11 @@ function resolveConcreteSharedImportSource(pkg, projectRoot) {
3026
3225
  if (resolved) return resolved;
3027
3226
  currentDir = path$1.dirname(currentDir);
3028
3227
  }
3029
- return tryResolveImportFromPackageRoot(pkg, currentDir);
3228
+ return tryResolveImportFromPackageRoot(pkg, currentDir) ?? getInstalledPackageEntry(pkg, {
3229
+ conditions: DEFAULT_SHARED_EXPORT_CONDITIONS,
3230
+ resolveSubpathWithRequire: false
3231
+ });
3030
3232
  }
3031
- const PREBUILD_TAG = "__prebuild__";
3032
3233
  const TREE_SHAKING_PROVIDER_TAG = "__treeShakingProvider__";
3033
3234
  const TREE_SHAKING_GRAPH_QUERY = "__mf_tree_shaking_graph__";
3034
3235
  const legacySharedVirtualModuleState = {
@@ -3037,9 +3238,11 @@ const legacySharedVirtualModuleState = {
3037
3238
  treeShakingProviderCacheMap: {},
3038
3239
  materializedTreeShakingProviders: /* @__PURE__ */ new Set(),
3039
3240
  loadShareCacheMap: {},
3040
- warnedMissingImportFalse: /* @__PURE__ */ new Set()
3241
+ warnedMissingImportFalse: /* @__PURE__ */ new Set(),
3242
+ coalescableLoadShares: /* @__PURE__ */ new Set()
3041
3243
  };
3042
3244
  const sharedVirtualModuleStates = /* @__PURE__ */ new WeakMap();
3245
+ const sharedVirtualModuleStatesByOwner = /* @__PURE__ */ new Map();
3043
3246
  function getSharedVirtualModuleState(options) {
3044
3247
  if (!options) try {
3045
3248
  const currentOptions = getNormalizeModuleFederationOptions();
@@ -3056,12 +3259,19 @@ function getSharedVirtualModuleState(options) {
3056
3259
  materializedTreeShakingProviders: /* @__PURE__ */ new Set(),
3057
3260
  loadShareCacheMap: {},
3058
3261
  warnedMissingImportFalse: /* @__PURE__ */ new Set(),
3262
+ coalescableLoadShares: /* @__PURE__ */ new Set(),
3059
3263
  ownerKey: getFederationScopeKey(options)
3060
3264
  };
3061
3265
  sharedVirtualModuleStates.set(options, state);
3266
+ if (state.ownerKey !== void 0) sharedVirtualModuleStatesByOwner.set(state.ownerKey, state);
3062
3267
  }
3063
3268
  return state;
3064
3269
  }
3270
+ /** State of the instance that owns a scoped virtual id; `options` covers unscoped ids. */
3271
+ function getSharedVirtualModuleStateForId(id, options) {
3272
+ const ownerKey = id === void 0 ? void 0 : VirtualModule.findById(id)?.getScopeName();
3273
+ return (ownerKey !== void 0 ? sharedVirtualModuleStatesByOwner.get(ownerKey) : void 0) ?? getSharedVirtualModuleState(options);
3274
+ }
3065
3275
  function createScopedSharedVirtualModule(pkg, tag, options) {
3066
3276
  return new VirtualModule(pkg, tag, ".js", getSharedVirtualModuleState(options).ownerKey);
3067
3277
  }
@@ -3178,7 +3388,7 @@ function writePreBuildLibPath(pkg, shareItem, options, exportConditions) {
3178
3388
  const cache = globalThis[__mfCacheGlobalKey]?.share;
3179
3389
  const sharedReact = cache && __mfReadSharedCache(cache, ${reactCacheDescriptor});
3180
3390
  const reactExports = sharedReact?.default ?? sharedReact;
3181
- const internals = reactExports?.__CLIENT_INTERNALS_DO_NOT_USE_OR_WARN_USERS_THEY_CANNOT_UPGRADE;
3391
+ const internals = reactExports?.[${JSON.stringify(REACT_CLIENT_INTERNALS_KEY)}];
3182
3392
  return internals?.H?.useMemoCache(size);
3183
3393
  };
3184
3394
  export default { c };
@@ -3256,7 +3466,6 @@ function getPreBuildShareItem(pkg, options) {
3256
3466
  function getSharedImportSource(pkg, shareItem, options) {
3257
3467
  return getConcreteSharedImportSource(pkg, shareItem) || getPreBuildLibImportId(pkg, options);
3258
3468
  }
3259
- const LOAD_SHARE_TAG = "__loadShare__";
3260
3469
  function getLoadShareImportId(pkg, _isRolldown, options) {
3261
3470
  const { loadShareCacheMap } = getSharedVirtualModuleState(options);
3262
3471
  if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = createScopedSharedVirtualModule(pkg, LOAD_SHARE_TAG, options);
@@ -3316,14 +3525,14 @@ function getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer) {
3316
3525
  * a merged chunk, TDZ bindings otherwise), so the exports stay unassigned until the deferred cache write
3317
3526
  * re-applies them; a host-provided copy re-applies them through the cache subscription as before.
3318
3527
  */
3319
- function generateEagerWorkspaceSingletonExports(namedExports, importSource, cacheDescriptor, cacheOwner, treeShakingConsumer, mutableExports = []) {
3528
+ function generateEagerWorkspaceSingletonExports(edges, namedExports, importSource, cacheDescriptor, cacheOwner, treeShakingConsumer, mutableExports = []) {
3320
3529
  const copiedExports = namedExports.filter((name) => !mutableExports.includes(name));
3321
3530
  const namedExportVars = copiedExports.map((_name, i) => `__mf_${i}`);
3322
3531
  const declarations = namedExports.length > 0 ? ["let __mf_default;", ...namedExportVars.map((name) => `let ${name};`)].join("\n ") : "let __mf_default;";
3323
3532
  const assignments = [...copiedExports.map((name, i) => `${namedExportVars[i]} = mod[${escapeGeneratedStringLiteral(name)}];`), "__mf_default = mod.default ?? mod;"].join("\n ");
3324
3533
  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)};
3534
+ const mutableExportLine = mutableExports.length ? `\n ${edges.reExportNames(mutableExports, importSource)}` : "";
3535
+ return `${edges.importNamespace(importSource)}
3327
3536
  let exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
3328
3537
  if (exportModule === undefined) {
3329
3538
  Promise.resolve().then(() => {
@@ -3351,28 +3560,26 @@ function generateEagerWorkspaceSingletonExports(namedExports, importSource, cach
3351
3560
  __mfApplyEagerShareExportsWhenReady(exportModule);
3352
3561
  export { __mf_default as default };${namedExportLine}${mutableExportLine}`;
3353
3562
  }
3354
- function generateLazyWorkspaceSingletonExports(namedExports, importSource, cacheDescriptor, cacheOwner, treeShakingConsumer, serveLocalFallback = false, mutableExports = []) {
3563
+ function generateLazyWorkspaceSingletonExports(edges, namedExports, importSource, cacheDescriptor, cacheOwner, treeShakingConsumer, serveLocalFallback = false, mutableExports = [], deferredEntryFallback = false) {
3355
3564
  const copiedExports = namedExports.filter((name) => !mutableExports.includes(name));
3356
3565
  const namedExportVars = copiedExports.map((_name, i) => `__mf_${i}`);
3357
3566
  const declarations = namedExports.length > 0 ? ["let __mf_default;", ...namedExportVars.map((name) => `let ${name};`)].join("\n ") : "let __mf_default;";
3358
3567
  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
3568
  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)};` : "";
3569
+ const mutableExportLine = mutableExports.length ? `\n ${edges.reExportNames(mutableExports, importSource)}` : "";
3361
3570
  const applyLocalFallback = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
3362
3571
  __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});
3363
3572
  __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)};
3573
+ const readDeferredShare = getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer);
3574
+ const deferredEntryLoad = `Promise.race([
3575
+ initPromise.then(() => ${readDeferredShare}),
3576
+ new Promise((resolve) => {
3577
+ const current = ${readDeferredShare};
3578
+ if (current !== undefined) resolve(current);
3579
+ else __mfSubscribeSharedCache(__mfModuleCache.share, ${cacheDescriptor}, resolve);
3580
+ })
3581
+ ]).then((cached) => {
3582
+ exportModule = cached;
3376
3583
  if (exportModule !== undefined) {
3377
3584
  __mfApplyLazyShareExports(exportModule);
3378
3585
  return;
@@ -3381,8 +3588,32 @@ function generateLazyWorkspaceSingletonExports(namedExports, importSource, cache
3381
3588
  exportModule = __mfNormalizeShareModule(mod);
3382
3589
  __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});
3383
3590
  });
3384
- }));
3385
- }
3591
+ })`;
3592
+ const deferredInitLoad = `initPromise.then(() => {
3593
+ exportModule = ${readDeferredShare};
3594
+ if (exportModule !== undefined) {
3595
+ __mfApplyLazyShareExports(exportModule);
3596
+ return;
3597
+ }
3598
+ return import(${escapeGeneratedStringLiteral(importSource)}).then((mod) => {
3599
+ exportModule = __mfNormalizeShareModule(mod);
3600
+ __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});
3601
+ });
3602
+ })`;
3603
+ const synchronousFallbackConditions = [...deferredEntryFallback ? [] : ["import.meta.env.SSR"], ...serveLocalFallback ? ["(import.meta.env.DEV && typeof __mfLocalShare !== 'undefined')"] : []];
3604
+ const trackPendingLoad = `__mfTrackPendingShareLoad(${deferredEntryFallback ? deferredEntryLoad : deferredInitLoad});`;
3605
+ return `${declarations}
3606
+ const __mfApplyLazyShareExports = (mod) => {
3607
+ ${assignments}
3608
+ };
3609
+ __mfSubscribeSharedCache(__mfModuleCache.share, ${cacheDescriptor}, __mfApplyLazyShareExports);
3610
+ let exportModule = ${readDeferredShare};
3611
+ if (exportModule === undefined) {
3612
+ ${synchronousFallbackConditions.length > 0 ? `if (${synchronousFallbackConditions.join(" || ")}) {
3613
+ ${applyLocalFallback}
3614
+ } else {
3615
+ ${trackPendingLoad}
3616
+ }` : trackPendingLoad}
3386
3617
  } else {
3387
3618
  __mfApplyLazyShareExports(exportModule);
3388
3619
  }
@@ -3418,6 +3649,14 @@ function generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor,
3418
3649
  if (exportModule === undefined) {
3419
3650
  __mfTrackPendingShareLoad(initPromise.then(() => {
3420
3651
  exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
3652
+ // A share init() left to its dynamic import is normally bridged before that import runs;
3653
+ // bridge it here when this wrapper is reached another way.
3654
+ if (exportModule === undefined && typeof __mfPromiseState.loadLazyShares === "function") {
3655
+ return __mfPromiseState.loadLazyShares([${escapeGeneratedStringLiteral(pkg)}]).then(() => {
3656
+ exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)};
3657
+ });
3658
+ }
3659
+ }).then(() => {
3421
3660
  if (exportModule === undefined) {
3422
3661
  throw new Error("[Module Federation] Shared module ${pkg} was imported before federation bootstrap finished.");
3423
3662
  }
@@ -3426,7 +3665,7 @@ function generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor,
3426
3665
  } else {
3427
3666
  __mfApplyHostProvidedExports(exportModule);
3428
3667
  }
3429
- export { __mf_default as default };${namedExportLine}`;
3668
+ export { __mf_default as default, exportModule as __moduleExports };${namedExportLine}`;
3430
3669
  }
3431
3670
  function selectImportFalseNamedExports(detectedNamedExports, usage) {
3432
3671
  if (!detectedNamedExports || usage?.kind !== "exports") return detectedNamedExports ?? [];
@@ -3465,9 +3704,49 @@ const initializedLocalShareModuleCode = `const __mfInitializedLocalShare = (mod)
3465
3704
  throw error;
3466
3705
  }
3467
3706
  };`;
3707
+ function createLocalPayloadEdges() {
3708
+ let edges = 0;
3709
+ return {
3710
+ importNamespace(source) {
3711
+ edges++;
3712
+ return `import * as __mfLocalShare from ${escapeGeneratedStringLiteral(source)};`;
3713
+ },
3714
+ reExportAll(source) {
3715
+ edges++;
3716
+ return `export * from ${escapeGeneratedStringLiteral(source)}`;
3717
+ },
3718
+ reExportNames(names, source) {
3719
+ if (names.length === 0) return "";
3720
+ edges++;
3721
+ return `export { ${names.join(", ")} } from ${escapeGeneratedStringLiteral(source)};`;
3722
+ },
3723
+ get none() {
3724
+ return edges === 0;
3725
+ }
3726
+ };
3727
+ }
3728
+ function recordCoalescability(pkg, hasNoLocalPayloadEdge, command, shareConfig, coalescableLoadShares) {
3729
+ const coalescable = command === "build" && shareConfig.eager !== true && shareConfig.import !== false && hasNoLocalPayloadEdge;
3730
+ if (coalescable) coalescableLoadShares.add(pkg);
3731
+ else coalescableLoadShares.delete(pkg);
3732
+ return coalescable;
3733
+ }
3734
+ /**
3735
+ * `prependWorkspaceSingletonSsrImport` adds a local-payload edge in the server
3736
+ * build's load hook, after this module has generated the wrapper. `id` names
3737
+ * the owning instance when the hook belongs to a different one.
3738
+ */
3739
+ function markLoadShareWrapperNotCoalescable(pkg, options, id) {
3740
+ getSharedVirtualModuleStateForId(id, options).coalescableLoadShares.delete(pkg);
3741
+ }
3742
+ /** With `id`, answers from the owning instance's state, whichever instance asks. */
3743
+ function isCoalescableLoadShareWrapper(pkg, options, id) {
3744
+ return getSharedVirtualModuleStateForId(id, options).coalescableLoadShares.has(pkg);
3745
+ }
3468
3746
  function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exportConditions, importFalseExportUsage) {
3469
3747
  const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
3470
- const { loadShareCacheMap } = getSharedVirtualModuleState(options);
3748
+ const { loadShareCacheMap, coalescableLoadShares } = getSharedVirtualModuleState(options);
3749
+ const edges = createLocalPayloadEdges();
3471
3750
  if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = createScopedSharedVirtualModule(pkg, LOAD_SHARE_TAG, options);
3472
3751
  let importLine = getRuntimeModuleCacheBootstrapCode(exportConditions);
3473
3752
  const cacheDescriptor = getSharedCacheDescriptorLiteral(pkg, shareItem);
@@ -3487,6 +3766,7 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3487
3766
  }
3488
3767
  exportLine = generateDeferredHostProvidedExports([], pkg, cacheDescriptor, treeShakingConsumer);
3489
3768
  }
3769
+ recordCoalescability(pkg, edges.none, command, shareItem.shareConfig, coalescableLoadShares);
3490
3770
  loadShareCacheMap[pkg].writeSync(`
3491
3771
  ${getRuntimeInitPromiseBootstrapCode(false, runtimeInitOwnerImportId)}
3492
3772
  ${importLine}
@@ -3508,13 +3788,14 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3508
3788
  const mutableExports = new Set(isLocalOnlyContainer(resolvedOptions) ? getSharedMutableExports(pkg, shareItem, exportConditions) : []);
3509
3789
  const copiedNamedExports = namedExports.filter((name) => !mutableExports.has(name));
3510
3790
  const liveNamedExports = namedExports.filter((name) => mutableExports.has(name));
3511
- const liveNamedExportLine = liveNamedExports.length ? `export { ${liveNamedExports.join(", ")} } from ${escapeGeneratedStringLiteral(sharedImportSource)};` : "";
3791
+ const liveNamedExportLine = edges.reExportNames(liveNamedExports, sharedImportSource);
3512
3792
  const hasCompleteExportCoverage = detectedNamedExports !== void 0;
3513
3793
  const isWorkspaceSingleton = isWorkspacePackage && shareItem.shareConfig.singleton === true;
3514
3794
  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
3795
  const servesRemoteSingletonFallback = command !== "build" && isRemoteOnlyContainer(resolvedOptions) && shareItem.shareConfig.singleton === true;
3516
3796
  const isConsumedByPeerSingleton = isSharedSingletonConsumedByPeer(pkg, resolvedOptions);
3517
3797
  const usesEntryInjectedRemoteFallback = hasCompleteExportCoverage && !isWorkspaceSingleton && isRemoteContainer(resolvedOptions) && shareItem.shareConfig.singleton === true && resolvedOptions.hostInitInjectLocation === "entry" && (command === "build" || isConsumedByPeerSingleton);
3798
+ const usesDeferredEntryInjectedSingletonFallback = usesEntryInjectedRemoteFallback && !isReactCoreShare(pkg) && (pkg === "react-dom/client" || shareItem.shareConfig.eager !== true && !isSharedSingletonConsumedByPeer(pkg, resolvedOptions, true));
3518
3799
  const usesEagerWorkspaceFallback = hasCompleteExportCoverage && isWorkspaceSingleton && !servesRemoteSingletonFallback && (isConsumedByPeerSingleton || shareItem.shareConfig.eager === true);
3519
3800
  const usesDeferredTreeShakingFallback = hasCompleteExportCoverage && Boolean(treeShakingConsumer);
3520
3801
  const reactMixedModeGuard = pkg === "react" ? createReactMixedModeRuntimeGuard() : "";
@@ -3522,11 +3803,14 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3522
3803
  let initBlock = "";
3523
3804
  if (usesDeferredTreeShakingFallback) {
3524
3805
  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);
3806
+ exportLine = generateLazyWorkspaceSingletonExports(edges, namedExports, lazyLocalFallbackSource, cacheDescriptor, cacheOwner, treeShakingConsumer, command !== "build" && !servesRemoteSingletonFallback && (isWorkspaceSingleton || isWorkspacePackage), liveNamedExports);
3807
+ } else if (usesDeferredEntryInjectedSingletonFallback) {
3808
+ importLine = `${getRuntimeInitPromiseBootstrapCode(false, runtimeInitOwnerImportId)}\n ${importLine}`;
3809
+ exportLine = generateLazyWorkspaceSingletonExports(edges, namedExports, lazyLocalFallbackSource, cacheDescriptor, cacheOwner, treeShakingConsumer, false, liveNamedExports, true);
3810
+ } else if (usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback) exportLine = generateEagerWorkspaceSingletonExports(edges, namedExports, lazyLocalFallbackSource, cacheDescriptor, cacheOwner, treeShakingConsumer, liveNamedExports);
3527
3811
  else if (usesDeferredSingletonFallback) {
3528
3812
  importLine = `${getRuntimeInitPromiseBootstrapCode(false, runtimeInitOwnerImportId)}\n ${importLine}`;
3529
- exportLine = generateLazyWorkspaceSingletonExports(namedExports, lazyLocalFallbackSource, cacheDescriptor, cacheOwner, treeShakingConsumer, command !== "build" && !servesRemoteSingletonFallback && (isWorkspaceSingleton || isWorkspacePackage), liveNamedExports);
3813
+ exportLine = generateLazyWorkspaceSingletonExports(edges, namedExports, lazyLocalFallbackSource, cacheDescriptor, cacheOwner, treeShakingConsumer, command !== "build" && !servesRemoteSingletonFallback && (isWorkspaceSingleton || isWorkspacePackage), liveNamedExports);
3530
3814
  } else if (detectedNamedExports === void 0) {
3531
3815
  exportLine = `const __mfDefaultExport = (() => {
3532
3816
  ${generateShareModuleUnwrapCode({
@@ -3536,7 +3820,7 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3536
3820
  })}
3537
3821
  })();
3538
3822
  export default __mfDefaultExport;
3539
- export * from ${escapeGeneratedStringLiteral(coherentLocalSource)}`;
3823
+ ${edges.reExportAll(coherentLocalSource)}`;
3540
3824
  initBlock = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
3541
3825
  __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});`;
3542
3826
  } else if (namedExports.length > 0 && shareItem.shareConfig.singleton === true) {
@@ -3587,21 +3871,23 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3587
3871
  __mfSubscribeSharedCache(__mfModuleCache.share, ${cacheDescriptor}, __mfApplySharedDefaultExport);
3588
3872
  __mfApplySharedDefaultExport(exportModule);
3589
3873
  export { __mfDefaultExport as default };
3590
- export * from ${escapeGeneratedStringLiteral(sharedImportSource)}`;
3874
+ ${edges.reExportAll(sharedImportSource)}`;
3591
3875
  initBlock = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
3592
3876
  __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});`;
3593
3877
  } else {
3594
- exportLine = `export default exportModule.default ?? exportModule\n export * from ${escapeGeneratedStringLiteral(sharedImportSource)}`;
3878
+ exportLine = `export default exportModule.default ?? exportModule\n ${edges.reExportAll(sharedImportSource)}`;
3595
3879
  initBlock = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
3596
3880
  __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});`;
3597
3881
  }
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}
3882
+ const staticLocalShareSource = detectedNamedExports === void 0 ? coherentLocalSource : skipServePrebuildWarmup ? devImportSource : sharedImportSource;
3883
+ const prebuildImportLine = usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback ? "" : usesDeferredSingletonFallback || usesDeferredTreeShakingFallback ? !servesRemoteSingletonFallback && usesDeferredSingletonFallback && command !== "build" && (isWorkspaceSingleton || isWorkspacePackage) ? edges.importNamespace(lazyLocalFallbackSource) : "" : edges.importNamespace(staticLocalShareSource);
3884
+ const devDynamicImportLine = isWorkspacePackage ? "" : usesDeferredSingletonFallback || usesDeferredTreeShakingFallback || usesDeferredEntryInjectedSingletonFallback ? "" : command !== "build" && !skipServePrebuildWarmup ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
3885
+ const cacheHelpers = recordCoalescability(pkg, edges.none, command, shareItem.shareConfig, coalescableLoadShares) ? getSharedCacheHelpersImportCode(resolvedOptions) : sharedCacheHelperCode;
3886
+ const moduleBody = usesDeferredSingletonFallback || usesDeferredTreeShakingFallback || usesDeferredEntryInjectedSingletonFallback || usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback ? `
3887
+ ${usesDeferredEntryInjectedSingletonFallback ? "" : prebuildImportLine}
3602
3888
  ${devDynamicImportLine}
3603
3889
  ${importLine}
3604
- ${sharedCacheHelperCode}
3890
+ ${cacheHelpers}
3605
3891
  ${normalizeLocalShareModuleCode}
3606
3892
  ${initializedLocalShareModuleCode}
3607
3893
  ${exportLine}
@@ -3609,7 +3895,7 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3609
3895
  ${prebuildImportLine}
3610
3896
  ${devDynamicImportLine}
3611
3897
  ${importLine}
3612
- ${sharedCacheHelperCode}
3898
+ ${cacheHelpers}
3613
3899
  ${normalizeLocalShareModuleCode}
3614
3900
  let exportModule = ${getSharedCacheReadExpression(cacheDescriptor, treeShakingConsumer)}
3615
3901
  if (exportModule === undefined) {
@@ -3653,6 +3939,7 @@ function addConfiguredShare(pkg, options) {
3653
3939
  if (options) getScopedUsedShares(options).add(pkg);
3654
3940
  }
3655
3941
  const LOCAL_SHARED_IMPORT_MAP_ID = "virtual:mf-localSharedImportMap";
3942
+ const LAZY_CONSUME_ONLY_SHARES_PLACEHOLDER = "__MF_LAZY_CONSUME_ONLY_SHARES__";
3656
3943
  const localOwnerIds = /* @__PURE__ */ new WeakMap();
3657
3944
  let nextLocalOwnerId = 1;
3658
3945
  function getLocalOwnerKey(options) {
@@ -3690,6 +3977,10 @@ function getLocalSharedPackagePath(pkg, shareItem, options) {
3690
3977
  if (shouldUseDirectReactImport() && pkg === "react") return "react";
3691
3978
  return getConcreteSharedImportSource(pkg, shareItem) || getLocalProviderImportPath(pkg) || getSharedImportSource(pkg, shareItem, options);
3692
3979
  }
3980
+ function getCanonicalSharedKey(pkg, shareItem) {
3981
+ const { request, shareKey } = shareItem.shareConfig;
3982
+ return request !== void 0 || shareKey !== void 0 ? getSharedRuntimeKey(pkg, shareItem) : pkg;
3983
+ }
3693
3984
  function getDirectSharedCacheSeedImportPath(pkg, shareItem) {
3694
3985
  return getConcreteSharedImportSource(pkg, shareItem) || getProjectResolvedImportPath(pkg) || getLocalProviderImportPath(pkg) || pkg;
3695
3986
  }
@@ -3703,7 +3994,7 @@ function generateLocalSharedImportMap(options) {
3703
3994
  import {loadShare} from "@module-federation/runtime";
3704
3995
  ${orderedShares.map((pkg, index) => {
3705
3996
  const shareItem = getNormalizeShareItem(pkg, resolvedOptions);
3706
- if (!shareItem?.shareConfig.eager || shareItem.shareConfig.import === false) return "";
3997
+ if (!shareItem || !shareItem.shareConfig.eager || shareItem.shareConfig.import === false) return "";
3707
3998
  return `import * as __mfEagerShare_${index} from ${toSafeJsLiteral(getLocalSharedPackagePath(pkg, shareItem, options))};`;
3708
3999
  }).filter(Boolean).join("\n")}
3709
4000
  ${normalizeRuntimeShareCode}
@@ -3728,12 +4019,17 @@ function generateLocalSharedImportMap(options) {
3728
4019
  const __mfHostOnly = (name) => async () => {
3729
4020
  throw new Error(\`[Module Federation] Shared module '\${name}' must be provided by host\`);
3730
4021
  };
4022
+ // Replaced by the lazy consume-only share plugin with the keys that only a dynamic
4023
+ // import() reaches, so init() leaves them to that import; an unreplaced string matches no key.
4024
+ const __mfLazyShares = ${JSON.stringify(LAZY_CONSUME_ONLY_SHARES_PLACEHOLDER)};
4025
+ const __mfIsLazyShare = (name) => Array.isArray(__mfLazyShares) && __mfLazyShares.includes(name);
3731
4026
  const __mfConsumeOnly = (name, version, scope, materialize, shareConfig) => ({
3732
4027
  name,
3733
4028
  version,
3734
4029
  scope: [scope],
3735
4030
  loaded: false,
3736
- materialize,
4031
+ materialize: materialize && !__mfIsLazyShare(name),
4032
+ lazy: __mfIsLazyShare(name),
3737
4033
  eager: shareConfig.eager,
3738
4034
  from: ${toSafeJsLiteral(resolvedOptions.name)},
3739
4035
  canLiveRebind: true,
@@ -3743,7 +4039,8 @@ function generateLocalSharedImportMap(options) {
3743
4039
  const importMap = {
3744
4040
  ${orderedShares.map((pkg, index) => {
3745
4041
  const shareItem = getNormalizeShareItem(pkg, resolvedOptions);
3746
- if (shareItem?.shareConfig.import === false) return `
4042
+ if (!shareItem) return "";
4043
+ if (shareItem.shareConfig.import === false) return `
3747
4044
  ${toSafeJsLiteral(pkg)}: __mfHostOnly(${toSafeJsLiteral(pkg)})`;
3748
4045
  return `
3749
4046
  ${toSafeJsLiteral(pkg)}: async () => {
@@ -3759,7 +4056,7 @@ function generateLocalSharedImportMap(options) {
3759
4056
  const shareItem = getNormalizeShareItem(key, resolvedOptions);
3760
4057
  if (!shareItem) return null;
3761
4058
  const isReactFamily = key.startsWith("react/") || key === "react-dom/client";
3762
- const cacheKeys = [key, ...key === "react-dom/client" ? ["react-dom"] : []].flatMap((pkg) => {
4059
+ const cacheKeys = [key, ...key === "react-dom/client" ? [getPackageName(REACT_DOM_CLIENT_SHARE)] : []].flatMap((pkg) => {
3763
4060
  const descriptor = getSharedCacheDescriptor(pkg, shareItem);
3764
4061
  return [descriptor.canonical, ...descriptor.aliases ?? []];
3765
4062
  });
@@ -3771,7 +4068,7 @@ function generateLocalSharedImportMap(options) {
3771
4068
  const canLiveRebind = shareItem.shareConfig.import === false || detectedNamedExports !== void 0;
3772
4069
  const treeShakingConfig = canLiveRebind ? shareItem.shareConfig.treeShaking : void 0;
3773
4070
  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)}})`;
4071
+ ${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
4072
  const treeShakingUsage = treeShakingConfig ? getTreeShakingExportUsage(key, shareItem, shareItem.name, options) : void 0;
3776
4073
  const treeShakingProviderExports = treeShakingUsage?.kind === "exports" ? treeShakingUsage.usedExports : [];
3777
4074
  const treeShakingUsedExports = resolvedOptions.injectTreeShakingUsedExports === false ? treeShakingConfig?.usedExports || [] : treeShakingProviderExports;
@@ -3842,6 +4139,8 @@ function generateLocalSharedImportMap(options) {
3842
4139
  requiredVersion: ${toSafeJsLiteral(shareItem.shareConfig.requiredVersion)},
3843
4140
  strictVersion: ${shareItem.shareConfig.strictVersion},
3844
4141
  eager: ${Boolean(shareItem.shareConfig.eager)},
4142
+ ${shareItem.shareConfig.request !== void 0 ? `request: ${toSafeJsLiteral(shareItem.shareConfig.request)},` : ""}
4143
+ ${shareItem.shareConfig.shareKey !== void 0 ? `shareKey: ${toSafeJsLiteral(shareItem.shareConfig.shareKey)},` : ""}
3845
4144
  ${shareItem.shareConfig.import === false ? "import: false," : ""}
3846
4145
  },
3847
4146
  ${treeShakingConfig ? `treeShaking: {
@@ -3894,11 +4193,17 @@ function expandSharedPrefixKey(prefixKey, used) {
3894
4193
  function getOrderedUsedShares(options) {
3895
4194
  const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
3896
4195
  const used = getUsedShares(options);
3897
- const shares = new Set(used);
4196
+ const shares = /* @__PURE__ */ new Set();
4197
+ const addShare = (pkg) => {
4198
+ const shareItem = getNormalizeShareItem(pkg, resolvedOptions);
4199
+ shares.add(shareItem ? getCanonicalSharedKey(pkg, shareItem) : pkg);
4200
+ };
4201
+ used.forEach(addShare);
3898
4202
  Object.keys(resolvedOptions.shared ?? {}).forEach((pkg) => {
3899
- if (!pkg.endsWith("/")) shares.add(pkg);
4203
+ const share = resolvedOptions.shared?.[pkg];
4204
+ if (share && !getSharedRequest(pkg, share).endsWith("/")) addShare(pkg);
3900
4205
  });
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);
4206
+ 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
4207
  return orderSharedDependenciesFirst(Array.from(shares).sort((a, b) => {
3903
4208
  const priority = (pkg) => pkg === "react" ? 0 : pkg === "react-dom" ? 1 : pkg.startsWith("react/") ? 2 : 3;
3904
4209
  return priority(a) - priority(b) || a.localeCompare(b);
@@ -3911,7 +4216,8 @@ function getMaterializedShares(options) {
3911
4216
  const usedForEager = options ? usedSharesByOptions.get(options) ?? [] : usedShares;
3912
4217
  for (const [pkg, share] of Object.entries(resolvedOptions.shared ?? {})) {
3913
4218
  if (!share.shareConfig?.eager) continue;
3914
- if (pkg.endsWith("/")) for (const concrete of expandSharedPrefixKey(pkg, usedForEager)) shares.add(concrete);
4219
+ const request = getSharedRequest(pkg, share);
4220
+ if (request.endsWith("/")) for (const concrete of expandSharedPrefixKey(request, usedForEager)) shares.add(concrete);
3915
4221
  else shares.add(pkg);
3916
4222
  }
3917
4223
  const configured = /* @__PURE__ */ new Map();
@@ -3939,10 +4245,14 @@ function getMaterializedShares(options) {
3939
4245
  }
3940
4246
  }
3941
4247
  }
3942
- return orderSharedDependenciesFirst([...shares].sort((a, b) => {
4248
+ const sorted = [...shares].sort((a, b) => {
3943
4249
  const priority = (pkg) => pkg === "react" ? 0 : pkg === "react-dom" ? 1 : pkg.startsWith("react/") ? 2 : 3;
3944
4250
  return priority(a) - priority(b) || a.localeCompare(b);
3945
- }));
4251
+ });
4252
+ return orderSharedDependenciesFirst([...new Set(sorted.map((pkg) => {
4253
+ const shareItem = getNormalizeShareItem(pkg, resolvedOptions);
4254
+ return shareItem ? getCanonicalSharedKey(pkg, shareItem) : pkg;
4255
+ }))]);
3946
4256
  }
3947
4257
  /** Shared keys a share's package.json depends on (roots stand in for their subpaths, subpaths for their root), keyed by share. */
3948
4258
  function getSharePrerequisites(ordered) {
@@ -4030,9 +4340,30 @@ function orderSharedDependenciesFirst(sharedPackages) {
4030
4340
  }
4031
4341
  function getShareItemForPreload(pkg, options = getNormalizeModuleFederationOptions()) {
4032
4342
  const shared = options.shared;
4033
- const wildcardKey = `${getPackageName(pkg)}/`;
4343
+ const packageName = getPackageName(pkg);
4344
+ const wildcardKey = `${packageName}/`;
4034
4345
  if (isExplicitSharedKey(pkg, options)) return shared[pkg];
4035
4346
  if (isExplicitSharedKey(wildcardKey, options)) return shared[wildcardKey];
4347
+ if (pkg !== packageName && isExplicitSharedKey(packageName, options) && shared[packageName]?.shareConfig.import !== false && getCommonSharedSubpaths(packageName).includes(pkg)) return shared[packageName];
4348
+ const shareItem = getNormalizeShareItem(pkg, options);
4349
+ if (!shareItem) return void 0;
4350
+ if (shareItem.shareConfig.request === void 0 && shareItem.shareConfig.shareKey === void 0) return;
4351
+ const runtimeKey = getSharedRuntimeKey(pkg, shareItem);
4352
+ if (runtimeKey === pkg || runtimeKey.endsWith("/") && (pkg === runtimeKey.slice(0, -1) || pkg.startsWith(runtimeKey))) return shareItem;
4353
+ }
4354
+ /**
4355
+ * Entry-injected renderer wrappers (see `REACT_DOM_CLIENT_SHARE`) assign
4356
+ * `createRoot` only after `initPromise` and a dynamic import, so a standalone
4357
+ * remote must evaluate that wrapper before the app entry. The subpath is often
4358
+ * absent from `getMaterializedShares()` when pending shares is emitted:
4359
+ * `react-dom/` collapses to `react-dom`, and the entry import may not be
4360
+ * recorded yet.
4361
+ */
4362
+ function shouldPreloadEntryDeferredReactDomClient(options) {
4363
+ if (options.hostInitInjectLocation !== "entry" || !isRemoteContainer(options)) return false;
4364
+ const shareItem = getShareItemForPreload(REACT_DOM_CLIENT_SHARE, options);
4365
+ if (!shareItem || shareItem.shareConfig.singleton !== true) return false;
4366
+ return shareItem.shareConfig.import !== false && !shareItem.shareConfig.treeShaking;
4036
4367
  }
4037
4368
  function generateSharedCacheSeedItem(pkg, shareItem, importPath, options = getNormalizeModuleFederationOptions()) {
4038
4369
  const cacheDescriptor = getSharedCacheDescriptor(pkg, shareItem);
@@ -4217,7 +4548,28 @@ const externalSharedProviderSelectionHelperCode = `const __mfSelectExternalShare
4217
4548
  ) return undefined;
4218
4549
  return { provider, scopeRootProvider };
4219
4550
  };`;
4220
- function generateRuntimeSharedCacheSeedCode(shareStrategy, options) {
4551
+ /**
4552
+ * A consume-only stub never outranks a provider: when registering this container's
4553
+ * `import: false` share replaces an unloaded provider of the same version (#1311),
4554
+ * the `afterRegisterShare` hook restores the provider. Registered once per instance.
4555
+ */
4556
+ function generateKeepProvidersOverStubsCode(runtimeVar) {
4557
+ return `if (!${runtimeVar}.__mfKeepAdoptedProviders) {
4558
+ ${runtimeVar}.__mfKeepAdoptedProviders = true;
4559
+ ${runtimeVar}.sharedHandler?.hooks?.lifecycle?.afterRegisterShare?.on?.((args) => {
4560
+ const { shared, previousShared, registeredShared } = args || {};
4561
+ if (
4562
+ shared?.shareConfig?.import !== false ||
4563
+ registeredShared !== shared ||
4564
+ !previousShared ||
4565
+ previousShared.shareConfig?.import === false
4566
+ ) return;
4567
+ const versions = ${runtimeVar}.shareScopeMap?.[args.scope]?.[args.pkgName];
4568
+ if (versions && versions[shared.version] === shared) versions[shared.version] = previousShared;
4569
+ });
4570
+ }`;
4571
+ }
4572
+ function generateRuntimeSharedCacheSeedCode(shareStrategy, options, command = "build") {
4221
4573
  const seedBatches = getShareBatches(options, false);
4222
4574
  const seedOrder = seedBatches.flat();
4223
4575
  const seedIndex = new Map(seedOrder.map((pkg, index) => [pkg, index]));
@@ -4231,7 +4583,7 @@ function generateRuntimeSharedCacheSeedCode(shareStrategy, options) {
4231
4583
  // import and set materialize. An import:false share has no local fallback
4232
4584
  // though, so on a cold request (materialize not set yet) it must still be
4233
4585
  // 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));
4586
+ const __mfSeedKeys = __mfSeedOrder.filter((pkg) => usedShared[pkg] && (usedShared[pkg].materialize !== false || (usedShared[pkg].shareConfig?.import === false && !usedShared[pkg].lazy)));
4235
4587
  __mfModuleCache.providerInit ||= new Map();
4236
4588
  const __mfInitializeProviderOnce = (key, initialize) => {
4237
4589
  const existing = __mfModuleCache.providerInit.get(key);
@@ -4264,6 +4616,16 @@ function generateRuntimeSharedCacheSeedCode(shareStrategy, options) {
4264
4616
  );
4265
4617
  return;
4266
4618
  }
4619
+ ${command === "serve" ? `// A pending webpack provider for this share, or for its package when this
4620
+ // is a subpath, is only bridged after init(). Seeding the local fallback now
4621
+ // would evaluate the package's dev proxy, which snapshots its exports, before
4622
+ // the bridge runs and pin a second copy. The proxy seeds itself on first import.
4623
+ if (
4624
+ typeof __mfGetPendingExternalSharedProvider === 'function' &&
4625
+ __mfGetPendingExternalSharedProvider(pkg, share)
4626
+ ) {
4627
+ return;
4628
+ }` : ""}
4267
4629
  const externalProvider = typeof __mfGetExternalSharedProvider === 'function'
4268
4630
  ? __mfGetExternalSharedProvider(pkg, share)
4269
4631
  : undefined;
@@ -4292,6 +4654,12 @@ function generateRuntimeSharedCacheSeedCode(shareStrategy, options) {
4292
4654
  const mod = typeof factory === "function" ? factory() : factory;
4293
4655
  return Promise.resolve(mod);
4294
4656
  });
4657
+ // The seeded local copy is what this container's consumers are bound to.
4658
+ // Flag the Runtime's provider as eager so a same-version sibling cannot
4659
+ // take over the share scope slot via the Runtime's name tie-break.
4660
+ for (const provider of initRes.options.shared?.[pkg] || []) {
4661
+ if (provider.get === share.get) provider.eager = true;
4662
+ }
4295
4663
  ${normalizeRuntimeShareCode}
4296
4664
  const normalizedModule = __mfNormalizeRuntimeShare(resolved);
4297
4665
  const exportModule = normalizedModule === resolved ? {...resolved} : normalizedModule;
@@ -4564,7 +4932,7 @@ function generateTreeShakingSnapshotPluginCode(enabled) {
4564
4932
  },
4565
4933
  });`;
4566
4934
  }
4567
- function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(options), command = "build", exportConditions) {
4935
+ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(options), command = "build", exportConditions, isSsrBuild = false) {
4568
4936
  const needsSharedProviderSelectionHelper = hasShared(options);
4569
4937
  const hasTreeShakingShared = Object.values(options.shared ?? {}).some((share) => !!share?.shareConfig.treeShaking);
4570
4938
  const hasMultipleShareScopes = Array.isArray(options.shareScope);
@@ -4576,7 +4944,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
4576
4944
  ...hasTreeShakingShared ? ["getRemoteEntry"] : []
4577
4945
  ].join(", ");
4578
4946
  const runtimeHelperImports = [...hasTreeShakingShared ? ["global as runtimeGlobal"] : [], ...needsSharedProviderSelectionHelper ? ["share as runtimeShare"] : []];
4579
- const pluginImportNames = options.runtimePlugins.map((p, i) => {
4947
+ const pluginImportNames = filterRuntimePluginsForTarget(options.runtimePlugins, SSR_ONLY_RUNTIME_PLUGINS, isSsrBuild).map((p, i) => {
4580
4948
  if (typeof p === "string") return [
4581
4949
  `$runtimePlugin_${i}`,
4582
4950
  `import $runtimePlugin_${i} from "${p}";`,
@@ -4899,13 +5267,36 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
4899
5267
  };
4900
5268
  }
4901
5269
  const runtimeResolveShareHook = initRes.sharedHandler.hooks.lifecycle.resolveShare;
5270
+ // Registering this container's shares lets its consume-only stub displace the parent's
5271
+ // unloaded same-version provider whenever this container's name sorts after the parent's
5272
+ // (the Runtime keeps the higher name). Nothing can be loaded from a stub, so put the
5273
+ // provider back; a share bridged later, e.g. from a lazy import(), still finds it.
5274
+ ${generateKeepProvidersOverStubsCode("initRes")}
4902
5275
  const __mfRuntimeProviderOrigins = new WeakMap();
4903
5276
  runtimeResolveShareHook.on((args) => {
4904
5277
  const loadId = args.shareInfo?.[__mfRuntimeShareLoadIdKey];
4905
5278
  const resolver = args.resolver;
4906
5279
  if (typeof resolver !== "function") return args;
4907
5280
  const instrumentedResolver = (...resolverArgs) => {
4908
- const resolved = resolver(...resolverArgs);
5281
+ let resolved = resolver(...resolverArgs);
5282
+ // A consume-only stub can never be loaded. The Runtime still settles on one when
5283
+ // it carries the highest version, e.g. a parent that registers its provider under
5284
+ // "0.0.0"; hand back the provider this container selects for itself instead.
5285
+ if (
5286
+ resolved?.shared?.shareConfig?.import === false &&
5287
+ typeof __mfSelectSharedProvider === "function" &&
5288
+ usedShared[args.pkgName]
5289
+ ) {
5290
+ const provider = __mfSelectSharedProvider(
5291
+ args.shareScopeMap?.[args.scope]?.[args.pkgName],
5292
+ args.pkgName,
5293
+ usedShared[args.pkgName],
5294
+ '${options.shareStrategy}'
5295
+ );
5296
+ if (provider && provider.shareConfig?.import !== false) {
5297
+ resolved = { shared: provider, useTreesShaking: resolved.useTreesShaking };
5298
+ }
5299
+ }
4909
5300
  const selectedProvider = resolved?.shared;
4910
5301
  if (
4911
5302
  selectedProvider &&
@@ -5318,7 +5709,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
5318
5709
  );
5319
5710
  }
5320
5711
  }
5321
- ${generateRuntimeSharedCacheSeedCode(options.shareStrategy, options)}
5712
+ ${generateRuntimeSharedCacheSeedCode(options.shareStrategy, options, command)}
5322
5713
  ${initializeSharingCode}
5323
5714
  __mfRestoreForeignSharedProviders();
5324
5715
  // Calling provider.get() marks a provider as loaded. Wait until the Runtime has
@@ -5336,9 +5727,13 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
5336
5727
  );
5337
5728
  }));
5338
5729
  };
5339
- await __mfBridgeSharedProviders();
5340
5730
  if (__mfUsesWebpackShareScope) {
5731
+ // A webpack host's loadShare() awaits initializeSharing(), which awaits this
5732
+ // init(). Bridging here would call the host's provider.get() and re-enter
5733
+ // loadShare(), so both promises wait on each other forever (#1326).
5341
5734
  __mfLateBridgeShared = __mfBridgeSharedProviders;
5735
+ } else {
5736
+ await __mfBridgeSharedProviders();
5342
5737
  }
5343
5738
  try {
5344
5739
  const allInstances = globalThis.__FEDERATION__?.__SHARE__;
@@ -5492,6 +5887,29 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
5492
5887
  (pkg) => !__mfBlockedSeedKeys.has(__mfSeedIndex.get(pkg))
5493
5888
  ));
5494
5889
  await __mfSeedLocalShared(__mfReadyDeferredSeedKeys);
5890
+ ${command === "build" ? `// A consume-only share reached only through import() is bridged when that import runs
5891
+ // (see pluginLazyConsumeOnlyShares), through the same provider selection init() uses.
5892
+ const __mfLazyShareLoads = new Map();
5893
+ __mfResolveState.loadLazyShares = async (names) => {
5894
+ const requested = new Set(names);
5895
+ for (const batch of __mfMaterializedShareBatches) await Promise.all(batch.filter((pkg) => requested.has(pkg)).map((pkg) => {
5896
+ const share = usedShared[pkg];
5897
+ if (!share || !share.lazy || !__mfIsRuntimeOnlySharePending(pkg)) return;
5898
+ let load = __mfLazyShareLoads.get(pkg);
5899
+ if (!load) {
5900
+ load = __mfBridgeExternalSharedProvider(
5901
+ pkg,
5902
+ share,
5903
+ ${hasMultipleShareScopes ? "getShareVersions(pkg, share)" : "shared[pkg]"},
5904
+ initialShared[pkg],
5905
+ undefined
5906
+ ).then(() => __mfIsRuntimeOnlySharePending(pkg) ? __mfResolveImportFalseShared(pkg, share) : undefined);
5907
+ load.catch(() => __mfLazyShareLoads.delete(pkg));
5908
+ __mfLazyShareLoads.set(pkg, load);
5909
+ }
5910
+ return load;
5911
+ }));
5912
+ };` : ""}
5495
5913
  initResolve(initRes)
5496
5914
  return initRes
5497
5915
  }
@@ -5508,8 +5926,13 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
5508
5926
  ${guardHostAutoInit ? `let __mfInitPromise;
5509
5927
  function __mfGuardedInit(shared, initScope, remoteEntryInitOptions) {
5510
5928
  if (shared === undefined && __mfInitPromise) return __mfInitPromise;
5511
- __mfInitPromise = init(shared, initScope, remoteEntryInitOptions);
5512
- return __mfInitPromise;
5929
+ // A call skipped by the circular-init guard resolves to undefined and must not
5930
+ // replace the cached result of the call that actually initialized the container.
5931
+ const prev = __mfInitPromise;
5932
+ const next = init(shared, initScope, remoteEntryInitOptions);
5933
+ __mfInitPromise = prev ? next.then((res) => (res === undefined ? prev : res)) : next;
5934
+ if (prev) __mfInitPromise.catch(() => {});
5935
+ return next;
5513
5936
  }
5514
5937
  export { __mfGuardedInit as init, getExposes as get }` : `export { init, getExposes as get }`}
5515
5938
  `;
@@ -5590,7 +6013,8 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build", options
5590
6013
  for (const __mfHostInitShareBatch of __mfHostInitShareBatches) {
5591
6014
  await Promise.all(__mfHostInitShareBatch.map(async (pkg) => {
5592
6015
  const share = usedShared[pkg];
5593
- if (!share || share.materialize === false) return;
6016
+ // A standalone container has no dynamic-import boundary to load a lazy share behind.
6017
+ if (!share || (share.materialize === false && !share.lazy)) return;
5594
6018
  // remoteEntry.init resolves tree-enabled shares into the
5595
6019
  // coverage-aware cache. Never republish that selected partial under
5596
6020
  // a generic full-module key here.
@@ -5621,20 +6045,7 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build", options
5621
6045
  // container's own stub and lets it displace an unloaded adopted
5622
6046
  // provider whenever this container's name sorts after the provider's
5623
6047
  // (#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
- }
6048
+ ${generateKeepProvidersOverStubsCode("runtime")}
5638
6049
  for (const instance of globalThis.__FEDERATION__?.__INSTANCES__ || []) {
5639
6050
  for (const scopeName of __mfScopeNames) {
5640
6051
  const versions = instance?.shareScopeMap?.[scopeName]?.[pkg];
@@ -5734,22 +6145,32 @@ function getPendingSharesState(options) {
5734
6145
  }
5735
6146
  function generatePendingSharesCode(command = "build", options) {
5736
6147
  const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
5737
- const pendingShareImports = command === "build" ? getMaterializedShares(options).filter((pkg) => {
6148
+ const pendingSharePkgs = command === "build" ? getMaterializedShares(options).filter((pkg) => {
5738
6149
  const shareItem = getShareItemForPreload(pkg, resolvedOptions);
5739
6150
  if (!shareItem || pkg.endsWith("/")) return false;
5740
6151
  if (shareItem.shareConfig.eager) return false;
5741
6152
  return shareItem.shareConfig.import !== false && !shareItem.shareConfig.treeShaking;
5742
- }).map((pkg) => `[${toSafeJsLiteral(pkg)}, () => import(${toSafeJsLiteral(getLoadShareModulePath(pkg, false, options))})]`) : [];
6153
+ }) : [];
6154
+ if (command === "build" && shouldPreloadEntryDeferredReactDomClient(resolvedOptions) && !pendingSharePkgs.includes("react-dom/client")) pendingSharePkgs.push(REACT_DOM_CLIENT_SHARE);
6155
+ const pendingShareImports = pendingSharePkgs.map((pkg) => `[${toSafeJsLiteral(pkg)}, () => import(${toSafeJsLiteral(getLoadShareModulePath(pkg, false, options))})]`);
5743
6156
  return `
5744
6157
  ${getRuntimeModuleCacheBootstrapCode()}
5745
6158
  ${sharedCacheHelperCode}
5746
6159
  const __mfPendingShareImports = [${pendingShareImports.join(", ")}];
5747
6160
  export async function preloadPendingShares() {
5748
6161
  if (__mfPendingShareImports.length === 0) return;
6162
+ const __mfRendererShare = ${toSafeJsLiteral(REACT_DOM_CLIENT_SHARE)};
6163
+ const __mfRendererParent = ${toSafeJsLiteral(getPackageName(REACT_DOM_CLIENT_SHARE))};
5749
6164
  const {usedShared} = await import("${getLocalSharedImportMapPath(options)}");
5750
6165
  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;
6166
+ const exactShare = usedShared[pkg];
6167
+ const share = exactShare ?? (pkg === __mfRendererShare ? usedShared[__mfRendererParent] : undefined);
6168
+ if (!share || share.treeShaking || share.shareConfig?.import === false) return;
6169
+ // The collapsed parent does not mark the renderer subpath materialized until the entry
6170
+ // imports it, and that import map can be emitted first. The deferred renderer wrapper
6171
+ // still has to run before a standalone entry reads createRoot. A cache hit (the host
6172
+ // renderer) skips load(), so a nested leaf does not import its own client.
6173
+ if (exactShare && exactShare.materialize === false && pkg !== __mfRendererShare) return;
5753
6174
  const cacheDescriptor = __mfGetSharedCacheDescriptor(pkg, share.shareConfig?.singleton, share.version, share.scope);
5754
6175
  if (__mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined) return;
5755
6176
  await load().catch((err) => console.warn("[module-federation] shared preload failed:", pkg, err));
@@ -6413,7 +6834,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
6413
6834
  }
6414
6835
  ` : "";
6415
6836
  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];
6837
+ const shareItem = getNormalizeShareItem(pkg, federationOptions);
6417
6838
  const isExplicitShare = Object.hasOwn(federationOptions.shared, pkg);
6418
6839
  return shareItem?.shareConfig?.singleton === true && shareItem?.shareConfig?.import !== false && !shareItem?.shareConfig?.treeShaking && (isExplicitShare || typeof shareItem?.shareConfig?.import === "string" || Boolean(getProjectResolvedImportPath(pkg)));
6419
6840
  }).map((pkg) => toViteEncodedId(getLoadShareModulePath(pkg, false, federationOptions))) : [];
@@ -6842,17 +7263,20 @@ function checkAliasConflicts(options) {
6842
7263
  }
6843
7264
  return false;
6844
7265
  };
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
- });
7266
+ for (const sharedKey of sharedKeys) {
7267
+ const request = getSharedRequest(sharedKey, shared[sharedKey]);
7268
+ for (const aliasEntry of userAliases) {
7269
+ const replacement = aliasEntry.replacement;
7270
+ if (!matchesSharedKey(aliasEntry, request)) continue;
7271
+ if (replacement === "$1") break;
7272
+ if (typeof replacement === "string") {
7273
+ if (getPackageNameFromNodeModulePath(replacement) === (request.endsWith("/") ? request.slice(0, -1) : request)) continue;
7274
+ conflicts.push({
7275
+ sharedModule: sharedKey,
7276
+ alias: String(aliasEntry.find),
7277
+ target: replacement
7278
+ });
7279
+ }
6856
7280
  }
6857
7281
  }
6858
7282
  if (conflicts.length > 0) {
@@ -7567,9 +7991,6 @@ function pluginExternalRuntimeCore() {
7567
7991
  };
7568
7992
  }
7569
7993
  //#endregion
7570
- //#region package.json
7571
- var version$1 = "1.22.1";
7572
- //#endregion
7573
7994
  //#region src/virtualModules/index.ts
7574
7995
  function initVirtualModules(command, remoteEntryId, enableSsrInit = false, options) {
7575
7996
  writeLocalSharedImportMap(options);
@@ -7587,6 +8008,11 @@ const JS_EXTENSIONS = [
7587
8008
  ".mjs",
7588
8009
  ".cjs"
7589
8010
  ];
8011
+ /** A module path without its JS extension, so `./src/App` matches `/root/src/App.tsx`. */
8012
+ const stripKnownJsExtension = (file) => {
8013
+ const ext = path$1.extname(file);
8014
+ return JS_EXTENSIONS.includes(ext) ? path$1.join(path$1.dirname(file), path$1.basename(file, ext)) : file;
8015
+ };
7590
8016
  /**
7591
8017
  * Creates an empty asset map structure for tracking JS and CSS assets
7592
8018
  * @returns Initialized asset map with sync/async arrays for JS and CSS
@@ -7705,8 +8131,8 @@ const processModuleAssets = (bundle, filesMap, moduleMatcher, options = {}) => {
7705
8131
  const comparableModulePath = options.root ? path$1.resolve(options.root, modulePath) : modulePath;
7706
8132
  const comparableModulePaths = [comparableModulePath];
7707
8133
  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)));
8134
+ const stripped = stripKnownJsExtension(comparableModulePath);
8135
+ if (stripped !== comparableModulePath) comparableModulePaths.push(stripped);
7710
8136
  }
7711
8137
  const matchKey = comparableModulePaths.map(moduleMatcher).find(Boolean);
7712
8138
  if (!matchKey) continue;
@@ -7767,6 +8193,118 @@ const buildFileToShareKeyMap = async (shareKeys, resolveFn, options) => {
7767
8193
  return fileToShareKey;
7768
8194
  };
7769
8195
  //#endregion
8196
+ //#region src/plugins/pluginLazyConsumeOnlyShares.ts
8197
+ const chunkModuleIds = (chunk) => [...chunk.facadeModuleId ? [chunk.facadeModuleId] : [], ...chunk.moduleIds ?? Object.keys(chunk.modules ?? {})];
8198
+ function buildLazyShareGraph(chunks, wrapperShares, exposeModules) {
8199
+ const sharesInChunk = /* @__PURE__ */ new Map();
8200
+ const startupRoots = [];
8201
+ for (const [fileName, chunk] of Object.entries(chunks)) {
8202
+ if (chunk.type !== "chunk") continue;
8203
+ const moduleIds = chunkModuleIds(chunk);
8204
+ sharesInChunk.set(fileName, new Set(moduleIds.map((id) => wrapperShares.get(normalizeVirtualModuleId(id))).filter((share) => share !== void 0)));
8205
+ if (chunk.isEntry || moduleIds.some((id) => exposeModules.has(stripKnownJsExtension(id)))) startupRoots.push(fileName);
8206
+ }
8207
+ const sharesInClosure = (roots) => new Set(collectStaticChunks(chunks, roots).flatMap((chunk) => [...sharesInChunk.get(chunk.fileName) ?? []]));
8208
+ const lazyShares = new Set([...sharesInChunk.values()].flatMap((shares) => [...shares]));
8209
+ for (const share of sharesInClosure(startupRoots)) lazyShares.delete(share);
8210
+ const sharesByChunk = /* @__PURE__ */ new Map();
8211
+ if (lazyShares.size > 0) for (const fileName of sharesInChunk.keys()) {
8212
+ const shares = [...sharesInClosure([fileName])].filter((share) => lazyShares.has(share));
8213
+ if (shares.length > 0) sharesByChunk.set(fileName, shares.sort());
8214
+ }
8215
+ return {
8216
+ lazyShares,
8217
+ sharesByChunk
8218
+ };
8219
+ }
8220
+ const COMMENTS = String.raw`(?:\s|\/\*[\s\S]*?\*\/|\/\/[^\n]*\n)*`;
8221
+ const DYNAMIC_IMPORT_REGEX = new RegExp(String.raw`\bimport\(${COMMENTS}(["'` + "`" + String.raw`])([^"'` + "`" + String.raw`\n]+)\1${COMMENTS}\)`, "g");
8222
+ const QUOTES = [
8223
+ "\"",
8224
+ "'",
8225
+ "`"
8226
+ ];
8227
+ /**
8228
+ * A consume-only (`import: false`) share that only a dynamic `import()` reaches is
8229
+ * left out of `init()` and bridged when that import runs: the import expression is
8230
+ * wrapped so the share is in the cache before the chunk evaluates. There is no
8231
+ * other async boundary in an ESM graph without top-level await, so a wrapper
8232
+ * reached statically from an entry or an expose keeps loading during `init()`.
8233
+ */
8234
+ function pluginLazyConsumeOnlyShares(options) {
8235
+ let viteConfig;
8236
+ const graphs = /* @__PURE__ */ new WeakMap();
8237
+ const helperName = `__mfLoadLazyShares_${options.internalName.replace(/[^A-Za-z0-9_$]/g, "_")}`;
8238
+ return {
8239
+ name: "module-federation:lazy-consume-only-shares",
8240
+ apply: "build",
8241
+ configResolved(config) {
8242
+ viteConfig = config;
8243
+ },
8244
+ renderChunk(code, chunk, _outputOptions, meta) {
8245
+ const renderedChunk = chunk;
8246
+ const chunks = meta?.chunks;
8247
+ if (!chunks || Object.keys(options.exposes).length === 0) return null;
8248
+ if (isServerBuildContext(this, viteConfig)) return null;
8249
+ let graph = graphs.get(chunks);
8250
+ if (!graph) {
8251
+ const isRolldown = getIsRolldown(this);
8252
+ const wrapperShares = /* @__PURE__ */ new Map();
8253
+ for (const shareKey of getUsedShares(options)) {
8254
+ const shareConfig = getNormalizeShareItem(shareKey, options)?.shareConfig;
8255
+ if (shareConfig?.import !== false || shareConfig.eager || shareConfig.treeShaking) continue;
8256
+ wrapperShares.set(normalizeVirtualModuleId(getLoadShareModulePath(shareKey, isRolldown, options)), shareKey);
8257
+ }
8258
+ const root = viteConfig?.root ?? process.cwd();
8259
+ graph = buildLazyShareGraph(chunks, wrapperShares, new Set(Object.values(options.exposes).map((expose) => stripKnownJsExtension(path$1.resolve(root, expose.import)))));
8260
+ graphs.set(chunks, graph);
8261
+ }
8262
+ if (graph.lazyShares.size === 0) return null;
8263
+ const rewriter = new CodeRewriter(code);
8264
+ let edited = false;
8265
+ const importMapId = normalizeVirtualModuleId(getLocalSharedImportMapPath(options));
8266
+ if (chunkModuleIds(renderedChunk).some((id) => normalizeVirtualModuleId(id) === importMapId)) for (const quote of QUOTES) {
8267
+ const literal = `${quote}${LAZY_CONSUME_ONLY_SHARES_PLACEHOLDER}${quote}`;
8268
+ const start = code.indexOf(literal);
8269
+ if (start === -1) continue;
8270
+ rewriter.overwrite(start, start + literal.length, JSON.stringify([...graph.lazyShares].sort()));
8271
+ edited = true;
8272
+ break;
8273
+ }
8274
+ const chunkDir = path$1.posix.dirname(renderedChunk.fileName);
8275
+ const codePositions = createCodePositionMap(code);
8276
+ let usesHelper = false;
8277
+ for (const match of code.matchAll(DYNAMIC_IMPORT_REGEX)) {
8278
+ const [expression, , specifier] = match;
8279
+ const start = match.index;
8280
+ if (!codePositions[start]) continue;
8281
+ const target = path$1.posix.normalize(path$1.posix.join(chunkDir, specifier));
8282
+ const shares = graph.sharesByChunk.get(target);
8283
+ if (!shares || !renderedChunk.dynamicImports.includes(target)) continue;
8284
+ rewriter.overwrite(start, start + expression.length, `${helperName}(${JSON.stringify(shares)}).then(() => ${expression})`);
8285
+ usesHelper = edited = true;
8286
+ }
8287
+ if (!edited) return null;
8288
+ if (usesHelper) {
8289
+ const stateKey = JSON.stringify(getRuntimeInitGlobalKey(getRuntimeInitStatusImportId(options)));
8290
+ rewriter.overwrite(code.length, code.length, `
8291
+ function ${helperName}(names) {
8292
+ const state = globalThis[${stateKey}];
8293
+ return state ? state.initPromise.then(() => (typeof state.loadLazyShares === "function" ? state.loadLazyShares(names) : undefined)) : Promise.resolve();
8294
+ }
8295
+ `);
8296
+ }
8297
+ return {
8298
+ code: rewriter.toString(),
8299
+ map: rewriter.generateMap(renderedChunk.fileName)
8300
+ };
8301
+ }
8302
+ };
8303
+ }
8304
+ //#endregion
8305
+ //#region package.json
8306
+ var version$1 = "1.23.0";
8307
+ //#endregion
7770
8308
  //#region src/virtualModules/virtualExposesSSR.ts
7771
8309
  /**
7772
8310
  * Virtual module ID for the SSR exposes map.
@@ -7821,7 +8359,8 @@ function getSsrFileNameParts(browserFilename) {
7821
8359
  ext
7822
8360
  };
7823
8361
  }
7824
- function getSsrRemoteEntryFileName(browserFilename) {
8362
+ function getSsrRemoteEntryFileName(options, browserFilename = options.filename) {
8363
+ if (options.ssrFilename) return options.ssrFilename;
7825
8364
  const { base, ext } = getSsrFileNameParts(browserFilename);
7826
8365
  return `${base}.ssr${ext ?? ".js"}`;
7827
8366
  }
@@ -7835,14 +8374,15 @@ function getSsrSharedSingletons(options) {
7835
8374
  const result = {};
7836
8375
  for (const [pkg, share] of Object.entries(options.shared)) {
7837
8376
  if (!share.shareConfig.singleton) continue;
7838
- if (pkg.endsWith("/")) {
7839
- for (const concrete of expandSharedPrefixKey(pkg, used)) result[concrete] = {
8377
+ const request = getSharedRequest(pkg, share);
8378
+ if (request.endsWith("/")) {
8379
+ for (const concrete of expandSharedPrefixKey(request, used)) result[getSharedRuntimeKey(concrete, share)] = {
7840
8380
  ...share,
7841
8381
  name: concrete
7842
8382
  };
7843
8383
  continue;
7844
8384
  }
7845
- result[pkg] = share;
8385
+ result[getSharedRuntimeKey(pkg, share)] = share;
7846
8386
  }
7847
8387
  return result;
7848
8388
  }
@@ -8187,7 +8727,7 @@ const Manifest = (providedOptions) => {
8187
8727
  type: "module"
8188
8728
  },
8189
8729
  ssrRemoteEntry: {
8190
- name: getSsrRemoteEntryFileName(devRemoteEntryFile),
8730
+ name: getSsrRemoteEntryFileName(mfOptions, devRemoteEntryFile),
8191
8731
  path: "/__mf_ssr__/",
8192
8732
  type: "module"
8193
8733
  },
@@ -8230,6 +8770,33 @@ const Manifest = (providedOptions) => {
8230
8770
  publicPath = mfOptions.publicPath === "auto" ? "auto" : resolvePublicPath(mfOptions, base, _originalConfigBase);
8231
8771
  },
8232
8772
  /**
8773
+ * A standalone `vite build --ssr` may run with its own `filename`, e.g.
8774
+ * `defineConfig(({ isSsrBuild }) => ...)`. The manifest written by the
8775
+ * earlier client build then advertises an SSR entry derived from the
8776
+ * browser filename, which is not the file this build emitted. Point the
8777
+ * manifest and stats on disk at the emitted SSR entry.
8778
+ */
8779
+ writeBundle(outputOptions) {
8780
+ if (!mfManifestName || _command !== "build" || isConsumerProject) return;
8781
+ const environment = this.environment;
8782
+ if (!(environment ? environment.name === "ssr" : Boolean(viteConfig?.build?.ssr))) return;
8783
+ const ssrEntryName = getSsrRemoteEntryFileName(mfOptions);
8784
+ const outDirs = [...new Set([outputOptions.dir, viteConfig?.environments?.client?.build?.outDir].filter((dir) => typeof dir === "string").map((dir) => path$1.resolve(root, dir)))];
8785
+ if (!outDirs.some((dir) => fs$1.existsSync(path$1.resolve(dir, ssrEntryName)))) return;
8786
+ for (const dir of outDirs) for (const fileName of [mfManifestName, mfManifestStatsName]) {
8787
+ if (!fileName) continue;
8788
+ const file = path$1.resolve(dir, fileName);
8789
+ if (!fs$1.existsSync(file)) continue;
8790
+ try {
8791
+ const data = JSON.parse(fs$1.readFileSync(file, "utf8"));
8792
+ const entry = data?.metaData?.ssrRemoteEntry;
8793
+ if (!entry || typeof entry !== "object" || entry.name === ssrEntryName) continue;
8794
+ entry.name = ssrEntryName;
8795
+ fs$1.writeFileSync(file, JSON.stringify(data));
8796
+ } catch {}
8797
+ }
8798
+ },
8799
+ /**
8233
8800
  * Generates the module federation manifest file
8234
8801
  * @param options - Rollup output options
8235
8802
  * @param bundle - Generated bundle assets
@@ -8239,10 +8806,10 @@ const Manifest = (providedOptions) => {
8239
8806
  if (this.environment?.name === "ssr") return;
8240
8807
  let filesMap = {};
8241
8808
  const foundRemoteEntryFile = findRemoteEntryFile(mfOptions.filename, bundle);
8242
- const expectedSsrRemoteEntryFile = getSsrRemoteEntryFileName(mfOptions.filename);
8809
+ const expectedSsrRemoteEntryFile = getSsrRemoteEntryFileName(mfOptions);
8243
8810
  const foundSsrRemoteEntryFile = Object.values(bundle).find((file) => file.fileName === expectedSsrRemoteEntryFile)?.fileName;
8244
8811
  if (foundRemoteEntryFile) remoteEntryFile = foundRemoteEntryFile;
8245
- ssrRemoteEntryFile = foundSsrRemoteEntryFile || (_command === "serve" ? getSsrRemoteEntryFileName(resolveHashPlaceholderFileName(mfOptions.filename)) : expectedSsrRemoteEntryFile);
8812
+ ssrRemoteEntryFile = foundSsrRemoteEntryFile || (_command === "serve" ? getSsrRemoteEntryFileName(mfOptions, resolveHashPlaceholderFileName(mfOptions.filename)) : expectedSsrRemoteEntryFile);
8246
8813
  const allCssAssets = mfOptions.bundleAllCSS && !disableAssetsAnalyze ? collectCssAssets(bundle) : /* @__PURE__ */ new Set();
8247
8814
  if (allCssAssets.size > 0) {
8248
8815
  const secondaryCss = /* @__PURE__ */ new Set();
@@ -8319,7 +8886,7 @@ const Manifest = (providedOptions) => {
8319
8886
  type: "module"
8320
8887
  };
8321
8888
  const ssrRemoteEntry = {
8322
- name: ssrRemoteEntryFile || getSsrRemoteEntryFileName(_command === "serve" ? resolveHashPlaceholderFileName(filename) : filename),
8889
+ name: ssrRemoteEntryFile || getSsrRemoteEntryFileName(mfOptions, _command === "serve" ? resolveHashPlaceholderFileName(filename) : filename),
8323
8890
  path: _command === "serve" ? "/__mf_ssr__/" : "",
8324
8891
  type: "module"
8325
8892
  };
@@ -8636,6 +9203,7 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
8636
9203
  return cleanId.includes(getHostAutoInitPath(options)) || cleanId.includes(getHostAutoInitPath());
8637
9204
  };
8638
9205
  const getEnvironmentConditions = (context) => context.environment?.config?.resolve?.conditions;
9206
+ const isSsrBuild = (context) => isServerBuildContext(context, viteConfig);
8639
9207
  function isRemoteImport(source) {
8640
9208
  return Object.keys(options.remotes).some((name) => source === name || source.startsWith(name + "/"));
8641
9209
  }
@@ -8739,7 +9307,7 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
8739
9307
  }
8740
9308
  },
8741
9309
  async load(id) {
8742
- if (id === remoteEntryId) return getParsePromise().then((_) => generateRemoteEntry(options, virtualExposesId, _command, getEnvironmentConditions(this)));
9310
+ if (id === remoteEntryId) return getParsePromise().then((_) => generateRemoteEntry(options, virtualExposesId, _command, getEnvironmentConditions(this), isSsrBuild(this)));
8743
9311
  if (id === virtualExposesId) {
8744
9312
  await refreshExposeRemoteDependencies(this);
8745
9313
  return generateExposes(options, exposeRemoteDependencies, _command, reactIslandExposes);
@@ -8749,7 +9317,7 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
8749
9317
  async transform(code, id) {
8750
9318
  return mapCodeToCodeWithSourcemap(await (async () => {
8751
9319
  if (!filterId(id)) return;
8752
- if (id.includes(remoteEntryId)) return getParsePromise().then((_) => generateRemoteEntry(options, virtualExposesId, _command, getEnvironmentConditions(this)));
9320
+ if (id.includes(remoteEntryId)) return getParsePromise().then((_) => generateRemoteEntry(options, virtualExposesId, _command, getEnvironmentConditions(this), isSsrBuild(this)));
8753
9321
  if (id === virtualExposesId) {
8754
9322
  await refreshExposeRemoteDependencies(this);
8755
9323
  return generateExposes(options, exposeRemoteDependencies, _command, reactIslandExposes);
@@ -8847,7 +9415,7 @@ function pluginProxyRemotes_default(options) {
8847
9415
  const remoteModule = getRemoteVirtualModule(source, command, enableSsrInit, consumer, options);
8848
9416
  addUsedRemote(remoteName, source, options);
8849
9417
  refreshHostAutoInit(options);
8850
- return remoteModule.getImportId();
9418
+ return remoteModule.getResolvedId();
8851
9419
  }
8852
9420
  return {
8853
9421
  name: "proxyRemotes",
@@ -8867,7 +9435,7 @@ function pluginProxyRemotes_default(options) {
8867
9435
  },
8868
9436
  configResolved(config) {
8869
9437
  hasMultiEnvironment = Boolean(config.environments?.ssr);
8870
- enableSsrInit = getSsrCapabilities(parseInt(version, 10), command, Object.keys(remotes).length > 0).enableSsrInitBootstrap;
9438
+ enableSsrInit = getSsrCapabilities(parseInt(version, 10), command, Object.keys(remotes).length > 0, isSsrConfig(config)).enableSsrInitBootstrap;
8871
9439
  },
8872
9440
  resolveId(source, importer) {
8873
9441
  const resolvedIslandConsumerId = resolveReactIslandConsumerId(source);
@@ -8892,6 +9460,12 @@ function pluginProxyRemotes_default(options) {
8892
9460
  }
8893
9461
  //#endregion
8894
9462
  //#region src/utils/sharedSource.ts
9463
+ const pendingEntryLookups = /* @__PURE__ */ new Map();
9464
+ const getEntryLookupKey = (source, importer) => `${source}\0${importer}`;
9465
+ /** Whether a resolveId call is one of the shared source resolver's own entry lookups. */
9466
+ function isSharedEntryLookup(source, importer, options) {
9467
+ return options.custom?.__mfSharedEntryLookup === true || pendingEntryLookups.has(getEntryLookupKey(source, importer));
9468
+ }
8895
9469
  /** Identify shared entries through Vite, with a cache scoped to this federation instance. */
8896
9470
  function createSharedSourceResolver(shared, getResolutionConfig) {
8897
9471
  const caches = /* @__PURE__ */ new Map();
@@ -8902,9 +9476,10 @@ function createSharedSourceResolver(shared, getResolutionConfig) {
8902
9476
  if (findSharedKey(packageName, shared)) candidates.add(packageName);
8903
9477
  if (findSharedKey(suffix, shared)) candidates.add(suffix);
8904
9478
  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);
9479
+ const request = getSharedRequest(key, shared[key]);
9480
+ if (getPackageName(request) !== packageName) continue;
9481
+ if (!request.endsWith("/")) candidates.add(request);
9482
+ for (const subpath of getCommonSharedSubpaths(request)) if (findSharedKey(subpath, shared)) candidates.add(subpath);
8908
9483
  }
8909
9484
  if (candidates.size === 0) return;
8910
9485
  const resolvedSource = await resolveEntry(source);
@@ -8912,7 +9487,8 @@ function createSharedSourceResolver(shared, getResolutionConfig) {
8912
9487
  for (const candidate of candidates) {
8913
9488
  const entry = await resolveEntry(candidate);
8914
9489
  if (!entry) continue;
8915
- if (normalizeNodeModulePath(entry) === normalizeNodeModulePath(resolvedSource) || getNodeModulesSuffix(entry) === suffix) return candidate;
9490
+ const allowNodeModulesSuffixMatch = shared[findSharedKey(candidate, shared) ?? candidate]?.shareConfig?.allowNodeModulesSuffixMatch === true;
9491
+ if (normalizeNodeModulePath(entry) === normalizeNodeModulePath(resolvedSource) || allowNodeModulesSuffixMatch && getNodeModulesSuffix(entry) === suffix) return candidate;
8916
9492
  }
8917
9493
  }
8918
9494
  return {
@@ -8946,8 +9522,11 @@ function createSharedSourceResolver(shared, getResolutionConfig) {
8946
9522
  cwd: root,
8947
9523
  conditions
8948
9524
  })) return void 0;
9525
+ const importer = path$1.join(root, "package.json");
9526
+ const lookupKey = getEntryLookupKey(request, importer);
9527
+ pendingEntryLookups.set(lookupKey, (pendingEntryLookups.get(lookupKey) ?? 0) + 1);
8949
9528
  try {
8950
- const resolved = await context.resolve(request, path$1.join(root, "package.json"), {
9529
+ const resolved = await context.resolve(request, importer, {
8951
9530
  ...options,
8952
9531
  skipSelf: true,
8953
9532
  custom: {
@@ -8958,6 +9537,10 @@ function createSharedSourceResolver(shared, getResolutionConfig) {
8958
9537
  return resolved && !resolved.external ? resolved.id : void 0;
8959
9538
  } catch {
8960
9539
  return;
9540
+ } finally {
9541
+ const remaining = pendingEntryLookups.get(lookupKey) - 1;
9542
+ if (remaining) pendingEntryLookups.set(lookupKey, remaining);
9543
+ else pendingEntryLookups.delete(lookupKey);
8961
9544
  }
8962
9545
  });
8963
9546
  cache?.set(normalizedSource, result);
@@ -9006,7 +9589,7 @@ function tryResolveFromProjectRoot(source) {
9006
9589
  const browserEntry = getInstalledPackageEntry(source, { cwd: getPackageDetectionCwd() });
9007
9590
  if (browserEntry) return browserEntry;
9008
9591
  try {
9009
- return createRequire$1(pathToFileURL(path$1.join(getPackageDetectionCwd(), "package.json"))).resolve(source);
9592
+ return resolveModulePath(source, path$1.join(getPackageDetectionCwd(), "package.json"));
9010
9593
  } catch {
9011
9594
  return;
9012
9595
  }
@@ -9032,9 +9615,13 @@ function getPackageDependencies(pkg) {
9032
9615
  */
9033
9616
  function excludeSharedSubDependencies(shared) {
9034
9617
  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]));
9618
+ const requestBase = (key) => {
9619
+ const request = getSharedRequest(key, shared[key]);
9620
+ return request.endsWith("/") ? request.slice(0, -1) : request;
9621
+ };
9622
+ const sharedKeyByBase = new Map(Object.keys(shared).map((key) => [requestBase(key), key]));
9036
9623
  for (const parentKey of sharedKeys) {
9037
- const deps = getPackageDependencies(parentKey);
9624
+ const deps = getPackageDependencies(requestBase(parentKey));
9038
9625
  for (const dep of deps) {
9039
9626
  const depKey = sharedKeyByBase.get(dep);
9040
9627
  if (depKey && depKey !== parentKey) {
@@ -9361,6 +9948,7 @@ function isSharedPackageRuntimeDependency(sharedKey, dependency, conditions) {
9361
9948
  function proxySharedModule(options) {
9362
9949
  const { shared = {}, federationOptions, getParsePromise = () => Promise.resolve() } = options;
9363
9950
  let _config;
9951
+ const getBuildImportAnalysis = (environment) => getImportAnalysis(environment ?? _config ?? options);
9364
9952
  let _command = "serve";
9365
9953
  let useDirectReactImport = false;
9366
9954
  let useRolldown = false;
@@ -9378,7 +9966,7 @@ function proxySharedModule(options) {
9378
9966
  const getRuntimeDependencyConditions = (context, resolveOptions) => {
9379
9967
  const environment = context.environment;
9380
9968
  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";
9969
+ const isSsr = resolveOptions.ssr === true || Boolean(_config?.build?.ssr) || isServerEnvironment(environment?.name, environmentConfig);
9382
9970
  return getSharedExportConditions({
9383
9971
  environmentConditions: environmentConfig?.resolve?.conditions,
9384
9972
  isProduction: environmentConfig?.isProduction ?? isProduction,
@@ -9434,12 +10022,13 @@ function proxySharedModule(options) {
9434
10022
  }, federationOptions);
9435
10023
  },
9436
10024
  resolveId(source) {
9437
- if (source === getLocalSharedImportMapPath(federationOptions)) return getResolvedLocalSharedImportMapId(federationOptions);
10025
+ const resolvedId = getResolvedLocalSharedImportMapId(federationOptions);
10026
+ if (source === getLocalSharedImportMapPath(federationOptions) || source === resolvedId) return resolvedId;
9438
10027
  },
9439
10028
  load(id) {
9440
10029
  if (id === getResolvedLocalSharedImportMapId(federationOptions)) return getParsePromise().then((_) => {
9441
10030
  refreshTreeShakingForEnvironment(this);
9442
- const providerPackages = /* @__PURE__ */ new Set([...Object.keys(shared).filter((pkg) => !pkg.endsWith("/")), ...getUsedShares(federationOptions)]);
10031
+ const providerPackages = /* @__PURE__ */ new Set([...Object.keys(shared).filter((pkg) => !getSharedRequest(pkg, shared[pkg]).endsWith("/")), ...getUsedShares(federationOptions)]);
9443
10032
  for (const pkg of providerPackages) {
9444
10033
  const sharedKey = findSharedKey(pkg, shared);
9445
10034
  const shareItem = shared[pkg] || (sharedKey ? shared[sharedKey] : void 0);
@@ -9484,14 +10073,15 @@ function proxySharedModule(options) {
9484
10073
  const resolvedOptions = federationOptions ?? getNormalizeModuleFederationOptions();
9485
10074
  const registerConfiguredShare = _command === "build" && Object.keys(resolvedOptions.exposes).length > 0 ? addUsedShares : addConfiguredShare;
9486
10075
  Object.keys(shared).forEach((key) => {
9487
- if (key.endsWith("/")) return;
9488
- if (useDirectReactImport && key === "react") {
9489
- registerConfiguredShare(key, federationOptions);
10076
+ if (key.endsWith("/") || getSharedRequest(key, shared[key]).endsWith("/")) return;
10077
+ const runtimeKey = getSharedRuntimeKey(key, shared[key]);
10078
+ if (useDirectReactImport && runtimeKey === "react") {
10079
+ registerConfiguredShare(runtimeKey, federationOptions);
9490
10080
  return;
9491
10081
  }
9492
- writeLoadShareModule(key, shared[key], _command, isRolldown, federationOptions);
9493
- if (shared[key].shareConfig.import !== false) writePreBuildLibPath(key, shared[key], federationOptions);
9494
- registerConfiguredShare(key, federationOptions);
10082
+ writeLoadShareModule(runtimeKey, shared[key], _command, isRolldown, federationOptions);
10083
+ if (shared[key].shareConfig.import !== false) writePreBuildLibPath(runtimeKey, shared[key], federationOptions);
10084
+ registerConfiguredShare(runtimeKey, federationOptions);
9495
10085
  });
9496
10086
  writeLocalSharedImportMap(federationOptions);
9497
10087
  refreshHostAutoInit(federationOptions);
@@ -9502,10 +10092,14 @@ function proxySharedModule(options) {
9502
10092
  buildStart() {
9503
10093
  sharedSourceResolver.clear();
9504
10094
  if (_command !== "build") return;
10095
+ if (hasAnalyzableShares) getBuildImportAnalysis(this.environment).clear();
9505
10096
  resetTreeShakingExports(federationOptions);
9506
10097
  emittedTreeShakingProviders.clear();
9507
10098
  refreshTreeShakingForEnvironment(this);
9508
10099
  },
10100
+ buildEnd() {
10101
+ if (_command === "build" && hasAnalyzableShares) getBuildImportAnalysis(this.environment).clear();
10102
+ },
9509
10103
  shouldTransformCachedModule() {
9510
10104
  return _command === "build" && hasAnalyzableShares;
9511
10105
  },
@@ -9514,7 +10108,7 @@ function proxySharedModule(options) {
9514
10108
  await collectTreeShakingImports(code, id, shared, async (source, shares) => {
9515
10109
  const request = await sharedSourceResolver.resolve(this, source, transformOptions);
9516
10110
  return request ? findSharedKey(request, shares) : void 0;
9517
- }, (sharedKey, exports, request) => recordTreeShakingExports(sharedKey, exports, request, federationOptions), (sharedKey, request) => markTreeShakingPackageUnsafe(sharedKey, request, federationOptions));
10111
+ }, (sharedKey, exports, request) => recordTreeShakingExports(sharedKey, exports, request, federationOptions), (sharedKey, request) => markTreeShakingPackageUnsafe(sharedKey, request, federationOptions), getBuildImportAnalysis(this.environment));
9518
10112
  refreshTreeShakingForEnvironment(this);
9519
10113
  }
9520
10114
  },
@@ -9523,7 +10117,7 @@ function proxySharedModule(options) {
9523
10117
  enforce: "pre",
9524
10118
  apply: "build",
9525
10119
  async resolveId(source, importer, resolveOptions) {
9526
- if (resolveOptions.custom?.__mfSharedEntryLookup) return;
10120
+ if (isSharedEntryLookup(source, importer, resolveOptions)) return;
9527
10121
  const sourceToken = getTreeShakingGraphToken(source);
9528
10122
  const importerToken = getTreeShakingGraphToken(importer);
9529
10123
  const token = sourceToken || importerToken;
@@ -9559,7 +10153,7 @@ function proxySharedModule(options) {
9559
10153
  name: "proxyPreBuildShared:resolve-shared-loadShare",
9560
10154
  enforce: "pre",
9561
10155
  async resolveId(source, importer, resolveOptions) {
9562
- if (resolveOptions.custom?.__mfSharedEntryLookup || resolveOptions.custom?.__mfTreeShakingGraph) return;
10156
+ if (isSharedEntryLookup(source, importer, resolveOptions) || resolveOptions.custom?.__mfTreeShakingGraph) return;
9563
10157
  const sharedSource = await sharedSourceResolver.resolve(this, source, resolveOptions);
9564
10158
  if (!sharedSource) return;
9565
10159
  const key = findSharedKey(sharedSource, shared);
@@ -9574,8 +10168,9 @@ function proxySharedModule(options) {
9574
10168
  if (importerPackage === getPackageName(key)) return;
9575
10169
  if (importerPackage && shared[key].shareConfig.import !== false) {
9576
10170
  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;
10171
+ const request = getSharedRequest(key, shared[key]);
10172
+ const runtimeDependencyRequest = request.endsWith("/") && matchesSharedSource(sharedSource, key, shared[key]) ? sharedSource : request;
10173
+ if (importerIsUnsharedWorkspacePackage ? isSharedPackageRuntimeDependency(runtimeDependencyRequest, importerPackage, getRuntimeDependencyConditions(this, resolveOptions)) : isSharedPackageDependency(request, importerPackage)) return;
9579
10174
  }
9580
10175
  if (useDirectReactImport && key === "react") return;
9581
10176
  if (isAssetLikeImport(source)) return;
@@ -9876,17 +10471,21 @@ function collectFromRegex(code, isRemoteImport) {
9876
10471
  }
9877
10472
  function pluginRemoteNamedExports(options) {
9878
10473
  const remoteNames = Object.keys(options.remotes);
10474
+ let root = process.cwd();
9879
10475
  const isNodeModulesId = (id) => id.includes("/node_modules/") || id.includes("\\node_modules\\");
9880
10476
  function isRemoteImport(source, importerId) {
9881
10477
  return remoteNames.some((name) => {
9882
10478
  if (source.startsWith(name + "/")) return true;
9883
10479
  if (source !== name) return false;
9884
- return !isNodeModulesId(importerId);
10480
+ return !isNodeModulesId(importerId) || !getInstalledPackageEntry(source, { cwd: root });
9885
10481
  }) || source.includes("__loadRemote__");
9886
10482
  }
9887
10483
  return {
9888
10484
  name: "module-federation-remote-named-exports",
9889
10485
  enforce: "post",
10486
+ configResolved(config) {
10487
+ root = config.root || process.cwd();
10488
+ },
9890
10489
  async transform(code, id) {
9891
10490
  if (remoteNames.length === 0) return;
9892
10491
  if (id.includes("__loadRemote__") || id.includes("__loadShare__")) return;
@@ -10038,18 +10637,25 @@ function pluginSSRRemoteEntry(options) {
10038
10637
  const remoteEntrySSRId = getRemoteEntrySSRId(options);
10039
10638
  const virtualExposesSSRId = getVirtualExposesSSRId(options);
10040
10639
  let cachedSsrRemoteEntrySource;
10041
- const ssrOutputFilename = getSsrRemoteEntryFileName(options.filename);
10640
+ const ssrOutputFilename = getSsrRemoteEntryFileName(options);
10042
10641
  const ssrExposesFileName = getSsrExposesFileName(options.filename);
10043
10642
  let ssrOutputFiles = /* @__PURE__ */ new Set();
10044
10643
  let ssrOutputDir = "";
10045
10644
  let clientOutputDir = "";
10046
- const ssrOnlyExternals = [
10645
+ const mfRuntimePackages = [
10047
10646
  "@module-federation/runtime",
10048
10647
  "@module-federation/runtime-core",
10049
- "@module-federation/sdk",
10050
- ...options.ssrExternals ?? []
10648
+ "@module-federation/sdk"
10051
10649
  ];
10650
+ const ssrOnlyExternals = [...mfRuntimePackages, ...options.ssrExternals ?? []];
10052
10651
  const ssrOnlyExternalPattern = new RegExp(`^(${ssrOnlyExternals.map((e) => e.replace(/[/\\^$*+?.()|[\]{}]/g, "\\$&")).join("|")})(\\/.*)?$`);
10652
+ let noExternal;
10653
+ const isNoExternal = (id) => {
10654
+ const pkg = ssrOnlyExternalPattern.exec(id)?.[1] ?? id;
10655
+ if (!noExternal || !mfRuntimePackages.includes(pkg)) return false;
10656
+ if (noExternal === true) return true;
10657
+ return (Array.isArray(noExternal) ? noExternal : [noExternal]).some((rule) => typeof rule === "string" ? rule === pkg : rule.test(pkg));
10658
+ };
10053
10659
  const ssrModuleIds = /* @__PURE__ */ new Set([remoteEntrySSRId, virtualExposesSSRId]);
10054
10660
  const resolvedAbsToPackage = /* @__PURE__ */ new Map();
10055
10661
  let isServe = false;
@@ -10080,7 +10686,9 @@ function pluginSSRRemoteEntry(options) {
10080
10686
  enforce: "pre",
10081
10687
  configResolved(config) {
10082
10688
  isServe = config.command === "serve";
10689
+ noExternal = config.environments?.ssr?.resolve?.noExternal ?? config.ssr?.noExternal;
10083
10690
  for (const pkg of ssrOnlyExternals) {
10691
+ if (isNoExternal(pkg)) continue;
10084
10692
  const aliasEntry = (config.resolve?.alias)?.find((a) => a.find === pkg || a.find instanceof RegExp && a.find.test(pkg));
10085
10693
  if (aliasEntry?.replacement) resolvedAbsToPackage.set(aliasEntry.replacement, pkg);
10086
10694
  }
@@ -10089,7 +10697,7 @@ function pluginSSRRemoteEntry(options) {
10089
10697
  if (id === remoteEntrySSRId || id.startsWith(remoteEntrySSRId)) return id;
10090
10698
  if (id === virtualExposesSSRId || id.startsWith(virtualExposesSSRId)) return id;
10091
10699
  if (!importer || !ssrModuleIds.has(importer)) return;
10092
- if (ssrOnlyExternalPattern.test(id)) return {
10700
+ if (ssrOnlyExternalPattern.test(id) && !isNoExternal(id)) return {
10093
10701
  id,
10094
10702
  external: true
10095
10703
  };
@@ -10114,7 +10722,7 @@ function pluginSSRRemoteEntry(options) {
10114
10722
  configureServer(server) {
10115
10723
  const base = "/__mf_ssr__";
10116
10724
  const basePath = getBasePath$1(viteConfig?.base);
10117
- const ssrEntryFileName = getSsrRemoteEntryFileName(options.filename);
10725
+ const ssrEntryFileName = getSsrRemoteEntryFileName(options);
10118
10726
  if (isNuxtProject || isNuxtClientBase(basePath)) server.middlewares.use((req, _res, next) => {
10119
10727
  if (req.url?.replace(/\?.*/, "") === `${basePath}/${ssrEntryFileName}`) req.url = `${basePath}/__mf_ssr__/${ssrEntryFileName}`;
10120
10728
  next();
@@ -10183,7 +10791,7 @@ function pluginSSRRemoteEntry(options) {
10183
10791
  resolveId(id) {
10184
10792
  if (id === remoteEntrySSRId || id.startsWith(remoteEntrySSRId)) return id;
10185
10793
  if (id === virtualExposesSSRId || id.startsWith(virtualExposesSSRId)) return id;
10186
- if (id === `/__mf_ssr__/${getSsrRemoteEntryFileName(options.filename)}`) return remoteEntrySSRId;
10794
+ if (id === `/__mf_ssr__/${getSsrRemoteEntryFileName(options)}`) return remoteEntrySSRId;
10187
10795
  if (id === `/__mf_ssr__/${ssrExposesFileName}`) return virtualExposesSSRId;
10188
10796
  },
10189
10797
  load(id) {
@@ -10388,6 +10996,85 @@ var aliasToArrayPlugin_default = {
10388
10996
  }
10389
10997
  };
10390
10998
  //#endregion
10999
+ //#region src/utils/deferredPrebuildHelper.ts
11000
+ function isExportAllHelper(code, exportName) {
11001
+ try {
11002
+ const ast = parseAst(code);
11003
+ let localName;
11004
+ for (const node of ast.body) {
11005
+ if (node.type !== "ExportNamedDeclaration") continue;
11006
+ 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;
11007
+ }
11008
+ if (!localName) return false;
11009
+ for (const node of ast.body) {
11010
+ if (node.type !== "VariableDeclaration") continue;
11011
+ for (const declaration of node.declarations) {
11012
+ if (declaration.id.type !== "Identifier" || declaration.id.name !== localName) continue;
11013
+ const initializer = declaration.init;
11014
+ if (!initializer) return false;
11015
+ const source = code.slice(initializer.start, initializer.end);
11016
+ return source.includes("Symbol.toStringTag") && source.includes("Module");
11017
+ }
11018
+ }
11019
+ } catch {}
11020
+ return false;
11021
+ }
11022
+ /**
11023
+ * Rolldown sometimes places its shared namespace helper in a local prebuild
11024
+ * chunk. A loadShare wrapper then imports that helper statically, evaluating the
11025
+ * fallback even when a host provider is already in the cache. Inline only the
11026
+ * recognized Rolldown helper; leave every other prebuild import untouched.
11027
+ */
11028
+ function inlineDeferredPrebuildNamespaceHelper(bundle) {
11029
+ for (const chunk of Object.values(bundle)) {
11030
+ if (chunk.type !== "chunk" || !chunk.fileName.includes("__loadShare__")) continue;
11031
+ let ast;
11032
+ try {
11033
+ ast = parseAst(chunk.code);
11034
+ } catch {
11035
+ continue;
11036
+ }
11037
+ const edits = [];
11038
+ const deferredSources = /* @__PURE__ */ new Set();
11039
+ forEachAstNode(ast, (node) => {
11040
+ if (node.type !== "ImportExpression") return;
11041
+ const source = getModuleSource(node.source);
11042
+ if (source) deferredSources.add(source);
11043
+ });
11044
+ const retainedImports = /* @__PURE__ */ new Set();
11045
+ const removedImports = /* @__PURE__ */ new Set();
11046
+ for (const node of ast.body) {
11047
+ if (node.type !== "ImportDeclaration") continue;
11048
+ const source = getModuleSource(node.source);
11049
+ if (!source) continue;
11050
+ const targetName = path.posix.normalize(path.posix.join(path.posix.dirname(chunk.fileName), source));
11051
+ const [specifier] = node.specifiers;
11052
+ const exported = specifier?.type === "ImportSpecifier" && specifier.imported;
11053
+ const target = bundle[targetName];
11054
+ 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)) {
11055
+ retainedImports.add(targetName);
11056
+ continue;
11057
+ }
11058
+ removedImports.add(targetName);
11059
+ edits.push({
11060
+ start: node.start,
11061
+ end: node.end,
11062
+ replacement: `const ${specifier.local.name} = (all, noSymbols) => {
11063
+ const namespace = {};
11064
+ for (const name in all) Object.defineProperty(namespace, name, {
11065
+ get: all[name], enumerable: true,
11066
+ });
11067
+ if (!noSymbols) Object.defineProperty(namespace, Symbol.toStringTag, { value: 'Module' });
11068
+ return namespace;
11069
+ };`
11070
+ });
11071
+ }
11072
+ if (edits.length === 0) continue;
11073
+ for (const edit of edits.reverse()) chunk.code = chunk.code.slice(0, edit.start) + edit.replacement + chunk.code.slice(edit.end);
11074
+ if (chunk.imports) chunk.imports = chunk.imports.filter((imported) => !removedImports.has(imported) || retainedImports.has(imported));
11075
+ }
11076
+ }
11077
+ //#endregion
10391
11078
  //#region src/utils/controlChunkSanitizer.ts
10392
11079
  const FEDERATION_CONTROL_CHUNK_HINTS = ["hostInit", "localSharedImportMap"];
10393
11080
  function stripEmptyPreloadCalls(code) {
@@ -10605,7 +11292,7 @@ function isFederationHtmlPreloadDependency(dep, includeSharedRuntime = false) {
10605
11292
  }
10606
11293
  function canResolveSharedSubpath(subpath, projectRoot) {
10607
11294
  try {
10608
- return isViteOptimizableEntry(createRequire$1(pathToFileURL(path$1.join(projectRoot, "package.json"))).resolve(subpath));
11295
+ return isViteOptimizableEntry(resolveModulePath(subpath, path$1.join(projectRoot, "package.json")));
10609
11296
  } catch (error) {
10610
11297
  if (error?.code === "ERR_PACKAGE_PATH_NOT_EXPORTED" && !isBarePackageSubpath(subpath)) {
10611
11298
  const entry = resolveViteImportPackageEntry(subpath, projectRoot);
@@ -10843,11 +11530,21 @@ function createEarlyVirtualModulesPlugin(options) {
10843
11530
  config.optimizeDeps = config.optimizeDeps || {};
10844
11531
  config.optimizeDeps.include = config.optimizeDeps.include || [];
10845
11532
  const optimizeDeps = config.optimizeDeps;
11533
+ const preparedShares = /* @__PURE__ */ new Map();
11534
+ const writeSharedModules = (source, shareItem) => {
11535
+ if (preparedShares.get(source) === shareItem) return;
11536
+ writeLoadShareModule(source, shareItem, _command, isRolldown, options);
11537
+ if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(source, shareItem, options);
11538
+ preparedShares.set(source, shareItem);
11539
+ };
10846
11540
  if (isRolldown) {
10847
11541
  optimizeDeps.rolldownOptions ??= {};
10848
11542
  optimizeDeps.rolldownOptions.plugins ??= [];
10849
11543
  optimizeDeps.rolldownOptions.plugins.push({
10850
11544
  name: "module-federation:optimize-shared-resolver",
11545
+ buildStart() {
11546
+ preparedShares.clear();
11547
+ },
10851
11548
  load(id) {
10852
11549
  if (!id.startsWith("module-federation:optimized-require-")) return;
10853
11550
  const sourcePackage = id.slice(36);
@@ -10875,13 +11572,11 @@ function createEarlyVirtualModulesPlugin(options) {
10875
11572
  if (isCommonJsImporter(importer) && !isReactSingleton && !isReactDomRequire) return;
10876
11573
  if (resolveOptions?.kind !== "entry-point") addUsedShares(source, options);
10877
11574
  if (isReactRequire || isReactDomRequire) {
10878
- writeLoadShareModule(source, shareItem, _command, isRolldown, options);
10879
- if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(source, shareItem, options);
11575
+ writeSharedModules(source, shareItem);
10880
11576
  return { id: `module-federation:optimized-require-${source}` };
10881
11577
  }
10882
11578
  const loadSharePath = getLoadShareModulePath(source, isRolldown, options);
10883
- writeLoadShareModule(source, shareItem, _command, isRolldown, options);
10884
- if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(source, shareItem, options);
11579
+ writeSharedModules(source, shareItem);
10885
11580
  return {
10886
11581
  id: loadSharePath,
10887
11582
  external: true
@@ -10894,6 +11589,9 @@ function createEarlyVirtualModulesPlugin(options) {
10894
11589
  optimizeDeps.esbuildOptions.plugins.push({
10895
11590
  name: "module-federation:optimize-shared-proxy",
10896
11591
  setup(build) {
11592
+ build.onStart(() => {
11593
+ preparedShares.clear();
11594
+ });
10897
11595
  build.onResolve({ filter: createViteEncodedIdPrefixRegExp("virtual:mf:") }, (args) => ({
10898
11596
  path: args.path,
10899
11597
  external: true
@@ -10911,8 +11609,7 @@ function createEarlyVirtualModulesPlugin(options) {
10911
11609
  if (args.kind === "import-statement" || args.kind === "dynamic-import") {
10912
11610
  const shareItem = shared[key];
10913
11611
  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);
11612
+ writeSharedModules(args.path, shareItem);
10916
11613
  return {
10917
11614
  path: loadSharePath,
10918
11615
  external: true
@@ -10931,8 +11628,7 @@ function createEarlyVirtualModulesPlugin(options) {
10931
11628
  if (!key) return;
10932
11629
  const shareItem = shared[key];
10933
11630
  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);
11631
+ writeSharedModules(args.path, shareItem);
10936
11632
  return {
10937
11633
  loader: "js",
10938
11634
  resolveDir: root,
@@ -10947,12 +11643,14 @@ export default __mfShared.default ?? __mfShared;`
10947
11643
  }
10948
11644
  for (const key of Object.keys(shared)) {
10949
11645
  const shareItem = shared[key];
10950
- if (key.endsWith("/")) {
11646
+ const request = getSharedRequest(key, shareItem);
11647
+ const runtimeKey = getSharedRuntimeKey(key, shareItem);
11648
+ if (key.endsWith("/") || request.endsWith("/") || runtimeKey.endsWith("/")) {
10951
11649
  if (_command === "serve" && shareItem.shareConfig?.import !== false) {
10952
11650
  const optimizeDeps = config.optimizeDeps ??= {};
10953
11651
  optimizeDeps.include ??= [];
10954
11652
  optimizeDeps.exclude ??= [];
10955
- for (const subpath of getCommonSharedSubpaths(key)) {
11653
+ for (const subpath of getCommonSharedSubpaths(request)) {
10956
11654
  writePreBuildLibPath(subpath, shareItem, options);
10957
11655
  if (canResolveSharedSubpath(subpath, root)) optimizeDeps.include.push(subpath);
10958
11656
  else optimizeDeps.exclude.push(subpath);
@@ -10960,23 +11658,24 @@ export default __mfShared.default ?? __mfShared;`
10960
11658
  }
10961
11659
  continue;
10962
11660
  }
10963
- if (isVinext && key === "react") {
10964
- addConfiguredShare(key, options);
11661
+ if (isVinext && runtimeKey === "react") {
11662
+ addConfiguredShare(runtimeKey, options);
10965
11663
  continue;
10966
11664
  }
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);
11665
+ getLoadShareModulePath(runtimeKey, isRolldown, options);
11666
+ writeLoadShareModule(runtimeKey, shareItem, _command, isRolldown, options);
11667
+ if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(runtimeKey, shareItem, options);
11668
+ addConfiguredShare(runtimeKey, options);
10971
11669
  if (_command === "serve" && shareItem.shareConfig?.import !== false) {
10972
11670
  const optimizeDeps = config.optimizeDeps ??= {};
10973
11671
  optimizeDeps.include ??= [];
10974
11672
  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)) {
11673
+ const shouldBypassOptimizeDep = isLitShare(runtimeKey) || !canResolveSharedSubpath(runtimeKey, root);
11674
+ if (optimizeDeps.include.includes(runtimeKey)) optimizeDeps.exclude = optimizeDeps.exclude.filter((dep) => dep !== runtimeKey);
11675
+ else if (shouldBypassOptimizeDep || optimizeDeps.exclude.includes(runtimeKey)) optimizeDeps.exclude.push(runtimeKey);
11676
+ else optimizeDeps.include.push(runtimeKey);
11677
+ const commonSubpaths = shareItem.shareConfig.request === void 0 && shareItem.shareConfig.shareKey === void 0 ? getCommonSharedSubpaths(runtimeKey) : [];
11678
+ for (const subpath of commonSubpaths) {
10980
11679
  const canResolveSubpath = canResolveSharedSubpath(subpath, root);
10981
11680
  if ([
10982
11681
  "react/compiler-runtime",
@@ -10992,7 +11691,7 @@ export default __mfShared.default ?? __mfShared;`
10992
11691
  addConfiguredShare(subpath, options);
10993
11692
  if (canResolveSubpath) {
10994
11693
  optimizeDeps.include.push(subpath);
10995
- if (key === "react-dom") optimizeDeps.include.push(`${key} > ${subpath}`);
11694
+ if (runtimeKey === "react-dom") optimizeDeps.include.push(`${runtimeKey} > ${subpath}`);
10996
11695
  } else optimizeDeps.exclude.push(subpath);
10997
11696
  }
10998
11697
  }
@@ -11010,10 +11709,8 @@ export default __mfShared.default ?? __mfShared;`
11010
11709
  const automaticJsxRuntime = getAutomaticJsxRuntime(config);
11011
11710
  if (automaticJsxRuntime && materializeAutomaticJsxRuntime(options, automaticJsxRuntime)) writeLocalSharedImportMap(options);
11012
11711
  }
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;
11712
+ if (!getSsrCapabilities(parseInt(version, 10), config.command, hasRemotes(options), isSsrConfig(config)).injectSsrEntryLoader) return;
11713
+ if (options.runtimePlugins.some((p) => getRuntimePluginSpecifier(p) === "@module-federation/vite/ssrEntryLoader")) return;
11017
11714
  const projectRequire = createRequire$1(pathToFileURL(path$1.join(config.root, "package.json")));
11018
11715
  const sharedKeys = Object.keys(options.shared ?? {});
11019
11716
  const commonSharedPkgs = [
@@ -11056,16 +11753,14 @@ function applyBuildTimeRuntimeDefines(define, options, { target, isAstro, defaul
11056
11753
  }
11057
11754
  function loadPluginDts(options) {
11058
11755
  if (options.dts === false) return [];
11059
- return [import("./pluginDts-CQ088qGF.js").then(({ default: pluginDts }) => pluginDts(options))];
11756
+ return [import("./pluginDts-VSLhAx6d.js").then(({ default: pluginDts }) => pluginDts(options))];
11060
11757
  }
11061
11758
  const INJECT_EXTERNAL_RUNTIME_CORE_PLUGIN = "@module-federation/vite/injectExternalRuntimeCorePlugin";
11062
11759
  function isInjectExternalRuntimeCorePlugin(specifier) {
11063
11760
  return specifier === INJECT_EXTERNAL_RUNTIME_CORE_PLUGIN || specifier.includes("injectExternalRuntimeCorePlugin") || specifier.includes("inject-external-runtime-core-plugin");
11064
11761
  }
11065
11762
  function hasInjectExternalRuntimeCorePlugin(runtimePlugins) {
11066
- return runtimePlugins.some((plugin) => {
11067
- return isInjectExternalRuntimeCorePlugin(typeof plugin === "string" ? plugin : plugin[0]);
11068
- });
11763
+ return runtimePlugins.some((plugin) => isInjectExternalRuntimeCorePlugin(getRuntimePluginSpecifier(plugin)));
11069
11764
  }
11070
11765
  function resolveInjectExternalRuntimeCorePlugin() {
11071
11766
  try {
@@ -11112,7 +11807,7 @@ function federation(mfUserOptions) {
11112
11807
  const emittedRuntimeCapabilityWarnings = /* @__PURE__ */ new Set();
11113
11808
  const getLoadHookExportConditions = (context, loadOptions) => {
11114
11809
  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";
11810
+ const isSsr = loadOptions?.ssr === true || isSsrBuild || isServerEnvironment(environment?.name, environment?.config);
11116
11811
  return getSharedExportConditions({
11117
11812
  environmentConditions: environment?.config?.resolve?.conditions,
11118
11813
  isProduction: environment?.config?.isProduction ?? isProduction,
@@ -11236,7 +11931,7 @@ function federation(mfUserOptions) {
11236
11931
  ssrResolveConditions = config.ssr?.resolve?.conditions ? [...config.ssr.resolve.conditions] : void 0;
11237
11932
  ssrTarget = config.ssr?.target ?? "node";
11238
11933
  isProduction = config.isProduction;
11239
- const ssrCapabilities = getSsrCapabilities(parseInt(version, 10), command, Object.keys(options.remotes).length > 0);
11934
+ const ssrCapabilities = getSsrCapabilities(parseInt(version, 10), command, Object.keys(options.remotes).length > 0, isSsrConfig(config));
11240
11935
  resolveSharedVersions(shared, config.root);
11241
11936
  initVirtualModules(command, remoteEntryId, ssrCapabilities.enableSsrInitBootstrap, options);
11242
11937
  }
@@ -11286,6 +11981,7 @@ function federation(mfUserOptions) {
11286
11981
  federationOptions: options,
11287
11982
  getParsePromise: () => moduleParseController.parsePromise
11288
11983
  }),
11984
+ pluginLazyConsumeOnlyShares(options),
11289
11985
  {
11290
11986
  name: "module-federation-esm-shims",
11291
11987
  enforce: "pre",
@@ -11337,6 +12033,7 @@ function federation(mfUserOptions) {
11337
12033
  priority: USER_GROUP_MAX_PRIORITY
11338
12034
  };
11339
12035
  };
12036
+ const federationGroupDebugName = supportsCodeSplittingGroupDebugName(this) ? { debugName: "module-federation" } : {};
11340
12037
  let warnedAboutManualChunks = false;
11341
12038
  let warnedAboutObjectManualChunks = false;
11342
12039
  const applyManualChunks = (output, useCodeSplitting) => {
@@ -11344,11 +12041,13 @@ function federation(mfUserOptions) {
11344
12041
  const isPatchedByPlugin = typeof output.manualChunks === "function" && patchedManualChunks.has(output.manualChunks);
11345
12042
  const mfChunkName = function(id) {
11346
12043
  if (id.includes(runtimeInitId) || id.includes("__mf_v__runtimeInit__mf_v__")) return "runtimeInit";
12044
+ if (isSharedCacheHelpersId(id)) return getSharedChunkName(id);
11347
12045
  if (id.includes("__loadShare__")) {
11348
12046
  const pkg = getCachedLoadSharePkg(id);
11349
12047
  const key = pkg && findSharedKey(pkg, shared);
11350
12048
  if (key && shared[key].shareConfig.eager === true) return "loadShare-eager";
11351
12049
  if (key && shared[key].shareConfig.import === false) return null;
12050
+ if (pkg && !id.includes("commonjs-proxy") && isCoalescableLoadShareWrapper(pkg, options, id)) return getSharedChunkName(id);
11352
12051
  const match = id.match(/([^/\\]+__loadShare__[^/\\]+)/);
11353
12052
  return match ? match[1] : "loadShare";
11354
12053
  }
@@ -11385,7 +12084,8 @@ function federation(mfUserOptions) {
11385
12084
  };
11386
12085
  const mfNameGroup = {
11387
12086
  name: mfChunkName,
11388
- priority: MF_GROUP_PRIORITY
12087
+ priority: MF_GROUP_PRIORITY,
12088
+ ...federationGroupDebugName
11389
12089
  };
11390
12090
  federationGroups.add(mfPreloadGroup);
11391
12091
  federationGroups.add(mfNameGroup);
@@ -11458,7 +12158,14 @@ function federation(mfUserOptions) {
11458
12158
  if (!virtualModule?.code) return null;
11459
12159
  let code = virtualModule.code;
11460
12160
  const consumerTarget = resolveEnvironmentConsumerTarget(this);
11461
- if (consumerTarget === "server" || !consumerTarget && isSsrBuild) code = prependWorkspaceSingletonSsrImport(code);
12161
+ if (consumerTarget === "server" || !consumerTarget && isSsrBuild) {
12162
+ const withSsrImport = prependWorkspaceSingletonSsrImport(code);
12163
+ if (withSsrImport !== code) {
12164
+ const pkg = getCachedLoadSharePkg(id);
12165
+ if (pkg) markLoadShareWrapperNotCoalescable(pkg, options, id);
12166
+ code = withSsrImport;
12167
+ }
12168
+ }
11462
12169
  code = code.replace(/import\s+["'][^"']*__prebuild__[^"']*["']\s*;?/g, "");
11463
12170
  code = code.replace(/export\s+\*\s+from\s+["'][^"']*__prebuild__[^"']*["']\s*;?/g, "");
11464
12171
  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 +12183,9 @@ function federation(mfUserOptions) {
11476
12183
  return loadVirtualModule();
11477
12184
  },
11478
12185
  generateBundle(_outputOptions, bundle, _isWrite) {
12186
+ inlineDeferredPrebuildNamespaceHelper(bundle);
12187
+ 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.
12188
+ Stop the shared module from statically importing another share.`);
11479
12189
  for (const [fileName, chunk] of Object.entries(bundle)) {
11480
12190
  if (!isOutputChunk(chunk)) continue;
11481
12191
  if (!isFederationControlChunk(fileName, filename)) continue;
@@ -11541,7 +12251,7 @@ function federation(mfUserOptions) {
11541
12251
  config.optimizeDeps.include.push("@module-federation/runtime");
11542
12252
  if (needsRuntimeHelpers) config.optimizeDeps.include.push("@module-federation/runtime/helpers");
11543
12253
  options.runtimePlugins.forEach((p) => {
11544
- const pluginPath = typeof p === "string" ? p : p[0];
12254
+ const pluginPath = getRuntimePluginSpecifier(p);
11545
12255
  if (SSR_ONLY_RUNTIME_PLUGINS.has(pluginPath)) return;
11546
12256
  if (pluginPath && !pluginPath.startsWith(".") && !pluginPath.startsWith("/") && !pluginPath.startsWith("\0") && !pluginPath.startsWith("virtual:")) {
11547
12257
  let optimizeDep = pluginPath;
@@ -11577,7 +12287,7 @@ function federation(mfUserOptions) {
11577
12287
  if (prematureExit) prematureExit.closeBundle = void 0;
11578
12288
  },
11579
12289
  configEnvironment(name, config) {
11580
- if (!(config.consumer === "server" || name === "ssr" || name === "server" || config.build?.ssr === true)) return;
12290
+ if (!isServerEnvironment(name, config)) return;
11581
12291
  const isAstro = hasPackageDependency("astro");
11582
12292
  config.define = { ...config.define ?? {} };
11583
12293
  applyBuildTimeRuntimeDefines(config.define, options, {