@module-federation/vite 1.23.5 → 1.23.7

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 removeTrailingSlash, a as matchesSharedSource, b as stripViteFsPrefix, 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 resolvePublicPath, y as stripQueryAndHash } from "./sharedKeyMatcher-CHp4QRNq.js";
2
- import { a as CodeRewriter, c as isAbsoluteUrl, d as resolveHashPlaceholderFileName, i as createCodePositionMap, l as normalizePathForImport, o as createSourceMap, r as mfWarn, t as createModuleFederationError, u as rebaseImport } from "./logger-DOwfTlw5.js";
3
- import { C as REACT_DOM_CLIENT_SHARE, S as REACT_CLIENT_INTERNALS_KEY, _ as resolveImportPath, a as getIsRolldown, b as sharedCacheHelperCode, c as getPackageName, d as hasPackageDependency, f as isNuxtProjectRoot, g as packageNameEncode, h as packageNameDecode, i as getInstalledPackageJson, l as getPackageNameFromNodeModulePath, m as isPackageInstalled, n as getDependencyNames, o as getPackageDetectionCwd, p as isPackageExportAvailable, r as getInstalledPackageEntry, s as getPackageExportSpecifiersForFile, u as getSharedCacheDescriptor, v as resolveModulePath, w as isReactCoreShare, x as supportsCodeSplittingGroupDebugName, y as setPackageDetectionCwd } from "./dtsConstants-BQdFpgKb.js";
1
+ import { a as CodeRewriter, c as isAbsoluteUrl, d as rebaseImport, f as resolveHashPlaceholderFileName, i as createCodePositionMap, l as isHttpUrl, o as createSourceMap, r as mfWarn, t as createModuleFederationError, u as normalizePathForImport } from "./logger-D67aJYOe.js";
2
+ import { _ as removeTrailingSlash, a as matchesSharedSource, b as stripViteFsPrefix, 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 resolvePublicPath, x as toRelativeImport, y as stripQueryAndHash } from "./sharedKeyMatcher-C04bVN1q.js";
3
+ import { C as supportsCodeSplittingGroupDebugName, E as isReactCoreShare, S as sharedCacheHelperCode, T as REACT_DOM_CLIENT_SHARE, _ as packageNameDecode, a as getInstalledPackageEntry, b as resolveModulePath, c as getPackageDetectionCwd, d as getPackageNameFromNodeModulePath, f as getSharedCacheDescriptor, g as isPackageInstalled, h as isPackageExportAvailable, i as getDependencyNames, l as getPackageExportSpecifiersForFile, m as isNuxtProjectRoot, n as formatDevServerHostForOrigin, o as getInstalledPackageJson, p as hasPackageDependency, r as watchFileEvents, s as getIsRolldown, u as getPackageName, v as packageNameEncode, w as REACT_CLIENT_INTERNALS_KEY, x as setPackageDetectionCwd, y as resolveImportPath } from "./dtsConstants-CDuC8Bb7.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";
@@ -14,7 +14,6 @@ import { createHash } from "node:crypto";
14
14
  import * as fs$1 from "node:fs";
15
15
  import { existsSync as existsSync$1, readFileSync as readFileSync$1 } from "node:fs";
16
16
  import { pathToFileURL as pathToFileURL$1 } from "node:url";
17
- import { isIPv6 } from "node:net";
18
17
  import { inferAutoPublicPath } from "@module-federation/sdk";
19
18
  import { readFile } from "node:fs/promises";
20
19
  //#region src/utils/regexEscape.ts
@@ -259,8 +258,8 @@ function getPluginEnvironmentName(ctx) {
259
258
  /**
260
259
  * Classify a plugin hook context's Vite environment. Environment names are
261
260
  * user-defined, so Vite's `config.consumer` is the semantic role; fall back to
262
- * the name only when it is missing (Vite 5–7). Returns `undefined` when the hook
263
- * has no environment context at all.
261
+ * the name only when it is missing. Returns `undefined` when the hook has no
262
+ * environment context at all (Vite 5).
264
263
  */
265
264
  function resolveEnvironmentConsumerTarget(ctx) {
266
265
  if (ctx == null || typeof ctx !== "object") return void 0;
@@ -271,7 +270,7 @@ function resolveEnvironmentConsumerTarget(ctx) {
271
270
  const envName = getPluginEnvironmentName(ctx);
272
271
  return !envName || envName === "client" ? "client" : "server";
273
272
  }
274
- /** Vite 5–7 hooks have no environment context and keep their client build behavior. */
273
+ /** Hooks without an environment context (Vite 5) keep their client build behavior. */
275
274
  function isClientEnvironment(ctx) {
276
275
  return resolveEnvironmentConsumerTarget(ctx) !== "server";
277
276
  }
@@ -721,6 +720,11 @@ function normalizeLibrary(library) {
721
720
  if (!library) return void 0;
722
721
  return library;
723
722
  }
723
+ /** An explicit `manifest.disableAssetsAnalyze` wins; otherwise `fallback` applies. */
724
+ function resolveDisableAssetsAnalyze(manifest, fallback) {
725
+ if (typeof manifest === "object" && manifest !== null && Object.hasOwn(manifest, "disableAssetsAnalyze")) return manifest.disableAssetsAnalyze === true;
726
+ return fallback;
727
+ }
724
728
  function normalizeManifest(manifest) {
725
729
  if (manifest === void 0) return;
726
730
  if (typeof manifest === "boolean") return manifest;
@@ -977,16 +981,6 @@ function getSsrCapabilities(viteMajor, command, hasRemotes, isSsr = false) {
977
981
  };
978
982
  }
979
983
  //#endregion
980
- //#region src/utils/runtimePluginSpecifier.ts
981
- function getRuntimePluginSpecifier(plugin) {
982
- return typeof plugin === "string" ? plugin : plugin[0];
983
- }
984
- /** Drop SSR-only plugins from a client graph; a server graph keeps them all. */
985
- function filterRuntimePluginsForTarget(runtimePlugins, ssrOnlySpecifiers, isServer) {
986
- if (isServer) return [...runtimePlugins];
987
- return runtimePlugins.filter((plugin) => !ssrOnlySpecifiers.has(getRuntimePluginSpecifier(plugin)));
988
- }
989
- //#endregion
990
984
  //#region src/utils/serializeRuntimeOptions.ts
991
985
  const UNSAFE_JS_CHAR_MAP = {
992
986
  "<": "\\u003C",
@@ -999,6 +993,11 @@ function toSafeJsLiteral(value) {
999
993
  if (json === void 0) return "undefined";
1000
994
  return json.replace(UNSAFE_JS_CHAR_PATTERN, (char) => UNSAFE_JS_CHAR_MAP[char]);
1001
995
  }
996
+ const JS_IDENTIFIER_PATTERN = `[\$_\\p{ID_Start}][\$_\\u200C\\u200D\\p{ID_Continue}]*`;
997
+ const JS_IDENTIFIER_REGEX = new RegExp(`^${JS_IDENTIFIER_PATTERN}$`, "u");
998
+ function isValidJsIdentifier(name) {
999
+ return JS_IDENTIFIER_REGEX.test(name);
1000
+ }
1002
1001
  /**
1003
1002
  * Serializes a JavaScript object into a string of source code that can be evaluated.
1004
1003
  * This function is used to create runtime plugin options without relying solely on JSON.stringify,
@@ -1233,7 +1232,62 @@ function collectReExport(node, source, record, requireAllExports) {
1233
1232
  }
1234
1233
  record(names, source);
1235
1234
  }
1235
+ const NEEDS_AST_RE = /\brequire\s*(?:\?\.\s*)?(?:\(|\/[*/])|\bexport(?:\s|\/\*[^*]*\*+(?:[^/*][^*]*\*+)*\/|\/\/[^\n]*\n)*\{(?:\s|\/\*[^*]*\*+(?:[^/*][^*]*\*+)*\/|\/\/[^\n]*\n)*\}/;
1236
+ /**
1237
+ * Vite 8 parses with oxc, whose module record lists static imports, re-exports
1238
+ * and dynamic imports without materializing the AST. Same result as the AST
1239
+ * walk below; `undefined` when this input needs the AST.
1240
+ */
1241
+ function analyzeImportsFromModuleRecord(code) {
1242
+ const parseSync = vite.parseSync;
1243
+ if (typeof parseSync !== "function" || NEEDS_AST_RE.test(code)) return void 0;
1244
+ const result = parseSync("file.js", code, {
1245
+ lang: "js",
1246
+ preserveParens: false
1247
+ });
1248
+ if (result.errors.length > 0) return null;
1249
+ const { staticImports, staticExports, dynamicImports } = result.module;
1250
+ const found = [];
1251
+ const isStringName = (name) => name.start !== null && (code[name.start] === "\"" || code[name.start] === "'");
1252
+ const add = (start, source, names) => found.push({
1253
+ start,
1254
+ usage: {
1255
+ source,
1256
+ usedExports: names
1257
+ }
1258
+ });
1259
+ for (const declaration of staticImports) {
1260
+ const source = declaration.moduleRequest.value;
1261
+ let names = declaration.entries.length === 0 ? null : [];
1262
+ for (const { importName } of declaration.entries) if (importName.kind === "Default") names?.push("default");
1263
+ else if (importName.kind === "Name" && importName.name && !isStringName(importName)) names?.push(importName.name);
1264
+ else names = null;
1265
+ add(declaration.start, source, names);
1266
+ }
1267
+ const importStarts = new Set(staticImports.map((declaration) => declaration.start));
1268
+ for (const declaration of staticExports) {
1269
+ const request = declaration.entries[0]?.moduleRequest;
1270
+ if (!request || importStarts.has(declaration.start)) continue;
1271
+ const source = request.value;
1272
+ let names = [];
1273
+ for (const { importName } of declaration.entries) if (importName.kind === "Name" && importName.name && !isStringName(importName)) names?.push(importName.name);
1274
+ else names = null;
1275
+ add(declaration.start, source, names);
1276
+ }
1277
+ const dynamicStarts = /* @__PURE__ */ new Set();
1278
+ for (const { start, moduleRequest } of dynamicImports) {
1279
+ if (dynamicStarts.has(start)) continue;
1280
+ dynamicStarts.add(start);
1281
+ const text = code.slice(moduleRequest.start, moduleRequest.end);
1282
+ const quote = text[0];
1283
+ if (text.length >= 2 && (quote === "\"" || quote === "'" || quote === "`") && text.at(-1) === quote && !text.includes("\\") && !text.slice(1, -1).includes(quote) && !(quote === "`" && text.includes("${"))) add(start, text.slice(1, -1), null);
1284
+ else if (text.includes("\\")) return;
1285
+ }
1286
+ return found.sort((a, b) => a.start - b.start).map(({ usage }) => usage);
1287
+ }
1236
1288
  function analyzeImports(code) {
1289
+ const fromModuleRecord = analyzeImportsFromModuleRecord(code);
1290
+ if (fromModuleRecord !== void 0) return fromModuleRecord;
1237
1291
  let ast;
1238
1292
  try {
1239
1293
  ast = vite.parseAst(code);
@@ -1299,13 +1353,8 @@ function analyzeImports(code) {
1299
1353
  function shouldAnalyzeSharedExports(shareItem) {
1300
1354
  return !!(shareItem && (shareItem.shareConfig.treeShaking || shareItem.shareConfig.import === false));
1301
1355
  }
1302
- const legacyTreeShakingState = {
1303
- inferredUsage: /* @__PURE__ */ new Map(),
1304
- buildMode: false
1305
- };
1306
1356
  const treeShakingStates = /* @__PURE__ */ new WeakMap();
1307
1357
  function getTreeShakingState(options) {
1308
- if (!options) return legacyTreeShakingState;
1309
1358
  let state = treeShakingStates.get(options);
1310
1359
  if (!state) {
1311
1360
  state = {
@@ -1358,7 +1407,7 @@ function getExportRecords(sharedKey, request, options) {
1358
1407
  inferredUsage.forEach((byRequest, configuredKey) => {
1359
1408
  const wildcard = byRequest.get("*");
1360
1409
  const exact = byRequest.get(request);
1361
- const configuredRequest = getSharedRequest(configuredKey, options?.shared?.[configuredKey]);
1410
+ const configuredRequest = getSharedRequest(configuredKey, options.shared?.[configuredKey]);
1362
1411
  const keyBase = configuredRequest.endsWith("/") ? configuredRequest.slice(0, -1) : configuredRequest;
1363
1412
  const requestMatchesConfiguredKey = request === keyBase || request.startsWith(`${keyBase}/`);
1364
1413
  if (wildcard && requestMatchesConfiguredKey) records.push(wildcard);
@@ -1423,240 +1472,117 @@ async function collectTreeShakingImports(code, id, shared, findSharedKey, record
1423
1472
  await Promise.all(pending);
1424
1473
  }
1425
1474
  //#endregion
1426
- //#region src/utils/reactIsland.ts
1427
- const SOURCE_EXTENSIONS$1 = [
1428
- ".tsx",
1429
- ".jsx",
1430
- ".ts",
1431
- ".js",
1432
- ".mts",
1433
- ".mjs",
1434
- ".cts",
1435
- ".cjs"
1436
- ];
1437
- function resolveSourceFile(importPath, root) {
1438
- const cleanImport = stripQueryAndHash(importPath);
1439
- if (!cleanImport.startsWith(".") && !path$1.isAbsolute(cleanImport)) return;
1440
- const candidate = path$1.isAbsolute(cleanImport) ? cleanImport : path$1.resolve(root, cleanImport);
1441
- return [
1442
- candidate,
1443
- ...SOURCE_EXTENSIONS$1.map((extension) => `${candidate}${extension}`),
1444
- ...SOURCE_EXTENSIONS$1.map((extension) => path$1.join(candidate, `index${extension}`))
1445
- ].find((filePath) => {
1446
- try {
1447
- return fs$1.statSync(filePath).isFile();
1448
- } catch {
1449
- return false;
1450
- }
1451
- });
1452
- }
1453
- function localDefaultReexport(source) {
1454
- const match = source.match(/export\s*{\s*(?:default(?:\s+as\s+default)?|[A-Za-z_$][\w$]*\s+as\s+default)\s*}\s*from\s*["']([^"']+)["']/);
1455
- return match?.[1]?.startsWith(".") ? match[1] : void 0;
1475
+ //#region src/utils/typeArgumentScanner.ts
1476
+ function getTypeArgumentStartContext(source, start) {
1477
+ let previous = start - 1;
1478
+ while (previous >= 0 && /\s/.test(source[previous])) previous--;
1479
+ const previousChar = source[previous] || "";
1480
+ const followsNamedExpression = /[$_\u200C\u200D\p{ID_Continue})\]>]/u.test(previousChar);
1481
+ const startsStandaloneGeneric = previousChar !== "" && "=([{,:".includes(previousChar);
1482
+ if (!followsNamedExpression && !startsStandaloneGeneric) return void 0;
1483
+ return { followsNamedExpression };
1456
1484
  }
1457
- function isReactComponentSource(source, filePath = "component.tsx") {
1458
- if (!(/\bexport\s+default\b/.test(source) || /\bexport\s*{[^}]*\bdefault\b[^}]*}(?:\s*from\s*["'][^"']+["'])?/.test(source))) return false;
1459
- const extension = path$1.extname(stripQueryAndHash(filePath)).toLowerCase();
1460
- const canContainJsx = extension === ".tsx" || extension === ".jsx";
1461
- const hasJsx = /<>|<\s*[A-Za-z][\w.:-]*(?:\s[^<>]*?)?\s*\/?>/.test(source);
1462
- const importsReact = /\bfrom\s*["']react["']|\brequire\(\s*["']react["']\s*\)/.test(source);
1463
- const usesReactApi = /\b(?:React\.)?(?:createElement|jsx|jsxs)\s*\(/.test(source);
1464
- const isClientModule = /^\s*["']use client["']\s*;?/m.test(source);
1465
- return canContainJsx && hasJsx || importsReact && (hasJsx || usesReactApi || isClientModule);
1485
+ function updateTypeArgumentGroupDepth(char, state) {
1486
+ if (char === "(" || char === "[" || char === "{") {
1487
+ state.groupDepth++;
1488
+ return "handled";
1489
+ }
1490
+ if (char !== ")" && char !== "]" && char !== "}") return void 0;
1491
+ if (state.groupDepth === 0) return "invalid";
1492
+ state.groupDepth--;
1493
+ return "handled";
1466
1494
  }
1467
- function isReactComponentFile(filePath, seen = /* @__PURE__ */ new Set()) {
1468
- const normalizedPath = path$1.resolve(filePath);
1469
- if (seen.has(normalizedPath)) return false;
1470
- seen.add(normalizedPath);
1471
- let source;
1472
- try {
1473
- source = fs$1.readFileSync(normalizedPath, "utf8");
1474
- } catch {
1475
- return false;
1495
+ function updateTypeArgumentAngleDepth(source, index, state) {
1496
+ const char = source[index];
1497
+ if (char === "<") {
1498
+ if (source[index + 1] === "=" || source[index + 1] === "<") return "invalid";
1499
+ state.angleDepth++;
1500
+ return "handled";
1476
1501
  }
1477
- if (isReactComponentSource(source, normalizedPath)) return true;
1478
- const reexport = localDefaultReexport(source);
1479
- if (!reexport) return false;
1480
- const reexportPath = resolveSourceFile(reexport, path$1.dirname(normalizedPath));
1481
- return reexportPath ? isReactComponentFile(reexportPath, seen) : false;
1502
+ if (char !== ">") return void 0;
1503
+ if (source[index - 1] === "=" || source[index + 1] === "=") return "handled";
1504
+ state.angleDepth--;
1505
+ return state.angleDepth === 0 ? "closed" : "handled";
1506
+ }
1507
+ function hasLikelyTypeArgumentFollower(source, end, codePositions, followsNamedExpression) {
1508
+ let next = end + 1;
1509
+ while (next < source.length && (!codePositions[next] || /\s/.test(source[next]))) next++;
1510
+ if (next >= source.length || /[([.!?=;,)\]}:|&]/.test(source[next])) return true;
1511
+ if (source.slice(end + 1, next).includes("\n")) return true;
1512
+ const followingToken = source.slice(next).match(/^[$_\p{ID_Start}][$_\u200C\u200D\p{ID_Continue}]*/u)?.[0];
1513
+ return followingToken === "as" || followingToken === "satisfies" || !followsNamedExpression && followingToken !== void 0;
1514
+ }
1515
+ function isInvalidTypeArgumentTerminator(source, index, followsNamedExpression) {
1516
+ const char = source[index];
1517
+ return char === ";" || char === "=" && source[index + 1] !== ">" && followsNamedExpression;
1482
1518
  }
1483
1519
  /**
1484
- * React is shared by the normal MF runtime when explicitly configured. When it
1485
- * is local, UI exposes can safely advertise an island capability in addition
1486
- * to their unchanged default export.
1520
+ * Finds the end of a balanced, type-like angle-bracket range that contains a
1521
+ * comma. Ambiguous syntax returns `undefined` so callers can fail closed.
1487
1522
  */
1488
- function getReactIslandExposes(options, root) {
1489
- if (options.experiments.ssrMode !== "ISLAND") return /* @__PURE__ */ new Set();
1490
- if (Object.hasOwn(options.shared, "react")) return /* @__PURE__ */ new Set();
1491
- const islandExposes = /* @__PURE__ */ new Set();
1492
- for (const [key, expose] of Object.entries(options.exposes)) {
1493
- const sourceFile = resolveSourceFile(expose.import, root);
1494
- if (sourceFile && isReactComponentFile(sourceFile)) islandExposes.add(key);
1523
+ function findLikelyTypeArgumentEnd(source, start, codePositions) {
1524
+ const context = getTypeArgumentStartContext(source, start);
1525
+ if (!context) return void 0;
1526
+ const state = {
1527
+ angleDepth: 1,
1528
+ groupDepth: 0,
1529
+ sawTypeComma: false
1530
+ };
1531
+ for (let index = start + 1; index < source.length; index++) {
1532
+ if (!codePositions[index]) continue;
1533
+ const char = source[index];
1534
+ const groupAction = updateTypeArgumentGroupDepth(char, state);
1535
+ if (groupAction === "invalid") return void 0;
1536
+ if (groupAction === "handled") continue;
1537
+ const angleAction = updateTypeArgumentAngleDepth(source, index, state);
1538
+ if (angleAction === "invalid") return void 0;
1539
+ if (angleAction === "closed") return state.sawTypeComma && hasLikelyTypeArgumentFollower(source, index, codePositions, context.followsNamedExpression) ? index : void 0;
1540
+ if (angleAction === "handled") continue;
1541
+ if (char === "," && state.groupDepth === 0) {
1542
+ state.sawTypeComma = true;
1543
+ continue;
1544
+ }
1545
+ if (state.angleDepth === 1 && state.groupDepth === 0 && isInvalidTypeArgumentTerminator(source, index, context.followsNamedExpression)) return;
1495
1546
  }
1496
- return islandExposes;
1497
1547
  }
1498
- function generateReactIslandBrowserDefinition(enabled) {
1499
- if (!enabled) return "";
1500
- return `
1501
- exportModule.__mf_island = {
1502
- version: 1,
1503
- renderToHtml() {
1504
- return Promise.reject(new Error("[Module Federation] renderToHtml is only available in the SSR remote entry"));
1505
- },
1506
- hydrate(element, props) {
1507
- const root = element && element.hasAttribute && element.hasAttribute("data-mf-island-state")
1508
- ? element
1509
- : element && element.querySelector
1510
- ? element.querySelector("[data-mf-island-state]") || element
1511
- : element;
1512
- if (!root) {
1513
- return Promise.reject(new Error("[Module Federation] Cannot hydrate an island without a root element"));
1514
- }
1515
- let serverProps = {};
1516
- const encodedState = root.getAttribute && root.getAttribute("data-mf-island-state");
1517
- if (encodedState) {
1518
- try {
1519
- serverProps = JSON.parse(decodeURIComponent(encodedState));
1520
- } catch {
1521
- serverProps = {};
1522
- }
1523
- }
1524
- const finalProps = Object.assign({}, serverProps, props || {});
1525
- return Promise.all([import("react"), import("react-dom/client")]).then(([React, ReactDOMClient]) => {
1526
- if (typeof ReactDOMClient.hydrateRoot !== "function") {
1527
- throw new Error("[Module Federation] react-dom/client does not provide hydrateRoot");
1528
- }
1529
- return ReactDOMClient.hydrateRoot(
1530
- root,
1531
- React.createElement(importModule.default, finalProps)
1532
- );
1533
- });
1534
- }
1535
- }`;
1548
+ //#endregion
1549
+ //#region src/utils/sharedExportConditions.ts
1550
+ const DEFAULT_CLIENT_EXPORT_CONDITIONS = [
1551
+ "browser",
1552
+ "import",
1553
+ "module",
1554
+ "default"
1555
+ ];
1556
+ const DEFAULT_NODE_SSR_EXPORT_CONDITIONS = [
1557
+ "node",
1558
+ "import",
1559
+ "module",
1560
+ "default"
1561
+ ];
1562
+ const DEFAULT_WEBWORKER_SSR_EXPORT_CONDITIONS = [
1563
+ "worker",
1564
+ "browser",
1565
+ "import",
1566
+ "module",
1567
+ "default"
1568
+ ];
1569
+ const VITE_DEV_PROD_CONDITION = "development|production";
1570
+ function appendConditions(conditions, fallbackConditions) {
1571
+ return [.../* @__PURE__ */ new Set([...conditions, ...fallbackConditions])];
1536
1572
  }
1537
- function generateReactIslandSSRDefinition(enabled) {
1538
- if (!enabled) return "";
1539
- return `
1540
- exportModule.__mf_island = {
1541
- version: 1,
1542
- async renderToHtml(props) {
1543
- if (typeof importModule.default !== "function" && typeof importModule.default !== "object") {
1544
- throw new Error("[Module Federation] A React island expose must have a default component export");
1545
- }
1546
- const loadedProps = typeof importModule.load === "function" ? await importModule.load() : {};
1547
- const finalProps = Object.assign({}, loadedProps || {}, props || {});
1548
- const [React, ReactDOMServer] = await Promise.all([
1549
- import("react"),
1550
- import("react-dom/server")
1551
- ]);
1552
- const body = ReactDOMServer.renderToString(
1553
- React.createElement(importModule.default, finalProps)
1554
- );
1555
- const state = encodeURIComponent(JSON.stringify(finalProps));
1556
- return '<div data-mf-island-state="' + state + '">' + body + '</div>';
1557
- },
1558
- hydrate() {
1559
- return Promise.reject(new Error("[Module Federation] hydrate is only available in the browser remote entry"));
1560
- }
1561
- }`;
1573
+ function resolveViteModeCondition(conditions, isProduction) {
1574
+ const modeCondition = isProduction ? "production" : "development";
1575
+ return [...new Set(conditions.map((condition) => condition === VITE_DEV_PROD_CONDITION ? modeCondition : condition))];
1562
1576
  }
1563
- const REACT_ISLAND_CLIENT_ID_PREFIX = "virtual:mf-react-island-client:";
1564
- const REACT_ISLAND_SERVER_ID_PREFIX = "virtual:mf-react-island-server:";
1565
- const RESOLVED_REACT_ISLAND_CLIENT_ID_PREFIX = `\0${REACT_ISLAND_CLIENT_ID_PREFIX}`;
1566
- const RESOLVED_REACT_ISLAND_SERVER_ID_PREFIX = `\0${REACT_ISLAND_SERVER_ID_PREFIX}`;
1567
- function encodeIslandRemoteId(remoteId) {
1568
- return encodeURIComponent(remoteId);
1577
+ function getSharedExportConditions({ environmentConditions, isProduction, isSsr, rootConditions, ssrConditions, ssrTarget = "node" }) {
1578
+ if (environmentConditions !== void 0) return resolveViteModeCondition(appendConditions(environmentConditions, ["import", "default"]), isProduction);
1579
+ const defaultConditions = isSsr ? ssrTarget === "webworker" ? DEFAULT_WEBWORKER_SSR_EXPORT_CONDITIONS : DEFAULT_NODE_SSR_EXPORT_CONDITIONS : DEFAULT_CLIENT_EXPORT_CONDITIONS;
1580
+ const configuredConditions = isSsr ? ssrConditions ?? rootConditions : rootConditions;
1581
+ if (configuredConditions !== void 0) return resolveViteModeCondition(appendConditions(configuredConditions, defaultConditions), isProduction);
1582
+ return [...defaultConditions];
1569
1583
  }
1570
- function decodeIslandRemoteId(encodedRemoteId) {
1571
- return decodeURIComponent(encodedRemoteId);
1572
- }
1573
- function getReactIslandImportRemoteId(source) {
1574
- const queryIndex = source.indexOf("?");
1575
- if (queryIndex === -1) return;
1576
- if (!new URLSearchParams(source.slice(queryIndex + 1)).has("mf-island")) return;
1577
- return source.slice(0, queryIndex);
1578
- }
1579
- function getReactIslandServerImportId(remoteId) {
1580
- return `${REACT_ISLAND_SERVER_ID_PREFIX}${encodeIslandRemoteId(remoteId)}`;
1581
- }
1582
- function getReactIslandClientImportId(remoteId) {
1583
- return `${REACT_ISLAND_CLIENT_ID_PREFIX}${encodeIslandRemoteId(remoteId)}`;
1584
- }
1585
- function resolveReactIslandConsumerId(id) {
1586
- if (id.startsWith("virtual:mf-react-island-server:")) return `\0${id}`;
1587
- if (id.startsWith("virtual:mf-react-island-client:")) return `\0${id}`;
1588
- }
1589
- function remoteIdFromResolvedIslandId(id, prefix) {
1590
- if (!id.startsWith(prefix)) return;
1591
- return decodeIslandRemoteId(id.slice(prefix.length));
1592
- }
1593
- /** Generates the server half of the opt-in `?mf-island` consumer component. */
1594
- function generateReactIslandConsumerServer(remoteId) {
1595
- const source = JSON.stringify(remoteId);
1596
- return `import * as React from "react";
1597
- import IslandClient from ${JSON.stringify(getReactIslandClientImportId(remoteId))};
1598
-
1599
- const islandModulePromise = import(${source});
1600
-
1601
- async function loadIslandModule() {
1602
- const namespace = await islandModulePromise;
1603
- const pending = namespace && namespace.__mf_remote_pending;
1604
- if (pending && typeof pending.then === "function") return pending;
1605
- return namespace && namespace.__moduleExports || namespace;
1606
- }
1607
-
1608
- export default async function ModuleFederationIsland(props) {
1609
- const remoteModule = await loadIslandModule();
1610
- const shell = remoteModule && remoteModule.__mf_island;
1611
- if (!shell || typeof shell.renderToHtml !== "function") {
1612
- throw new Error(${JSON.stringify(`[Module Federation] ${remoteId} does not expose an SSR island capability`)});
1613
- }
1614
- const html = await shell.renderToHtml(props);
1615
- return React.createElement(IslandClient, { html, islandProps: props });
1616
- }`;
1617
- }
1618
- /** Generates the client boundary which hydrates with the remote-owned React. */
1619
- function generateReactIslandConsumerClient(remoteId) {
1620
- return `"use client";
1621
-
1622
- import * as React from "react";
1623
-
1624
- const islandModulePromise = import(${JSON.stringify(remoteId)});
1625
-
1626
- async function loadIslandModule() {
1627
- const namespace = await islandModulePromise;
1628
- const pending = namespace && namespace.__mf_remote_pending;
1629
- if (pending && typeof pending.then === "function") return pending;
1630
- return namespace && namespace.__moduleExports || namespace;
1631
- }
1632
-
1633
- export default function ModuleFederationIslandClient({ html, islandProps }) {
1634
- const ref = React.useRef(null);
1635
-
1636
- React.useEffect(() => {
1637
- const element = ref.current;
1638
- if (!element) return;
1639
- void loadIslandModule().then((remoteModule) => {
1640
- const shell = remoteModule && remoteModule.__mf_island;
1641
- if (!shell || typeof shell.hydrate !== "function") {
1642
- throw new Error(${JSON.stringify(`[Module Federation] ${remoteId} does not expose a client island capability`)});
1643
- }
1644
- return shell.hydrate(element, islandProps);
1645
- });
1646
- }, []);
1647
-
1648
- return React.createElement("div", {
1649
- ref,
1650
- suppressHydrationWarning: true,
1651
- dangerouslySetInnerHTML: { __html: html },
1652
- });
1653
- }`;
1654
- }
1655
- function loadReactIslandConsumerModule(id) {
1656
- const serverRemoteId = remoteIdFromResolvedIslandId(id, RESOLVED_REACT_ISLAND_SERVER_ID_PREFIX);
1657
- if (serverRemoteId !== void 0) return generateReactIslandConsumerServer(serverRemoteId);
1658
- const clientRemoteId = remoteIdFromResolvedIslandId(id, RESOLVED_REACT_ISLAND_CLIENT_ID_PREFIX);
1659
- if (clientRemoteId !== void 0) return generateReactIslandConsumerClient(clientRemoteId);
1584
+ function isReactServerConditions(conditions) {
1585
+ return Boolean(conditions?.includes("react-server"));
1660
1586
  }
1661
1587
  //#endregion
1662
1588
  //#region src/virtualModules/virtualModuleScope.ts
@@ -1701,157 +1627,19 @@ function stableConfigValue(value, ancestors = /* @__PURE__ */ new WeakSet()) {
1701
1627
  ancestors.delete(value);
1702
1628
  return result;
1703
1629
  }
1630
+ function hashConfig(value) {
1631
+ const identity = JSON.stringify(stableConfigValue(value));
1632
+ return BigInt(`0x${createHash("sha256").update(identity).digest("hex").slice(0, 12)}`);
1633
+ }
1634
+ const ownerIdFilenames = /* @__PURE__ */ new Map();
1704
1635
  function getFederationScopeKey(options) {
1705
- const identity = JSON.stringify(stableConfigValue(options));
1706
- const ownerId = BigInt(`0x${createHash("sha256").update(identity).digest("hex").slice(0, 12)}`);
1636
+ const { filename, ...identity } = options;
1637
+ let ownerId = hashConfig(identity);
1638
+ if (!ownerIdFilenames.has(ownerId)) ownerIdFilenames.set(ownerId, filename);
1639
+ else if (ownerIdFilenames.get(ownerId) !== filename) ownerId = hashConfig(options);
1707
1640
  return `${options.internalName}${MF_OWNER_INFIX}${ownerId}`;
1708
1641
  }
1709
1642
  //#endregion
1710
- //#region src/virtualModules/virtualExposes.ts
1711
- const EXPOSES_CSS_MAP_PLACEHOLDER = "__MF_EXPOSES_CSS_MAP__";
1712
- function getExposesCssMapPlaceholder() {
1713
- return EXPOSES_CSS_MAP_PLACEHOLDER;
1714
- }
1715
- function getVirtualExposesId(options) {
1716
- return `virtual:mf-exposes:${getVirtualModuleScopeKey(options)}`;
1717
- }
1718
- function generateExposes(options, remoteDependencyMap = {}, command = "build", reactIslandExposes = /* @__PURE__ */ new Set()) {
1719
- return `
1720
- const cssAssetMap = ${JSON.stringify(options.bundleAllCSS ? EXPOSES_CSS_MAP_PLACEHOLDER : {})};
1721
- const injectedCssHrefs = new Set();
1722
- const exposeLoadPromises = new Map();
1723
-
1724
- // Shared and remote readiness is handled by explicit Promise barriers below
1725
- // and by remoteEntry's pendingShareLoads barrier. Keep this map scoped to a
1726
- // single expose: unrelated exposes must stay independent and load in parallel.
1727
- function loadExposedModule(exposeKey, loader) {
1728
- let load = exposeLoadPromises.get(exposeKey);
1729
- if (!load) {
1730
- load = Promise.resolve()
1731
- .then(loader)
1732
- .catch((error) => {
1733
- exposeLoadPromises.delete(exposeKey);
1734
- throw error;
1735
- });
1736
- exposeLoadPromises.set(exposeKey, load);
1737
- }
1738
- return load;
1739
- }
1740
-
1741
- async function injectCssAssets(exposeKey) {
1742
- if (typeof document === "undefined") {
1743
- return;
1744
- }
1745
-
1746
- // Replaced at build time with expose -> css asset paths.
1747
- const cssAssets = cssAssetMap[exposeKey] || [];
1748
-
1749
- await Promise.all(
1750
- cssAssets.map((cssAsset) => {
1751
- const href = new URL(cssAsset, import.meta.url).href;
1752
-
1753
- // Same expose can be resolved multiple times in one page.
1754
- if (injectedCssHrefs.has(href)) {
1755
- return Promise.resolve();
1756
- }
1757
- injectedCssHrefs.add(href);
1758
-
1759
- // Check for any existing stylesheet with the same href, not just
1760
- // MF-injected ones. This prevents duplicate <link> tags when Vite's
1761
- // own CSS module injection or MF runtime's createLink has already
1762
- // created a <link rel="stylesheet"> for the same URL.
1763
- const existingLink = document.querySelector(
1764
- \`link[rel="stylesheet"][href="\${href}"]\`
1765
- );
1766
- if (existingLink) {
1767
- return Promise.resolve();
1768
- }
1769
-
1770
- return new Promise((resolve, reject) => {
1771
- const link = document.createElement("link");
1772
- link.rel = "stylesheet";
1773
- link.href = href;
1774
- link.onload = () => resolve();
1775
- link.onerror = () => reject(new Error(\`[Module Federation] Failed to load CSS asset: \${href}\`));
1776
- document.head.appendChild(link);
1777
- });
1778
- })
1779
- );
1780
- }
1781
-
1782
- export default {
1783
- ${Object.keys(options.exposes).map((key) => {
1784
- const remoteDependencyPreloads = (remoteDependencyMap[key] ?? []).map((remoteId) => {
1785
- const virtualRemote = getRemoteVirtualModule(remoteId, command, false, "unified", options);
1786
- return `import(${JSON.stringify(virtualRemote.getImportId())})
1787
- .then((mod) => mod.__mf_remote_pending)`;
1788
- }).join(",");
1789
- return `
1790
- ${JSON.stringify(key)}: async () => {
1791
- await injectCssAssets(${JSON.stringify(key)})
1792
- await Promise.all([${remoteDependencyPreloads}])
1793
- const importModule = await loadExposedModule(
1794
- ${JSON.stringify(key)},
1795
- () => import(${JSON.stringify(options.exposes[key].import)})
1796
- )
1797
- const dependencyPending = importModule && importModule.__mf_remote_dependency_pending;
1798
- if (dependencyPending && typeof dependencyPending.then === "function") {
1799
- await dependencyPending;
1800
- }
1801
- const exportModule = {}
1802
- Object.assign(exportModule, importModule)
1803
- ${generateReactIslandBrowserDefinition(reactIslandExposes.has(key))}
1804
- Object.defineProperty(exportModule, "__esModule", {
1805
- value: true,
1806
- enumerable: false
1807
- })
1808
- return exportModule
1809
- }
1810
- `;
1811
- }).join(",")}
1812
- }
1813
- `;
1814
- }
1815
- //#endregion
1816
- //#region src/utils/sharedExportConditions.ts
1817
- const DEFAULT_CLIENT_EXPORT_CONDITIONS = [
1818
- "browser",
1819
- "import",
1820
- "module",
1821
- "default"
1822
- ];
1823
- const DEFAULT_NODE_SSR_EXPORT_CONDITIONS = [
1824
- "node",
1825
- "import",
1826
- "module",
1827
- "default"
1828
- ];
1829
- const DEFAULT_WEBWORKER_SSR_EXPORT_CONDITIONS = [
1830
- "worker",
1831
- "browser",
1832
- "import",
1833
- "module",
1834
- "default"
1835
- ];
1836
- const VITE_DEV_PROD_CONDITION = "development|production";
1837
- function appendConditions(conditions, fallbackConditions) {
1838
- return [.../* @__PURE__ */ new Set([...conditions, ...fallbackConditions])];
1839
- }
1840
- function resolveViteModeCondition(conditions, isProduction) {
1841
- const modeCondition = isProduction ? "production" : "development";
1842
- return [...new Set(conditions.map((condition) => condition === VITE_DEV_PROD_CONDITION ? modeCondition : condition))];
1843
- }
1844
- function getSharedExportConditions({ environmentConditions, isProduction, isSsr, rootConditions, ssrConditions, ssrTarget = "node" }) {
1845
- if (environmentConditions !== void 0) return resolveViteModeCondition(appendConditions(environmentConditions, ["import", "default"]), isProduction);
1846
- const defaultConditions = isSsr ? ssrTarget === "webworker" ? DEFAULT_WEBWORKER_SSR_EXPORT_CONDITIONS : DEFAULT_NODE_SSR_EXPORT_CONDITIONS : DEFAULT_CLIENT_EXPORT_CONDITIONS;
1847
- const configuredConditions = isSsr ? ssrConditions ?? rootConditions : rootConditions;
1848
- if (configuredConditions !== void 0) return resolveViteModeCondition(appendConditions(configuredConditions, defaultConditions), isProduction);
1849
- return [...defaultConditions];
1850
- }
1851
- function isReactServerConditions(conditions) {
1852
- return Boolean(conditions?.includes("react-server"));
1853
- }
1854
- //#endregion
1855
1643
  //#region src/virtualModules/virtualRuntimeInitStatus.ts
1856
1644
  const virtualRuntimeInitStatus = new VirtualModule("runtimeInit");
1857
1645
  const runtimeInitModules = /* @__PURE__ */ new WeakMap();
@@ -2034,102 +1822,10 @@ ${exportStatement}
2034
1822
  `);
2035
1823
  }
2036
1824
  //#endregion
2037
- //#region src/plugins/pluginReactMixedModeGuard.ts
2038
- function createReactMixedModeRuntimeGuard() {
2039
- return `const __mfReactInternals = mod[${JSON.stringify(REACT_CLIENT_INTERNALS_KEY)}];
2040
- if (__mfReactInternals && "A" in __mfReactInternals) {
2041
- let __mfReactDispatcher = __mfReactInternals.A;
2042
- Object.defineProperty(__mfReactInternals, "A", {
2043
- configurable: true,
2044
- enumerable: true,
2045
- get: () => __mfReactDispatcher,
2046
- set: (next) => {
2047
- if (next && typeof next.getOwner !== "function") next.getOwner = () => null;
2048
- __mfReactDispatcher = next;
2049
- },
2050
- });
2051
- __mfReactInternals.A = __mfReactDispatcher;
2052
- }`;
2053
- }
2054
- //#endregion
2055
- //#region src/utils/typeArgumentScanner.ts
2056
- function getTypeArgumentStartContext(source, start) {
2057
- let previous = start - 1;
2058
- while (previous >= 0 && /\s/.test(source[previous])) previous--;
2059
- const previousChar = source[previous] || "";
2060
- const followsNamedExpression = /[$_\u200C\u200D\p{ID_Continue})\]>]/u.test(previousChar);
2061
- const startsStandaloneGeneric = previousChar !== "" && "=([{,:".includes(previousChar);
2062
- if (!followsNamedExpression && !startsStandaloneGeneric) return void 0;
2063
- return { followsNamedExpression };
2064
- }
2065
- function updateTypeArgumentGroupDepth(char, state) {
2066
- if (char === "(" || char === "[" || char === "{") {
2067
- state.groupDepth++;
2068
- return "handled";
2069
- }
2070
- if (char !== ")" && char !== "]" && char !== "}") return void 0;
2071
- if (state.groupDepth === 0) return "invalid";
2072
- state.groupDepth--;
2073
- return "handled";
2074
- }
2075
- function updateTypeArgumentAngleDepth(source, index, state) {
2076
- const char = source[index];
2077
- if (char === "<") {
2078
- if (source[index + 1] === "=" || source[index + 1] === "<") return "invalid";
2079
- state.angleDepth++;
2080
- return "handled";
2081
- }
2082
- if (char !== ">") return void 0;
2083
- if (source[index - 1] === "=" || source[index + 1] === "=") return "handled";
2084
- state.angleDepth--;
2085
- return state.angleDepth === 0 ? "closed" : "handled";
2086
- }
2087
- function hasLikelyTypeArgumentFollower(source, end, codePositions, followsNamedExpression) {
2088
- let next = end + 1;
2089
- while (next < source.length && (!codePositions[next] || /\s/.test(source[next]))) next++;
2090
- if (next >= source.length || /[([.!?=;,)\]}:|&]/.test(source[next])) return true;
2091
- if (source.slice(end + 1, next).includes("\n")) return true;
2092
- const followingToken = source.slice(next).match(/^[$_\p{ID_Start}][$_\u200C\u200D\p{ID_Continue}]*/u)?.[0];
2093
- return followingToken === "as" || followingToken === "satisfies" || !followsNamedExpression && followingToken !== void 0;
2094
- }
2095
- function isInvalidTypeArgumentTerminator(source, index, followsNamedExpression) {
2096
- const char = source[index];
2097
- return char === ";" || char === "=" && source[index + 1] !== ">" && followsNamedExpression;
2098
- }
2099
- /**
2100
- * Finds the end of a balanced, type-like angle-bracket range that contains a
2101
- * comma. Ambiguous syntax returns `undefined` so callers can fail closed.
2102
- */
2103
- function findLikelyTypeArgumentEnd(source, start, codePositions) {
2104
- const context = getTypeArgumentStartContext(source, start);
2105
- if (!context) return void 0;
2106
- const state = {
2107
- angleDepth: 1,
2108
- groupDepth: 0,
2109
- sawTypeComma: false
2110
- };
2111
- for (let index = start + 1; index < source.length; index++) {
2112
- if (!codePositions[index]) continue;
2113
- const char = source[index];
2114
- const groupAction = updateTypeArgumentGroupDepth(char, state);
2115
- if (groupAction === "invalid") return void 0;
2116
- if (groupAction === "handled") continue;
2117
- const angleAction = updateTypeArgumentAngleDepth(source, index, state);
2118
- if (angleAction === "invalid") return void 0;
2119
- if (angleAction === "closed") return state.sawTypeComma && hasLikelyTypeArgumentFollower(source, index, codePositions, context.followsNamedExpression) ? index : void 0;
2120
- if (angleAction === "handled") continue;
2121
- if (char === "," && state.groupDepth === 0) {
2122
- state.sawTypeComma = true;
2123
- continue;
2124
- }
2125
- if (state.angleDepth === 1 && state.groupDepth === 0 && isInvalidTypeArgumentTerminator(source, index, context.followsNamedExpression)) return;
2126
- }
2127
- }
2128
- //#endregion
2129
- //#region src/virtualModules/shareTags.ts
2130
- const LOAD_SHARE_TAG = "__loadShare__";
2131
- /** A share's local copy. Reachable only through `import()`, so it stays lazy. */
2132
- const PREBUILD_TAG = "__prebuild__";
1825
+ //#region src/virtualModules/shareTags.ts
1826
+ const LOAD_SHARE_TAG = "__loadShare__";
1827
+ /** A share's local copy. Reachable only through `import()`, so it stays lazy. */
1828
+ const PREBUILD_TAG = "__prebuild__";
2133
1829
  //#endregion
2134
1830
  //#region src/virtualModules/loadShareSharedChunk.ts
2135
1831
  const HELPERS_MODULE_NAME = "loadShareHelpers";
@@ -2208,7 +1904,6 @@ function findEagerFallbacksInSharedChunk(bundle) {
2208
1904
  * 1. __prebuild__: export shareModule (pre-built source code of modules such as vue, react, etc.)
2209
1905
  * 2. __loadShare__: load shareModule (mfRuntime.loadShare('vue'))
2210
1906
  */
2211
- const JS_IDENTIFIER_REGEX = /* @__PURE__ */ new RegExp("^[$_\\p{ID_Start}][$_\\u200C\\u200D\\p{ID_Continue}]*$", "u");
2212
1907
  function escapeGeneratedStringLiteral(value) {
2213
1908
  return JSON.stringify(value).replace(/[<>\u2028\u2029]/g, (char) => {
2214
1909
  switch (char) {
@@ -2220,16 +1915,15 @@ function escapeGeneratedStringLiteral(value) {
2220
1915
  }
2221
1916
  });
2222
1917
  }
1918
+ function getDefaultOrNamespaceExpression(namespace) {
1919
+ return `Reflect.get(${namespace}, "default") ?? ${namespace}`;
1920
+ }
2223
1921
  function getSharedCacheDescriptorLiteral(pkg, shareItem) {
2224
1922
  return JSON.stringify(getSharedCacheDescriptor(pkg, shareItem));
2225
1923
  }
2226
- function isValidJsIdentifier(name) {
2227
- return JS_IDENTIFIER_REGEX.test(name);
2228
- }
2229
1924
  function isValidEsmExportName(name) {
2230
1925
  return !!name && name !== "default" && name !== "__esModule" && isValidJsIdentifier(name);
2231
1926
  }
2232
- const JS_IDENTIFIER_PATTERN = `[\$_\\p{ID_Start}][\$_\\u200C\\u200D\\p{ID_Continue}]*`;
2233
1927
  function resolvePackageEntryFromProjectRoot(pkg) {
2234
1928
  try {
2235
1929
  return resolveModulePath(pkg, path$1.join(getPackageDetectionCwd(), "package.json"));
@@ -2237,14 +1931,18 @@ function resolvePackageEntryFromProjectRoot(pkg) {
2237
1931
  return;
2238
1932
  }
2239
1933
  }
1934
+ let workspaceEntryConditions = [
1935
+ "browser",
1936
+ "import",
1937
+ "module",
1938
+ "default"
1939
+ ];
1940
+ function setWorkspaceEntryConditions(conditions) {
1941
+ workspaceEntryConditions = conditions;
1942
+ }
2240
1943
  function getPackageEsmEntryPath(pkg) {
2241
1944
  return getInstalledPackageEntry(pkg, {
2242
- conditions: [
2243
- "browser",
2244
- "import",
2245
- "module",
2246
- "default"
2247
- ],
1945
+ conditions: workspaceEntryConditions,
2248
1946
  resolveSubpathWithRequire: false
2249
1947
  }) || resolvePackageEntryFromProjectRoot(pkg);
2250
1948
  }
@@ -2484,160 +2182,59 @@ function resolveReExportModule(filePath, specifier, exportConditions) {
2484
2182
  return;
2485
2183
  }
2486
2184
  }
2487
- /** Marks a template-literal frame whose text (not its interpolation) is being scanned. */
2488
- const TEMPLATE_TEXT = Symbol("templateText");
2489
2185
  function getAdditionalTopLevelDeclaratorNames(source, start, codePositions) {
2490
2186
  const names = [];
2491
2187
  let depth = 0;
2492
- let quote;
2493
- let escaped = false;
2494
- let canStartRegex = true;
2495
- const templateFrames = [];
2496
- const inTemplateText = () => templateFrames[templateFrames.length - 1] === TEMPLATE_TEXT;
2497
2188
  for (let index = start; index < source.length; index++) {
2498
2189
  const char = source[index];
2499
- if (inTemplateText()) {
2500
- if (escaped) escaped = false;
2501
- else if (char === "\\") escaped = true;
2502
- else if (char === "$" && source[index + 1] === "{") {
2503
- templateFrames.push(depth);
2504
- index++;
2505
- canStartRegex = true;
2506
- } else if (char === "`") {
2507
- templateFrames.pop();
2508
- canStartRegex = false;
2509
- }
2510
- continue;
2511
- }
2512
- if (quote) {
2513
- if (escaped) escaped = false;
2514
- else if (char === "\\") escaped = true;
2515
- else if (char === quote) quote = void 0;
2516
- continue;
2517
- }
2518
- if (char === "`") {
2519
- templateFrames.push(TEMPLATE_TEXT);
2520
- canStartRegex = false;
2521
- continue;
2522
- }
2523
- if (char === "\"" || char === "'") {
2524
- quote = char;
2525
- canStartRegex = false;
2526
- continue;
2527
- }
2190
+ if (!codePositions[index]) continue;
2528
2191
  if (char === "<" && source[index + 1] === "/") {
2529
2192
  const jsxClosingTag = source.slice(index).match(/^<\/\s*(?:[$_\p{ID_Start}][$_\u200C\u200D\p{ID_Continue}.:-]*\s*)?>/u);
2530
2193
  if (jsxClosingTag) {
2531
2194
  index += jsxClosingTag[0].length - 1;
2532
- canStartRegex = false;
2533
2195
  continue;
2534
2196
  }
2535
2197
  }
2536
- if (char === "/" && source[index + 1] === "/") {
2537
- index = source.indexOf("\n", index + 2);
2538
- if (index === -1) return names;
2539
- continue;
2540
- }
2541
- if (char === "/" && source[index + 1] === "*") {
2542
- const commentEnd = source.indexOf("*/", index + 2);
2543
- if (commentEnd === -1) return void 0;
2544
- index = commentEnd + 1;
2545
- continue;
2546
- }
2547
- if (char === "/" && canStartRegex) {
2548
- let regexEscaped = false;
2549
- let inCharacterClass = false;
2550
- let closed = false;
2551
- for (index++; index < source.length; index++) {
2552
- const regexChar = source[index];
2553
- if (regexEscaped) {
2554
- regexEscaped = false;
2555
- continue;
2556
- }
2557
- if (regexChar === "\\") {
2558
- regexEscaped = true;
2559
- continue;
2560
- }
2561
- if (regexChar === "[") {
2562
- inCharacterClass = true;
2563
- continue;
2564
- }
2565
- if (regexChar === "]" && inCharacterClass) {
2566
- inCharacterClass = false;
2567
- continue;
2568
- }
2569
- if (regexChar === "/" && !inCharacterClass) {
2570
- closed = true;
2571
- while (/[$_\p{ID_Continue}]/u.test(source[index + 1] || "")) index++;
2572
- break;
2573
- }
2574
- if (regexChar === "\n" || regexChar === "\r") return void 0;
2575
- }
2576
- if (!closed) return void 0;
2577
- canStartRegex = false;
2578
- continue;
2579
- }
2580
- if (char === "/") {
2581
- canStartRegex = true;
2582
- continue;
2583
- }
2584
2198
  if (/[$_\p{ID_Start}]/u.test(char)) {
2585
2199
  const tokenStart = index;
2586
2200
  while (/[$_\u200C\u200D\p{ID_Continue}]/u.test(source[index + 1] || "")) index++;
2587
2201
  const token = source.slice(tokenStart, index + 1);
2588
- if (depth === 0 && templateFrames.length === 0 && token === "export") {
2202
+ if (depth === 0 && token === "export") {
2589
2203
  let previous = tokenStart - 1;
2590
2204
  while (/\s/.test(source[previous] || "")) previous--;
2591
2205
  if (source[previous] !== "." && /^\s+(?:(?:async\s+)?function\b|(?:abstract\s+)?class\b|const\b|let\b|var\b|enum\b|namespace\b|module\b|interface\b|type\b|declare\b|default\b|\{|\*)/.test(source.slice(index + 1))) return names;
2592
2206
  }
2593
- canStartRegex = /^(?:await|case|delete|in|instanceof|new|return|throw|typeof|void|yield)$/.test(token);
2594
2207
  continue;
2595
2208
  }
2596
2209
  if (/\d/.test(char)) {
2597
2210
  while (/[\w.]/.test(source[index + 1] || "")) index++;
2598
- canStartRegex = false;
2599
- continue;
2600
- }
2601
- if ((char === "+" || char === "-") && source[index + 1] === char) {
2602
- index++;
2603
2211
  continue;
2604
2212
  }
2605
- if (char === "!" && source[index + 1] !== "=") continue;
2606
2213
  if (char === "<") {
2607
2214
  const typeArgumentEnd = findLikelyTypeArgumentEnd(source, index, codePositions);
2608
2215
  if (typeArgumentEnd !== void 0) {
2609
2216
  index = typeArgumentEnd;
2610
- canStartRegex = false;
2611
2217
  continue;
2612
2218
  }
2613
2219
  }
2614
2220
  if (char === "(" || char === "[" || char === "{") {
2615
2221
  depth++;
2616
- canStartRegex = true;
2617
2222
  continue;
2618
2223
  }
2619
2224
  if (char === ")" || char === "]" || char === "}") {
2620
- if (char === "}" && templateFrames.length > 0 && templateFrames[templateFrames.length - 1] === depth) {
2621
- templateFrames.pop();
2622
- canStartRegex = false;
2623
- continue;
2624
- }
2625
2225
  depth = Math.max(0, depth - 1);
2626
- canStartRegex = false;
2627
2226
  continue;
2628
2227
  }
2629
- if (templateFrames.length === 0 && depth === 0 && char === ",") {
2228
+ if (depth === 0 && char === ",") {
2630
2229
  let bindingStart = index + 1;
2631
2230
  while (/\s/.test(source[bindingStart] || "")) bindingStart++;
2632
2231
  const binding = source.slice(bindingStart).match(new RegExp(`^(${JS_IDENTIFIER_PATTERN})`, "u"));
2633
2232
  if (!binding || !isValidEsmExportName(binding[1])) return void 0;
2634
2233
  names.push(binding[1]);
2635
2234
  index = bindingStart + binding[1].length - 1;
2636
- canStartRegex = false;
2637
2235
  continue;
2638
2236
  }
2639
- if (templateFrames.length === 0 && depth === 0 && char === ";") return names;
2640
- if (!/\s/.test(char)) canStartRegex = char !== ".";
2237
+ if (depth === 0 && char === ";") return names;
2641
2238
  }
2642
2239
  return names;
2643
2240
  }
@@ -2855,12 +2452,7 @@ function getLocalProviderImportPath(pkg) {
2855
2452
  return isWorkspaceFilePath(resolved) ? resolved : void 0;
2856
2453
  } catch {
2857
2454
  const resolved = getInstalledPackageEntry(pkg, {
2858
- conditions: [
2859
- "browser",
2860
- "import",
2861
- "module",
2862
- "default"
2863
- ],
2455
+ conditions: workspaceEntryConditions,
2864
2456
  resolveSubpathWithRequire: false
2865
2457
  });
2866
2458
  return isWorkspaceFilePath(resolved) ? resolved : void 0;
@@ -2898,12 +2490,7 @@ function resolveWorkspaceEsmEntry(pkg, resolved, cwd = getPackageDetectionCwd())
2898
2490
  if (!isWorkspaceFilePath(resolved)) return resolved;
2899
2491
  const esmEntry = getInstalledPackageEntry(pkg, {
2900
2492
  cwd,
2901
- conditions: [
2902
- "browser",
2903
- "import",
2904
- "module",
2905
- "default"
2906
- ],
2493
+ conditions: workspaceEntryConditions,
2907
2494
  resolveSubpathWithRequire: false
2908
2495
  });
2909
2496
  if (esmEntry && isWorkspaceFilePath(esmEntry)) return esmEntry;
@@ -3024,30 +2611,15 @@ function resolveConcreteSharedImportSource(pkg, projectRoot) {
3024
2611
  currentDir = path$1.dirname(currentDir);
3025
2612
  }
3026
2613
  return tryResolveImportFromPackageRoot(pkg, currentDir) ?? getInstalledPackageEntry(pkg, {
3027
- conditions: DEFAULT_SHARED_EXPORT_CONDITIONS,
2614
+ conditions: workspaceEntryConditions,
3028
2615
  resolveSubpathWithRequire: false
3029
2616
  });
3030
2617
  }
3031
2618
  const TREE_SHAKING_PROVIDER_TAG = "__treeShakingProvider__";
3032
2619
  const TREE_SHAKING_GRAPH_QUERY = "__mf_tree_shaking_graph__";
3033
- const legacySharedVirtualModuleState = {
3034
- preBuildCacheMap: {},
3035
- preBuildShareItemMap: {},
3036
- treeShakingProviderCacheMap: {},
3037
- materializedTreeShakingProviders: /* @__PURE__ */ new Set(),
3038
- loadShareCacheMap: {},
3039
- warnedMissingImportFalse: /* @__PURE__ */ new Set(),
3040
- coalescableLoadShares: /* @__PURE__ */ new Set()
3041
- };
3042
2620
  const sharedVirtualModuleStates = /* @__PURE__ */ new WeakMap();
3043
2621
  const sharedVirtualModuleStatesByOwner = /* @__PURE__ */ new Map();
3044
2622
  function getSharedVirtualModuleState(options) {
3045
- if (!options) try {
3046
- const currentOptions = getNormalizeModuleFederationOptions();
3047
- return sharedVirtualModuleStates.get(currentOptions) ?? legacySharedVirtualModuleState;
3048
- } catch {
3049
- return legacySharedVirtualModuleState;
3050
- }
3051
2623
  let state = sharedVirtualModuleStates.get(options);
3052
2624
  if (!state) {
3053
2625
  state = {
@@ -3107,8 +2679,7 @@ function getConcreteTreeShakingExportUsage(pkg, shareItem, options) {
3107
2679
  return getTreeShakingExportUsage(pkg, shareItem, shareItem?.name, options);
3108
2680
  }
3109
2681
  function getTreeShakingSharedProviderName(pkg, options) {
3110
- const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
3111
- return `${getSharedVirtualModuleState(options).ownerKey ?? resolvedOptions.internalName ?? resolvedOptions.name}__tree_shaking__${packageNameEncode(pkg)}`;
2682
+ return `${getSharedVirtualModuleState(options).ownerKey ?? options.internalName ?? options.name}__tree_shaking__${packageNameEncode(pkg)}`;
3112
2683
  }
3113
2684
  function getTreeShakingSharedProviderImportId(pkg, options) {
3114
2685
  const { treeShakingProviderCacheMap } = getSharedVirtualModuleState(options);
@@ -3166,7 +2737,6 @@ export default { get, init };
3166
2737
  materializedTreeShakingProviders.add(pkg);
3167
2738
  }
3168
2739
  function writePreBuildLibPath(pkg, shareItem, options, exportConditions) {
3169
- const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
3170
2740
  const { preBuildCacheMap, preBuildShareItemMap } = getSharedVirtualModuleState(options);
3171
2741
  if (!preBuildCacheMap[pkg]) preBuildCacheMap[pkg] = createScopedSharedVirtualModule(pkg, PREBUILD_TAG, options);
3172
2742
  preBuildShareItemMap[pkg] = shareItem;
@@ -3195,9 +2765,8 @@ function writePreBuildLibPath(pkg, shareItem, options, exportConditions) {
3195
2765
  }
3196
2766
  if (pkg === "react/jsx-dev-runtime") {
3197
2767
  preBuildCacheMap[pkg].writeSync(`
3198
- import __mfPrebuildDefault from ${escapeGeneratedStringLiteral(importSource)};
3199
2768
  import * as __mfPrebuildNamespace from ${escapeGeneratedStringLiteral(importSource)};
3200
- const __mfPrebuildExports = __mfPrebuildDefault ?? __mfPrebuildNamespace;
2769
+ const __mfPrebuildExports = ${getDefaultOrNamespaceExpression("__mfPrebuildNamespace")};
3201
2770
  export const Fragment = __mfPrebuildExports.Fragment;
3202
2771
  export const jsxDEV = __mfPrebuildExports.jsxDEV;
3203
2772
  export default __mfPrebuildExports;
@@ -3206,9 +2775,8 @@ function writePreBuildLibPath(pkg, shareItem, options, exportConditions) {
3206
2775
  }
3207
2776
  if (pkg === "react/jsx-runtime") {
3208
2777
  preBuildCacheMap[pkg].writeSync(`
3209
- import __mfPrebuildDefault from ${escapeGeneratedStringLiteral(importSource)};
3210
2778
  import * as __mfPrebuildNamespace from ${escapeGeneratedStringLiteral(importSource)};
3211
- const __mfPrebuildExports = __mfPrebuildDefault ?? __mfPrebuildNamespace;
2779
+ const __mfPrebuildExports = ${getDefaultOrNamespaceExpression("__mfPrebuildNamespace")};
3212
2780
  export const Fragment = __mfPrebuildExports.Fragment;
3213
2781
  export const jsx = __mfPrebuildExports.jsx;
3214
2782
  export const jsxs = __mfPrebuildExports.jsxs;
@@ -3218,7 +2786,7 @@ function writePreBuildLibPath(pkg, shareItem, options, exportConditions) {
3218
2786
  }
3219
2787
  const namedExports = getSharedNamedExports(pkg, shareItem, exportConditions) ?? [];
3220
2788
  if (namedExports.length > 0) {
3221
- const mutableExports = new Set(isLocalOnlyContainer(resolvedOptions) ? getSharedMutableExports(pkg, shareItem, exportConditions) : []);
2789
+ const mutableExports = new Set(isLocalOnlyContainer(options) ? getSharedMutableExports(pkg, shareItem, exportConditions) : []);
3222
2790
  const copiedExports = namedExports.filter((name) => !mutableExports.has(name));
3223
2791
  const liveExports = namedExports.filter((name) => mutableExports.has(name));
3224
2792
  const namedExportVars = copiedExports.map((_name, i) => `__mf_${i}`);
@@ -3231,26 +2799,23 @@ function writePreBuildLibPath(pkg, shareItem, options, exportConditions) {
3231
2799
  ${declarations}
3232
2800
  ${namedExportLine}
3233
2801
  ${liveExportLine}
3234
- export default Reflect.get(__mfPrebuildNamespace, "default") ?? __mfPrebuildNamespace;
2802
+ export default ${getDefaultOrNamespaceExpression("__mfPrebuildNamespace")};
3235
2803
  `, true);
3236
2804
  return;
3237
2805
  }
3238
2806
  preBuildCacheMap[pkg].writeSync(`
3239
2807
  import * as __mfPrebuildExports from ${escapeGeneratedStringLiteral(importSource)};
3240
2808
  export * from ${escapeGeneratedStringLiteral(importSource)};
3241
- // Reflect access avoids bundler warnings for ESM packages without a
3242
- // default export (for example antd/es/index.js), while preserving the
3243
- // namespace fallback for packages that do provide one.
3244
- export default Reflect.get(__mfPrebuildExports, "default") ?? __mfPrebuildExports;
2809
+ export default ${getDefaultOrNamespaceExpression("__mfPrebuildExports")};
3245
2810
  `, true);
3246
2811
  }
3247
2812
  /** Re-render already materialized wrappers after import analysis discovers exports. */
3248
- function refreshTreeShakingModules(options, command = "build", isRolldown = false, exportConditions) {
2813
+ function refreshTreeShakingModules(options, command = "build", exportConditions) {
3249
2814
  const { preBuildShareItemMap } = getSharedVirtualModuleState(options);
3250
2815
  for (const [pkg, shareItem] of Object.entries(preBuildShareItemMap)) {
3251
2816
  if (!shareItem?.shareConfig.treeShaking) continue;
3252
2817
  writePreBuildLibPath(pkg, shareItem, options, exportConditions);
3253
- writeLoadShareModule(pkg, shareItem, command, isRolldown, options, exportConditions);
2818
+ writeLoadShareModule(pkg, shareItem, command, options, exportConditions);
3254
2819
  }
3255
2820
  }
3256
2821
  function getPreBuildLibImportId(pkg, options) {
@@ -3264,16 +2829,11 @@ function getPreBuildShareItem(pkg, options) {
3264
2829
  function getSharedImportSource(pkg, shareItem, options) {
3265
2830
  return getConcreteSharedImportSource(pkg, shareItem) || getPreBuildLibImportId(pkg, options);
3266
2831
  }
3267
- function getLoadShareImportId(pkg, _isRolldown, options) {
2832
+ function getLoadShareModulePath(pkg, options) {
3268
2833
  const { loadShareCacheMap } = getSharedVirtualModuleState(options);
3269
2834
  if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = createScopedSharedVirtualModule(pkg, LOAD_SHARE_TAG, options);
3270
2835
  return loadShareCacheMap[pkg].getImportId();
3271
2836
  }
3272
- function getLoadShareModulePath(pkg, isRolldown, options) {
3273
- const { loadShareCacheMap } = getSharedVirtualModuleState(options);
3274
- if (!loadShareCacheMap[pkg]) getLoadShareImportId(pkg, isRolldown, options);
3275
- return loadShareCacheMap[pkg].getImportId();
3276
- }
3277
2837
  function getCachedSharedVirtualPkg(id, tag) {
3278
2838
  if (!id.includes(tag)) return;
3279
2839
  const normalized = normalizeVirtualModuleId(id);
@@ -3297,7 +2857,7 @@ function materializeCachedLoadShareModule(options) {
3297
2857
  const key = options.findSharedKey(pkg, options.shared);
3298
2858
  if (!key) return;
3299
2859
  const shareItem = options.shared[key];
3300
- writeLoadShareModule(pkg, shareItem, options.command, options.isRolldown, options.federationOptions);
2860
+ writeLoadShareModule(pkg, shareItem, options.command, options.federationOptions);
3301
2861
  if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(pkg, shareItem, options.federationOptions);
3302
2862
  options.addUsedShares(pkg);
3303
2863
  options.writeLocalSharedImportMap();
@@ -3542,23 +3102,37 @@ function markLoadShareWrapperNotCoalescable(pkg, options, id) {
3542
3102
  function isCoalescableLoadShareWrapper(pkg, options, id) {
3543
3103
  return getSharedVirtualModuleStateForId(id, options).coalescableLoadShares.has(pkg);
3544
3104
  }
3545
- function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exportConditions, importFalseExportUsage) {
3546
- const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
3105
+ /** Keeps runtime-shared React dispatchers usable when a mixed-mode remote swaps them in. */
3106
+ const REACT_MIXED_MODE_GUARD = `const __mfReactInternals = mod[${JSON.stringify(REACT_CLIENT_INTERNALS_KEY)}];
3107
+ if (__mfReactInternals && "A" in __mfReactInternals) {
3108
+ let __mfReactDispatcher = __mfReactInternals.A;
3109
+ Object.defineProperty(__mfReactInternals, "A", {
3110
+ configurable: true,
3111
+ enumerable: true,
3112
+ get: () => __mfReactDispatcher,
3113
+ set: (next) => {
3114
+ if (next && typeof next.getOwner !== "function") next.getOwner = () => null;
3115
+ __mfReactDispatcher = next;
3116
+ },
3117
+ });
3118
+ __mfReactInternals.A = __mfReactDispatcher;
3119
+ }`;
3120
+ function writeLoadShareModule(pkg, shareItem, command, options, exportConditions, importFalseExportUsage) {
3547
3121
  const { loadShareCacheMap, coalescableLoadShares } = getSharedVirtualModuleState(options);
3548
3122
  const edges = createLocalPayloadEdges();
3549
3123
  if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = createScopedSharedVirtualModule(pkg, LOAD_SHARE_TAG, options);
3550
3124
  let importLine = getRuntimeModuleCacheBootstrapCode(exportConditions);
3551
3125
  const cacheDescriptor = getSharedCacheDescriptorLiteral(pkg, shareItem);
3552
- const cacheOwner = JSON.stringify(resolvedOptions.name);
3553
- const runtimeInitOwnerImportId = options ? getRuntimeInitStatusImportId(options) : void 0;
3554
- const treeShakingConsumer = command === "build" && shareItem.shareConfig.treeShaking ? resolvedOptions.name : void 0;
3126
+ const cacheOwner = JSON.stringify(options.name);
3127
+ const runtimeInitOwnerImportId = getRuntimeInitStatusImportId(options);
3128
+ const treeShakingConsumer = command === "build" && shareItem.shareConfig.treeShaking ? options.name : void 0;
3555
3129
  if (shareItem.shareConfig.import === false) {
3556
3130
  const detectedNamedExports = getPackageNamedExports(pkg, exportConditions);
3557
3131
  const namedExports = selectImportFalseNamedExports(detectedNamedExports, importFalseExportUsage);
3558
3132
  let exportLine;
3559
3133
  if (namedExports.length > 0) exportLine = generateDeferredHostProvidedExports(namedExports, pkg, cacheDescriptor, treeShakingConsumer);
3560
3134
  else {
3561
- const { warnedMissingImportFalse } = getSharedVirtualModuleState(resolvedOptions);
3135
+ const { warnedMissingImportFalse } = getSharedVirtualModuleState(options);
3562
3136
  if (detectedNamedExports === void 0 && !shareItem.shareConfig.suppressMissingImportWarning && !warnedMissingImportFalse.has(pkg)) {
3563
3137
  warnedMissingImportFalse.add(pkg);
3564
3138
  mfWarn(`Shared dependency "${pkg}" has import: false but is not installed locally.\n Named imports (e.g. import { ... } from '${pkg}') will not work in production builds.\n Install it as a devDependency to enable named export detection.`);
@@ -3584,20 +3158,22 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3584
3158
  const skipServePrebuildWarmup = command !== "build" && (pkg === "lit" || pkg.startsWith("lit/"));
3585
3159
  const detectedNamedExports = getSharedNamedExports(pkg, shareItem, exportConditions);
3586
3160
  const namedExports = detectedNamedExports ?? [];
3587
- const mutableExports = new Set(isLocalOnlyContainer(resolvedOptions) ? getSharedMutableExports(pkg, shareItem, exportConditions) : []);
3161
+ const mutableExports = new Set(isLocalOnlyContainer(options) ? getSharedMutableExports(pkg, shareItem, exportConditions) : []);
3588
3162
  const copiedNamedExports = namedExports.filter((name) => !mutableExports.has(name));
3589
3163
  const liveNamedExports = namedExports.filter((name) => mutableExports.has(name));
3590
3164
  const liveNamedExportLine = edges.reExportNames(liveNamedExports, sharedImportSource);
3591
3165
  const hasCompleteExportCoverage = detectedNamedExports !== void 0;
3592
- const isWorkspaceSingleton = isWorkspacePackage && shareItem.shareConfig.singleton === true;
3593
- const usesDeferredSingletonFallback = hasCompleteExportCoverage && shareItem.shareConfig.eager !== true && (isWorkspacePackage || command !== "build" && isRemoteOnlyContainer(resolvedOptions) && shareItem.shareConfig.singleton === true || command === "build" && isRemoteContainer(resolvedOptions) && !isSharedSingletonConsumedByPeer(pkg, resolvedOptions, true));
3594
- const servesRemoteSingletonFallback = command !== "build" && isRemoteOnlyContainer(resolvedOptions) && shareItem.shareConfig.singleton === true;
3595
- const isConsumedByPeerSingleton = isSharedSingletonConsumedByPeer(pkg, resolvedOptions);
3596
- const usesEntryInjectedRemoteFallback = hasCompleteExportCoverage && !isWorkspaceSingleton && isRemoteContainer(resolvedOptions) && shareItem.shareConfig.singleton === true && resolvedOptions.hostInitInjectLocation === "entry" && (command === "build" || isConsumedByPeerSingleton);
3597
- const usesDeferredEntryInjectedSingletonFallback = usesEntryInjectedRemoteFallback && !isReactCoreShare(pkg) && (pkg === "react-dom/client" || shareItem.shareConfig.eager !== true && !isSharedSingletonConsumedByPeer(pkg, resolvedOptions, true));
3166
+ const isSingleton = shareItem.shareConfig.singleton === true;
3167
+ const isWorkspaceSingleton = isWorkspacePackage && isSingleton;
3168
+ const usesDeferredSingletonFallback = hasCompleteExportCoverage && shareItem.shareConfig.eager !== true && (isWorkspacePackage || command !== "build" && isRemoteOnlyContainer(options) && isSingleton || command === "build" && isRemoteContainer(options) && !isSharedSingletonConsumedByPeer(pkg, options, true));
3169
+ const servesRemoteSingletonFallback = command !== "build" && isRemoteOnlyContainer(options) && isSingleton;
3170
+ const isConsumedByPeerSingleton = isSharedSingletonConsumedByPeer(pkg, options);
3171
+ const usesEntryInjectedRemoteFallback = hasCompleteExportCoverage && !isWorkspaceSingleton && isRemoteContainer(options) && isSingleton && options.hostInitInjectLocation === "entry" && (command === "build" || isConsumedByPeerSingleton);
3172
+ const usesDeferredEntryInjectedSingletonFallback = usesEntryInjectedRemoteFallback && !isReactCoreShare(pkg) && (pkg === "react-dom/client" || shareItem.shareConfig.eager !== true && !isSharedSingletonConsumedByPeer(pkg, options, true));
3598
3173
  const usesEagerWorkspaceFallback = hasCompleteExportCoverage && isWorkspaceSingleton && !servesRemoteSingletonFallback && (isConsumedByPeerSingleton || shareItem.shareConfig.eager === true);
3599
3174
  const usesDeferredTreeShakingFallback = hasCompleteExportCoverage && Boolean(treeShakingConsumer);
3600
- const reactMixedModeGuard = pkg === "react" ? createReactMixedModeRuntimeGuard() : "";
3175
+ const rebindsSharedExports = isSingleton || options.shareStrategy === "version-first";
3176
+ const reactMixedModeGuard = pkg === "react" && isSingleton ? REACT_MIXED_MODE_GUARD : "";
3601
3177
  let exportLine;
3602
3178
  let initBlock = "";
3603
3179
  if (usesDeferredTreeShakingFallback) {
@@ -3622,7 +3198,7 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3622
3198
  ${edges.reExportAll(coherentLocalSource)}`;
3623
3199
  initBlock = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
3624
3200
  __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});`;
3625
- } else if (namedExports.length > 0 && shareItem.shareConfig.singleton === true) {
3201
+ } else if (namedExports.length > 0 && rebindsSharedExports) {
3626
3202
  const namedExportVars = copiedNamedExports.map((_name, i) => `__mf_${i}`);
3627
3203
  exportLine = `${["let __mfDefaultExport;", ...namedExportVars.map((name) => `let ${name};`)].join("\n ")}
3628
3204
  const __mfApplySharedExports = (mod) => {
@@ -3661,7 +3237,7 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3661
3237
  ${liveNamedExportLine}`;
3662
3238
  initBlock = `exportModule = __mfNormalizeShareModule(__mfLocalShare);
3663
3239
  __mfWriteSharedCache(__mfModuleCache.share, ${cacheDescriptor}, exportModule, ${cacheOwner});`;
3664
- } else if (shareItem.shareConfig.singleton === true) {
3240
+ } else if (rebindsSharedExports) {
3665
3241
  exportLine = `let __mfDefaultExport;
3666
3242
  const __mfApplySharedDefaultExport = (mod) => {
3667
3243
  ${reactMixedModeGuard}
@@ -3681,7 +3257,7 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3681
3257
  const staticLocalShareSource = detectedNamedExports === void 0 ? coherentLocalSource : skipServePrebuildWarmup ? devImportSource : sharedImportSource;
3682
3258
  const prebuildImportLine = usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback ? "" : usesDeferredSingletonFallback || usesDeferredTreeShakingFallback ? !servesRemoteSingletonFallback && usesDeferredSingletonFallback && command !== "build" && (isWorkspaceSingleton || isWorkspacePackage) ? edges.importNamespace(lazyLocalFallbackSource) : "" : edges.importNamespace(staticLocalShareSource);
3683
3259
  const devDynamicImportLine = isWorkspacePackage ? "" : usesDeferredSingletonFallback || usesDeferredTreeShakingFallback || usesDeferredEntryInjectedSingletonFallback ? "" : command !== "build" && !skipServePrebuildWarmup ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
3684
- const cacheHelpers = recordCoalescability(pkg, edges.none, command, shareItem.shareConfig, coalescableLoadShares) ? getSharedCacheHelpersImportCode(resolvedOptions) : sharedCacheHelperCode;
3260
+ const cacheHelpers = recordCoalescability(pkg, edges.none, command, shareItem.shareConfig, coalescableLoadShares) ? getSharedCacheHelpersImportCode(options) : sharedCacheHelperCode;
3685
3261
  const moduleBody = usesDeferredSingletonFallback || usesDeferredTreeShakingFallback || usesDeferredEntryInjectedSingletonFallback || usesEagerWorkspaceFallback || usesEntryInjectedRemoteFallback ? `
3686
3262
  ${usesDeferredEntryInjectedSingletonFallback ? "" : prebuildImportLine}
3687
3263
  ${devDynamicImportLine}
@@ -3702,14 +3278,430 @@ function writeLoadShareModule(pkg, shareItem, command, _isRolldown, options, exp
3702
3278
  }
3703
3279
  ${exportLine}
3704
3280
  `;
3705
- loadShareCacheMap[pkg].writeSync(moduleBody, true);
3281
+ loadShareCacheMap[pkg].writeSync(moduleBody, true);
3282
+ }
3283
+ //#endregion
3284
+ //#region src/utils/localShareImports.ts
3285
+ /**
3286
+ * The source file of a share whose `import` points at a project file rather than an installed
3287
+ * package, such as an application module shared with its micro frontends. Installed packages
3288
+ * describe their dependencies in `package.json`, so a path import of an installed package (a shim)
3289
+ * is not local. Undefined when the file cannot be found.
3290
+ */
3291
+ function getLocalShareSourceFile(pkg, shareItem) {
3292
+ const importSource = shareItem?.shareConfig?.import;
3293
+ if (typeof importSource !== "string") return void 0;
3294
+ if (!importSource.startsWith(".") && !path$1.isAbsolute(importSource)) return void 0;
3295
+ if (getInstalledPackageJson(getPackageName(pkg)) !== void 0) return void 0;
3296
+ return resolveConfiguredImportPath(importSource);
3297
+ }
3298
+ const specifiersByFile = /* @__PURE__ */ new Map();
3299
+ /** Specifiers a file evaluates (static, not type-only), cached until the file changes; empty when it cannot be read. */
3300
+ function readStaticImportSpecifiers(file) {
3301
+ try {
3302
+ const { mtimeMs } = statSync(file);
3303
+ const cached = specifiersByFile.get(file);
3304
+ if (cached && cached.mtimeMs === mtimeMs) return cached.specifiers;
3305
+ const specifiers = findModuleImportDescriptors(readFileSync(file, "utf-8")).filter(({ kind, typeOnly }) => kind === "static" && !typeOnly).map(({ source }) => source);
3306
+ specifiersByFile.set(file, {
3307
+ mtimeMs,
3308
+ specifiers
3309
+ });
3310
+ return specifiers;
3311
+ } catch {
3312
+ return [];
3313
+ }
3314
+ }
3315
+ /**
3316
+ * Keys of the other local shares that `sourceFile` imports at evaluation time, by key (or request)
3317
+ * or by source file, directly or through relative imports of project files that are not shared.
3318
+ * `localShareFiles` maps each local share's key to its source file; `requests` maps a share's
3319
+ * request to its key when they differ.
3320
+ */
3321
+ function getImportedLocalShares(sourceFile, localShareFiles, requests = /* @__PURE__ */ new Map()) {
3322
+ const keysByFile = new Map(Array.from(localShareFiles, ([key, file]) => [file, key]));
3323
+ const imported = /* @__PURE__ */ new Set();
3324
+ const visited = /* @__PURE__ */ new Set();
3325
+ const visit = (file) => {
3326
+ if (visited.has(file)) return;
3327
+ visited.add(file);
3328
+ for (const specifier of readStaticImportSpecifiers(file)) if (specifier.startsWith(".")) {
3329
+ const resolved = resolveRelativeModule(file, specifier);
3330
+ if (!resolved || resolved.split(path$1.sep).includes("node_modules")) continue;
3331
+ const key = keysByFile.get(resolved);
3332
+ if (key !== void 0) imported.add(key);
3333
+ else visit(resolved);
3334
+ } else {
3335
+ const key = localShareFiles.has(specifier) ? specifier : requests.get(specifier);
3336
+ if (key !== void 0) imported.add(key);
3337
+ }
3338
+ };
3339
+ visit(sourceFile);
3340
+ const self = keysByFile.get(sourceFile);
3341
+ if (self !== void 0) imported.delete(self);
3342
+ return [...imported];
3343
+ }
3344
+ //#endregion
3345
+ //#region src/utils/runtimePluginSpecifier.ts
3346
+ function getRuntimePluginSpecifier(plugin) {
3347
+ return typeof plugin === "string" ? plugin : plugin[0];
3348
+ }
3349
+ /** Drop SSR-only plugins from a client graph; a server graph keeps them all. */
3350
+ function filterRuntimePluginsForTarget(runtimePlugins, ssrOnlySpecifiers, isServer) {
3351
+ if (isServer) return [...runtimePlugins];
3352
+ return runtimePlugins.filter((plugin) => !ssrOnlySpecifiers.has(getRuntimePluginSpecifier(plugin)));
3353
+ }
3354
+ //#endregion
3355
+ //#region src/utils/reactIsland.ts
3356
+ const SOURCE_EXTENSIONS$1 = [
3357
+ ".tsx",
3358
+ ".jsx",
3359
+ ".ts",
3360
+ ".js",
3361
+ ".mts",
3362
+ ".mjs",
3363
+ ".cts",
3364
+ ".cjs"
3365
+ ];
3366
+ function resolveSourceFile(importPath, root) {
3367
+ const cleanImport = stripQueryAndHash(importPath);
3368
+ if (!cleanImport.startsWith(".") && !path$1.isAbsolute(cleanImport)) return;
3369
+ const candidate = path$1.isAbsolute(cleanImport) ? cleanImport : path$1.resolve(root, cleanImport);
3370
+ return [
3371
+ candidate,
3372
+ ...SOURCE_EXTENSIONS$1.map((extension) => `${candidate}${extension}`),
3373
+ ...SOURCE_EXTENSIONS$1.map((extension) => path$1.join(candidate, `index${extension}`))
3374
+ ].find((filePath) => {
3375
+ try {
3376
+ return fs$1.statSync(filePath).isFile();
3377
+ } catch {
3378
+ return false;
3379
+ }
3380
+ });
3381
+ }
3382
+ function localDefaultReexport(source) {
3383
+ const match = source.match(/export\s*{\s*(?:default(?:\s+as\s+default)?|[A-Za-z_$][\w$]*\s+as\s+default)\s*}\s*from\s*["']([^"']+)["']/);
3384
+ return match?.[1]?.startsWith(".") ? match[1] : void 0;
3385
+ }
3386
+ function isReactComponentSource(source, filePath = "component.tsx") {
3387
+ if (!(/\bexport\s+default\b/.test(source) || /\bexport\s*{[^}]*\bdefault\b[^}]*}(?:\s*from\s*["'][^"']+["'])?/.test(source))) return false;
3388
+ const extension = path$1.extname(stripQueryAndHash(filePath)).toLowerCase();
3389
+ const canContainJsx = extension === ".tsx" || extension === ".jsx";
3390
+ const hasJsx = /<>|<\s*[A-Za-z][\w.:-]*(?:\s[^<>]*?)?\s*\/?>/.test(source);
3391
+ const importsReact = /\bfrom\s*["']react["']|\brequire\(\s*["']react["']\s*\)/.test(source);
3392
+ const usesReactApi = /\b(?:React\.)?(?:createElement|jsx|jsxs)\s*\(/.test(source);
3393
+ const isClientModule = /^\s*["']use client["']\s*;?/m.test(source);
3394
+ return canContainJsx && hasJsx || importsReact && (hasJsx || usesReactApi || isClientModule);
3395
+ }
3396
+ function isReactComponentFile(filePath, seen = /* @__PURE__ */ new Set()) {
3397
+ const normalizedPath = path$1.resolve(filePath);
3398
+ if (seen.has(normalizedPath)) return false;
3399
+ seen.add(normalizedPath);
3400
+ let source;
3401
+ try {
3402
+ source = fs$1.readFileSync(normalizedPath, "utf8");
3403
+ } catch {
3404
+ return false;
3405
+ }
3406
+ if (isReactComponentSource(source, normalizedPath)) return true;
3407
+ const reexport = localDefaultReexport(source);
3408
+ if (!reexport) return false;
3409
+ const reexportPath = resolveSourceFile(reexport, path$1.dirname(normalizedPath));
3410
+ return reexportPath ? isReactComponentFile(reexportPath, seen) : false;
3411
+ }
3412
+ /**
3413
+ * React is shared by the normal MF runtime when explicitly configured. When it
3414
+ * is local, UI exposes can safely advertise an island capability in addition
3415
+ * to their unchanged default export.
3416
+ */
3417
+ function getReactIslandExposes(options, root) {
3418
+ if (options.experiments.ssrMode !== "ISLAND") return /* @__PURE__ */ new Set();
3419
+ if (Object.hasOwn(options.shared, "react")) return /* @__PURE__ */ new Set();
3420
+ const islandExposes = /* @__PURE__ */ new Set();
3421
+ for (const [key, expose] of Object.entries(options.exposes)) {
3422
+ const sourceFile = resolveSourceFile(expose.import, root);
3423
+ if (sourceFile && isReactComponentFile(sourceFile)) islandExposes.add(key);
3424
+ }
3425
+ return islandExposes;
3426
+ }
3427
+ function generateReactIslandBrowserDefinition(enabled) {
3428
+ if (!enabled) return "";
3429
+ return `
3430
+ exportModule.__mf_island = {
3431
+ version: 1,
3432
+ renderToHtml() {
3433
+ return Promise.reject(new Error("[Module Federation] renderToHtml is only available in the SSR remote entry"));
3434
+ },
3435
+ hydrate(element, props) {
3436
+ const root = element && element.hasAttribute && element.hasAttribute("data-mf-island-state")
3437
+ ? element
3438
+ : element && element.querySelector
3439
+ ? element.querySelector("[data-mf-island-state]") || element
3440
+ : element;
3441
+ if (!root) {
3442
+ return Promise.reject(new Error("[Module Federation] Cannot hydrate an island without a root element"));
3443
+ }
3444
+ let serverProps = {};
3445
+ const encodedState = root.getAttribute && root.getAttribute("data-mf-island-state");
3446
+ if (encodedState) {
3447
+ try {
3448
+ serverProps = JSON.parse(decodeURIComponent(encodedState));
3449
+ } catch {
3450
+ serverProps = {};
3451
+ }
3452
+ }
3453
+ const finalProps = Object.assign({}, serverProps, props || {});
3454
+ return Promise.all([import("react"), import("react-dom/client")]).then(([React, ReactDOMClient]) => {
3455
+ if (typeof ReactDOMClient.hydrateRoot !== "function") {
3456
+ throw new Error("[Module Federation] react-dom/client does not provide hydrateRoot");
3457
+ }
3458
+ return ReactDOMClient.hydrateRoot(
3459
+ root,
3460
+ React.createElement(importModule.default, finalProps)
3461
+ );
3462
+ });
3463
+ }
3464
+ }`;
3465
+ }
3466
+ function generateReactIslandSSRDefinition(enabled) {
3467
+ if (!enabled) return "";
3468
+ return `
3469
+ exportModule.__mf_island = {
3470
+ version: 1,
3471
+ async renderToHtml(props) {
3472
+ if (typeof importModule.default !== "function" && typeof importModule.default !== "object") {
3473
+ throw new Error("[Module Federation] A React island expose must have a default component export");
3474
+ }
3475
+ const loadedProps = typeof importModule.load === "function" ? await importModule.load() : {};
3476
+ const finalProps = Object.assign({}, loadedProps || {}, props || {});
3477
+ const [React, ReactDOMServer] = await Promise.all([
3478
+ import("react"),
3479
+ import("react-dom/server")
3480
+ ]);
3481
+ const body = ReactDOMServer.renderToString(
3482
+ React.createElement(importModule.default, finalProps)
3483
+ );
3484
+ const state = encodeURIComponent(JSON.stringify(finalProps));
3485
+ return '<div data-mf-island-state="' + state + '">' + body + '</div>';
3486
+ },
3487
+ hydrate() {
3488
+ return Promise.reject(new Error("[Module Federation] hydrate is only available in the browser remote entry"));
3489
+ }
3490
+ }`;
3491
+ }
3492
+ const REACT_ISLAND_CLIENT_ID_PREFIX = "virtual:mf-react-island-client:";
3493
+ const REACT_ISLAND_SERVER_ID_PREFIX = "virtual:mf-react-island-server:";
3494
+ const RESOLVED_REACT_ISLAND_CLIENT_ID_PREFIX = `\0${REACT_ISLAND_CLIENT_ID_PREFIX}`;
3495
+ const RESOLVED_REACT_ISLAND_SERVER_ID_PREFIX = `\0${REACT_ISLAND_SERVER_ID_PREFIX}`;
3496
+ function encodeIslandRemoteId(remoteId) {
3497
+ return encodeURIComponent(remoteId);
3498
+ }
3499
+ function decodeIslandRemoteId(encodedRemoteId) {
3500
+ return decodeURIComponent(encodedRemoteId);
3501
+ }
3502
+ function getReactIslandImportRemoteId(source) {
3503
+ const queryIndex = source.indexOf("?");
3504
+ if (queryIndex === -1) return;
3505
+ if (!new URLSearchParams(source.slice(queryIndex + 1)).has("mf-island")) return;
3506
+ return source.slice(0, queryIndex);
3507
+ }
3508
+ function getReactIslandServerImportId(remoteId) {
3509
+ return `${REACT_ISLAND_SERVER_ID_PREFIX}${encodeIslandRemoteId(remoteId)}`;
3510
+ }
3511
+ function getReactIslandClientImportId(remoteId) {
3512
+ return `${REACT_ISLAND_CLIENT_ID_PREFIX}${encodeIslandRemoteId(remoteId)}`;
3513
+ }
3514
+ function resolveReactIslandConsumerId(id) {
3515
+ if (id.startsWith("virtual:mf-react-island-server:")) return `\0${id}`;
3516
+ if (id.startsWith("virtual:mf-react-island-client:")) return `\0${id}`;
3517
+ }
3518
+ function remoteIdFromResolvedIslandId(id, prefix) {
3519
+ if (!id.startsWith(prefix)) return;
3520
+ return decodeIslandRemoteId(id.slice(prefix.length));
3521
+ }
3522
+ /** Generates the server half of the opt-in `?mf-island` consumer component. */
3523
+ function generateReactIslandConsumerServer(remoteId) {
3524
+ const source = JSON.stringify(remoteId);
3525
+ return `import * as React from "react";
3526
+ import IslandClient from ${JSON.stringify(getReactIslandClientImportId(remoteId))};
3527
+
3528
+ const islandModulePromise = import(${source});
3529
+
3530
+ async function loadIslandModule() {
3531
+ const namespace = await islandModulePromise;
3532
+ const pending = namespace && namespace.__mf_remote_pending;
3533
+ if (pending && typeof pending.then === "function") return pending;
3534
+ return namespace && namespace.__moduleExports || namespace;
3535
+ }
3536
+
3537
+ export default async function ModuleFederationIsland(props) {
3538
+ const remoteModule = await loadIslandModule();
3539
+ const shell = remoteModule && remoteModule.__mf_island;
3540
+ if (!shell || typeof shell.renderToHtml !== "function") {
3541
+ throw new Error(${JSON.stringify(`[Module Federation] ${remoteId} does not expose an SSR island capability`)});
3542
+ }
3543
+ const html = await shell.renderToHtml(props);
3544
+ return React.createElement(IslandClient, { html, islandProps: props });
3545
+ }`;
3546
+ }
3547
+ /** Generates the client boundary which hydrates with the remote-owned React. */
3548
+ function generateReactIslandConsumerClient(remoteId) {
3549
+ return `"use client";
3550
+
3551
+ import * as React from "react";
3552
+
3553
+ const islandModulePromise = import(${JSON.stringify(remoteId)});
3554
+
3555
+ async function loadIslandModule() {
3556
+ const namespace = await islandModulePromise;
3557
+ const pending = namespace && namespace.__mf_remote_pending;
3558
+ if (pending && typeof pending.then === "function") return pending;
3559
+ return namespace && namespace.__moduleExports || namespace;
3560
+ }
3561
+
3562
+ export default function ModuleFederationIslandClient({ html, islandProps }) {
3563
+ const ref = React.useRef(null);
3564
+
3565
+ React.useEffect(() => {
3566
+ const element = ref.current;
3567
+ if (!element) return;
3568
+ void loadIslandModule().then((remoteModule) => {
3569
+ const shell = remoteModule && remoteModule.__mf_island;
3570
+ if (!shell || typeof shell.hydrate !== "function") {
3571
+ throw new Error(${JSON.stringify(`[Module Federation] ${remoteId} does not expose a client island capability`)});
3572
+ }
3573
+ return shell.hydrate(element, islandProps);
3574
+ });
3575
+ }, []);
3576
+
3577
+ return React.createElement("div", {
3578
+ ref,
3579
+ suppressHydrationWarning: true,
3580
+ dangerouslySetInnerHTML: { __html: html },
3581
+ });
3582
+ }`;
3583
+ }
3584
+ function loadReactIslandConsumerModule(id) {
3585
+ const serverRemoteId = remoteIdFromResolvedIslandId(id, RESOLVED_REACT_ISLAND_SERVER_ID_PREFIX);
3586
+ if (serverRemoteId !== void 0) return generateReactIslandConsumerServer(serverRemoteId);
3587
+ const clientRemoteId = remoteIdFromResolvedIslandId(id, RESOLVED_REACT_ISLAND_CLIENT_ID_PREFIX);
3588
+ if (clientRemoteId !== void 0) return generateReactIslandConsumerClient(clientRemoteId);
3589
+ }
3590
+ //#endregion
3591
+ //#region src/virtualModules/virtualExposes.ts
3592
+ const EXPOSES_CSS_MAP_PLACEHOLDER = "__MF_EXPOSES_CSS_MAP__";
3593
+ function getExposesCssMapPlaceholder() {
3594
+ return EXPOSES_CSS_MAP_PLACEHOLDER;
3595
+ }
3596
+ function getVirtualExposesId(options) {
3597
+ return `virtual:mf-exposes:${getVirtualModuleScopeKey(options)}`;
3598
+ }
3599
+ function generateExposes(options, remoteDependencyMap = {}, command = "build", reactIslandExposes = /* @__PURE__ */ new Set()) {
3600
+ return `
3601
+ const cssAssetMap = ${JSON.stringify(options.bundleAllCSS ? EXPOSES_CSS_MAP_PLACEHOLDER : {})};
3602
+ const injectedCssHrefs = new Set();
3603
+ const exposeLoadPromises = new Map();
3604
+
3605
+ // Shared and remote readiness is handled by explicit Promise barriers below
3606
+ // and by remoteEntry's pendingShareLoads barrier. Keep this map scoped to a
3607
+ // single expose: unrelated exposes must stay independent and load in parallel.
3608
+ function loadExposedModule(exposeKey, loader) {
3609
+ let load = exposeLoadPromises.get(exposeKey);
3610
+ if (!load) {
3611
+ load = Promise.resolve()
3612
+ .then(loader)
3613
+ .catch((error) => {
3614
+ exposeLoadPromises.delete(exposeKey);
3615
+ throw error;
3616
+ });
3617
+ exposeLoadPromises.set(exposeKey, load);
3618
+ }
3619
+ return load;
3620
+ }
3621
+
3622
+ async function injectCssAssets(exposeKey) {
3623
+ if (typeof document === "undefined") {
3624
+ return;
3625
+ }
3626
+
3627
+ // Replaced at build time with expose -> css asset paths.
3628
+ const cssAssets = cssAssetMap[exposeKey] || [];
3629
+
3630
+ await Promise.all(
3631
+ cssAssets.map((cssAsset) => {
3632
+ const href = new URL(cssAsset, import.meta.url).href;
3633
+
3634
+ // Same expose can be resolved multiple times in one page.
3635
+ if (injectedCssHrefs.has(href)) {
3636
+ return Promise.resolve();
3637
+ }
3638
+ injectedCssHrefs.add(href);
3639
+
3640
+ // Check for any existing stylesheet with the same href, not just
3641
+ // MF-injected ones. This prevents duplicate <link> tags when Vite's
3642
+ // own CSS module injection or MF runtime's createLink has already
3643
+ // created a <link rel="stylesheet"> for the same URL.
3644
+ const existingLink = document.querySelector(
3645
+ \`link[rel="stylesheet"][href="\${href}"]\`
3646
+ );
3647
+ if (existingLink) {
3648
+ return Promise.resolve();
3649
+ }
3650
+
3651
+ return new Promise((resolve, reject) => {
3652
+ const link = document.createElement("link");
3653
+ link.rel = "stylesheet";
3654
+ link.href = href;
3655
+ link.onload = () => resolve();
3656
+ link.onerror = () => {
3657
+ injectedCssHrefs.delete(href);
3658
+ link.remove();
3659
+ reject(new Error(\`[Module Federation] Failed to load CSS asset: \${href}\`));
3660
+ };
3661
+ document.head.appendChild(link);
3662
+ });
3663
+ })
3664
+ );
3665
+ }
3666
+
3667
+ export default {
3668
+ ${Object.keys(options.exposes).map((key) => {
3669
+ const remoteDependencyPreloads = (remoteDependencyMap[key] ?? []).map((remoteId) => {
3670
+ const virtualRemote = getRemoteVirtualModule(remoteId, command, false, "unified", options);
3671
+ return `import(${JSON.stringify(virtualRemote.getImportId())})
3672
+ .then((mod) => mod.__mf_remote_pending)`;
3673
+ }).join(",");
3674
+ return `
3675
+ ${JSON.stringify(key)}: async () => {
3676
+ await injectCssAssets(${JSON.stringify(key)})
3677
+ await Promise.all([${remoteDependencyPreloads}])
3678
+ const importModule = await loadExposedModule(
3679
+ ${JSON.stringify(key)},
3680
+ () => import(${JSON.stringify(options.exposes[key].import)})
3681
+ )
3682
+ const dependencyPending = importModule && importModule.__mf_remote_dependency_pending;
3683
+ if (dependencyPending && typeof dependencyPending.then === "function") {
3684
+ await dependencyPending;
3685
+ }
3686
+ const exportModule = {}
3687
+ Object.assign(exportModule, importModule)
3688
+ ${generateReactIslandBrowserDefinition(reactIslandExposes.has(key))}
3689
+ Object.defineProperty(exportModule, "__esModule", {
3690
+ value: true,
3691
+ enumerable: false
3692
+ })
3693
+ return exportModule
3694
+ }
3695
+ `;
3696
+ }).join(",")}
3697
+ }
3698
+ `;
3706
3699
  }
3707
3700
  //#endregion
3708
3701
  //#region src/virtualModules/virtualRemoteEntry.ts
3709
- let usedShares = /* @__PURE__ */ new Set();
3710
3702
  const usedSharesByOptions = /* @__PURE__ */ new WeakMap();
3711
3703
  const materializedSharesByOptions = /* @__PURE__ */ new WeakMap();
3712
- function getScopedUsedShares(options) {
3704
+ function getUsedShares(options) {
3713
3705
  let scoped = usedSharesByOptions.get(options);
3714
3706
  if (!scoped) {
3715
3707
  scoped = /* @__PURE__ */ new Set();
@@ -3717,25 +3709,17 @@ function getScopedUsedShares(options) {
3717
3709
  }
3718
3710
  return scoped;
3719
3711
  }
3720
- function getUsedShares(options) {
3721
- if (options) return getScopedUsedShares(options);
3722
- return usedShares;
3723
- }
3724
3712
  function addUsedShares(pkg, options) {
3725
- usedShares.add(pkg);
3726
- if (options) getScopedUsedShares(options).add(pkg);
3727
- if (options) {
3728
- let scoped = materializedSharesByOptions.get(options);
3729
- if (!scoped) {
3730
- scoped = /* @__PURE__ */ new Set();
3731
- materializedSharesByOptions.set(options, scoped);
3732
- }
3733
- scoped.add(pkg);
3713
+ getUsedShares(options).add(pkg);
3714
+ let scoped = materializedSharesByOptions.get(options);
3715
+ if (!scoped) {
3716
+ scoped = /* @__PURE__ */ new Set();
3717
+ materializedSharesByOptions.set(options, scoped);
3734
3718
  }
3719
+ scoped.add(pkg);
3735
3720
  }
3736
3721
  function addConfiguredShare(pkg, options) {
3737
- usedShares.add(pkg);
3738
- if (options) getScopedUsedShares(options).add(pkg);
3722
+ getUsedShares(options).add(pkg);
3739
3723
  }
3740
3724
  const LOCAL_SHARED_IMPORT_MAP_ID = "virtual:mf-localSharedImportMap";
3741
3725
  const LAZY_CONSUME_ONLY_SHARES_PLACEHOLDER = "__MF_LAZY_CONSUME_ONLY_SHARES__";
@@ -3757,15 +3741,13 @@ function getLocalSharedImportMapPath(options) {
3757
3741
  function getResolvedLocalSharedImportMapId(options) {
3758
3742
  return `\0${getLocalSharedImportMapPath(options)}`;
3759
3743
  }
3760
- let invalidateLocalSharedImportMap;
3761
3744
  const localSharedImportMapInvalidators = /* @__PURE__ */ new WeakMap();
3762
3745
  function setLocalSharedImportMapInvalidator(invalidator, options) {
3763
- if (!options) invalidateLocalSharedImportMap = invalidator;
3764
- else if (invalidator) localSharedImportMapInvalidators.set(options, invalidator);
3746
+ if (invalidator) localSharedImportMapInvalidators.set(options, invalidator);
3765
3747
  else localSharedImportMapInvalidators.delete(options);
3766
3748
  }
3767
3749
  function writeLocalSharedImportMap(options) {
3768
- (options ? localSharedImportMapInvalidators.get(options) : invalidateLocalSharedImportMap)?.();
3750
+ localSharedImportMapInvalidators.get(options)?.();
3769
3751
  }
3770
3752
  function shouldUseDirectReactImport() {
3771
3753
  const isVinext = hasPackageDependency("vinext");
@@ -3786,15 +3768,15 @@ function getDirectSharedCacheSeedImportPath(pkg, shareItem) {
3786
3768
  function generateLocalSharedImportMap(options) {
3787
3769
  const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
3788
3770
  const useDirectReactImport = shouldUseDirectReactImport();
3789
- const orderedShares = getOrderedUsedShares(options);
3790
- const sharesToMaterialize = new Set(getMaterializedShares(options));
3771
+ const orderedShares = getOrderedUsedShares(resolvedOptions);
3772
+ const sharesToMaterialize = new Set(getMaterializedShares(resolvedOptions));
3791
3773
  const hasConsumeOnlyShare = orderedShares.some((pkg) => getNormalizeShareItem(pkg, resolvedOptions)?.shareConfig.import === false);
3792
3774
  return `
3793
3775
  import {loadShare} from "@module-federation/runtime";
3794
3776
  ${orderedShares.map((pkg, index) => {
3795
3777
  const shareItem = getNormalizeShareItem(pkg, resolvedOptions);
3796
3778
  if (!shareItem || !shareItem.shareConfig.eager || shareItem.shareConfig.import === false) return "";
3797
- return `import * as __mfEagerShare_${index} from ${toSafeJsLiteral(getLocalSharedPackagePath(pkg, shareItem, options))};`;
3779
+ return `import * as __mfEagerShare_${index} from ${toSafeJsLiteral(getLocalSharedPackagePath(pkg, shareItem, resolvedOptions))};`;
3798
3780
  }).filter(Boolean).join("\n")}
3799
3781
  ${normalizeRuntimeShareCode}
3800
3782
  const __mfGetCachedReactFamily = (keys, reactKeys, localVersion, requiredExport) => {
@@ -3867,7 +3849,7 @@ function generateLocalSharedImportMap(options) {
3867
3849
  return `
3868
3850
  ${toSafeJsLiteral(pkg)}: async () => {
3869
3851
  ${shareItem?.shareConfig.eager ? `let pkg = __mfEagerShare_${index};
3870
- return pkg;` : `let pkg = await import(${toSafeJsLiteral(getLocalSharedPackagePath(pkg, shareItem, options))});
3852
+ return pkg;` : `let pkg = await import(${toSafeJsLiteral(getLocalSharedPackagePath(pkg, shareItem, resolvedOptions))});
3871
3853
  return pkg;`}
3872
3854
  }
3873
3855
  `;
@@ -3891,11 +3873,11 @@ function generateLocalSharedImportMap(options) {
3891
3873
  const treeShakingConfig = canLiveRebind ? shareItem.shareConfig.treeShaking : void 0;
3892
3874
  if (shareItem.shareConfig.import === false && !treeShakingConfig) return `
3893
3875
  ${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)},` : ""}})`;
3894
- const treeShakingUsage = treeShakingConfig ? getTreeShakingExportUsage(key, shareItem, shareItem.name, options) : void 0;
3876
+ const treeShakingUsage = treeShakingConfig ? getTreeShakingExportUsage(key, shareItem, shareItem.name, resolvedOptions) : void 0;
3895
3877
  const treeShakingProviderExports = treeShakingUsage?.kind === "exports" ? treeShakingUsage.usedExports : [];
3896
3878
  const treeShakingUsedExports = resolvedOptions.injectTreeShakingUsedExports === false ? treeShakingConfig?.usedExports || [] : treeShakingProviderExports;
3897
3879
  const disableRuntimeInference = treeShakingConfig?.mode === "runtime-infer" && resolvedOptions.injectTreeShakingUsedExports === false;
3898
- const treeShakingProviderImportId = treeShakingConfig && !disableRuntimeInference && hasTreeShakingSharedProvider(key, shareItem, options) ? getTreeShakingSharedProviderImportId(key, options) : void 0;
3880
+ const treeShakingProviderImportId = treeShakingConfig && !disableRuntimeInference && hasTreeShakingSharedProvider(key, shareItem, resolvedOptions) ? getTreeShakingSharedProviderImportId(key, resolvedOptions) : void 0;
3899
3881
  const treeShakingStatus = treeShakingUsage?.kind === "full" || disableRuntimeInference || treeShakingConfig?.mode === "runtime-infer" && !treeShakingProviderImportId && shareItem.shareConfig.import !== false ? 0 : 1;
3900
3882
  return `
3901
3883
  ${toSafeJsLiteral(key)}: {
@@ -3980,7 +3962,7 @@ function generateLocalSharedImportMap(options) {
3980
3962
  `;
3981
3963
  }).filter((x) => x !== null).join(",")}
3982
3964
  }
3983
- const usedRemotes = [${Object.keys(getUsedRemotesMap(options)).map((key) => {
3965
+ const usedRemotes = [${Object.keys(getUsedRemotesMap(resolvedOptions)).map((key) => {
3984
3966
  const remote = resolvedOptions.remotes[key];
3985
3967
  if (!remote) return null;
3986
3968
  return `
@@ -4013,44 +3995,47 @@ function expandSharedPrefixKey(prefixKey, used) {
4013
3995
  return [...expanded];
4014
3996
  }
4015
3997
  function getOrderedUsedShares(options) {
4016
- const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
4017
3998
  const used = getUsedShares(options);
4018
3999
  const shares = /* @__PURE__ */ new Set();
4019
4000
  const addShare = (pkg) => {
4020
- const shareItem = getNormalizeShareItem(pkg, resolvedOptions);
4001
+ const shareItem = getNormalizeShareItem(pkg, options);
4021
4002
  shares.add(shareItem ? getCanonicalSharedKey(pkg, shareItem) : pkg);
4022
4003
  };
4023
4004
  used.forEach(addShare);
4024
- Object.keys(resolvedOptions.shared ?? {}).forEach((pkg) => {
4025
- const share = resolvedOptions.shared?.[pkg];
4005
+ Object.keys(options.shared ?? {}).forEach((pkg) => {
4006
+ const share = options.shared?.[pkg];
4026
4007
  if (share && !getSharedRequest(pkg, share).endsWith("/")) addShare(pkg);
4027
4008
  });
4028
- 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);
4009
+ for (const [pkg, share] of Object.entries(options.shared ?? {})) if (share.shareConfig?.eager && getSharedRequest(pkg, share).endsWith("/")) for (const concrete of expandSharedPrefixKey(getSharedRequest(pkg, share), used)) addShare(concrete);
4029
4010
  return orderSharedDependenciesFirst(Array.from(shares).sort((a, b) => {
4030
4011
  const priority = (pkg) => pkg === "react" ? 0 : pkg === "react-dom" ? 1 : pkg.startsWith("react/") ? 2 : 3;
4031
4012
  return priority(a) - priority(b) || a.localeCompare(b);
4032
- }));
4013
+ }), options);
4033
4014
  }
4034
4015
  function getMaterializedShares(options) {
4035
- const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
4036
- const scopedRegistrations = options ? usedSharesByOptions.get(options) : void 0;
4037
- const shares = new Set(options && scopedRegistrations?.size ? materializedSharesByOptions.get(options) ?? [] : usedShares);
4038
- const usedForEager = options ? usedSharesByOptions.get(options) ?? [] : usedShares;
4039
- for (const [pkg, share] of Object.entries(resolvedOptions.shared ?? {})) {
4016
+ const shares = new Set(materializedSharesByOptions.get(options));
4017
+ const usedForEager = usedSharesByOptions.get(options) ?? [];
4018
+ for (const [pkg, share] of Object.entries(options.shared ?? {})) {
4040
4019
  if (!share.shareConfig?.eager) continue;
4041
4020
  const request = getSharedRequest(pkg, share);
4042
4021
  if (request.endsWith("/")) for (const concrete of expandSharedPrefixKey(request, usedForEager)) shares.add(concrete);
4043
4022
  else shares.add(pkg);
4044
4023
  }
4045
4024
  const configured = /* @__PURE__ */ new Map();
4046
- for (const pkg of getOrderedUsedShares(options)) {
4025
+ const orderedUsed = getOrderedUsedShares(options);
4026
+ for (const pkg of orderedUsed) {
4047
4027
  const packageName = getPackageName(pkg);
4048
4028
  if (!configured.has(packageName) || pkg === packageName) configured.set(packageName, pkg);
4049
4029
  }
4030
+ const localImports = getLocalShareImports(orderedUsed, options);
4050
4031
  const pending = [...shares];
4051
4032
  while (pending.length) {
4052
4033
  const pkg = pending.pop();
4053
- const share = getNormalizeShareItem(pkg, resolvedOptions);
4034
+ const share = getNormalizeShareItem(pkg, options);
4035
+ for (const imported of localImports.get(pkg) ?? []) if (!shares.has(imported) && getNormalizeShareItem(imported, options)?.scope === share?.scope) {
4036
+ shares.add(imported);
4037
+ pending.push(imported);
4038
+ }
4054
4039
  const packageName = getPackageName(pkg);
4055
4040
  const packageJson = getInstalledPackageJson(pkg)?.packageJson ?? (pkg !== packageName ? getInstalledPackageJson(packageName)?.packageJson : void 0);
4056
4041
  const dependencies = {
@@ -4061,7 +4046,7 @@ function getMaterializedShares(options) {
4061
4046
  };
4062
4047
  for (const dependency of Object.keys(dependencies)) {
4063
4048
  const sharedDependency = configured.get(dependency);
4064
- const dependencyShare = sharedDependency ? getNormalizeShareItem(sharedDependency, resolvedOptions) : void 0;
4049
+ const dependencyShare = sharedDependency ? getNormalizeShareItem(sharedDependency, options) : void 0;
4065
4050
  if (sharedDependency && !shares.has(sharedDependency) && dependencyShare?.scope === share?.scope) {
4066
4051
  shares.add(sharedDependency);
4067
4052
  pending.push(sharedDependency);
@@ -4073,12 +4058,41 @@ function getMaterializedShares(options) {
4073
4058
  return priority(a) - priority(b) || a.localeCompare(b);
4074
4059
  });
4075
4060
  return orderSharedDependenciesFirst([...new Set(sorted.map((pkg) => {
4076
- const shareItem = getNormalizeShareItem(pkg, resolvedOptions);
4061
+ const shareItem = getNormalizeShareItem(pkg, options);
4077
4062
  return shareItem ? getCanonicalSharedKey(pkg, shareItem) : pkg;
4078
- }))]);
4063
+ }))], options);
4064
+ }
4065
+ /**
4066
+ * The other local shares each local share (one whose `import` is a project file) imports at module
4067
+ * evaluation, found through the static imports of its source and of the unshared project files it
4068
+ * imports, keyed by share. Only local shares have an entry.
4069
+ */
4070
+ function getLocalShareImports(shares, options) {
4071
+ const localShareFiles = /* @__PURE__ */ new Map();
4072
+ const requests = /* @__PURE__ */ new Map();
4073
+ for (const pkg of shares) {
4074
+ const shareItem = getNormalizeShareItem(pkg, options);
4075
+ const sourceFile = getLocalShareSourceFile(pkg, shareItem);
4076
+ if (sourceFile === void 0) continue;
4077
+ localShareFiles.set(pkg, sourceFile);
4078
+ const request = getSharedRequest(pkg, shareItem);
4079
+ if (request !== pkg) requests.set(request, pkg);
4080
+ }
4081
+ return new Map(Array.from(localShareFiles, ([pkg, sourceFile]) => [pkg, getImportedLocalShares(sourceFile, localShareFiles, requests)]));
4082
+ }
4083
+ /**
4084
+ * Shares that must be materialized before each local share, keyed by share. A project file has no
4085
+ * package.json to read dependencies from and may import any shared package, directly or through
4086
+ * other project files, so every installed-package share comes first, followed by the local shares
4087
+ * its source imports (see #1507).
4088
+ */
4089
+ function getLocalSharePrerequisites(shares, options) {
4090
+ const localImports = getLocalShareImports(shares, options);
4091
+ const packageShares = shares.filter((pkg) => !localImports.has(pkg));
4092
+ return new Map(Array.from(localImports, ([pkg, imports]) => [pkg, [...packageShares, ...imports]]));
4079
4093
  }
4080
4094
  /** Shared keys a share's package.json depends on (roots stand in for their subpaths, subpaths for their root), keyed by share. */
4081
- function getSharePrerequisites(ordered) {
4095
+ function getSharePrerequisites(ordered, options) {
4082
4096
  const roots = /* @__PURE__ */ new Map();
4083
4097
  const subpaths = /* @__PURE__ */ new Map();
4084
4098
  for (const pkg of ordered) {
@@ -4087,7 +4101,13 @@ function getSharePrerequisites(ordered) {
4087
4101
  else subpaths.set(packageName, [...subpaths.get(packageName) ?? [], pkg]);
4088
4102
  }
4089
4103
  const prerequisitesByShare = /* @__PURE__ */ new Map();
4104
+ const localPrerequisites = getLocalSharePrerequisites(ordered, options);
4090
4105
  for (const pkg of ordered) {
4106
+ const local = localPrerequisites.get(pkg);
4107
+ if (local) {
4108
+ prerequisitesByShare.set(pkg, local);
4109
+ continue;
4110
+ }
4091
4111
  const packageName = getPackageName(pkg);
4092
4112
  const packageJson = getInstalledPackageJson(pkg)?.packageJson ?? (pkg !== packageName ? getInstalledPackageJson(packageName)?.packageJson : void 0);
4093
4113
  const dependencies = {
@@ -4107,14 +4127,15 @@ function getSharePrerequisites(ordered) {
4107
4127
  }
4108
4128
  function getShareBatches(options, materializedOnly = true) {
4109
4129
  const ordered = materializedOnly ? getMaterializedShares(options) : getOrderedUsedShares(options);
4110
- const prerequisitesByShare = getSharePrerequisites(ordered);
4130
+ const prerequisitesByShare = getSharePrerequisites(ordered, options);
4111
4131
  const levels = /* @__PURE__ */ new Map();
4112
4132
  for (const pkg of ordered) levels.set(pkg, (prerequisitesByShare.get(pkg) ?? []).reduce((level, dependency) => Math.max(level, (levels.get(dependency) ?? 0) + 1), 0));
4113
4133
  const batches = [];
4114
4134
  for (const pkg of ordered) (batches[levels.get(pkg) ?? 0] ??= []).push(pkg);
4115
4135
  return batches.filter(Boolean);
4116
4136
  }
4117
- function orderSharedDependenciesFirst(sharedPackages) {
4137
+ function orderSharedDependenciesFirst(sharedPackages, options) {
4138
+ const localPrerequisites = getLocalSharePrerequisites(sharedPackages, options);
4118
4139
  const sharedKeyByPackageName = /* @__PURE__ */ new Map();
4119
4140
  const subpathKeysByPackageName = /* @__PURE__ */ new Map();
4120
4141
  sharedPackages.forEach((pkg) => {
@@ -4133,6 +4154,14 @@ function orderSharedDependenciesFirst(sharedPackages) {
4133
4154
  if (visited.has(pkg)) return;
4134
4155
  if (visiting.has(pkg)) return;
4135
4156
  visiting.add(pkg);
4157
+ const local = localPrerequisites.get(pkg);
4158
+ if (local) {
4159
+ local.forEach(visit);
4160
+ visiting.delete(pkg);
4161
+ visited.add(pkg);
4162
+ ordered.push(pkg);
4163
+ return;
4164
+ }
4136
4165
  const packageName = getPackageName(pkg);
4137
4166
  const packageJson = getInstalledPackageJson(pkg)?.packageJson ?? (pkg !== packageName ? getInstalledPackageJson(packageName)?.packageJson : void 0);
4138
4167
  const dependencies = {
@@ -4413,7 +4442,7 @@ function generateRuntimeSharedCacheSeedCode(shareStrategy, options, command = "b
4413
4442
  const seedBatches = getShareBatches(options, false);
4414
4443
  const seedOrder = seedBatches.flat();
4415
4444
  const seedIndex = new Map(seedOrder.map((pkg, index) => [pkg, index]));
4416
- const seedPrerequisites = Object.fromEntries(Array.from(getSharePrerequisites(seedOrder)).filter(([, prerequisites]) => prerequisites.length > 0).map(([pkg, prerequisites]) => [seedIndex.get(pkg), prerequisites.map((prerequisite) => seedIndex.get(prerequisite))]));
4445
+ const seedPrerequisites = Object.fromEntries(Array.from(getSharePrerequisites(seedOrder, options)).filter(([, prerequisites]) => prerequisites.length > 0).map(([pkg, prerequisites]) => [seedIndex.get(pkg), prerequisites.map((prerequisite) => seedIndex.get(prerequisite))]));
4417
4446
  return `
4418
4447
  const __mfSeedOrder = ${toSafeJsLiteral(seedOrder)};
4419
4448
  const __mfSeedBatches = ${toSafeJsLiteral(seedBatches)};
@@ -4487,6 +4516,19 @@ function generateRuntimeSharedCacheSeedCode(shareStrategy, options, command = "b
4487
4516
  );
4488
4517
  return;
4489
4518
  }
4519
+ // A Vite container seeds its own copy into the module cache before the Runtime
4520
+ // marks its provider loaded. A non-singleton is cached under its version, so
4521
+ // look the selected provider's copy up under that version, not this share's.
4522
+ if (!share.shareConfig?.singleton && typeof externalProvider.version === 'string') {
4523
+ const externalCached = __mfReadSharedCache(
4524
+ __mfModuleCache.share,
4525
+ __mfGetSharedCacheDescriptor(pkg, false, externalProvider.version, share.scope)
4526
+ );
4527
+ if (externalCached !== undefined) {
4528
+ __mfWriteSharedCache(__mfModuleCache.share, cacheDescriptor, externalCached, externalProvider.from);
4529
+ return;
4530
+ }
4531
+ }
4490
4532
  // Leave an unloaded webpack provider to the late bridge, which only takes a
4491
4533
  // non-singleton of this share's own version; any other version seeds locally.
4492
4534
  if (
@@ -4596,10 +4638,9 @@ function getBrowserImportPath(importPath) {
4596
4638
  return importPath;
4597
4639
  }
4598
4640
  function getHostAutoInitSharedSeedItems(options) {
4599
- const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
4600
4641
  return getMaterializedShares(options).map((pkg) => ({
4601
4642
  pkg,
4602
- shareItem: getShareItemForPreload(pkg, resolvedOptions)
4643
+ shareItem: getShareItemForPreload(pkg, options)
4603
4644
  })).filter(({ shareItem }) => shareItem?.shareConfig?.import === false).sort((a, b) => {
4604
4645
  const priority = (pkg) => pkg === "vue" ? 0 : pkg === "pinia" ? 1 : 2;
4605
4646
  const aIsLocal = !!getLocalProviderImportPath(a.pkg);
@@ -4610,7 +4651,7 @@ function getHostAutoInitSharedSeedItems(options) {
4610
4651
  function generateHostAutoInitSharedCacheSeedCode(command = "build", options) {
4611
4652
  if (command === "build") return "";
4612
4653
  const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
4613
- return getHostAutoInitSharedSeedItems(options).map(({ pkg, shareItem }) => {
4654
+ return getHostAutoInitSharedSeedItems(resolvedOptions).map(({ pkg, shareItem }) => {
4614
4655
  if (!shareItem) return null;
4615
4656
  return generateSharedCacheSeedItem(pkg, shareItem, getBrowserImportPath(getDirectSharedCacheSeedImportPath(pkg, shareItem)), resolvedOptions);
4616
4657
  }).filter((item) => item !== null).join("\n");
@@ -5796,13 +5837,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
5796
5837
  */
5797
5838
  const HOST_AUTO_INIT_TAG = "__H_A_I__";
5798
5839
  const hostAutoInitStates = /* @__PURE__ */ new WeakMap();
5799
- const legacyHostAutoInitState = {
5800
- module: new VirtualModule("hostAutoInit", HOST_AUTO_INIT_TAG),
5801
- remoteEntryId: REMOTE_ENTRY_ID,
5802
- command: "build"
5803
- };
5804
5840
  function getHostAutoInitState(options) {
5805
- if (!options) return legacyHostAutoInitState;
5806
5841
  let state = hostAutoInitStates.get(options);
5807
5842
  if (!state) {
5808
5843
  const ownerKey = getLocalOwnerKey(options);
@@ -5818,7 +5853,7 @@ function getHostAutoInitState(options) {
5818
5853
  function generateHostAutoInitCode(remoteEntryImport, _command = "build", options, exportConditions) {
5819
5854
  const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
5820
5855
  const shouldPreloadShares = resolvedOptions.shareStrategy !== "loaded-first";
5821
- const hostInitShareBatches = toSafeJsLiteral(getShareBatches(options, false));
5856
+ const hostInitShareBatches = toSafeJsLiteral(getShareBatches(resolvedOptions, false));
5822
5857
  const cacheOwner = toSafeJsLiteral(resolvedOptions.name);
5823
5858
  const preferLocalVinextReact = hasPackageDependency("vinext") && (!exportConditions?.includes("browser") || exportConditions.includes("worker"));
5824
5859
  const hasConfiguredShared = hasShared(resolvedOptions);
@@ -5862,6 +5897,15 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build", options
5862
5897
  )
5863
5898
  );
5864
5899
  const __mfHostInitShareBatches = ${hostInitShareBatches};
5900
+ // The baked batches are generated before the build has seen every import, so a
5901
+ // share first used later in the graph, such as react-dom/client, is missing from
5902
+ // them. Negotiate those after the baked batches, once their package roots have
5903
+ // settled (#1503).
5904
+ {
5905
+ const bakedKeys = new Set(__mfHostInitShareBatches.flat());
5906
+ const lateKeys = Object.keys(usedShared).filter((pkg) => !bakedKeys.has(pkg));
5907
+ if (lateKeys.length) __mfHostInitShareBatches.push(lateKeys);
5908
+ }
5865
5909
  ${hostInitSharedProviderHelperCode}
5866
5910
  for (const __mfHostInitShareBatch of __mfHostInitShareBatches) {
5867
5911
  await Promise.all(__mfHostInitShareBatch.map(async (pkg) => {
@@ -5876,9 +5920,10 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build", options
5876
5920
  if (
5877
5921
  __mfReadSharedCache(__mfModuleCache.share, cacheDescriptor) !== undefined &&
5878
5922
  ${_command === "serve" ? `__mfReadSharedCacheOwner(__mfModuleCache.share, cacheDescriptor) !== undefined &&
5879
- !(share.shareConfig?.singleton && __mfHasAlternativeSharedVersion(pkg, share))` : `(
5880
- (!share.shareConfig?.singleton && __mfReadSharedCacheOwner(__mfModuleCache.share, cacheDescriptor) === ${cacheOwner}) ||
5881
- (share.shareConfig?.singleton && !__mfHasAlternativeSharedVersion(pkg, share))
5923
+ !__mfHasAlternativeSharedVersion(pkg, share)` : `(
5924
+ !__mfHasAlternativeSharedVersion(pkg, share) &&
5925
+ (share.shareConfig?.singleton ||
5926
+ __mfReadSharedCacheOwner(__mfModuleCache.share, cacheDescriptor) === ${cacheOwner})
5882
5927
  )`}
5883
5928
  ) return;
5884
5929
  // An import:false share has nothing to load until a foreign provider
@@ -5968,7 +6013,7 @@ function generateHostAutoInitCode(remoteEntryImport, _command = "build", options
5968
6013
  export { initHost, hostInitPromise };
5969
6014
  `;
5970
6015
  }
5971
- function writeHostAutoInit(remoteEntryId = REMOTE_ENTRY_ID, command = "build", options, exportConditions) {
6016
+ function writeHostAutoInit(remoteEntryId = REMOTE_ENTRY_ID, command, options, exportConditions) {
5972
6017
  const state = getHostAutoInitState(options);
5973
6018
  state.remoteEntryId = remoteEntryId;
5974
6019
  state.command = command;
@@ -5996,13 +6041,8 @@ function isOwnedHostAutoInitId(id, options) {
5996
6041
  * free of wrapper references.
5997
6042
  */
5998
6043
  const PENDING_SHARES_TAG = "__P_S__";
5999
- const legacyPendingSharesState = {
6000
- module: new VirtualModule("pendingShares", PENDING_SHARES_TAG),
6001
- command: "build"
6002
- };
6003
6044
  const pendingSharesStates = /* @__PURE__ */ new WeakMap();
6004
6045
  function getPendingSharesState(options) {
6005
- if (!options) return legacyPendingSharesState;
6006
6046
  let state = pendingSharesStates.get(options);
6007
6047
  if (!state) {
6008
6048
  state = {
@@ -6015,14 +6055,14 @@ function getPendingSharesState(options) {
6015
6055
  }
6016
6056
  function generatePendingSharesCode(command = "build", options) {
6017
6057
  const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
6018
- const pendingSharePkgs = command === "build" ? getMaterializedShares(options).filter((pkg) => {
6058
+ const pendingSharePkgs = command === "build" ? getMaterializedShares(resolvedOptions).filter((pkg) => {
6019
6059
  const shareItem = getShareItemForPreload(pkg, resolvedOptions);
6020
6060
  if (!shareItem || pkg.endsWith("/")) return false;
6021
6061
  if (shareItem.shareConfig.eager) return false;
6022
6062
  return shareItem.shareConfig.import !== false && !shareItem.shareConfig.treeShaking;
6023
6063
  }) : [];
6024
6064
  if (command === "build" && shouldPreloadEntryDeferredReactDomClient(resolvedOptions) && !pendingSharePkgs.includes("react-dom/client")) pendingSharePkgs.push(REACT_DOM_CLIENT_SHARE);
6025
- const pendingShareImports = pendingSharePkgs.map((pkg) => `[${toSafeJsLiteral(pkg)}, () => import(${toSafeJsLiteral(getLoadShareModulePath(pkg, false, options))})]`);
6065
+ const pendingShareImports = pendingSharePkgs.map((pkg) => `[${toSafeJsLiteral(pkg)}, () => import(${toSafeJsLiteral(getLoadShareModulePath(pkg, resolvedOptions))})]`);
6026
6066
  return `
6027
6067
  ${getRuntimeModuleCacheBootstrapCode()}
6028
6068
  ${sharedCacheHelperCode}
@@ -6048,7 +6088,7 @@ function generatePendingSharesCode(command = "build", options) {
6048
6088
  }
6049
6089
  `;
6050
6090
  }
6051
- function writePendingShares(command = "build", options) {
6091
+ function writePendingShares(command, options) {
6052
6092
  const state = getPendingSharesState(options);
6053
6093
  state.command = command;
6054
6094
  state.module.writeSync(generatePendingSharesCode(command, options), true);
@@ -6107,20 +6147,11 @@ function refreshRemoteModuleForEnvironment(id, options, exportConditions) {
6107
6147
  virtual.write(generateRemotes(metadata.remote, metadata.command, metadata.enableSsrInit, metadata.consumer, options, exportConditions));
6108
6148
  return true;
6109
6149
  }
6110
- const usedRemotesMap = {};
6111
6150
  const usedRemotesByOptions = /* @__PURE__ */ new WeakMap();
6112
6151
  const dynamicRemotesByOptions = /* @__PURE__ */ new WeakMap();
6113
6152
  const staticRemotesByOptions = /* @__PURE__ */ new WeakMap();
6114
6153
  const preloadRemotesByOptions = /* @__PURE__ */ new WeakMap();
6115
6154
  const EMPTY_STATIC_REMOTES = /* @__PURE__ */ new Set();
6116
- function getScopedUsedRemotesMap(options) {
6117
- let scoped = usedRemotesByOptions.get(options);
6118
- if (!scoped) {
6119
- scoped = {};
6120
- usedRemotesByOptions.set(options, scoped);
6121
- }
6122
- return scoped;
6123
- }
6124
6155
  function recordUsedRemote(map, remoteKey, remoteModule) {
6125
6156
  ensureUsedRemoteKey(map, remoteKey).add(remoteModule);
6126
6157
  }
@@ -6129,16 +6160,18 @@ function ensureUsedRemoteKey(map, remoteKey) {
6129
6160
  return map[remoteKey];
6130
6161
  }
6131
6162
  function ensureUsedRemote(remoteKey, options) {
6132
- ensureUsedRemoteKey(usedRemotesMap, remoteKey);
6133
- if (options) ensureUsedRemoteKey(getScopedUsedRemotesMap(options), remoteKey);
6163
+ ensureUsedRemoteKey(getUsedRemotesMap(options), remoteKey);
6134
6164
  }
6135
6165
  function addUsedRemote(remoteKey, remoteModule, options) {
6136
- recordUsedRemote(usedRemotesMap, remoteKey, remoteModule);
6137
- if (options) recordUsedRemote(getScopedUsedRemotesMap(options), remoteKey, remoteModule);
6166
+ recordUsedRemote(getUsedRemotesMap(options), remoteKey, remoteModule);
6138
6167
  }
6139
6168
  function getUsedRemotesMap(options) {
6140
- if (options) return getScopedUsedRemotesMap(options);
6141
- return usedRemotesMap;
6169
+ let usedRemotes = usedRemotesByOptions.get(options);
6170
+ if (!usedRemotes) {
6171
+ usedRemotes = {};
6172
+ usedRemotesByOptions.set(options, usedRemotes);
6173
+ }
6174
+ return usedRemotes;
6142
6175
  }
6143
6176
  function markDynamicRemote(remote, options) {
6144
6177
  let remotes = dynamicRemotesByOptions.get(options);
@@ -6208,12 +6241,6 @@ function getEagerDeferredClientInit() {
6208
6241
  return `__mfRemotePending = __mfStartRemoteLoad().then(__mfAssignRemoteModule);
6209
6242
  exportModule = __mfCreateDeferredRemoteProxy();`;
6210
6243
  }
6211
- function shouldIncludeDeferredProxy(initMode, consumer, eagerLoadClientRemote, deferRemoteLoad) {
6212
- if (eagerLoadClientRemote && consumer !== "server") return true;
6213
- if (initMode === "eager") return consumer !== "server" && (consumer === "unified" || !eagerLoadClientRemote);
6214
- if (consumer === "client" && eagerLoadClientRemote) return false;
6215
- return deferRemoteLoad || consumer !== "server";
6216
- }
6217
6244
  /** Codegen shared by every remote virtual module (no top-level await). */
6218
6245
  function getRemoteModuleRuntimeHelpers() {
6219
6246
  return `
@@ -6254,12 +6281,16 @@ function getDeferredProxyHelper(remoteCacheKey) {
6254
6281
  function __mfCreateDeferredRemoteProxy() {
6255
6282
  let pendingPromise;
6256
6283
  const ensurePending = () => {
6257
- pendingPromise ||= __mfStartRemoteLoad();
6284
+ if (!pendingPromise) {
6285
+ pendingPromise = __mfStartRemoteLoad();
6286
+ // Property reads can start a load without an awaiter to handle failure.
6287
+ pendingPromise.then(undefined, () => { pendingPromise = undefined; });
6288
+ }
6258
6289
  return pendingPromise;
6259
6290
  };
6260
6291
  const getModule = () => __mfModuleCache.remote[${JSON.stringify(remoteCacheKey)}];
6261
6292
  const proxyTarget = function (...args) {
6262
- pendingPromise ||= __mfStartRemoteLoad();
6293
+ ensurePending();
6263
6294
  const mod = getModule();
6264
6295
  const fn = mod && (mod.default ?? mod);
6265
6296
  if (fn !== undefined && fn !== null) {
@@ -6278,7 +6309,7 @@ function getDeferredProxyHelper(remoteCacheKey) {
6278
6309
  if (mod) {
6279
6310
  return prop in mod ? mod[prop] : mod.default?.[prop];
6280
6311
  }
6281
- pendingPromise ||= __mfStartRemoteLoad();
6312
+ ensurePending();
6282
6313
  if (prop === "default") return proxyTarget;
6283
6314
  throw ensurePending();
6284
6315
  },
@@ -6318,9 +6349,19 @@ function getDeferredProxyHelper(remoteCacheKey) {
6318
6349
  }`;
6319
6350
  }
6320
6351
  function getLazyRemotePendingExport() {
6321
- return `export const __mf_remote_pending = __mfRemotePending ?? {
6352
+ return `function __mfResetFailedRemotePending(pending) {
6353
+ pending.then(undefined, () => {
6354
+ if (__mfRemotePending === pending) __mfRemotePending = undefined;
6355
+ });
6356
+ }
6357
+ if (__mfRemotePending) __mfResetFailedRemotePending(__mfRemotePending);
6358
+ export const __mf_remote_pending = {
6322
6359
  then(onFulfilled, onRejected) {
6323
- return (__mfRemotePending ??= __mfStartRemoteLoad().then(__mfAssignRemoteModule)).then(onFulfilled, onRejected);
6360
+ if (!__mfRemotePending) {
6361
+ __mfRemotePending = __mfStartRemoteLoad().then(__mfAssignRemoteModule);
6362
+ __mfResetFailedRemotePending(__mfRemotePending);
6363
+ }
6364
+ return __mfRemotePending.then(onFulfilled, onRejected);
6324
6365
  },
6325
6366
  };`;
6326
6367
  }
@@ -6380,12 +6421,11 @@ export { __mfDefaultExport as default };`;
6380
6421
  function generateRemotes(id, command, enableSsrInit = false, consumer = "unified", options, exportConditions) {
6381
6422
  const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
6382
6423
  const isLoadedFirst = resolvedOptions.shareStrategy === "loaded-first";
6383
- const initMode = resolveRemoteInitMode(resolvedOptions.shareStrategy, consumer);
6384
- const deferRemoteLoad = shouldDeferRemoteLoad(initMode);
6424
+ const deferRemoteLoad = shouldDeferRemoteLoad(resolveRemoteInitMode(resolvedOptions.shareStrategy, consumer));
6385
6425
  const runtimeRemoteId = getRuntimeRemoteId(id, resolvedOptions.remotes, options);
6386
6426
  const remoteRegistration = getRemoteRegistration(id, resolvedOptions.remotes, options);
6387
6427
  const registerRemoteCode = isLoadedFirst && remoteRegistration ? `runtime.registerRemotes([${JSON.stringify(remoteRegistration)}]);` : "";
6388
- const hostAutoInitPath = getHostAutoInitPath(options);
6428
+ const hostAutoInitPath = getHostAutoInitPath(resolvedOptions);
6389
6429
  const ssrRemotes = getSsrRuntimeRemotes(resolvedOptions.remotes, options);
6390
6430
  const browserHostInitCode = `import(${JSON.stringify(hostAutoInitPath)})
6391
6431
  .then((mod) => mod.hostInitPromise)
@@ -6398,20 +6438,13 @@ function generateRemotes(id, command, enableSsrInit = false, consumer = "unified
6398
6438
  ${command === "serve" && consumer !== "server" ? browserHostInitCode : ""}`;
6399
6439
  const remoteLoadRuntimePromise = command === "build" ? "__mfHostInitPromise()" : "initPromise";
6400
6440
  const remoteCacheKey = `${getRuntimeRemoteCachePrefix(options)}${id}`;
6401
- const remoteLoadFailureHandler = command === "build" ? `.catch((error) => {
6402
- delete __mfModuleCache.remote[pendingKey];
6403
- throw error;
6404
- })` : `.catch((error) => {
6405
- delete __mfModuleCache.remote[pendingKey];
6406
- throw error;
6407
- })`;
6408
6441
  const remoteLoadCode = `
6409
6442
  function __mfStartRemoteLoad() {
6410
6443
  ${`
6411
6444
  const remoteCacheKey = ${JSON.stringify(remoteCacheKey)};
6412
6445
  const pendingKey = "__mf_pending__" + remoteCacheKey;
6413
6446
  if (!__mfModuleCache.remote[pendingKey]) {
6414
- __mfModuleCache.remote[pendingKey] = ${remoteLoadRuntimePromise}
6447
+ const pending = ${remoteLoadRuntimePromise}
6415
6448
  .then((runtime) => {
6416
6449
  ${registerRemoteCode}
6417
6450
  const moduleCacheKey = Symbol.for(${JSON.stringify(MODULE_CACHE_SHARE_SCOPE_KEY)});
@@ -6428,22 +6461,25 @@ function generateRemotes(id, command, enableSsrInit = false, consumer = "unified
6428
6461
  delete __mfModuleCache.remote[pendingKey];
6429
6462
  return mod;
6430
6463
  })
6431
- ${remoteLoadFailureHandler};
6464
+ .catch((error) => {
6465
+ if (__mfModuleCache.remote[pendingKey] === pending) {
6466
+ delete __mfModuleCache.remote[pendingKey];
6467
+ }
6468
+ throw error;
6469
+ });
6470
+ __mfModuleCache.remote[pendingKey] = pending;
6432
6471
  }
6433
6472
  return __mfModuleCache.remote[pendingKey];`}
6434
6473
  }`;
6435
6474
  const realRemoteInit = `__mfRemotePending = __mfStartRemoteLoad().then(__mfAssignRemoteModule);`;
6436
- const deferredClientInit = `exportModule = __mfCreateDeferredRemoteProxy();`;
6437
- const eagerLoadClientRemote = id === remoteRegistration?.alias || shouldEagerLoadClientRemoteInDev(command, enableSsrInit);
6438
- const eagerClientInit = eagerLoadClientRemote ? getEagerDeferredClientInit() : deferredClientInit;
6439
- const loadedFirstClientInit = eagerLoadClientRemote ? getEagerDeferredClientInit() : deferredClientInit;
6475
+ const clientInit = id === remoteRegistration?.alias || shouldEagerLoadClientRemoteInDev(command, enableSsrInit) ? getEagerDeferredClientInit() : `exportModule = __mfCreateDeferredRemoteProxy();`;
6440
6476
  const environmentSplitInit = (clientInit, serverInit) => consumer === "client" ? clientInit : consumer === "server" ? serverInit : `if (${SERVER_ENV_GUARD}) {
6441
6477
  ${serverInit}
6442
6478
  } else {
6443
6479
  ${clientInit}
6444
6480
  }`;
6445
- const initExportModule = initMode === "eager" ? environmentSplitInit(eagerClientInit, realRemoteInit) : environmentSplitInit(loadedFirstClientInit, realRemoteInit);
6446
- const includeProxyHelper = shouldIncludeDeferredProxy(initMode, consumer, eagerLoadClientRemote, deferRemoteLoad);
6481
+ const initExportModule = environmentSplitInit(clientInit, realRemoteInit);
6482
+ const includeProxyHelper = consumer !== "server";
6447
6483
  const deferredProxyCode = getDeferredProxyHelper(remoteCacheKey);
6448
6484
  return `
6449
6485
  ${importLine}
@@ -6464,9 +6500,9 @@ const isPreloadableVirtualMfChunk = (name) => name.includes("virtual_mf") && !na
6464
6500
  const HOST_INIT_PRELOAD_CHUNKS = [
6465
6501
  (name) => name === "hostInit",
6466
6502
  (name) => name === "remoteEntry",
6467
- isPreloadableVirtualMfChunk,
6468
- (name) => name === "index"
6503
+ isPreloadableVirtualMfChunk
6469
6504
  ];
6505
+ const isHostInitPreloadSeed = (chunk) => chunk.isEntry || HOST_INIT_PRELOAD_CHUNKS.some((match) => match(chunk.name));
6470
6506
  const isRemoteWarmupExcluded = (name) => name.includes("__prebuild__") || name.includes("__loadShare__");
6471
6507
  const REMOTE_ENTRY_WARMUP_CHUNKS = [(name) => name === "hostInit", (name) => isPreloadableVirtualMfChunk(name) && !isRemoteWarmupExcluded(name)];
6472
6508
  function getChunksByFileName(bundle) {
@@ -6503,7 +6539,7 @@ function injectHostInitPreloads(html, bundle, resolvePath, externalHrefs = []) {
6503
6539
  hrefs.push(href);
6504
6540
  }
6505
6541
  const chunksByFileName = getChunksByFileName(bundle);
6506
- const seeds = Array.from(chunksByFileName.values()).filter((chunk) => HOST_INIT_PRELOAD_CHUNKS.some((match) => match(chunk.name)));
6542
+ const seeds = Array.from(chunksByFileName.values()).filter(isHostInitPreloadSeed);
6507
6543
  for (const fileName of collectPreloadChunkFiles(chunksByFileName, seeds)) {
6508
6544
  const href = resolvePath(fileName);
6509
6545
  if (existingHrefs.has(href)) continue;
@@ -6598,7 +6634,7 @@ const ROLLDOWN_RUNTIME_GLOBAL = "__rolldown_runtime__";
6598
6634
  * in every chunk and HMR patch it serves.
6599
6635
  */
6600
6636
  function renameBundledDevRuntime(req, res, remoteName) {
6601
- if (!req.url || !stripQueryAndHash(req.url).endsWith(".js")) return;
6637
+ if (!req.url || !/\.m?js$/.test(stripQueryAndHash(req.url))) return;
6602
6638
  const runtimeGlobal = `__mf_rt_${createHash("sha256").update(remoteName).digest("hex").slice(0, 10)}__`;
6603
6639
  const end = res.end;
6604
6640
  res.end = function(chunk, ...args) {
@@ -6615,6 +6651,7 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
6615
6651
  const ENTRY_BOOTSTRAP_QUERY = `?${ENTRY_BOOTSTRAP_PARAM}`;
6616
6652
  const waitsForInit = entryName === "hostInit";
6617
6653
  const getEntryPath = () => typeof entryPath === "function" ? entryPath() : entryPath;
6654
+ const getFederationOptions = () => federationOptions ?? getNormalizeModuleFederationOptions();
6618
6655
  let devEntryPath = "";
6619
6656
  let entryFiles = [];
6620
6657
  let htmlFilePath;
@@ -6634,8 +6671,14 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
6634
6671
  let isBundledDevRemote = false;
6635
6672
  let bundledDevRemoteEntryCode;
6636
6673
  let resolveBundledDevRemoteEntryCode;
6674
+ function isBuildCommand() {
6675
+ return _command === "build" || viteConfig?.command === "build";
6676
+ }
6677
+ function isLoadedFirstClientBuildFor(shareStrategy) {
6678
+ return isBuildCommand() && waitsForInit && !viteConfig?.build?.ssr && shareStrategy === "loaded-first";
6679
+ }
6637
6680
  function skipSvelteKitSsrBuild() {
6638
- return (_command === "build" || viteConfig?.command === "build") && viteConfig?.build?.ssr && hasPackageDependency("@sveltejs/kit");
6681
+ return isBuildCommand() && viteConfig?.build?.ssr && hasPackageDependency("@sveltejs/kit");
6639
6682
  }
6640
6683
  function isSvelteKitServerModule(id) {
6641
6684
  return hasPackageDependency("@sveltejs/kit") && (id.includes(".svelte-kit/generated/") || id.includes("/@sveltejs/kit/src/runtime/server/"));
@@ -6670,10 +6713,6 @@ const __mfCurrentScript = document.currentScript;
6670
6713
  function walkHtmlFiles(dir) {
6671
6714
  return walkFiles(dir, (fileName) => fileName.endsWith(".html"));
6672
6715
  }
6673
- function toRelativeImport(fromFile, targetFile) {
6674
- const relative = normalizePathForImport(path$1.relative(path$1.dirname(fromFile), targetFile));
6675
- return relative.startsWith(".") ? relative : `./${relative}`;
6676
- }
6677
6716
  function patchSvelteKitStaticHtml() {
6678
6717
  const buildDir = path$1.resolve(viteConfig.root, "build");
6679
6718
  let initFile = emittedFileName ? path$1.resolve(buildDir, emittedFileName) : void 0;
@@ -6694,10 +6733,10 @@ const __mfCurrentScript = document.currentScript;
6694
6733
  return patched;
6695
6734
  }
6696
6735
  function getRemoteEntryPreloadUrls() {
6697
- const normalizedOptions = federationOptions ?? getNormalizeModuleFederationOptions();
6698
- const isLoadedFirstClientBuild = (_command === "build" || viteConfig?.command === "build") && waitsForInit && !viteConfig?.build?.ssr && normalizedOptions.shareStrategy === "loaded-first";
6736
+ const normalizedOptions = getFederationOptions();
6737
+ const isLoadedFirstClientBuild = isLoadedFirstClientBuildFor(normalizedOptions.shareStrategy);
6699
6738
  if (normalizedOptions.shareStrategy === "loaded-first" && !isLoadedFirstClientBuild) return [];
6700
- const remoteSources = isLoadedFirstClientBuild ? Array.from(getPreloadRemotes(normalizedOptions)) : Object.keys(getUsedRemotesMap(federationOptions));
6739
+ const remoteSources = isLoadedFirstClientBuild ? Array.from(getPreloadRemotes(normalizedOptions)) : Object.keys(getUsedRemotesMap(normalizedOptions));
6701
6740
  return Array.from(new Set(remoteSources.flatMap((remote) => {
6702
6741
  const registration = getRemoteRegistration(remote, normalizedOptions.remotes, federationOptions);
6703
6742
  return registration && (registration.type === "module" || registration.type === "esm") && /^(?:https?:)?\/\//.test(registration.entry) && !/\.json(?:[?#]|$)/i.test(registration.entry) ? [registration.entry] : [];
@@ -6736,10 +6775,10 @@ const __mfCurrentScript = document.currentScript;
6736
6775
  const entryImportDeclaration = isEncodedVirtualEntry ? `const __mfEntryUrl = ${JSON.stringify(entrySrc)};
6737
6776
  ` : "";
6738
6777
  const entryImportExpression = isEncodedVirtualEntry ? "import(/* @vite-ignore */ __mfEntryUrl)" : importExpression(entrySrc);
6739
- const normalizedOptions = federationOptions ?? getNormalizeModuleFederationOptions();
6740
- const isLoadedFirstClientBuild = (_command === "build" || viteConfig?.command === "build") && waitsForInit && !viteConfig?.build?.ssr && normalizedOptions.shareStrategy === "loaded-first";
6778
+ const normalizedOptions = getFederationOptions();
6779
+ const isLoadedFirstClientBuild = isLoadedFirstClientBuildFor(normalizedOptions.shareStrategy);
6741
6780
  const shouldPreloadRemotes = !options?.skipRemotePreload && (normalizedOptions.shareStrategy !== "loaded-first" || isLoadedFirstClientBuild);
6742
- const remoteSources = isLoadedFirstClientBuild ? Array.from(getPreloadRemotes(normalizedOptions)) : Object.entries(getUsedRemotesMap(federationOptions)).flatMap(([, remotes]) => Array.from(remotes)).filter((remote) => !federationOptions || !isDynamicOnlyRemote(remote, federationOptions));
6781
+ const remoteSources = isLoadedFirstClientBuild ? Array.from(getPreloadRemotes(normalizedOptions)) : Object.entries(getUsedRemotesMap(normalizedOptions)).flatMap(([, remotes]) => Array.from(remotes)).filter((remote) => !federationOptions || !isDynamicOnlyRemote(remote, federationOptions));
6743
6782
  const remotePreloads = shouldPreloadRemotes ? remoteSources.sort().map((remote) => {
6744
6783
  const registration = isLoadedFirstClientBuild ? getRemoteRegistration(remote, normalizedOptions.remotes, federationOptions) : void 0;
6745
6784
  return `__mfPreloadRemote(${JSON.stringify(getRuntimeRemoteId(remote, normalizedOptions.remotes, federationOptions))}, ${JSON.stringify(remote)}${registration ? `, ${JSON.stringify(registration)}` : ""})`;
@@ -6754,7 +6793,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
6754
6793
  const shareItem = getNormalizeShareItem(pkg, federationOptions);
6755
6794
  const isExplicitShare = Object.hasOwn(federationOptions.shared, pkg);
6756
6795
  return shareItem?.shareConfig?.singleton === true && shareItem?.shareConfig?.import !== false && !shareItem?.shareConfig?.treeShaking && (isExplicitShare || typeof shareItem?.shareConfig?.import === "string" || Boolean(getProjectResolvedImportPath(pkg)));
6757
- }).map((pkg) => getLoadShareModulePath(pkg, false, federationOptions)) : [];
6796
+ }).map((pkg) => getLoadShareModulePath(pkg, federationOptions)) : [];
6758
6797
  const sharedPreloadBlock = sharedPreloadSources.length === 0 ? "" : options?.isBundled ? `
6759
6798
  await Promise.all([${sharedPreloadSources.map((src) => `[${JSON.stringify(src)}, import(${JSON.stringify(src)})]`).join(", ")}].map(([src, load]) => load.catch((err) => console.warn("[module-federation] shared preload failed:", src, err))));` : `
6760
6799
  const __mfSharedPreloadUrls = ${JSON.stringify(sharedPreloadSources.map(toViteEncodedId))};
@@ -6792,8 +6831,8 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
6792
6831
  if (__mfReactServerModuleCache?.pendingShareLoads) {
6793
6832
  await Promise.all(__mfReactServerModuleCache.pendingShareLoads);
6794
6833
  }`;
6795
- const pendingSharesBlock = waitsForInit && (_command === "build" || viteConfig?.command === "build") ? `
6796
- const __mfPendingShares = await ${importExpression(options?.pendingSharesSrc ?? getPendingSharesPath(federationOptions))}.catch(() => undefined);
6834
+ const pendingSharesBlock = waitsForInit && isBuildCommand() ? `
6835
+ const __mfPendingShares = await ${importExpression(options?.pendingSharesSrc ?? getPendingSharesPath(getFederationOptions()))}.catch(() => undefined);
6797
6836
  if (__mfPendingShares && typeof __mfPendingShares.preloadPendingShares === "function") await __mfPendingShares.preloadPendingShares();` : "";
6798
6837
  const importCode = `
6799
6838
  (async () => {
@@ -7045,6 +7084,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
7045
7084
  if (resolved && !resolved.external && (_command === "serve" || !resolved.id.startsWith("\0"))) addEntryFile(resolveProjectId(resolved.id));
7046
7085
  }
7047
7086
  if (_command === "serve") return;
7087
+ if (entryName === "hostInit" && federationOptions && !hasRemotes(federationOptions) && isServerBuildContext(this, viteConfig)) return;
7048
7088
  if (skipSvelteKitSsrBuild()) return;
7049
7089
  if (this.environment?.name === "ssr") return;
7050
7090
  const hasHash = fileName?.includes?.("[hash");
@@ -7059,7 +7099,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
7059
7099
  if (waitsForInit) pendingSharesEmitId = this.emitFile({
7060
7100
  name: "pendingShares",
7061
7101
  type: "chunk",
7062
- id: getPendingSharesPath(federationOptions),
7102
+ id: getPendingSharesPath(getFederationOptions()),
7063
7103
  preserveSignature: "strict"
7064
7104
  });
7065
7105
  if (htmlFilePath) addHtmlScriptEntries(htmlFilePath);
@@ -7068,7 +7108,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
7068
7108
  if (isBundledDevRemote && _command === "serve") {
7069
7109
  const remoteEntryChunk = Object.values(bundle).find((output) => output.type === "chunk" && output.isEntry && output.facadeModuleId === getEntryPath());
7070
7110
  if (remoteEntryChunk?.type === "chunk") {
7071
- const code = `export { ${remoteEntryChunk.exports.join(", ")} } from ${JSON.stringify(`./${remoteEntryChunk.fileName}`)};\n`;
7111
+ const code = `${Object.values(bundle).some((output) => output.type === "chunk" && output.code.includes("new ViteDevRuntime(")) ? "" : `import ${JSON.stringify(`${viteConfig.base}bundledDevClient.mjs`)};\n`}export { ${remoteEntryChunk.exports.join(", ")} } from ${JSON.stringify(`./${remoteEntryChunk.fileName}`)};\n`;
7072
7112
  bundledDevRemoteEntryCode = Promise.resolve(code);
7073
7113
  resolveBundledDevRemoteEntryCode?.(code);
7074
7114
  }
@@ -7111,7 +7151,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
7111
7151
  let bootstrapIndex = 0;
7112
7152
  for (const fileName of htmlFileNames) {
7113
7153
  let htmlAsset = bundle[fileName];
7114
- if (htmlAsset.type === "chunk") return;
7154
+ if (htmlAsset.type === "chunk") continue;
7115
7155
  let htmlContent = htmlAsset.source.toString() || "";
7116
7156
  const initPath = resolvePath(file, fileName);
7117
7157
  const scriptRegex = /<script\b(?=[^>]*\btype=["']module["'])(?=[^>]*\bsrc=["']([^"']+)["'])[^>]*>\s*<\/script>/gi;
@@ -7161,7 +7201,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
7161
7201
  load(id) {
7162
7202
  return virtualEntryCode.get(id);
7163
7203
  },
7164
- transform(code, id) {
7204
+ transform(code, id, transformOptions) {
7165
7205
  if (skipSvelteKitSsrBuild()) return;
7166
7206
  if (viteConfig?.command === "build" && !waitsForInit) return;
7167
7207
  if (isSvelteKitServerModule(id)) return;
@@ -7173,7 +7213,7 @@ for (const __mfRemoteEntryPrefetchUrl of __mfRemoteEntryPrefetchUrls) {
7173
7213
  if (normalizeModuleId(id).endsWith(".html")) return;
7174
7214
  const projectId = resolveProjectId(id);
7175
7215
  if (skipTransformIds.has(projectId)) return;
7176
- if (!isClientEnvironment(this)) return;
7216
+ if (isServerBuildContext(this, viteConfig) || transformOptions?.ssr) return;
7177
7217
  const isVinext = hasPackageDependency("vinext");
7178
7218
  if (isVinext && inject === "html" && id.includes("virtual:vite-rsc/remove-duplicate-server-css")) {
7179
7219
  const namespaceReactImport = `import * as React from 'react';`;
@@ -7474,21 +7514,6 @@ const vueAdapter = {
7474
7514
  } }
7475
7515
  };
7476
7516
  //#endregion
7477
- //#region src/utils/devServerHost.ts
7478
- const UNSPECIFIED_HOSTS = /* @__PURE__ */ new Set(["0.0.0.0", "::"]);
7479
- /**
7480
- * Hostname for client-facing HTTP/WS origins built from Vite `server.host`.
7481
- *
7482
- * Unspecified bind addresses (`0.0.0.0`, `::`) map to `localhost`, matching
7483
- * Vite's own printed local URL. IPv6 addresses are wrapped in brackets so
7484
- * `http://[::1]:5173` / `ws://[::1]:5173` parse as valid URLs.
7485
- */
7486
- function formatDevServerHostForOrigin(host) {
7487
- if (typeof host !== "string" || UNSPECIFIED_HOSTS.has(host)) return "localhost";
7488
- if (host.startsWith("[") && host.endsWith("]")) return host;
7489
- return isIPv6(host) ? `[${host}]` : host;
7490
- }
7491
- //#endregion
7492
7517
  //#region src/plugins/hmr/fullReload.ts
7493
7518
  const REMOTE_HMR_ENDPOINT = "__mf_hmr";
7494
7519
  const REMOTE_HMR_EVENT = "mf:remote-update";
@@ -7496,7 +7521,7 @@ const REMOTE_HMR_CONNECT_RETRY_DELAY_MS = 1e3;
7496
7521
  const REMOTE_HMR_CONNECT_MAX_RETRIES = 10;
7497
7522
  function getBasePath(base) {
7498
7523
  if (!base) return "/";
7499
- if (base.startsWith("http://") || base.startsWith("https://")) try {
7524
+ if (isHttpUrl(base)) try {
7500
7525
  return new URL(base).pathname || "/";
7501
7526
  } catch {
7502
7527
  return "/";
@@ -7595,14 +7620,8 @@ function setupRemoteBroadcast(server, options) {
7595
7620
  }
7596
7621
  });
7597
7622
  };
7598
- server.watcher.on("change", broadcast);
7599
- server.watcher.on("add", broadcast);
7600
- server.watcher.on("unlink", broadcast);
7601
- server.httpServer?.once("close", () => {
7602
- server.watcher.off("change", broadcast);
7603
- server.watcher.off("add", broadcast);
7604
- server.watcher.off("unlink", broadcast);
7605
- });
7623
+ const stopWatching = watchFileEvents(server.watcher, broadcast);
7624
+ server.httpServer?.once("close", stopWatching);
7606
7625
  }
7607
7626
  /**
7608
7627
  * Installs the host-side full-reload relay. For each configured remote:
@@ -7664,9 +7683,13 @@ function setupHostFullReloadRelay(server, options) {
7664
7683
  if (!message || message.event !== "mf:remote-update") return;
7665
7684
  server.ws.send({ type: "full-reload" });
7666
7685
  };
7667
- ws.onopen = () => clearReconnectTimer(remoteName);
7686
+ let opened = false;
7687
+ ws.onopen = () => {
7688
+ opened = true;
7689
+ clearReconnectTimer(remoteName);
7690
+ };
7668
7691
  ws.onerror = (error) => mfWarn(`Remote HMR socket error for "${remoteName}":`, error);
7669
- ws.onclose = () => scheduleReconnect(remoteName, remote, attempt, "socket closed");
7692
+ ws.onclose = () => scheduleReconnect(remoteName, remote, opened ? 0 : attempt, "socket closed");
7670
7693
  connections.push(ws);
7671
7694
  } catch (error) {
7672
7695
  mfWarn(`Failed to connect remote HMR for "${remoteName}" on attempt ${attempt + 1}: ${getStringPreview(error)}`);
@@ -7687,9 +7710,7 @@ function setupHostFullReloadRelay(server, options) {
7687
7710
  if (shouldIgnoreFile(file, options)) return;
7688
7711
  server.ws.send({ type: "full-reload" });
7689
7712
  };
7690
- server.watcher.on("change", triggerHostReload);
7691
- server.watcher.on("add", triggerHostReload);
7692
- server.watcher.on("unlink", triggerHostReload);
7713
+ watchFileEvents(server.watcher, triggerHostReload);
7693
7714
  server.httpServer?.once("close", teardown);
7694
7715
  }
7695
7716
  //#endregion
@@ -7760,8 +7781,8 @@ function collectHostTags(server, options, adapters) {
7760
7781
  return tags;
7761
7782
  }
7762
7783
  function pluginDevRemoteHmr(options) {
7763
- const isHost = Object.keys(options.remotes).length > 0;
7764
- const isRemote = Object.keys(options.exposes).length > 0;
7784
+ const isHost = hasRemotes(options);
7785
+ const isRemote = isRemoteContainer(options);
7765
7786
  let adapters = [];
7766
7787
  let strategy = "full-reload";
7767
7788
  let root;
@@ -8039,9 +8060,10 @@ function pluginExternalRuntimeCore() {
8039
8060
  //#endregion
8040
8061
  //#region src/virtualModules/index.ts
8041
8062
  function initVirtualModules(command, remoteEntryId, enableSsrInit = false, options) {
8042
- writeLocalSharedImportMap(options);
8043
- writeHostAutoInit(remoteEntryId, command, options);
8044
- writeRuntimeInitStatus(command, enableSsrInit, getHostAutoInitPath(options), options, options ? getSsrRuntimeRemotes(options.remotes, options) : void 0);
8063
+ const resolvedOptions = options ?? getNormalizeModuleFederationOptions();
8064
+ writeLocalSharedImportMap(resolvedOptions);
8065
+ writeHostAutoInit(remoteEntryId, command, resolvedOptions);
8066
+ writeRuntimeInitStatus(command, enableSsrInit, getHostAutoInitPath(resolvedOptions), options, options ? getSsrRuntimeRemotes(options.remotes, options) : void 0);
8045
8067
  }
8046
8068
  //#endregion
8047
8069
  //#region src/utils/cssModuleHelpers.ts
@@ -8290,16 +8312,15 @@ function pluginLazyConsumeOnlyShares(options) {
8290
8312
  renderChunk(code, chunk, _outputOptions, meta) {
8291
8313
  const renderedChunk = chunk;
8292
8314
  const chunks = meta?.chunks;
8293
- if (!chunks || Object.keys(options.exposes).length === 0) return null;
8315
+ if (!chunks || !isRemoteContainer(options)) return null;
8294
8316
  if (isServerBuildContext(this, viteConfig)) return null;
8295
8317
  let graph = graphs.get(chunks);
8296
8318
  if (!graph) {
8297
- const isRolldown = getIsRolldown(this);
8298
8319
  const wrapperShares = /* @__PURE__ */ new Map();
8299
8320
  for (const shareKey of getUsedShares(options)) {
8300
8321
  const shareConfig = getNormalizeShareItem(shareKey, options)?.shareConfig;
8301
8322
  if (shareConfig?.import !== false || shareConfig.eager || shareConfig.treeShaking) continue;
8302
- wrapperShares.set(normalizeVirtualModuleId(getLoadShareModulePath(shareKey, isRolldown, options)), shareKey);
8323
+ wrapperShares.set(normalizeVirtualModuleId(getLoadShareModulePath(shareKey, options)), shareKey);
8303
8324
  }
8304
8325
  const root = viteConfig?.root ?? process.cwd();
8305
8326
  graph = buildLazyShareGraph(chunks, wrapperShares, new Set(Object.values(options.exposes).map((expose) => stripKnownJsExtension(path$1.resolve(root, expose.import)))));
@@ -8319,15 +8340,16 @@ function pluginLazyConsumeOnlyShares(options) {
8319
8340
  break;
8320
8341
  }
8321
8342
  const chunkDir = path$1.posix.dirname(renderedChunk.fileName);
8322
- const codePositions = createCodePositionMap(code);
8343
+ let codePositions;
8323
8344
  let usesHelper = false;
8324
8345
  for (const match of isImportMapChunk ? [] : code.matchAll(DYNAMIC_IMPORT_REGEX)) {
8325
8346
  const [expression, , specifier] = match;
8326
8347
  const start = match.index;
8327
- if (!codePositions[start]) continue;
8328
8348
  const target = path$1.posix.normalize(path$1.posix.join(chunkDir, specifier));
8329
8349
  const shares = graph.sharesByChunk.get(target);
8330
8350
  if (!shares || !renderedChunk.dynamicImports.includes(target)) continue;
8351
+ codePositions ??= createCodePositionMap(code);
8352
+ if (!codePositions[start]) continue;
8331
8353
  rewriter.overwrite(start, start + expression.length, `${helperName}(${JSON.stringify(shares)}).then(() => ${expression})`);
8332
8354
  usesHelper = edited = true;
8333
8355
  }
@@ -8350,7 +8372,7 @@ function ${helperName}(names) {
8350
8372
  }
8351
8373
  //#endregion
8352
8374
  //#region package.json
8353
- var version$1 = "1.23.5";
8375
+ var version$1 = "1.23.7";
8354
8376
  //#endregion
8355
8377
  //#region src/virtualModules/virtualExposesSSR.ts
8356
8378
  /**
@@ -8397,6 +8419,15 @@ const REMOTE_ENTRY_SSR_ID = "virtual:mf-REMOTE_ENTRY_SSR_ID";
8397
8419
  function getRemoteEntrySSRId(options) {
8398
8420
  return `${REMOTE_ENTRY_SSR_ID}:${getVirtualModuleScopeKey(options)}`;
8399
8421
  }
8422
+ const SSR_HOST_INIT_ID = "virtual:mf-ssr-host-init";
8423
+ /**
8424
+ * The SSR entry's import of the host bootstrap. Keyed by config scope, not by federation()
8425
+ * instance: under the Vite builder the entry plugin is shared by every environment, so the
8426
+ * instance building each environment resolves it to its own bootstrap.
8427
+ */
8428
+ function getSsrHostInitId(options) {
8429
+ return `${SSR_HOST_INIT_ID}:${getVirtualModuleScopeKey(options)}`;
8430
+ }
8400
8431
  const FILE_EXTENSION_RE = /\.[^.]+$/;
8401
8432
  function getSsrFileNameParts(browserFilename) {
8402
8433
  const filename = resolveHashPlaceholderFileName(browserFilename);
@@ -8447,7 +8478,7 @@ function generateRemoteEntrySSR(options) {
8447
8478
  const virtualExposesSSRId = getVirtualExposesSSRId(options);
8448
8479
  const sharedSingletons = getSsrSharedSingletons(options);
8449
8480
  return `
8450
- import { init as runtimeInit } from "@module-federation/runtime";
8481
+ ${hasRemotes(options) ? `import { hostInitPromise } from ${JSON.stringify(getSsrHostInitId(options))};` : "import { init as runtimeInit } from \"@module-federation/runtime\";"}
8451
8482
 
8452
8483
  const sharedSingletons = ${JSON.stringify(sharedSingletons)};
8453
8484
  const moduleCacheKey = Symbol.for(${JSON.stringify(MODULE_CACHE_SHARE_SCOPE_KEY)});
@@ -8477,11 +8508,11 @@ function generateRemoteEntrySSR(options) {
8477
8508
  * to set up a minimal runtime instance for the remote container.
8478
8509
  */
8479
8510
  async function init(shared = {}, initScope = []) {
8480
- const initRes = runtimeInit({
8511
+ const initRes = ${hasRemotes(options) ? "await hostInitPromise" : `runtimeInit({
8481
8512
  name: ${JSON.stringify(options.name)},
8482
8513
  remotes: [],
8483
8514
  shared: {},
8484
- });
8515
+ })`};
8485
8516
  if (initScope.indexOf(initToken) >= 0) return;
8486
8517
  initScope.push(initToken);
8487
8518
  const shareScopeNames = Array.isArray(${JSON.stringify(options.shareScope)})
@@ -8626,13 +8657,13 @@ function collectImportedCss(chunks) {
8626
8657
  * dependency even though the expose statically imports it. Advertising it as a sync
8627
8658
  * asset makes a preloader fetch a provider the host is going to supply anyway.
8628
8659
  */
8629
- function collectDeferredShareModules(options, isRolldown) {
8660
+ function collectDeferredShareModules(options) {
8630
8661
  const deferred = /* @__PURE__ */ new Set();
8631
8662
  for (const shareKey of getUsedShares(options)) {
8632
8663
  const shareConfig = getNormalizeShareItem(shareKey, options)?.shareConfig;
8633
8664
  if (shareConfig?.eager === true) continue;
8634
8665
  if (shareConfig?.import === false) continue;
8635
- deferred.add(normalizeVirtualModuleId(getLoadShareModulePath(shareKey, isRolldown, options)));
8666
+ deferred.add(normalizeVirtualModuleId(getLoadShareModulePath(shareKey, options)));
8636
8667
  }
8637
8668
  return deferred;
8638
8669
  }
@@ -8647,9 +8678,9 @@ function isDeferredShareChunk(chunk, deferredShareModules) {
8647
8678
  if (!chunk || chunk.type !== "chunk" || deferredShareModules.size === 0) return false;
8648
8679
  return [chunk.facadeModuleId, ...chunk.moduleIds ?? []].some((id) => typeof id === "string" && deferredShareModules.has(normalizeVirtualModuleId(id)));
8649
8680
  }
8650
- function expandExposeAssets(filesMap, exposeModules, bundle, remoteEntryFileName, options, isRolldown) {
8681
+ function expandExposeAssets(filesMap, exposeModules, bundle, remoteEntryFileName, options) {
8651
8682
  if (exposeModules.length === 0) return;
8652
- const deferredShareModules = collectDeferredShareModules(options, isRolldown);
8683
+ const deferredShareModules = collectDeferredShareModules(options);
8653
8684
  const containerChunks = remoteEntryFileName ? collectStaticChunks(bundle, [remoteEntryFileName]) : [];
8654
8685
  const bootstrapChunks = containerChunks.slice(1);
8655
8686
  const seen = new Set(containerChunks.map((chunk) => chunk.fileName));
@@ -8705,18 +8736,11 @@ function getRemoteContainerName(remoteKey, remote) {
8705
8736
  }
8706
8737
  const Manifest = (providedOptions) => {
8707
8738
  const mfOptions = providedOptions ?? getNormalizeModuleFederationOptions();
8708
- const { name, filename, getPublicPath, manifest: manifestOptions, varFilename } = mfOptions;
8739
+ const { filename, getPublicPath, manifest: manifestOptions } = mfOptions;
8709
8740
  let mfManifestName = manifestOptions === true ? "mf-manifest.json" : typeof manifestOptions === "object" ? normalizePathForImport(path$1.join(manifestOptions?.filePath || "", manifestOptions?.fileName || "mf-manifest.json")) : void 0;
8710
8741
  let mfManifestStatsName = mfManifestName ? getStatsFileName(mfManifestName) : void 0;
8711
- const isConsumerProject = Object.keys(mfOptions.exposes).length === 0;
8742
+ const isConsumerProject = !isRemoteContainer(mfOptions);
8712
8743
  let disableAssetsAnalyze = false;
8713
- const getDefaultDisableAssetsAnalyze = (command) => command === "serve" && isConsumerProject && (typeof manifestOptions !== "object" || !Object.hasOwn(manifestOptions, "disableAssetsAnalyze"));
8714
- const getConfiguredDisableAssetsAnalyze = (command) => {
8715
- if (typeof manifestOptions === "object" && manifestOptions !== null) {
8716
- if (Object.hasOwn(manifestOptions, "disableAssetsAnalyze")) return manifestOptions.disableAssetsAnalyze === true;
8717
- }
8718
- return getDefaultDisableAssetsAnalyze(command);
8719
- };
8720
8744
  let root;
8721
8745
  let remoteEntryFile;
8722
8746
  let ssrRemoteEntryFile;
@@ -8744,7 +8768,7 @@ const Manifest = (providedOptions) => {
8744
8768
  configureServer(server) {
8745
8769
  server.middlewares.use((req, res, next) => {
8746
8770
  const devRemoteEntryFile = resolveHashPlaceholderFileName(filename);
8747
- if (devRemoteEntryFile !== filename && Object.keys(mfOptions.exposes).length > 0 && req.url?.startsWith((viteConfig.base + devRemoteEntryFile).replace(/^\/?/, "/"))) {
8771
+ if (devRemoteEntryFile !== filename && isRemoteContainer(mfOptions) && req.url?.startsWith((viteConfig.base + devRemoteEntryFile).replace(/^\/?/, "/"))) {
8748
8772
  req.url = req.url.replace(devRemoteEntryFile, filename);
8749
8773
  next();
8750
8774
  return;
@@ -8757,39 +8781,7 @@ const Manifest = (providedOptions) => {
8757
8781
  res.setHeader("Content-Type", "application/json");
8758
8782
  res.setHeader("Access-Control-Allow-Origin", "*");
8759
8783
  (async () => {
8760
- const manifest = await applyManifestAdditionalData({
8761
- ...generateMFManifest({}, disableAssetsAnalyze),
8762
- id: name,
8763
- name,
8764
- metaData: {
8765
- name,
8766
- type: "app",
8767
- buildInfo: {
8768
- buildVersion: getBuildVersion(),
8769
- buildName: name,
8770
- ...getTreeShakingBuildInfo(mfOptions)
8771
- },
8772
- remoteEntry: {
8773
- name: devRemoteEntryFile,
8774
- path: "",
8775
- type: "module"
8776
- },
8777
- ssrRemoteEntry: {
8778
- name: getSsrRemoteEntryFileName(mfOptions, devRemoteEntryFile),
8779
- path: "/__mf_ssr__/",
8780
- type: "module"
8781
- },
8782
- varRemoteEntry: varFilename ? {
8783
- name: varFilename,
8784
- path: "",
8785
- type: "var"
8786
- } : void 0,
8787
- types: resolveTypesMeta(mfOptions.dts),
8788
- globalName: name,
8789
- pluginVersion: version$1,
8790
- publicPath
8791
- }
8792
- });
8784
+ const manifest = await applyManifestAdditionalData(generateMFManifest({}, disableAssetsAnalyze));
8793
8785
  res.end(JSON.stringify(manifest));
8794
8786
  })().catch(next);
8795
8787
  } else next();
@@ -8807,7 +8799,7 @@ const Manifest = (providedOptions) => {
8807
8799
  _command = command;
8808
8800
  if (!config.build) config.build = {};
8809
8801
  if (!config.build.manifest) config.build.manifest = config.build.manifest || !!mfManifestName;
8810
- disableAssetsAnalyze = getConfiguredDisableAssetsAnalyze(command);
8802
+ disableAssetsAnalyze = resolveDisableAssetsAnalyze(manifestOptions, command === "serve" && isConsumerProject);
8811
8803
  _originalConfigBase = config.base;
8812
8804
  },
8813
8805
  configResolved(config) {
@@ -8864,7 +8856,7 @@ const Manifest = (providedOptions) => {
8864
8856
  const expectedSsrRemoteEntryFile = getSsrRemoteEntryFileName(mfOptions);
8865
8857
  const foundSsrRemoteEntryFile = Object.values(bundle).find((file) => file.fileName === expectedSsrRemoteEntryFile)?.fileName;
8866
8858
  if (foundRemoteEntryFile) remoteEntryFile = foundRemoteEntryFile;
8867
- ssrRemoteEntryFile = foundSsrRemoteEntryFile || (_command === "serve" ? getSsrRemoteEntryFileName(mfOptions, resolveHashPlaceholderFileName(mfOptions.filename)) : void 0);
8859
+ ssrRemoteEntryFile = foundSsrRemoteEntryFile;
8868
8860
  const allCssAssets = mfOptions.bundleAllCSS && !disableAssetsAnalyze ? collectCssAssets(bundle) : /* @__PURE__ */ new Set();
8869
8861
  if (allCssAssets.size > 0) {
8870
8862
  const secondaryCss = /* @__PURE__ */ new Set();
@@ -8886,7 +8878,7 @@ const Manifest = (providedOptions) => {
8886
8878
  root,
8887
8879
  stripKnownJsExtensions: true
8888
8880
  });
8889
- expandExposeAssets(filesMap, exposesModules, bundle, foundRemoteEntryFile, mfOptions, getIsRolldown(this));
8881
+ expandExposeAssets(filesMap, exposesModules, bundle, foundRemoteEntryFile, mfOptions);
8890
8882
  const fileToShareKey = await buildFileToShareKeyMap(getUsedShares(mfOptions), this.resolve.bind(this), mfOptions);
8891
8883
  processModuleAssets(Object.fromEntries(Object.entries(bundle).filter(([, file]) => !isTreeShakingProviderChunk(file))), filesMap, (modulePath) => fileToShareKey.get(modulePath));
8892
8884
  const deferredSharedAssets = {
@@ -8934,13 +8926,13 @@ const Manifest = (providedOptions) => {
8934
8926
  function generateMFManifest(preloadMap, disableAssetsAnalyze = false) {
8935
8927
  const options = mfOptions;
8936
8928
  const { name, varFilename } = options;
8937
- const resolvedRemoteEntryFile = _command === "serve" ? remoteEntryFile || resolveHashPlaceholderFileName(filename) : remoteEntryFile;
8929
+ const resolvedRemoteEntryFile = _command === "serve" ? resolveHashPlaceholderFileName(filename) : remoteEntryFile;
8938
8930
  const remoteEntry = {
8939
8931
  name: resolvedRemoteEntryFile,
8940
8932
  path: "",
8941
8933
  type: "module"
8942
8934
  };
8943
- const resolvedSsrRemoteEntryFile = _command === "serve" ? ssrRemoteEntryFile || getSsrRemoteEntryFileName(mfOptions, resolveHashPlaceholderFileName(filename)) : ssrRemoteEntryFile;
8935
+ const resolvedSsrRemoteEntryFile = _command === "serve" ? getSsrRemoteEntryFileName(mfOptions, resolvedRemoteEntryFile) : ssrRemoteEntryFile;
8944
8936
  const ssrRemoteEntry = resolvedSsrRemoteEntryFile ? {
8945
8937
  name: resolvedSsrRemoteEntryFile,
8946
8938
  path: _command === "serve" ? "/__mf_ssr__/" : "",
@@ -9239,6 +9231,8 @@ function createModuleParseController() {
9239
9231
  discardWarned: false,
9240
9232
  externalSet: /* @__PURE__ */ new Set(),
9241
9233
  resolutionProbed: /* @__PURE__ */ new Set(),
9234
+ reached: /* @__PURE__ */ new Set(),
9235
+ deferredImports: /* @__PURE__ */ new Map(),
9242
9236
  lastLoadedModule: "",
9243
9237
  lastParsedModule: ""
9244
9238
  };
@@ -9262,6 +9256,8 @@ function resetParseState(controller) {
9262
9256
  controller.parseEndSet = /* @__PURE__ */ new Set();
9263
9257
  controller.externalSet = /* @__PURE__ */ new Set();
9264
9258
  controller.resolutionProbed = /* @__PURE__ */ new Set();
9259
+ controller.reached = /* @__PURE__ */ new Set();
9260
+ controller.deferredImports = /* @__PURE__ */ new Map();
9265
9261
  controller.discardWarned = false;
9266
9262
  controller.lastLoadedModule = "";
9267
9263
  controller.lastParsedModule = "";
@@ -9337,7 +9333,10 @@ function pluginModuleParseEnd_default(excludeFn, options, controller = createMod
9337
9333
  const entryImports = /* @__PURE__ */ new Set([...options.exposedModuleImports || [], ...configuredInputImports]);
9338
9334
  for (const importSource of entryImports) {
9339
9335
  const resolved = await this.resolve(importSource);
9340
- if (resolved && !resolved.external && !excludeFn(resolved.id)) controller.parseStartSet.add(resolved.id);
9336
+ if (resolved && !resolved.external && !excludeFn(resolved.id)) {
9337
+ controller.parseStartSet.add(resolved.id);
9338
+ controller.reached.add(resolved.id);
9339
+ }
9341
9340
  }
9342
9341
  },
9343
9342
  load(id) {
@@ -9358,7 +9357,11 @@ function pluginModuleParseEnd_default(excludeFn, options, controller = createMod
9358
9357
  if (idleTimeout) resetIdleTimeout(controller, idleTimeout);
9359
9358
  const parsedModule = module;
9360
9359
  const addPendingResolutions = (resolutions) => {
9361
- for (const resolution of resolutions || []) if (!resolution.external && !excludeFn(resolution.id)) controller.parseStartSet.add(resolution.id);
9360
+ for (const resolution of resolutions || []) {
9361
+ if (resolution.external) continue;
9362
+ if (excludeFn(resolution.id)) reach(resolution.id);
9363
+ else addPending(resolution.id);
9364
+ }
9362
9365
  };
9363
9366
  const probeExternal = (pendingId) => {
9364
9367
  if (typeof this.resolve !== "function") return;
@@ -9373,15 +9376,39 @@ function pluginModuleParseEnd_default(excludeFn, options, controller = createMod
9373
9376
  };
9374
9377
  const addPendingIds = (ids) => {
9375
9378
  for (const pendingId of ids || []) {
9376
- if (controller.externalSet.has(pendingId) || matchesExternal(configuredExternal, pendingId, id) || excludeFn(pendingId)) continue;
9377
- controller.parseStartSet.add(pendingId);
9379
+ if (controller.externalSet.has(pendingId) || matchesExternal(configuredExternal, pendingId, id)) continue;
9380
+ if (excludeFn(pendingId)) {
9381
+ reach(pendingId);
9382
+ continue;
9383
+ }
9384
+ addPending(pendingId);
9378
9385
  if (!controller.parseEndSet.has(pendingId)) probeExternal(pendingId);
9379
9386
  }
9380
9387
  };
9381
- addPendingResolutions(parsedModule.importedIdResolutions);
9382
- addPendingResolutions(parsedModule.dynamicallyImportedIdResolutions);
9383
- if (parsedModule.importedIdResolutions === void 0) addPendingIds(module.importedIds);
9384
- if (parsedModule.dynamicallyImportedIdResolutions === void 0) addPendingIds(module.dynamicallyImportedIds);
9388
+ const seedImports = (resolutions, ids) => {
9389
+ if (resolutions === void 0) addPendingIds(ids);
9390
+ else addPendingResolutions(resolutions);
9391
+ };
9392
+ const reach = (moduleId) => {
9393
+ if (controller.reached.has(moduleId)) return;
9394
+ controller.reached.add(moduleId);
9395
+ const seedDeferred = controller.deferredImports.get(moduleId);
9396
+ controller.deferredImports.delete(moduleId);
9397
+ seedDeferred?.();
9398
+ };
9399
+ const addPending = (pendingId) => {
9400
+ controller.parseStartSet.add(pendingId);
9401
+ reach(pendingId);
9402
+ };
9403
+ const seedAllImports = () => {
9404
+ seedImports(parsedModule.importedIdResolutions, module.importedIds);
9405
+ seedImports(parsedModule.dynamicallyImportedIdResolutions, module.dynamicallyImportedIds);
9406
+ };
9407
+ if (module.isEntry === false && !controller.reached.has(id)) controller.deferredImports.set(id, seedAllImports);
9408
+ else {
9409
+ controller.reached.add(id);
9410
+ seedAllImports();
9411
+ }
9385
9412
  if (!excludeFn(id)) controller.parseEndSet.add(id);
9386
9413
  scheduleParseCompletionCheck(controller);
9387
9414
  },
@@ -9391,7 +9418,228 @@ function pluginModuleParseEnd_default(excludeFn, options, controller = createMod
9391
9418
  reason: "build-end"
9392
9419
  });
9393
9420
  }
9394
- }];
9421
+ }];
9422
+ }
9423
+ //#endregion
9424
+ //#region src/utils/hostProvidesAllShared.ts
9425
+ /** Virtual-module prefix of the host's per-share re-export entries. */
9426
+ const SHARE_MODULE_PREFIX = "\0mf-host-provided-share:";
9427
+ /** `./a/b` → `a/b`, `.` → `index`: the fixed entry name of an expose, without `.js`. */
9428
+ function exposeEntryName(exposeKey) {
9429
+ return exposeKey === "." ? "index" : exposeKey.replace(/^\.\//, "");
9430
+ }
9431
+ /** Bare specifier a host uses for an expose: `remote` for `.`, `remote/a/b` otherwise. */
9432
+ function remoteSpecifier(remoteName, exposeKey) {
9433
+ const entry = exposeEntryName(exposeKey);
9434
+ return entry === "index" ? remoteName : `${remoteName}/${entry}`;
9435
+ }
9436
+ /** `id` is a remote alias or a subpath of one. */
9437
+ function isRemoteSpecifier(id, remoteKeys) {
9438
+ return remoteKeys.some((key) => id === key || id.startsWith(`${key}/`));
9439
+ }
9440
+ /**
9441
+ * The shared key that owns `id`: an exact match, else the longest key `id` is a subpath
9442
+ * of (`lodash-es/debounce` → `lodash-es`). Used to spot an unshared subpath of a shared
9443
+ * package, which would bundle a private copy of that package into a remote.
9444
+ */
9445
+ function sharedKeyOwning(id, sharedKeys) {
9446
+ let owner;
9447
+ for (const key of sharedKeys) {
9448
+ if (id !== key && !id.startsWith(`${key}/`)) continue;
9449
+ if (!owner || key.length > owner.length) owner = key;
9450
+ }
9451
+ return owner;
9452
+ }
9453
+ /** Chunk name of the host's re-export entry for a shared key. */
9454
+ function shareChunkName(key) {
9455
+ return `shared/${key.replace(/^@/, "").replace(/[^\w-]+/g, "-")}`;
9456
+ }
9457
+ /** Reads a remote's `mf-manifest.json` from a URL or a path relative to `root`. */
9458
+ async function readHostProvidesAllSharedManifest(location, root) {
9459
+ let source;
9460
+ if (isAbsoluteUrl(location)) {
9461
+ const response = await fetch(location);
9462
+ if (!response.ok) throw new Error(`Failed to fetch ${location}: ${response.status} ${response.statusText}`);
9463
+ source = await response.text();
9464
+ } else source = await readFile(path$1.resolve(root, location), "utf8");
9465
+ const manifest = JSON.parse(source);
9466
+ if (!manifest.metaData || !Array.isArray(manifest.exposes)) throw new Error(`${location} is not a Module Federation manifest.`);
9467
+ if (manifest.metaData.remoteEntry) throw new Error(`${location} describes a Module Federation runtime remote (it has a remoteEntry). Build the remote with \`experiments: { hostProvidesAllShared: true }\`.`);
9468
+ return manifest;
9469
+ }
9470
+ /** URL prefix of a remote's files: `metaData.publicPath`, `auto` inferred from the manifest URL. */
9471
+ function remotePublicPath(manifest, location) {
9472
+ const publicPath = manifest.metaData.publicPath ?? "auto";
9473
+ if (publicPath !== "auto") return ensureTrailingSlash(publicPath);
9474
+ if (!isAbsoluteUrl(location)) throw new Error(`${location}: publicPath is "auto", which can only be inferred from a manifest URL. Reference the manifest by URL or set \`base\` / \`publicPath\` in the remote build.`);
9475
+ return ensureTrailingSlash(inferAutoPublicPath(location));
9476
+ }
9477
+ /** Import-map entries (`remote/Expose` → URL) for every expose of every remote. */
9478
+ async function collectRemoteImports(remotes, root) {
9479
+ const imports = {};
9480
+ for (const [alias, remote] of Object.entries(remotes)) {
9481
+ const manifest = await readHostProvidesAllSharedManifest(remote.entry, root);
9482
+ const publicPath = remotePublicPath(manifest, remote.entry);
9483
+ for (const expose of manifest.exposes) {
9484
+ const file = expose.assets.js.sync[0];
9485
+ if (!expose.path || !file) continue;
9486
+ imports[remoteSpecifier(alias, expose.path)] = isAbsoluteUrl(remote.entry) ? new URL(file, new URL(publicPath, remote.entry)).href : publicPath + file;
9487
+ }
9488
+ }
9489
+ return imports;
9490
+ }
9491
+ /** Top-level options that only the Module Federation runtime or `remoteEntry.js` pipeline reads. */
9492
+ const IGNORED_OPTIONS = [
9493
+ "filename",
9494
+ "ssrFilename",
9495
+ "varFilename",
9496
+ "library",
9497
+ "runtime",
9498
+ "shareScope",
9499
+ "shareStrategy",
9500
+ "runtimePlugins",
9501
+ "implementation",
9502
+ "getPublicPath",
9503
+ "ignoreOrigin",
9504
+ "virtualModuleDir",
9505
+ "hostInitInjectLocation",
9506
+ "bundleAllCSS",
9507
+ "treeShakingDir",
9508
+ "injectTreeShakingUsedExports",
9509
+ "treeShakingSharedPlugins",
9510
+ "treeShakingSharedExcludePlugins",
9511
+ "moduleParseTimeout",
9512
+ "moduleParseIdleTimeout",
9513
+ "target",
9514
+ "ssrExternals",
9515
+ "ssrEntryLoader",
9516
+ "disableRemote",
9517
+ "disableShared",
9518
+ "disableSnapshot"
9519
+ ];
9520
+ const IGNORED_EXPERIMENTS = [
9521
+ "externalRuntime",
9522
+ "provideExternalRuntime",
9523
+ "ssrMode"
9524
+ ];
9525
+ /** Per-share options: version negotiation, aliasing and fallbacks do not exist in this mode. */
9526
+ const IGNORED_SHARE_OPTIONS = [
9527
+ "eager",
9528
+ "requiredVersion",
9529
+ "strictVersion",
9530
+ "import",
9531
+ "request",
9532
+ "shareKey",
9533
+ "name",
9534
+ "version",
9535
+ "shareScope",
9536
+ "treeShaking",
9537
+ "allowNodeModulesSuffixMatch",
9538
+ "suppressMissingImportWarning"
9539
+ ];
9540
+ const isSet = (value) => value !== void 0 && value !== false && !(Array.isArray(value) && value.length === 0);
9541
+ /** A single warning naming every option the user set that import-map mode ignores. */
9542
+ function getIgnoredOptionWarning(options) {
9543
+ const shared = options.shared;
9544
+ const ignored = [
9545
+ ...IGNORED_OPTIONS.filter((key) => isSet(options[key])).map((key) => `\`${key}\``),
9546
+ ...IGNORED_EXPERIMENTS.filter((key) => isSet(options.experiments?.[key])).map((key) => `\`experiments.${key}\``),
9547
+ ...shared && !Array.isArray(shared) ? Object.entries(shared).flatMap(([key, config]) => typeof config === "object" && config !== null ? IGNORED_SHARE_OPTIONS.filter((option) => option === "import" ? config.import !== void 0 : isSet(config[option])).map((option) => `\`shared.${key}.${option}\``) : []) : []
9548
+ ];
9549
+ if (ignored.length === 0) return void 0;
9550
+ return `experiments.hostProvidesAllShared: ${ignored.join(", ")} ignored. The Module Federation runtime is not used and the host provides the only copy of every shared key.`;
9551
+ }
9552
+ //#endregion
9553
+ //#region src/utils/remoteDependencies.ts
9554
+ function collectImportSources(code) {
9555
+ const sources = /* @__PURE__ */ new Map();
9556
+ for (const { source, kind, syntax, typeOnly } of findModuleImportDescriptors(code)) {
9557
+ if (syntax !== "import" || typeOnly) continue;
9558
+ const dynamic = kind === "dynamic";
9559
+ sources.set(source, (sources.get(source) ?? true) && dynamic);
9560
+ }
9561
+ return Array.from(sources, ([source, dynamic]) => ({
9562
+ source,
9563
+ dynamic
9564
+ })).sort((a, b) => a.source.localeCompare(b.source));
9565
+ }
9566
+ function shouldScanResolvedImport(id) {
9567
+ if (!id || id.includes("\0")) return false;
9568
+ if (isNodeModulePath(id)) return false;
9569
+ return /\.(?:[cm]?[jt]sx?|vue|svelte)(?:\?|$)/.test(id);
9570
+ }
9571
+ const TS_MODULE_RE = /\.[cm]?tsx?$/;
9572
+ /**
9573
+ * The module as Vite's TypeScript transform leaves it. A value-style import used only as a type
9574
+ * (`import { Props } from 'remote/Widget'`) is dropped there, so it loads nothing at runtime.
9575
+ * `transformWithOxc` is Vite 8+; `transformWithEsbuild` needs esbuild, which Vite 8 no longer ships.
9576
+ */
9577
+ async function withoutTypeOnlyImports(id, code) {
9578
+ if (!TS_MODULE_RE.test(id)) return code;
9579
+ const { transformWithOxc } = vite;
9580
+ try {
9581
+ return (transformWithOxc ? await transformWithOxc(code, id, { jsx: "preserve" }) : await vite.transformWithEsbuild(code, id, { jsx: "preserve" })).code;
9582
+ } catch {
9583
+ return code;
9584
+ }
9585
+ }
9586
+ async function readModuleEdges(ctx, id, isRemoteImport) {
9587
+ let code;
9588
+ try {
9589
+ code = getScannableModuleSource(id, readFileSync$1(id, "utf8"));
9590
+ } catch {
9591
+ return {
9592
+ remotes: [],
9593
+ staticImports: [],
9594
+ dynamicImports: []
9595
+ };
9596
+ }
9597
+ let sources = collectImportSources(code);
9598
+ if (sources.some(({ source }) => isRemoteImport(source))) sources = collectImportSources(await withoutTypeOnlyImports(id, code));
9599
+ const edges = {
9600
+ remotes: [],
9601
+ staticImports: [],
9602
+ dynamicImports: []
9603
+ };
9604
+ for (const { source, dynamic } of sources) {
9605
+ if (isRemoteImport(source)) {
9606
+ if (!dynamic) edges.remotes.push(source);
9607
+ continue;
9608
+ }
9609
+ let resolved;
9610
+ try {
9611
+ resolved = await ctx.resolve(source, id);
9612
+ } catch {
9613
+ continue;
9614
+ }
9615
+ if (resolved?.id && shouldScanResolvedImport(resolved.id)) (dynamic ? edges.dynamicImports : edges.staticImports).push(resolved.id);
9616
+ }
9617
+ return edges;
9618
+ }
9619
+ /**
9620
+ * Static remote imports in the module graph rooted at `id`: the remotes whose
9621
+ * bindings must be ready before the graph is used. `followDynamicImports: false`
9622
+ * stops at local `import()` boundaries, which wait for their own remotes.
9623
+ */
9624
+ async function collectRemoteDependencies(ctx, id, isRemoteImport, { followDynamicImports = true, cache = /* @__PURE__ */ new Map() } = {}) {
9625
+ const dependencies = /* @__PURE__ */ new Set();
9626
+ const seen = /* @__PURE__ */ new Set();
9627
+ const pending = [id];
9628
+ while (pending.length) {
9629
+ const current = pending.pop();
9630
+ if (seen.has(current) || !shouldScanResolvedImport(current)) continue;
9631
+ seen.add(current);
9632
+ let edges = cache.get(current);
9633
+ if (!edges) {
9634
+ edges = readModuleEdges(ctx, current, isRemoteImport);
9635
+ cache.set(current, edges);
9636
+ }
9637
+ const { remotes, staticImports, dynamicImports } = await edges;
9638
+ for (const remote of remotes) dependencies.add(remote);
9639
+ pending.push(...staticImports);
9640
+ if (followDynamicImports) pending.push(...dynamicImports);
9641
+ }
9642
+ return Array.from(dependencies).sort();
9395
9643
  }
9396
9644
  //#endregion
9397
9645
  //#region src/plugins/pluginProxyRemoteEntry.ts
@@ -9407,67 +9655,39 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
9407
9655
  let refreshPromise;
9408
9656
  let dependencyInvalidationVersion = 0;
9409
9657
  let reactIslandExposes = /* @__PURE__ */ new Set();
9658
+ let isTanStackStart = false;
9410
9659
  const isHostAutoInitId = (id) => {
9411
- const cleanId = id.split("?")[0];
9412
- return cleanId.includes(getHostAutoInitPath(options)) || cleanId.includes(getHostAutoInitPath());
9660
+ return id.split("?")[0].includes(getHostAutoInitPath(options));
9413
9661
  };
9414
9662
  const getEnvironmentConditions = (context) => context.environment?.config?.resolve?.conditions;
9415
9663
  const isSsrBuild = (context) => isServerBuildContext(context, viteConfig);
9664
+ const loadRemoteEntryCode = (context) => getParsePromise().then((_) => generateRemoteEntry(options, virtualExposesId, _command, getEnvironmentConditions(context), isSsrBuild(context)));
9665
+ const loadExposesCode = async (context) => {
9666
+ await refreshExposeRemoteDependencies(context);
9667
+ return generateExposes(options, exposeRemoteDependencies, _command, reactIslandExposes);
9668
+ };
9416
9669
  function isRemoteImport(source) {
9417
- return Object.keys(options.remotes).some((name) => source === name || source.startsWith(name + "/"));
9418
- }
9419
- function collectImportSources(code) {
9420
- const sources = /* @__PURE__ */ new Map();
9421
- for (const { source, kind, syntax, typeOnly } of findModuleImportDescriptors(code)) {
9422
- if (syntax !== "import" || typeOnly) continue;
9423
- const dynamic = kind === "dynamic";
9424
- sources.set(source, (sources.get(source) ?? true) && dynamic);
9425
- }
9426
- return Array.from(sources, ([source, dynamic]) => ({
9427
- source,
9428
- dynamic
9429
- })).sort((a, b) => a.source.localeCompare(b.source));
9430
- }
9431
- function shouldScanResolvedImport(id) {
9432
- if (!id || id.includes("\0")) return false;
9433
- if (id.includes("/node_modules/") || id.includes("\\node_modules\\")) return false;
9434
- return /\.(?:[cm]?[jt]sx?|vue|svelte)(?:\?|$)/.test(id);
9435
- }
9436
- async function collectRemoteDependencies(ctx, id, seen = /* @__PURE__ */ new Set()) {
9437
- if (seen.has(id) || !shouldScanResolvedImport(id)) return [];
9438
- seen.add(id);
9439
- let code;
9440
- try {
9441
- code = getScannableModuleSource(id, readFileSync$1(id, "utf8"));
9442
- } catch {
9443
- return [];
9444
- }
9445
- const dependencies = /* @__PURE__ */ new Set();
9446
- for (const { source, dynamic } of collectImportSources(code)) {
9447
- if (isRemoteImport(source)) {
9448
- if (!dynamic) dependencies.add(source);
9449
- continue;
9450
- }
9451
- let resolved;
9452
- try {
9453
- resolved = await ctx.resolve(source, id);
9454
- } catch {
9455
- continue;
9456
- }
9457
- if (!resolved?.id || !shouldScanResolvedImport(resolved.id)) continue;
9458
- for (const dependency of await collectRemoteDependencies(ctx, resolved.id, seen)) dependencies.add(dependency);
9459
- }
9460
- return Array.from(dependencies).sort();
9670
+ return isRemoteSpecifier(source, Object.keys(options.remotes));
9461
9671
  }
9462
9672
  async function refreshExposeRemoteDependencies(ctx) {
9463
9673
  if (!exposeRemoteDependenciesDirty) return;
9674
+ if (!hasRemotes(options)) {
9675
+ exposeRemoteDependencies = {};
9676
+ exposeRemoteDependenciesDirty = false;
9677
+ return;
9678
+ }
9464
9679
  if (!refreshPromise) {
9465
9680
  const refreshVersion = dependencyInvalidationVersion;
9466
9681
  refreshPromise = (async () => {
9467
9682
  const next = {};
9683
+ const cache = /* @__PURE__ */ new Map();
9684
+ const followDynamicImports = options.shareStrategy !== "loaded-first";
9468
9685
  for (const [exposeKey, expose] of Object.entries(options.exposes)) {
9469
9686
  const resolved = await ctx.resolve(expose.import);
9470
- next[exposeKey] = resolved?.id ? await collectRemoteDependencies(ctx, resolved.id) : [];
9687
+ next[exposeKey] = resolved?.id ? await collectRemoteDependencies(ctx, resolved.id, isRemoteImport, {
9688
+ followDynamicImports,
9689
+ cache
9690
+ }) : [];
9471
9691
  }
9472
9692
  exposeRemoteDependencies = next;
9473
9693
  if (refreshVersion === dependencyInvalidationVersion) exposeRemoteDependenciesDirty = false;
@@ -9487,6 +9707,7 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
9487
9707
  configResolved(config) {
9488
9708
  viteConfig = config;
9489
9709
  root = config.root;
9710
+ isTanStackStart = config.plugins?.some((plugin) => plugin.name === "tanstack-start-core:config") ?? false;
9490
9711
  reactIslandExposes = getReactIslandExposes(options, root);
9491
9712
  },
9492
9713
  config(config, { command }) {
@@ -9495,7 +9716,7 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
9495
9716
  },
9496
9717
  async buildStart() {
9497
9718
  await refreshExposeRemoteDependencies(this);
9498
- if (_command !== "build" || hasPackageDependency("@tanstack/react-start", root)) return;
9719
+ if (_command !== "build" || isTanStackStart) return;
9499
9720
  for (const expose of Object.values(options.exposes)) {
9500
9721
  const resolved = await this.resolve(expose.import);
9501
9722
  if (resolved) this.emitFile({
@@ -9521,21 +9742,15 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
9521
9742
  }
9522
9743
  },
9523
9744
  async load(id) {
9524
- if (id === remoteEntryId) return getParsePromise().then((_) => generateRemoteEntry(options, virtualExposesId, _command, getEnvironmentConditions(this), isSsrBuild(this)));
9525
- if (id === virtualExposesId) {
9526
- await refreshExposeRemoteDependencies(this);
9527
- return generateExposes(options, exposeRemoteDependencies, _command, reactIslandExposes);
9528
- }
9745
+ if (id === remoteEntryId) return loadRemoteEntryCode(this);
9746
+ if (id === virtualExposesId) return loadExposesCode(this);
9529
9747
  if (_command === "serve" && isHostAutoInitId(id)) return id;
9530
9748
  },
9531
9749
  async transform(code, id) {
9532
9750
  return mapCodeToCodeWithSourcemap(await (async () => {
9533
9751
  if (!filterId(id)) return;
9534
- if (id.includes(remoteEntryId)) return getParsePromise().then((_) => generateRemoteEntry(options, virtualExposesId, _command, getEnvironmentConditions(this), isSsrBuild(this)));
9535
- if (id === virtualExposesId) {
9536
- await refreshExposeRemoteDependencies(this);
9537
- return generateExposes(options, exposeRemoteDependencies, _command, reactIslandExposes);
9538
- }
9752
+ if (id.includes(remoteEntryId)) return loadRemoteEntryCode(this);
9753
+ if (id === virtualExposesId) return loadExposesCode(this);
9539
9754
  if (isHostAutoInitId(id)) {
9540
9755
  if (_command === "serve") {
9541
9756
  const host = formatDevServerHostForOrigin(viteConfig.server?.host);
@@ -9649,7 +9864,7 @@ function pluginProxyRemotes_default(options) {
9649
9864
  },
9650
9865
  configResolved(config) {
9651
9866
  hasMultiEnvironment = Boolean(config.environments?.ssr);
9652
- enableSsrInit = getSsrCapabilities(parseInt(version, 10), command, Object.keys(remotes).length > 0, isSsrConfig(config)).enableSsrInitBootstrap;
9867
+ enableSsrInit = getSsrCapabilities(parseInt(version, 10), command, hasRemotes(options), isSsrConfig(config)).enableSsrInitBootstrap;
9653
9868
  },
9654
9869
  resolveId(source, importer) {
9655
9870
  const resolvedIslandConsumerId = resolveReactIslandConsumerId(source);
@@ -9782,6 +9997,20 @@ function getSharedPackageFromFile(importer, shared, cwd = getPackageDetectionCwd
9782
9997
  const normalizedImporter = normalizePathForImport(importer);
9783
9998
  return [...cached.entries].find(([dir]) => normalizedImporter === dir || normalizedImporter.startsWith(`${dir}/`))?.[1] ?? getWorkspacePackageNameFromFile(normalizedImporter);
9784
9999
  }
10000
+ /**
10001
+ * Whether an import of its own package from `importer` keeps an ordinary module edge. Internal
10002
+ * files and files of shared subpaths do; a file published only under an unshared subpath (e.g.
10003
+ * `vue/sub` when only `vue` is shared) imports the shared root like any consumer.
10004
+ */
10005
+ function keepsOwnPackageEdge(importer, shared, cwd = getPackageDetectionCwd()) {
10006
+ const nodeModulePackage = importer && getPackageNameFromNodeModulePath(importer);
10007
+ if (!nodeModulePackage) return true;
10008
+ if (getInstalledPackageJson(nodeModulePackage, { cwd })?.packageJson.exports == null) return true;
10009
+ const packageSubpath = getNodeModulesSuffix(importer)?.slice(nodeModulePackage.length + 1);
10010
+ if (!packageSubpath) return true;
10011
+ const specifiers = getPackageExportSpecifiersForFile(nodeModulePackage, packageSubpath, { cwd });
10012
+ return specifiers.length === 0 || specifiers.some((specifier) => findSharedKey(specifier, shared));
10013
+ }
9785
10014
  const workspacePackageNameCache = /* @__PURE__ */ new Map();
9786
10015
  /** Name from the nearest `package.json` above `file`, for files outside `node_modules`. */
9787
10016
  function getWorkspacePackageNameFromFile(file) {
@@ -10076,7 +10305,6 @@ function proxySharedModule(options) {
10076
10305
  const getBuildImportAnalysis = (environment) => getImportAnalysis(environment ?? _config ?? options);
10077
10306
  let _command = "serve";
10078
10307
  let useDirectReactImport = false;
10079
- let useRolldown = false;
10080
10308
  let isProduction = false;
10081
10309
  let rootResolveConditions;
10082
10310
  let ssrResolveConditions;
@@ -10105,7 +10333,7 @@ function proxySharedModule(options) {
10105
10333
  root: _config?.root || getPackageDetectionCwd(),
10106
10334
  conditions: getRuntimeDependencyConditions(context, resolveOptions)
10107
10335
  }));
10108
- const refreshTreeShakingForEnvironment = (context) => refreshTreeShakingModules(federationOptions, _command, getIsRolldown(context), getEnvironmentConditions(context));
10336
+ const refreshTreeShakingForEnvironment = (context) => refreshTreeShakingModules(federationOptions, _command, getEnvironmentConditions(context));
10109
10337
  const normalizeTreeShakingOutputPath = (value) => {
10110
10338
  const normalized = normalizePathForImport(value);
10111
10339
  if (path$1.posix.isAbsolute(normalized) || /^[A-Za-z]:\//.test(normalized) || normalized.split("/").includes("..")) throw new Error(`Invalid treeShakingDir "${value}": absolute paths and parent segments are not allowed.`);
@@ -10117,8 +10345,7 @@ function proxySharedModule(options) {
10117
10345
  };
10118
10346
  const getTreeShakingProviderFileName = (pkg, shareItem) => {
10119
10347
  if (!shareItem.shareConfig.treeShaking) return void 0;
10120
- const normalizedOptions = federationOptions ?? getNormalizeModuleFederationOptions();
10121
- const outputDir = normalizedOptions.treeShakingDir ? normalizeTreeShakingOutputPath(normalizedOptions.treeShakingDir) : void 0;
10348
+ const outputDir = federationOptions.treeShakingDir ? normalizeTreeShakingOutputPath(federationOptions.treeShakingDir) : void 0;
10122
10349
  const fileName = outputDir ? path$1.posix.join(outputDir, `${getTreeShakingSharedProviderName(pkg, federationOptions)}.js`) : void 0;
10123
10350
  if (!fileName) return void 0;
10124
10351
  return fileName;
@@ -10182,9 +10409,7 @@ function proxySharedModule(options) {
10182
10409
  workspacePackageNameCache.clear();
10183
10410
  const isVinext = hasPackageDependency("vinext");
10184
10411
  const isAstro = hasPackageDependency("astro");
10185
- const isRolldown = getIsRolldown(this);
10186
10412
  _command = command;
10187
- useRolldown = isRolldown;
10188
10413
  useDirectReactImport = isVinext || isAstro;
10189
10414
  if (command === "serve") excludeSharedSubDependencies(shared);
10190
10415
  },
@@ -10194,9 +10419,7 @@ function proxySharedModule(options) {
10194
10419
  rootResolveConditions = config.resolve?.conditions ? [...config.resolve.conditions] : void 0;
10195
10420
  ssrResolveConditions = config.ssr?.resolve?.conditions ? [...config.ssr.resolve.conditions] : void 0;
10196
10421
  ssrTarget = config.ssr?.target ?? "node";
10197
- const isRolldown = getIsRolldown(this);
10198
- const resolvedOptions = federationOptions ?? getNormalizeModuleFederationOptions();
10199
- const registerConfiguredShare = _command === "build" && Object.keys(resolvedOptions.exposes).length > 0 ? addUsedShares : addConfiguredShare;
10422
+ const registerConfiguredShare = _command === "build" && isRemoteContainer(federationOptions) ? addUsedShares : addConfiguredShare;
10200
10423
  Object.keys(shared).forEach((key) => {
10201
10424
  if (key.endsWith("/") || getSharedRequest(key, shared[key]).endsWith("/")) return;
10202
10425
  const runtimeKey = getSharedRuntimeKey(key, shared[key]);
@@ -10204,7 +10427,7 @@ function proxySharedModule(options) {
10204
10427
  registerConfiguredShare(runtimeKey, federationOptions);
10205
10428
  return;
10206
10429
  }
10207
- writeLoadShareModule(runtimeKey, shared[key], _command, isRolldown, federationOptions);
10430
+ writeLoadShareModule(runtimeKey, shared[key], _command, federationOptions);
10208
10431
  if (shared[key].shareConfig.import !== false) writePreBuildLibPath(runtimeKey, shared[key], federationOptions);
10209
10432
  registerConfiguredShare(runtimeKey, federationOptions);
10210
10433
  });
@@ -10291,7 +10514,7 @@ function proxySharedModule(options) {
10291
10514
  return taggedModule.name === sharedKey || matchesSharedSource(sharedSource, taggedModule.name);
10292
10515
  };
10293
10516
  const importerPackage = getSharedPackageFromFile(importer, shared);
10294
- if (importerPackage === getPackageName(key)) return;
10517
+ if (importerPackage === getPackageName(key) && keepsOwnPackageEdge(importer, shared)) return;
10295
10518
  if (importerPackage && shared[key].shareConfig.import !== false) {
10296
10519
  const importerIsUnsharedWorkspacePackage = !isNodeModulePath(importer) && !Object.keys(shared).some((sharedKey) => getPackageName(sharedKey) === importerPackage);
10297
10520
  const request = getSharedRequest(key, shared[key]);
@@ -10311,10 +10534,10 @@ function proxySharedModule(options) {
10311
10534
  const localSource = getPrebuildResolutionSource(shareSource, shared[key]);
10312
10535
  return tryResolveFromProjectRoot(localSource) || localSource;
10313
10536
  }
10314
- const loadSharePath = getLoadShareModulePath(shareSource, useRolldown, federationOptions);
10537
+ const loadSharePath = getLoadShareModulePath(shareSource, federationOptions);
10315
10538
  if (!materializedLoadShareSources.has(shareSource)) {
10316
10539
  materializedLoadShareSources.add(shareSource);
10317
- writeLoadShareModule(shareSource, shared[key], _command, useRolldown, federationOptions);
10540
+ writeLoadShareModule(shareSource, shared[key], _command, federationOptions);
10318
10541
  if (shared[key].shareConfig.import !== false) writePreBuildLibPath(shareSource, shared[key], federationOptions);
10319
10542
  addUsedShares(shareSource, federationOptions);
10320
10543
  writeLocalSharedImportMap(federationOptions);
@@ -10447,6 +10670,13 @@ function applyRewrites(code, imports, id) {
10447
10670
  ms.overwrite(imp.start, imp.end, wrapDynamicImport(imp.originalText));
10448
10671
  changed = true;
10449
10672
  break;
10673
+ case "local-dynamic": {
10674
+ if (imp.remotes.length === 0) break;
10675
+ const ready = imp.remotes.map((remote) => `import(${JSON.stringify(remote)}).then(function(__mf_m__) { return __mf_m__.__mf_remote_pending; })`);
10676
+ ms.overwrite(imp.start, imp.end, `Promise.all([${imp.originalText}, ${ready.join(", ")}]).then(function(__mf_r__) { return __mf_r__[0]; })`);
10677
+ changed = true;
10678
+ break;
10679
+ }
10450
10680
  }
10451
10681
  if (!changed) return;
10452
10682
  if (dependencyPendingIds.length > 0) ms.overwrite(code.length, code.length, `\nexport const __mf_remote_dependency_pending = Promise.all([${dependencyPendingIds.join(", ")}]);`);
@@ -10455,7 +10685,7 @@ function applyRewrites(code, imports, id) {
10455
10685
  map: ms.generateMap(id)
10456
10686
  };
10457
10687
  }
10458
- async function collectFromAST(ast, code, isRemoteImport) {
10688
+ async function collectFromAST(ast, code, isRemoteImport, collectLocalDynamic) {
10459
10689
  const result = [];
10460
10690
  walkAST(ast, { enter(node) {
10461
10691
  if (node.type === "ImportDeclaration" && node.source?.value) {
@@ -10505,19 +10735,28 @@ async function collectFromAST(ast, code, isRemoteImport) {
10505
10735
  const source = node.source;
10506
10736
  if (source.type !== "Literal" && source.type !== "StringLiteral" && source.type !== "TemplateLiteral") return;
10507
10737
  const value = source.type === "TemplateLiteral" ? source.quasis?.length === 1 ? source.quasis[0].value?.cooked : void 0 : source.value;
10508
- if (!value || !isRemoteImport(value)) return;
10509
- result.push({
10738
+ if (!value) return;
10739
+ const originalText = code.slice(node.start, node.end);
10740
+ if (isRemoteImport(value)) result.push({
10510
10741
  kind: "dynamic",
10511
10742
  source: value,
10512
10743
  start: node.start,
10513
10744
  end: node.end,
10514
- originalText: code.slice(node.start, node.end)
10745
+ originalText
10746
+ });
10747
+ else if (collectLocalDynamic) result.push({
10748
+ kind: "local-dynamic",
10749
+ source: value,
10750
+ start: node.start,
10751
+ end: node.end,
10752
+ originalText,
10753
+ remotes: []
10515
10754
  });
10516
10755
  }
10517
10756
  } });
10518
10757
  return result;
10519
10758
  }
10520
- function collectFromRegex(code, isRemoteImport) {
10759
+ function collectFromRegex(code, isRemoteImport, collectLocalDynamic) {
10521
10760
  const result = [];
10522
10761
  const codePositions = createCodePositionMap(code);
10523
10762
  const importAttributes = String.raw`(?:\s+(?:with|assert)\s+\{[^;]*\})?`;
@@ -10584,26 +10823,35 @@ function collectFromRegex(code, isRemoteImport) {
10584
10823
  for (const match of code.matchAll(/import\(\s*(?:\/\*[\s\S]*?\*\/\s*)?(['"])([^'"]+)\1\s*\)/g)) {
10585
10824
  const [full, , source] = match;
10586
10825
  if (!codePositions[match.index]) continue;
10587
- if (!isRemoteImport(source)) continue;
10588
- result.push({
10589
- kind: "dynamic",
10826
+ const position = {
10590
10827
  source,
10591
10828
  start: match.index,
10592
- end: match.index + full.length,
10829
+ end: match.index + full.length
10830
+ };
10831
+ if (isRemoteImport(source)) result.push({
10832
+ kind: "dynamic",
10833
+ ...position,
10593
10834
  originalText: full
10594
10835
  });
10836
+ else if (collectLocalDynamic) result.push({
10837
+ kind: "local-dynamic",
10838
+ ...position,
10839
+ originalText: full,
10840
+ remotes: []
10841
+ });
10595
10842
  }
10596
10843
  return result.length > 0 ? result : void 0;
10597
10844
  }
10598
10845
  function pluginRemoteNamedExports(options) {
10599
10846
  const remoteNames = Object.keys(options.remotes);
10847
+ const waitsAtDynamicImports = options.shareStrategy === "loaded-first";
10848
+ let remoteDependencyCache = /* @__PURE__ */ new Map();
10600
10849
  let root = process.cwd();
10601
- const isNodeModulesId = (id) => id.includes("/node_modules/") || id.includes("\\node_modules\\");
10602
10850
  function isRemoteImport(source, importerId) {
10603
10851
  return remoteNames.some((name) => {
10604
10852
  if (source.startsWith(name + "/")) return true;
10605
10853
  if (source !== name) return false;
10606
- return !isNodeModulesId(importerId) || !getInstalledPackageEntry(source, { cwd: root });
10854
+ return !isNodeModulePath(importerId) || !getInstalledPackageEntry(source, { cwd: root });
10607
10855
  }) || source.includes("__loadRemote__");
10608
10856
  }
10609
10857
  return {
@@ -10612,11 +10860,15 @@ function pluginRemoteNamedExports(options) {
10612
10860
  configResolved(config) {
10613
10861
  root = config.root || process.cwd();
10614
10862
  },
10863
+ watchChange() {
10864
+ remoteDependencyCache = /* @__PURE__ */ new Map();
10865
+ },
10615
10866
  async transform(code, id) {
10616
10867
  if (remoteNames.length === 0) return;
10617
10868
  if (id.includes("__loadRemote__") || id.includes("__loadShare__")) return;
10618
10869
  if (!JS_EXTENSIONS_RE.test(id)) return;
10619
- if (!remoteNames.some((name) => code.includes(name))) return;
10870
+ const collectLocalDynamic = waitsAtDynamicImports && !isNodeModulePath(id) && /\bimport\s*\(/.test(code);
10871
+ if (!collectLocalDynamic && !remoteNames.some((name) => code.includes(name))) return;
10620
10872
  const descriptors = findModuleImportDescriptors(code);
10621
10873
  const resolvedElsewhere = /* @__PURE__ */ new Set();
10622
10874
  for (const source of new Set(descriptors.map((d) => d.source))) {
@@ -10628,12 +10880,26 @@ function pluginRemoteNamedExports(options) {
10628
10880
  for (const { kind, source, typeOnly } of descriptors) if (kind === "static" && !typeOnly && matchesRemoteImport(source)) markStaticRemote(source, options);
10629
10881
  let imports;
10630
10882
  try {
10631
- imports = await collectFromAST(this.parse(code), code, matchesRemoteImport);
10883
+ imports = await collectFromAST(this.parse(code), code, matchesRemoteImport, collectLocalDynamic);
10632
10884
  } catch {
10633
10885
  if ((id.includes(".vue") || id.includes(".svelte")) && /^\s*</.test(code)) return;
10634
- imports = collectFromRegex(code, matchesRemoteImport);
10886
+ imports = collectFromRegex(code, matchesRemoteImport, collectLocalDynamic);
10635
10887
  }
10636
10888
  if (!imports) return;
10889
+ for (const localImport of imports) {
10890
+ if (localImport.kind !== "local-dynamic") continue;
10891
+ let resolved;
10892
+ try {
10893
+ resolved = await this.resolve(localImport.source, id);
10894
+ } catch {
10895
+ continue;
10896
+ }
10897
+ if (!resolved?.id) continue;
10898
+ localImport.remotes = await collectRemoteDependencies(this, resolved.id, (source) => isRemoteSpecifier(source, remoteNames), {
10899
+ followDynamicImports: false,
10900
+ cache: remoteDependencyCache
10901
+ });
10902
+ }
10637
10903
  for (const remoteImport of imports) if (remoteImport.kind === "dynamic") markDynamicRemote(remoteImport.source, options);
10638
10904
  return applyRewrites(code, imports, id);
10639
10905
  }
@@ -10768,6 +11034,8 @@ function readBoundedRunnerBody(req, res) {
10768
11034
  */
10769
11035
  function pluginSSRRemoteEntry(options) {
10770
11036
  const remoteEntrySSRId = getRemoteEntrySSRId(options);
11037
+ const ssrHostInitId = getSsrHostInitId(options);
11038
+ let hostInitChunkRef;
10771
11039
  const virtualExposesSSRId = getVirtualExposesSSRId(options);
10772
11040
  let cachedSsrRemoteEntrySource;
10773
11041
  const ssrOutputFilename = getSsrRemoteEntryFileName(options);
@@ -10799,7 +11067,7 @@ function pluginSSRRemoteEntry(options) {
10799
11067
  const environmentName = environment?.name;
10800
11068
  const hasSsrEnvironment = Boolean(viteConfig?.environments?.ssr);
10801
11069
  const isLegacySsrBuild = Boolean(environment?.config?.build?.ssr ?? viteConfig?.build?.ssr);
10802
- return Object.keys(options.exposes).length > 0 && !(hasSsrEnvironment && environmentName !== "ssr" || !hasSsrEnvironment && !isLegacySsrBuild);
11070
+ return isRemoteContainer(options) && !(hasSsrEnvironment && environmentName !== "ssr" || !hasSsrEnvironment && !isLegacySsrBuild);
10803
11071
  };
10804
11072
  const getSsrRemoteEntrySource = () => {
10805
11073
  if (cachedSsrRemoteEntrySource === void 0) cachedSsrRemoteEntrySource = generateRemoteEntrySSR(options);
@@ -10831,6 +11099,7 @@ function pluginSSRRemoteEntry(options) {
10831
11099
  resolveId(id, importer) {
10832
11100
  if (id === remoteEntrySSRId || id.startsWith(remoteEntrySSRId)) return id;
10833
11101
  if (id === virtualExposesSSRId || id.startsWith(virtualExposesSSRId)) return id;
11102
+ if (id === ssrHostInitId) return this.resolve(getHostAutoInitPath(options), importer, { skipSelf: true });
10834
11103
  if (!importer || !ssrModuleIds.has(importer)) return;
10835
11104
  if (ssrOnlyExternalPattern.test(id) && !isNoExternal(id)) return {
10836
11105
  id,
@@ -10901,8 +11170,13 @@ function pluginSSRRemoteEntry(options) {
10901
11170
  } };
10902
11171
  } catch {}
10903
11172
  }
11173
+ const fetchedId = body.data.name === "fetchModule" ? body.data.data[0] : void 0;
11174
+ const shared = typeof fetchedId === "string" && !!findSharedKey(fetchedId, options.shared);
10904
11175
  res.setHeader("Content-Type", "application/json");
10905
- res.end(JSON.stringify(result));
11176
+ res.end(JSON.stringify(shared ? {
11177
+ ...result,
11178
+ shared
11179
+ } : result));
10906
11180
  } catch (e) {
10907
11181
  res.setHeader("Content-Type", "application/json");
10908
11182
  res.end(JSON.stringify({ error: { message: String(e instanceof Error ? e.message : e) } }));
@@ -10938,6 +11212,12 @@ function pluginSSRRemoteEntry(options) {
10938
11212
  const isRolldown = getIsRolldown(this);
10939
11213
  const environment = this.environment;
10940
11214
  if (!isSsrRemoteEntryBuild(environment)) return;
11215
+ if (!isRolldown && hasRemotes(options)) hostInitChunkRef = this.emitFile({
11216
+ type: "chunk",
11217
+ id: ssrHostInitId,
11218
+ name: "hostInit",
11219
+ preserveSignature: "strict"
11220
+ });
10941
11221
  if (isRolldown) this.emitFile({
10942
11222
  type: "chunk",
10943
11223
  id: remoteEntrySSRId,
@@ -10945,7 +11225,7 @@ function pluginSSRRemoteEntry(options) {
10945
11225
  fileName: ssrOutputFilename,
10946
11226
  preserveSignature: "strict"
10947
11227
  });
10948
- else if (Object.keys(options.exposes).length > 0 && !isNuxtLike()) this.emitFile({
11228
+ else if (isRemoteContainer(options) && !isNuxtLike()) this.emitFile({
10949
11229
  type: "chunk",
10950
11230
  id: virtualExposesSSRId,
10951
11231
  name: "ssrExposes",
@@ -10960,11 +11240,8 @@ function pluginSSRRemoteEntry(options) {
10960
11240
  const exposesChunk = findNuxtExposesChunk(bundle) ?? findEmittedExposesChunk(bundle);
10961
11241
  if (!isRolldown && isSsrRemoteEntryBuild(environment)) {
10962
11242
  let source = getSsrRemoteEntrySource();
10963
- if (exposesChunk) {
10964
- let exposesImport = path$1.posix.relative(path$1.posix.dirname(ssrOutputFilename), exposesChunk);
10965
- if (!exposesImport.startsWith(".")) exposesImport = `./${exposesImport}`;
10966
- source = source.replace(/import\("virtual:mf-exposes-ssr:[^"]+"\)/g, `import("${exposesImport}")`);
10967
- }
11243
+ if (hasRemotes(options) && hostInitChunkRef) source = source.replace(JSON.stringify(ssrHostInitId), JSON.stringify(toRelativeImport(ssrOutputFilename, this.getFileName(hostInitChunkRef))));
11244
+ if (exposesChunk) source = source.replace(/import\("virtual:mf-exposes-ssr:[^"]+"\)/g, `import("${toRelativeImport(ssrOutputFilename, exposesChunk)}")`);
10968
11245
  this.emitFile({
10969
11246
  type: "asset",
10970
11247
  fileName: ssrOutputFilename,
@@ -11095,7 +11372,13 @@ const VarRemoteEntry = (providedOptions) => {
11095
11372
  }
11096
11373
  }];
11097
11374
  function isValidVarName(name) {
11098
- return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(name);
11375
+ if (!isValidJsIdentifier(name)) return false;
11376
+ try {
11377
+ new Function(`var ${name};`);
11378
+ return true;
11379
+ } catch {
11380
+ return false;
11381
+ }
11099
11382
  }
11100
11383
  /**
11101
11384
  * Generates the final "var" remote entry file
@@ -11107,27 +11390,122 @@ const VarRemoteEntry = (providedOptions) => {
11107
11390
  const isValidName = isValidVarName(name);
11108
11391
  return `
11109
11392
  ${isValidName ? `var ${name};` : ""}
11110
- ${isValidName ? name : `globalThis['${name}']`} = (function () {
11393
+ (function (global) {
11394
+ const name = ${toSafeJsLiteral(name)};
11395
+ const descriptor = Object.getOwnPropertyDescriptor(global, name);
11396
+ const prototype = Object.getPrototypeOf(global);
11397
+ const emptyVarSlot = ${isValidName} && descriptor && 'value' in descriptor && descriptor.value === undefined && descriptor.writable && !(prototype && name in prototype);
11398
+ if (name in global && !emptyVarSlot) {
11399
+ const existing = descriptor && 'value' in descriptor ? descriptor.value : undefined;
11400
+ if (existing && typeof existing.get === 'function' && typeof existing.init === 'function') {
11401
+ return;
11402
+ }
11403
+ throw new Error('[Module Federation] Cannot register var remote "' + name + '" because the global already exists. Choose a different federation name or use an ESM remote.');
11404
+ }
11405
+
11111
11406
  function getScriptUrl() {
11112
11407
  const currentScript = document.currentScript;
11113
11408
  if (!currentScript) {
11114
- console.error("[Module Federation] ${varFilename} script should be called from sync <script> tag (document.currentScript is undefined)")
11409
+ console.error(${toSafeJsLiteral(`[Module Federation] ${varFilename} script should be called from sync <script> tag (document.currentScript is undefined)`)})
11115
11410
  return '/';
11116
11411
  }
11117
11412
  return document.currentScript.src.replace(/\\/[^/]*$/, '/');
11118
11413
  }
11119
11414
 
11120
- const entry = getScriptUrl() + '${remoteEntryFile}';
11415
+ const entry = getScriptUrl() + ${toSafeJsLiteral(remoteEntryFile)};
11121
11416
 
11122
- return {
11417
+ global[name] = {
11123
11418
  get: (...args) => import(entry).then(m => m.get(...args)),
11124
11419
  init: (...args) => import(entry).then(m => m.init(...args)),
11125
11420
  };
11126
- })();
11421
+ })(globalThis);
11127
11422
  `;
11128
11423
  }
11129
11424
  };
11130
11425
  //#endregion
11426
+ //#region src/plugins/pluginSsrRuntimeInit.ts
11427
+ /** Register the SSR host before application evaluation, without preloading remotes. */
11428
+ function pluginSsrRuntimeInit(options) {
11429
+ if (!hasRemotes(options)) return [];
11430
+ let command;
11431
+ let legacySsr = false;
11432
+ let supported = false;
11433
+ const server = (ctx, ssr) => supported && isServerContext(ctx, ssr === true || legacySsr);
11434
+ return [{
11435
+ name: "module-federation-ssr-runtime-init",
11436
+ enforce: "post",
11437
+ config(_config, env) {
11438
+ command = env.command;
11439
+ },
11440
+ configResolved(config) {
11441
+ legacySsr = Boolean(config.build.ssr);
11442
+ supported = getSsrCapabilities(parseInt(version, 10), command, true, isSsrConfig(config)).enableSsrInitBootstrap;
11443
+ },
11444
+ resolveId: {
11445
+ order: "pre",
11446
+ handler(id, _importer, resolveOptions) {
11447
+ if (server(this, resolveOptions.ssr) && id === options.implementation) return {
11448
+ id: options.implementation,
11449
+ external: false
11450
+ };
11451
+ }
11452
+ },
11453
+ transform(code, id, transformOptions) {
11454
+ if (!server(this, transformOptions?.ssr)) return;
11455
+ if (isOwnedHostAutoInitId(id, options)) {
11456
+ const pluginImports = options.runtimePlugins.map((plugin, index) => `import plugin${index} from ${toSafeJsLiteral(getRuntimePluginSpecifier(plugin))};`).join("\n");
11457
+ const plugins = options.runtimePlugins.map((plugin, index) => `plugin${index}(${Array.isArray(plugin) ? serializeRuntimeOptions(plugin[1]) : ""})`).join(",");
11458
+ return {
11459
+ code: `
11460
+ import { init } from ${toSafeJsLiteral(options.implementation)};
11461
+ import { usedShared, usedRemotes } from ${toSafeJsLiteral(getLocalSharedImportMapPath(options))};
11462
+ ${pluginImports}
11463
+ ${getRuntimeInitBootstrapCode(false, getRuntimeInitStatusImportId(options))}
11464
+ globalThis[globalKey].ssrInitStarted = true;
11465
+ // These remotes are registered before application code, under owner-scoped
11466
+ // names aliased to their configured names, and the runtime resolves an id
11467
+ // against the first remote whose name or alias matches. Drop the alias once the
11468
+ // application registers a remote under that name or alias, so its entry wins.
11469
+ const bootstrapRemoteNames = new Set(usedRemotes.map((remote) => remote.name));
11470
+ const applicationRemotePlugin = {
11471
+ name: 'vite-ssr-application-remote-plugin',
11472
+ beforeRegisterRemote(args) {
11473
+ const { name, alias } = args.remote;
11474
+ if (bootstrapRemoteNames.has(name)) return args;
11475
+ for (const registered of args.origin.options.remotes) {
11476
+ if (
11477
+ bootstrapRemoteNames.has(registered.name) &&
11478
+ (registered.alias === name || registered.alias === alias)
11479
+ ) {
11480
+ delete registered.alias;
11481
+ }
11482
+ }
11483
+ return args;
11484
+ },
11485
+ };
11486
+ const runtime = init({
11487
+ name: ${toSafeJsLiteral(options.name)},
11488
+ remotes: usedRemotes,
11489
+ shared: usedShared,
11490
+ plugins: [applicationRemotePlugin, ${plugins}],
11491
+ shareStrategy: ${toSafeJsLiteral(options.shareStrategy)},
11492
+ });
11493
+ const hostInitPromise = Promise.resolve(runtime);
11494
+ globalThis[globalKey].initResolve(runtime);
11495
+ function initHost() { return hostInitPromise; }
11496
+ export { initHost, hostInitPromise };
11497
+ `,
11498
+ map: null
11499
+ };
11500
+ }
11501
+ if (!(command === "build" && this.getModuleInfo(id)?.isEntry) && !findModuleImportSources(code).includes("@module-federation/runtime")) return;
11502
+ const injection = `import ${toSafeJsLiteral(getHostAutoInitPath(options))};\n`;
11503
+ if (code.includes(injection.trim())) return;
11504
+ return mapCodeToCodeWithSourcemap(injection + code);
11505
+ }
11506
+ }];
11507
+ }
11508
+ //#endregion
11131
11509
  //#region src/utils/aliasToArrayPlugin.ts
11132
11510
  var aliasToArrayPlugin_default = {
11133
11511
  name: "alias-transform-plugin",
@@ -11276,145 +11654,6 @@ function sanitizeFederationControlChunk(code, fileName, filename) {
11276
11654
  return nextCode;
11277
11655
  }
11278
11656
  //#endregion
11279
- //#region src/utils/isTestEnv.ts
11280
- /**
11281
- * Detects whether the current process is running in a test environment
11282
- * Set `MFE_VITE_NO_TEST_ENV_CHECK=true` to load federation plugins during tests.
11283
- */
11284
- function isTestEnv() {
11285
- if (process.env.MFE_VITE_NO_TEST_ENV_CHECK === "true") return false;
11286
- return process.env.NODE_ENV === "test" || process.env.VITEST != null || process.env.JEST_WORKER_ID != null;
11287
- }
11288
- //#endregion
11289
- //#region src/utils/hostProvidesAllShared.ts
11290
- /** Virtual-module prefix of the host's per-share re-export entries. */
11291
- const SHARE_MODULE_PREFIX = "\0mf-host-provided-share:";
11292
- /** `./a/b` → `a/b`, `.` → `index`: the fixed entry name of an expose, without `.js`. */
11293
- function exposeEntryName(exposeKey) {
11294
- return exposeKey === "." ? "index" : exposeKey.replace(/^\.\//, "");
11295
- }
11296
- /** Bare specifier a host uses for an expose: `remote` for `.`, `remote/a/b` otherwise. */
11297
- function remoteSpecifier(remoteName, exposeKey) {
11298
- const entry = exposeEntryName(exposeKey);
11299
- return entry === "index" ? remoteName : `${remoteName}/${entry}`;
11300
- }
11301
- /** `id` is a remote alias or a subpath of one. */
11302
- function isRemoteSpecifier(id, remoteKeys) {
11303
- return remoteKeys.some((key) => id === key || id.startsWith(`${key}/`));
11304
- }
11305
- /**
11306
- * The shared key that owns `id`: an exact match, else the longest key `id` is a subpath
11307
- * of (`lodash-es/debounce` → `lodash-es`). Used to spot an unshared subpath of a shared
11308
- * package, which would bundle a private copy of that package into a remote.
11309
- */
11310
- function sharedKeyOwning(id, sharedKeys) {
11311
- let owner;
11312
- for (const key of sharedKeys) {
11313
- if (id !== key && !id.startsWith(`${key}/`)) continue;
11314
- if (!owner || key.length > owner.length) owner = key;
11315
- }
11316
- return owner;
11317
- }
11318
- /** Chunk name of the host's re-export entry for a shared key. */
11319
- function shareChunkName(key) {
11320
- return `shared/${key.replace(/^@/, "").replace(/[^\w-]+/g, "-")}`;
11321
- }
11322
- /** Reads a remote's `mf-manifest.json` from a URL or a path relative to `root`. */
11323
- async function readHostProvidesAllSharedManifest(location, root) {
11324
- let source;
11325
- if (isAbsoluteUrl(location)) {
11326
- const response = await fetch(location);
11327
- if (!response.ok) throw new Error(`Failed to fetch ${location}: ${response.status} ${response.statusText}`);
11328
- source = await response.text();
11329
- } else source = await readFile(path$1.resolve(root, location), "utf8");
11330
- const manifest = JSON.parse(source);
11331
- if (!manifest.metaData || !Array.isArray(manifest.exposes)) throw new Error(`${location} is not a Module Federation manifest.`);
11332
- if (manifest.metaData.remoteEntry) throw new Error(`${location} describes a Module Federation runtime remote (it has a remoteEntry). Build the remote with \`experiments: { hostProvidesAllShared: true }\`.`);
11333
- return manifest;
11334
- }
11335
- /** URL prefix of a remote's files: `metaData.publicPath`, `auto` inferred from the manifest URL. */
11336
- function remotePublicPath(manifest, location) {
11337
- const publicPath = manifest.metaData.publicPath ?? "auto";
11338
- if (publicPath !== "auto") return ensureTrailingSlash(publicPath);
11339
- if (!isAbsoluteUrl(location)) throw new Error(`${location}: publicPath is "auto", which can only be inferred from a manifest URL. Reference the manifest by URL or set \`base\` / \`publicPath\` in the remote build.`);
11340
- return ensureTrailingSlash(inferAutoPublicPath(location));
11341
- }
11342
- /** Import-map entries (`remote/Expose` → URL) for every expose of every remote. */
11343
- async function collectRemoteImports(remotes, root) {
11344
- const imports = {};
11345
- for (const [alias, remote] of Object.entries(remotes)) {
11346
- const manifest = await readHostProvidesAllSharedManifest(remote.entry, root);
11347
- const publicPath = remotePublicPath(manifest, remote.entry);
11348
- for (const expose of manifest.exposes) {
11349
- const file = expose.assets.js.sync[0];
11350
- if (!expose.path || !file) continue;
11351
- imports[remoteSpecifier(alias, expose.path)] = isAbsoluteUrl(remote.entry) ? new URL(file, new URL(publicPath, remote.entry)).href : publicPath + file;
11352
- }
11353
- }
11354
- return imports;
11355
- }
11356
- /** Top-level options that only the Module Federation runtime or `remoteEntry.js` pipeline reads. */
11357
- const IGNORED_OPTIONS = [
11358
- "filename",
11359
- "ssrFilename",
11360
- "varFilename",
11361
- "library",
11362
- "runtime",
11363
- "shareScope",
11364
- "shareStrategy",
11365
- "runtimePlugins",
11366
- "implementation",
11367
- "getPublicPath",
11368
- "ignoreOrigin",
11369
- "virtualModuleDir",
11370
- "hostInitInjectLocation",
11371
- "bundleAllCSS",
11372
- "treeShakingDir",
11373
- "injectTreeShakingUsedExports",
11374
- "treeShakingSharedPlugins",
11375
- "treeShakingSharedExcludePlugins",
11376
- "moduleParseTimeout",
11377
- "moduleParseIdleTimeout",
11378
- "target",
11379
- "ssrExternals",
11380
- "ssrEntryLoader",
11381
- "disableRemote",
11382
- "disableShared",
11383
- "disableSnapshot"
11384
- ];
11385
- const IGNORED_EXPERIMENTS = [
11386
- "externalRuntime",
11387
- "provideExternalRuntime",
11388
- "ssrMode"
11389
- ];
11390
- /** Per-share options: version negotiation, aliasing and fallbacks do not exist in this mode. */
11391
- const IGNORED_SHARE_OPTIONS = [
11392
- "eager",
11393
- "requiredVersion",
11394
- "strictVersion",
11395
- "import",
11396
- "request",
11397
- "shareKey",
11398
- "name",
11399
- "version",
11400
- "shareScope",
11401
- "treeShaking",
11402
- "allowNodeModulesSuffixMatch",
11403
- "suppressMissingImportWarning"
11404
- ];
11405
- const isSet = (value) => value !== void 0 && value !== false && !(Array.isArray(value) && value.length === 0);
11406
- /** A single warning naming every option the user set that import-map mode ignores. */
11407
- function getIgnoredOptionWarning(options) {
11408
- const shared = options.shared;
11409
- const ignored = [
11410
- ...IGNORED_OPTIONS.filter((key) => isSet(options[key])).map((key) => `\`${key}\``),
11411
- ...IGNORED_EXPERIMENTS.filter((key) => isSet(options.experiments?.[key])).map((key) => `\`experiments.${key}\``),
11412
- ...shared && !Array.isArray(shared) ? Object.entries(shared).flatMap(([key, config]) => typeof config === "object" && config !== null ? IGNORED_SHARE_OPTIONS.filter((option) => option === "import" ? config.import !== void 0 : isSet(config[option])).map((option) => `\`shared.${key}.${option}\``) : []) : []
11413
- ];
11414
- if (ignored.length === 0) return void 0;
11415
- return `experiments.hostProvidesAllShared: ${ignored.join(", ")} ignored. The Module Federation runtime is not used and the host provides the only copy of every shared key.`;
11416
- }
11417
- //#endregion
11418
11657
  //#region src/plugins/pluginHostProvidesAllSharedHost.ts
11419
11658
  const ESM_SYNTAX_RE = /(^|[\s;])(export|import)[\s{*]/m;
11420
11659
  const DEFAULT_EXPORT_RE = /export\s+default\b|export\s*\{[^}]*\bas\s+default\b/;
@@ -11640,28 +11879,6 @@ function pluginHostProvidesAllSharedRemote(options) {
11640
11879
  };
11641
11880
  }
11642
11881
  //#endregion
11643
- //#region src/utils/normalizeOptimizeDeps.ts
11644
- var normalizeOptimizeDeps_default = {
11645
- name: "normalizeOptimizeDeps",
11646
- config: (config) => {
11647
- let { optimizeDeps } = config;
11648
- if (!optimizeDeps) {
11649
- config.optimizeDeps = {};
11650
- optimizeDeps = config.optimizeDeps;
11651
- }
11652
- if (!optimizeDeps.include) optimizeDeps.include = [];
11653
- if (!optimizeDeps.exclude) optimizeDeps.exclude = [];
11654
- if (!optimizeDeps.needsInterop) optimizeDeps.needsInterop = [];
11655
- },
11656
- configResolved: (config) => {
11657
- const include = config.optimizeDeps?.include;
11658
- const exclude = config.optimizeDeps?.exclude;
11659
- if (!include?.length || !exclude?.length) return;
11660
- const included = new Set(include);
11661
- config.optimizeDeps.exclude = exclude.filter((dep) => !included.has(dep));
11662
- }
11663
- };
11664
- //#endregion
11665
11882
  //#region src/utils/runtimeCapabilityOptimization.ts
11666
11883
  const RUNTIME_CAPABILITIES = [
11667
11884
  {
@@ -11691,11 +11908,11 @@ function applyRuntimeCapabilityDefines(define, options, { defaultDisableSnapshot
11691
11908
  }
11692
11909
  if (explicitValue !== void 0 && !isEquivalentBooleanDefine(define[capability.define], explicitValue)) onConflict?.(`${capability.define} define (${define[capability.define]}) differs from ${capability.option} option (${explicitValue}). The existing define will not be overridden.`);
11693
11910
  }
11694
- if (!("FEDERATION_HAS_EXPOSES" in define)) define["FEDERATION_HAS_EXPOSES"] = JSON.stringify(Object.keys(options.exposes).length > 0);
11911
+ if (!("FEDERATION_HAS_EXPOSES" in define)) define["FEDERATION_HAS_EXPOSES"] = JSON.stringify(isRemoteContainer(options));
11695
11912
  }
11696
11913
  function getRuntimeCapabilityConfigurationWarnings(options) {
11697
11914
  const warnings = [];
11698
- if (options.disableRemote && Object.keys(options.remotes).length > 0) warnings.push("disableRemote is true, but remotes are configured. Remote loading will be unavailable at runtime.");
11915
+ if (options.disableRemote && hasRemotes(options)) warnings.push("disableRemote is true, but remotes are configured. Remote loading will be unavailable at runtime.");
11699
11916
  if (options.disableShared && hasShared(options)) warnings.push("disableShared is true, but shared dependencies are configured. Shared dependency loading will be unavailable at runtime.");
11700
11917
  return warnings;
11701
11918
  }
@@ -11863,15 +12080,8 @@ function isBarePackageSubpath(specifier) {
11863
12080
  * Vite then resolves the package's own dependency graph using its normal
11864
12081
  * scanner, preserving package and peer-dependency resolution semantics.
11865
12082
  */
11866
- function includeLinkedSharedEntries(optimizeDeps, shared, projectRoot, exposes, outDir) {
12083
+ function collectLinkedSharedEntries(shared, projectRoot, exposes) {
11867
12084
  const additions = /* @__PURE__ */ new Set();
11868
- const entries = new Set(Array.isArray(optimizeDeps.entries) ? optimizeDeps.entries : optimizeDeps.entries ? [optimizeDeps.entries] : [
11869
- "**/*.html",
11870
- "!**/node_modules/**",
11871
- `!**/${outDir.replace(/\\/g, "/")}/**`,
11872
- "!**/__tests__/**",
11873
- "!**/coverage/**"
11874
- ]);
11875
12085
  for (const [packageName, share] of Object.entries(shared ?? {})) {
11876
12086
  if (share?.shareConfig?.import === false) continue;
11877
12087
  const configuredImport = share?.shareConfig?.import;
@@ -11894,13 +12104,7 @@ function includeLinkedSharedEntries(optimizeDeps, shared, projectRoot, exposes,
11894
12104
  if (existsSync(entry)) additions.add(entry);
11895
12105
  }
11896
12106
  }
11897
- if (additions.size === 0) return;
11898
- for (const entry of additions) entries.add(entry);
11899
- optimizeDeps.entries = [...entries];
11900
- }
11901
- function stabilizeOptimizeDeps(optimizeDeps) {
11902
- optimizeDeps.include = [...new Set(optimizeDeps.include ?? [])].sort();
11903
- optimizeDeps.exclude = [...new Set(optimizeDeps.exclude ?? [])].sort();
12107
+ return [...additions];
11904
12108
  }
11905
12109
  function isFile(candidate) {
11906
12110
  try {
@@ -12012,18 +12216,23 @@ function createEarlyVirtualModulesPlugin(options) {
12012
12216
  return {
12013
12217
  name: "vite:module-federation-early-init",
12014
12218
  enforce: "pre",
12015
- config(config, { command: _command }) {
12219
+ config(config, { command: _command, mode }) {
12016
12220
  if (_command === "serve") ignoreFederationGeneratedFiles(config, options);
12017
12221
  const root = config.root || process.cwd();
12018
12222
  const buildInput = getBuildInput(config);
12019
12223
  const resolvedConfiguredEntryFiles = (typeof buildInput === "string" ? [buildInput] : Array.isArray(buildInput) ? buildInput : buildInput && typeof buildInput === "object" ? Object.values(buildInput) : []).map((entry) => String(entry)).filter((entry) => !isReactRouterBuildClientRouteInput(entry)).map((entry) => entry.split(/[?#]/)[0]).map((entry) => path$1.isAbsolute(entry) ? entry : path$1.resolve(root, entry));
12020
12224
  resetConcreteSharedImportSourceCache();
12021
12225
  setPackageDetectionCwd(root);
12226
+ setWorkspaceEntryConditions(getSharedExportConditions({
12227
+ isProduction: mode === "production",
12228
+ isSsr: false,
12229
+ rootConditions: config.resolve?.conditions
12230
+ }));
12022
12231
  resolveSharedVersions(shared, root);
12023
12232
  const isVinext = hasPackageDependency("vinext");
12024
12233
  initVirtualModules(_command, getRemoteEntryId(options), false, options);
12025
12234
  const isRolldown = getIsRolldown(this);
12026
- if (remotes && Object.keys(remotes).length > 0) {
12235
+ if (hasRemotes(options)) {
12027
12236
  for (const key of Object.keys(remotes)) ensureUsedRemote(key, options);
12028
12237
  if (_command === "serve") {
12029
12238
  config.optimizeDeps = config.optimizeDeps || {};
@@ -12045,7 +12254,7 @@ function createEarlyVirtualModulesPlugin(options) {
12045
12254
  const preparedShares = /* @__PURE__ */ new Map();
12046
12255
  const writeSharedModules = (source, shareItem) => {
12047
12256
  if (preparedShares.get(source) === shareItem) return;
12048
- writeLoadShareModule(source, shareItem, _command, isRolldown, options);
12257
+ writeLoadShareModule(source, shareItem, _command, options);
12049
12258
  if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(source, shareItem, options);
12050
12259
  preparedShares.set(source, shareItem);
12051
12260
  };
@@ -12061,7 +12270,7 @@ function createEarlyVirtualModulesPlugin(options) {
12061
12270
  if (!id.startsWith("module-federation:optimized-require-")) return;
12062
12271
  const sourcePackage = id.slice(36);
12063
12272
  if (sourcePackage !== "react" && sourcePackage !== "react-dom") return;
12064
- const loadSharePath = getLoadShareModulePath(sourcePackage, isRolldown, options);
12273
+ const loadSharePath = getLoadShareModulePath(sourcePackage, options);
12065
12274
  const source = JSON.stringify(loadSharePath);
12066
12275
  return "import * as __mfShared from " + source + ";\nexport * from " + source + ";\nexport default __mfShared.default ?? __mfShared;";
12067
12276
  },
@@ -12074,7 +12283,7 @@ function createEarlyVirtualModulesPlugin(options) {
12074
12283
  const key = findSharedKey(source, shared);
12075
12284
  if (!key) return;
12076
12285
  const importerPackage = getSharedPackageFromFile(importer, shared, root);
12077
- if (!isReactDomSelfReference(source, importer) && (importerPackage === getPackageName(key) || importerPackage && isSharedPackageDependency(key, importerPackage))) return;
12286
+ if (!isReactDomSelfReference(source, importer) && (importerPackage === getPackageName(key) && keepsOwnPackageEdge(importer, shared, root) || importerPackage && isSharedPackageDependency(key, importerPackage))) return;
12078
12287
  if (isAssetLikeImport(source)) return;
12079
12288
  const shareItem = shared[key];
12080
12289
  const isReactSingleton = source === "react" && key === "react" && shareItem.shareConfig?.singleton === true;
@@ -12087,7 +12296,7 @@ function createEarlyVirtualModulesPlugin(options) {
12087
12296
  writeSharedModules(source, shareItem);
12088
12297
  return { id: `module-federation:optimized-require-${source}` };
12089
12298
  }
12090
- const loadSharePath = getLoadShareModulePath(source, isRolldown, options);
12299
+ const loadSharePath = getLoadShareModulePath(source, options);
12091
12300
  writeSharedModules(source, shareItem);
12092
12301
  return {
12093
12302
  id: loadSharePath,
@@ -12115,12 +12324,12 @@ function createEarlyVirtualModulesPlugin(options) {
12115
12324
  const key = findSharedKey(args.path, shared);
12116
12325
  if (!key || isAssetLikeImport(args.path)) return;
12117
12326
  const importerPackage = getSharedPackageFromFile(args.importer, shared, root);
12118
- if (importerPackage === getPackageName(args.path) && !isReactDomSelfReference(args.path, args.importer)) return;
12327
+ if (importerPackage === getPackageName(args.path) && !isReactDomSelfReference(args.path, args.importer) && keepsOwnPackageEdge(args.importer, shared, root)) return;
12119
12328
  if (importerPackage && isSharedPackageDependency(key, importerPackage)) return;
12120
12329
  addUsedShares(args.path, options);
12121
12330
  if (args.kind === "import-statement" || args.kind === "dynamic-import") {
12122
12331
  const shareItem = shared[key];
12123
- const loadSharePath = getLoadShareModulePath(args.path, isRolldown, options);
12332
+ const loadSharePath = getLoadShareModulePath(args.path, options);
12124
12333
  writeSharedModules(args.path, shareItem);
12125
12334
  return {
12126
12335
  path: loadSharePath,
@@ -12139,7 +12348,7 @@ function createEarlyVirtualModulesPlugin(options) {
12139
12348
  const key = findSharedKey(args.path, shared);
12140
12349
  if (!key) return;
12141
12350
  const shareItem = shared[key];
12142
- const loadSharePath = getLoadShareModulePath(args.path, isRolldown, options);
12351
+ const loadSharePath = getLoadShareModulePath(args.path, options);
12143
12352
  writeSharedModules(args.path, shareItem);
12144
12353
  return {
12145
12354
  loader: "js",
@@ -12174,8 +12383,8 @@ export default __mfShared.default ?? __mfShared;`
12174
12383
  addConfiguredShare(runtimeKey, options);
12175
12384
  continue;
12176
12385
  }
12177
- getLoadShareModulePath(runtimeKey, isRolldown, options);
12178
- writeLoadShareModule(runtimeKey, shareItem, _command, isRolldown, options);
12386
+ getLoadShareModulePath(runtimeKey, options);
12387
+ writeLoadShareModule(runtimeKey, shareItem, _command, options);
12179
12388
  if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(runtimeKey, shareItem, options);
12180
12389
  addConfiguredShare(runtimeKey, options);
12181
12390
  if (_command === "serve" && shareItem.shareConfig?.import !== false) {
@@ -12197,8 +12406,8 @@ export default __mfShared.default ?? __mfShared;`
12197
12406
  optimizeDeps.exclude.push(subpath);
12198
12407
  continue;
12199
12408
  }
12200
- getLoadShareModulePath(subpath, isRolldown, options);
12201
- writeLoadShareModule(subpath, shareItem, _command, isRolldown, options);
12409
+ getLoadShareModulePath(subpath, options);
12410
+ writeLoadShareModule(subpath, shareItem, _command, options);
12202
12411
  writePreBuildLibPath(subpath, shareItem, options);
12203
12412
  addConfiguredShare(subpath, options);
12204
12413
  if (canResolveSubpath) {
@@ -12211,9 +12420,19 @@ export default __mfShared.default ?? __mfShared;`
12211
12420
  writeLocalSharedImportMap(options);
12212
12421
  }
12213
12422
  if (_command === "serve") {
12214
- config.optimizeDeps ??= {};
12215
- includeLinkedSharedEntries(config.optimizeDeps, shared, root, options.exposes, config.build?.outDir ?? "dist");
12216
- stabilizeOptimizeDeps(config.optimizeDeps);
12423
+ const generatedEntries = collectLinkedSharedEntries(shared, root, options.exposes);
12424
+ if (generatedEntries.length > 0) {
12425
+ config.optimizeDeps ??= {};
12426
+ const outDir = config.build?.outDir ?? "dist";
12427
+ const { entries } = config.optimizeDeps;
12428
+ config.optimizeDeps.entries = [.../* @__PURE__ */ new Set([...entries === void 0 ? [
12429
+ "**/*.html",
12430
+ "!**/node_modules/**",
12431
+ `!**/${outDir.replace(/\\/g, "/")}/**`,
12432
+ "!**/__tests__/**",
12433
+ "!**/coverage/**"
12434
+ ] : typeof entries === "string" ? [entries] : entries, ...generatedEntries])];
12435
+ }
12217
12436
  }
12218
12437
  },
12219
12438
  configResolved(config) {
@@ -12236,18 +12455,22 @@ export default __mfShared.default ?? __mfShared;`
12236
12455
  "@module-federation/sdk"
12237
12456
  ];
12238
12457
  const resolvedShared = {};
12239
- for (const pkg of [...commonSharedPkgs, ...sharedKeys]) try {
12240
- resolvedShared[pkg] = projectRequire.resolve(pkg);
12241
- } catch {
12458
+ for (const pkg of [...commonSharedPkgs, ...sharedKeys]) {
12459
+ const resolutionSpecifier = removeTrailingSlash(pkg);
12242
12460
  try {
12243
- resolvedShared[pkg] = resolveImportPath(pkg);
12244
- } catch {}
12461
+ resolvedShared[pkg] = projectRequire.resolve(resolutionSpecifier);
12462
+ } catch {
12463
+ try {
12464
+ resolvedShared[pkg] = resolveImportPath(resolutionSpecifier);
12465
+ } catch {}
12466
+ }
12245
12467
  }
12246
12468
  const ssrEntryLoaderSpecifier = SSR_ENTRY_LOADER_SPECIFIER;
12247
12469
  try {
12248
12470
  resolveImportPath(ssrEntryLoaderSpecifier);
12249
12471
  options.runtimePlugins.push([ssrEntryLoaderSpecifier, {
12250
12472
  resolvedShared,
12473
+ ...config.command === "build" && { rebaseSharedAtRuntime: true },
12251
12474
  ...options.ssrEntryLoader
12252
12475
  }]);
12253
12476
  } catch {}
@@ -12277,7 +12500,7 @@ function withoutDynamicRemoteTypeHints(options) {
12277
12500
  }
12278
12501
  function loadPluginDts(options) {
12279
12502
  if (options.dts === false) return [];
12280
- return [import("./pluginDts-DShMdjzR.js").then(({ default: pluginDts }) => pluginDts(options))];
12503
+ return [import("./pluginDts-rZMRTCTz.js").then(({ default: pluginDts }) => pluginDts(options))];
12281
12504
  }
12282
12505
  const INJECT_EXTERNAL_RUNTIME_CORE_PLUGIN = "@module-federation/vite/injectExternalRuntimeCorePlugin";
12283
12506
  function isInjectExternalRuntimeCorePlugin(specifier) {
@@ -12304,13 +12527,13 @@ function applyExternalRuntimeExperiments(options) {
12304
12527
  }
12305
12528
  }
12306
12529
  function federation(mfUserOptions) {
12307
- if (isTestEnv()) return [];
12530
+ if (process.env.MFE_VITE_NO_TEST_ENV_CHECK !== "true" && (process.env.NODE_ENV === "test" || process.env.VITEST != null || process.env.JEST_WORKER_ID != null)) return [];
12308
12531
  const options = normalizeModuleFederationOptions(mfUserOptions);
12309
12532
  if (!options.name) throw createModuleFederationError("name is required");
12310
12533
  if (options.experiments.hostProvidesAllShared) {
12311
12534
  const ignored = getIgnoredOptionWarning(mfUserOptions);
12312
12535
  if (ignored) mfWarn(ignored);
12313
- return [Object.keys(options.exposes).length > 0 ? pluginHostProvidesAllSharedRemote(options) : pluginHostProvidesAllSharedHost(options), ...loadPluginDts(withoutDynamicRemoteTypeHints(options))];
12536
+ return [isRemoteContainer(options) ? pluginHostProvidesAllSharedRemote(options) : pluginHostProvidesAllSharedHost(options), ...loadPluginDts(withoutDynamicRemoteTypeHints(options))];
12314
12537
  }
12315
12538
  applyExternalRuntimeExperiments(options);
12316
12539
  const isVinext = hasPackageDependency("vinext");
@@ -12365,9 +12588,9 @@ function federation(mfUserOptions) {
12365
12588
  const key = findSharedKey(pkg, shared);
12366
12589
  if (!key) return "not-applicable";
12367
12590
  const requestedModule = VirtualModule.findById(id);
12368
- const ownedModule = VirtualModule.findById(getLoadShareModulePath(pkg, false, options));
12591
+ const ownedModule = VirtualModule.findById(getLoadShareModulePath(pkg, options));
12369
12592
  if (!requestedModule || requestedModule !== ownedModule) return "not-owned";
12370
- writeLoadShareModule(pkg, shared[key], command, getIsRolldown(context), options, getLoadHookExportConditions(context, loadOptions), importFalseExportUsage);
12593
+ writeLoadShareModule(pkg, shared[key], command, options, getLoadHookExportConditions(context, loadOptions), importFalseExportUsage);
12371
12594
  return "refreshed";
12372
12595
  };
12373
12596
  const getCompleteImportFalseExportUsage = (id) => {
@@ -12510,9 +12733,7 @@ function federation(mfUserOptions) {
12510
12733
  name: "vite:module-federation-virtual-modules",
12511
12734
  enforce: "pre",
12512
12735
  configureServer(server) {
12513
- server.watcher.on("change", invalidateSharedExportInspectionCache);
12514
- server.watcher.on("add", invalidateSharedExportInspectionCache);
12515
- server.watcher.on("unlink", invalidateSharedExportInspectionCache);
12736
+ watchFileEvents(server.watcher, invalidateSharedExportInspectionCache);
12516
12737
  },
12517
12738
  resolveId(id) {
12518
12739
  if (id === "@module-federation/vite/ssrEntryLoader") return resolveImportPath(id);
@@ -12522,7 +12743,6 @@ function federation(mfUserOptions) {
12522
12743
  id,
12523
12744
  shared: options.shared,
12524
12745
  command,
12525
- isRolldown: getIsRolldown(this),
12526
12746
  findSharedKey,
12527
12747
  addUsedShares: (pkg) => addUsedShares(pkg, options),
12528
12748
  writeLocalSharedImportMap: () => writeLocalSharedImportMap(options),
@@ -12583,14 +12803,29 @@ function federation(mfUserOptions) {
12583
12803
  ssrResolveConditions = config.ssr?.resolve?.conditions ? [...config.ssr.resolve.conditions] : void 0;
12584
12804
  ssrTarget = config.ssr?.target ?? "node";
12585
12805
  isProduction = config.isProduction;
12586
- const ssrCapabilities = getSsrCapabilities(parseInt(version, 10), command, Object.keys(options.remotes).length > 0, isSsrConfig(config));
12806
+ const ssrCapabilities = getSsrCapabilities(parseInt(version, 10), command, hasRemotes(options), isSsrConfig(config));
12587
12807
  resolveSharedVersions(shared, config.root);
12588
12808
  initVirtualModules(command, remoteEntryId, ssrCapabilities.enableSsrInitBootstrap, options);
12589
12809
  }
12590
12810
  },
12591
12811
  aliasToArrayPlugin_default,
12592
12812
  checkAliasConflicts({ shared }),
12593
- normalizeOptimizeDeps_default,
12813
+ {
12814
+ name: "normalizeOptimizeDeps",
12815
+ config(config) {
12816
+ config.optimizeDeps ||= {};
12817
+ config.optimizeDeps.include ||= [];
12818
+ config.optimizeDeps.exclude ||= [];
12819
+ config.optimizeDeps.needsInterop ||= [];
12820
+ },
12821
+ configResolved(config) {
12822
+ const include = config.optimizeDeps?.include;
12823
+ const exclude = config.optimizeDeps?.exclude;
12824
+ if (!include?.length || !exclude?.length) return;
12825
+ const included = new Set(include);
12826
+ config.optimizeDeps.exclude = exclude.filter((dep) => !included.has(dep));
12827
+ }
12828
+ },
12594
12829
  ...loadPluginDts(options),
12595
12830
  pluginDevRemoteHmr(options),
12596
12831
  {
@@ -12615,7 +12850,7 @@ function federation(mfUserOptions) {
12615
12850
  entryName: "hostInit",
12616
12851
  entryPath: () => getHostAutoInitPath(options),
12617
12852
  inject: hostInitInjectLocation,
12618
- forceClientInjected: Object.keys(options.exposes).length > 0,
12853
+ forceClientInjected: isRemoteContainer(options),
12619
12854
  skipTransformFor: Object.values(options.exposes).map((expose) => expose.import),
12620
12855
  federationOptions: options
12621
12856
  }),
@@ -12813,10 +13048,6 @@ function federation(mfUserOptions) {
12813
13048
  config.optimizeDeps.include.push(optimizeDep);
12814
13049
  }
12815
13050
  });
12816
- if (isRolldown) {
12817
- config.build ??= {};
12818
- config.build.target ??= "esnext";
12819
- }
12820
13051
  const isBundledDev = Boolean(config.experimental?.bundledDev);
12821
13052
  if (isRolldown && _command === "serve" && isBundledDev) {
12822
13053
  config.build.rolldownOptions ??= {};
@@ -12860,6 +13091,7 @@ function federation(mfUserOptions) {
12860
13091
  },
12861
13092
  ...Manifest(options),
12862
13093
  ...pluginSSRRemoteEntry(options),
13094
+ ...pluginSsrRuntimeInit(options),
12863
13095
  ...VarRemoteEntry(options),
12864
13096
  {
12865
13097
  name: "module-federation-vinext-fix-rsc-preload-as",
@@ -12896,20 +13128,12 @@ function federation(mfUserOptions) {
12896
13128
  },
12897
13129
  ...(function() {
12898
13130
  let disablePreload = false;
12899
- return Object.keys(options.exposes).length > 0 ? [{
13131
+ return isRemoteContainer(options) ? [{
12900
13132
  name: "module-federation-fix-preload",
12901
13133
  enforce: "post",
12902
13134
  apply: "build",
12903
- config(_config, { command }) {
12904
- const manifest = options.manifest;
12905
- const getDefaultDisableAssetsAnalyze = (cfgCommand) => cfgCommand === "serve" && (typeof manifest !== "object" || !Object.hasOwn(manifest, "disableAssetsAnalyze"));
12906
- const getConfiguredDisableAssetsAnalyze = (cfgCommand) => {
12907
- if (typeof manifest === "object" && manifest !== null) {
12908
- if (Object.hasOwn(manifest, "disableAssetsAnalyze")) return manifest.disableAssetsAnalyze === true;
12909
- }
12910
- return getDefaultDisableAssetsAnalyze(cfgCommand);
12911
- };
12912
- disablePreload = getConfiguredDisableAssetsAnalyze(command);
13135
+ config() {
13136
+ disablePreload = resolveDisableAssetsAnalyze(options.manifest, false);
12913
13137
  },
12914
13138
  generateBundle(_outputOptions, bundle, _isWrite) {
12915
13139
  if (disablePreload) return;