@module-federation/vite 1.14.3 → 1.14.5

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.d.mts CHANGED
@@ -6,6 +6,7 @@ import { ShareStrategy } from "@module-federation/runtime/types";
6
6
  interface RemoteObjectConfig {
7
7
  type?: string;
8
8
  name: string;
9
+ internalName?: string;
9
10
  entry: string;
10
11
  entryGlobalName?: string;
11
12
  shareScope?: string;
package/lib/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { createRequire } from "node:module";
2
2
  import defu from "defu";
3
3
  import * as fs from "fs";
4
- import { existsSync, mkdirSync, readFileSync, statSync, writeFile, writeFileSync } from "fs";
4
+ import { existsSync, mkdirSync, readFileSync, readdirSync, statSync, writeFile, writeFileSync } from "fs";
5
5
  import { createRequire as createRequire$1 } from "module";
6
6
  import * as path$1 from "pathe";
7
7
  import path, { basename, dirname, join, parse, resolve } from "pathe";
@@ -95,6 +95,15 @@ function setPackageDetectionCwd(cwd) {
95
95
  function getPackageDetectionCwd() {
96
96
  return packageDetectionCwd || process.cwd();
97
97
  }
98
+ function resolveExportsEntry(exportsField) {
99
+ if (typeof exportsField === "string") return exportsField;
100
+ if (!exportsField || typeof exportsField !== "object") return void 0;
101
+ const rootExport = exportsField["."];
102
+ if (typeof rootExport === "string") return rootExport;
103
+ if (!rootExport || typeof rootExport !== "object") return void 0;
104
+ const rootExportObject = rootExport;
105
+ return typeof rootExportObject.import === "string" && rootExportObject.import || typeof rootExportObject.default === "string" && rootExportObject.default || typeof rootExportObject.require === "string" && rootExportObject.require || void 0;
106
+ }
98
107
  /**
99
108
  * Escaping rules:
100
109
  * Convert using the format __${mapping}__, where _ and $ are not allowed in npm package names but can be used in variable names.
@@ -130,6 +139,84 @@ function removePathFromNpmPackage(packageString) {
130
139
  const match = packageString.match(/^(?:@[^/]+\/)?[^/]+/);
131
140
  return match ? match[0] : packageString;
132
141
  }
142
+ function getInstalledPackageJson(pkg, opts) {
143
+ const cwd = opts?.cwd || getPackageDetectionCwd();
144
+ const packageName = opts?.packageName || removePathFromNpmPackage(pkg);
145
+ const tryReadPackageJson = (packageJsonPath) => {
146
+ if (!existsSync(packageJsonPath)) return void 0;
147
+ try {
148
+ return {
149
+ path: packageJsonPath,
150
+ dir: path.dirname(packageJsonPath),
151
+ packageJson: JSON.parse(readFileSync(packageJsonPath, "utf-8"))
152
+ };
153
+ } catch {
154
+ return;
155
+ }
156
+ };
157
+ const findPackageInPnpmStore = (startDir) => {
158
+ let currentDir = startDir;
159
+ const rootDir = path.parse(currentDir).root;
160
+ while (true) {
161
+ const pnpmStoreDir = path.join(currentDir, "node_modules", ".pnpm");
162
+ if (existsSync(pnpmStoreDir)) try {
163
+ for (const entry of readdirSync(pnpmStoreDir, { withFileTypes: true })) {
164
+ if (!entry.isDirectory()) continue;
165
+ const candidate = tryReadPackageJson(path.join(pnpmStoreDir, entry.name, "node_modules", packageName, "package.json"));
166
+ if (candidate?.packageJson.name === packageName) return candidate;
167
+ }
168
+ } catch {}
169
+ if (currentDir === rootDir) break;
170
+ currentDir = path.dirname(currentDir);
171
+ }
172
+ };
173
+ try {
174
+ const projectRequire = createRequire$1(new URL(`file://${path.join(cwd, "package.json")}`));
175
+ let resolvedPath;
176
+ try {
177
+ resolvedPath = projectRequire.resolve(pkg);
178
+ } catch {
179
+ resolvedPath = projectRequire.resolve(packageName);
180
+ }
181
+ let currentDir = path.dirname(resolvedPath);
182
+ const rootDir = path.parse(currentDir).root;
183
+ while (true) {
184
+ const packageJsonPath = path.join(currentDir, "package.json");
185
+ if (existsSync(packageJsonPath)) {
186
+ const packageJsonContent = readFileSync(packageJsonPath, "utf-8");
187
+ try {
188
+ const packageJson = JSON.parse(packageJsonContent);
189
+ if (packageJson.name === packageName) return {
190
+ path: packageJsonPath,
191
+ dir: currentDir,
192
+ packageJson
193
+ };
194
+ } catch (error) {
195
+ if (!(error instanceof SyntaxError)) throw error;
196
+ }
197
+ }
198
+ if (currentDir === rootDir) break;
199
+ currentDir = path.dirname(currentDir);
200
+ }
201
+ } catch {
202
+ let currentDir = cwd;
203
+ const rootDir = path.parse(currentDir).root;
204
+ while (true) {
205
+ const directCandidate = tryReadPackageJson(path.join(currentDir, "node_modules", packageName, "package.json"));
206
+ if (directCandidate?.packageJson.name === packageName) return directCandidate;
207
+ if (currentDir === rootDir) break;
208
+ currentDir = path.dirname(currentDir);
209
+ }
210
+ return findPackageInPnpmStore(cwd);
211
+ }
212
+ }
213
+ function getInstalledPackageEntry(pkg, opts) {
214
+ const installed = getInstalledPackageJson(pkg, opts);
215
+ if (!installed) return void 0;
216
+ const packageJson = installed.packageJson;
217
+ const explicitEntry = resolveExportsEntry(packageJson.exports) || (typeof packageJson.module === "string" ? packageJson.module : void 0) || (typeof packageJson.main === "string" ? packageJson.main : void 0) || "index.js";
218
+ return path.join(installed.dir, explicitEntry);
219
+ }
133
220
  /**
134
221
  * Detect whether the current runtime is Vite 8+ by checking for a Vite version flag
135
222
  * on the plugin hook context, with Rolldown metadata kept as a compatibility fallback.
@@ -855,6 +942,14 @@ function pluginDts(options) {
855
942
  }
856
943
  //#endregion
857
944
  //#region src/utils/normalizeModuleFederationOptions.ts
945
+ const INTERNAL_NAME_PREFIX = "__mfe_internal__";
946
+ function toInternalModuleFederationName(name) {
947
+ return name.startsWith(INTERNAL_NAME_PREFIX) ? name : `${INTERNAL_NAME_PREFIX}${name}`;
948
+ }
949
+ function warnOnReservedInternalNamePrefix(name, kind) {
950
+ if (!name.startsWith(INTERNAL_NAME_PREFIX)) return;
951
+ mfWarn(`Reserved internal ${kind} prefix "${INTERNAL_NAME_PREFIX}" detected in public ${kind} "${name}". This prefix is reserved for internal module federation names and may cause conflicts.`);
952
+ }
858
953
  function normalizeExposesItem(key, item) {
859
954
  let importPath = "";
860
955
  if (typeof item === "string") importPath = item;
@@ -878,6 +973,7 @@ function normalizeRemotes(remotes) {
878
973
  return result;
879
974
  }
880
975
  function normalizeRemoteItem(key, remote) {
976
+ warnOnReservedInternalNamePrefix(key, "remoteAlias");
881
977
  if (typeof remote === "string") {
882
978
  const separatorIndex = remote.startsWith("@") ? remote.indexOf("@", 1) : remote.indexOf("@");
883
979
  let entryGlobalName;
@@ -892,6 +988,7 @@ function normalizeRemoteItem(key, remote) {
892
988
  return {
893
989
  type: "var",
894
990
  name: key,
991
+ internalName: toInternalModuleFederationName(key),
895
992
  entry,
896
993
  entryGlobalName,
897
994
  shareScope: "default"
@@ -900,9 +997,13 @@ function normalizeRemoteItem(key, remote) {
900
997
  return Object.assign({
901
998
  type: "var",
902
999
  name: key,
1000
+ internalName: toInternalModuleFederationName(key),
903
1001
  shareScope: "default",
904
1002
  entryGlobalName: key
905
- }, remote);
1003
+ }, {
1004
+ ...remote,
1005
+ internalName: toInternalModuleFederationName(remote.name || key)
1006
+ });
906
1007
  }
907
1008
  /**
908
1009
  * Tries to find the package.json's version of a shared package
@@ -934,6 +1035,12 @@ function inferVersionFromRequiredVersion(requiredVersion) {
934
1035
  if (!requiredVersion) return void 0;
935
1036
  return requiredVersion.match(/\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?/)?.[0];
936
1037
  }
1038
+ function getLitExportSubpathShares(sharedName) {
1039
+ if (sharedName !== "lit") return [];
1040
+ const exportsField = getInstalledPackageJson(sharedName, { packageName: sharedName })?.packageJson.exports;
1041
+ if (!exportsField || typeof exportsField === "string") return [];
1042
+ return Object.keys(exportsField).filter((key) => key.startsWith("./") && key !== "." && !key.includes("*")).map((key) => `${sharedName}/${key.slice(2)}`);
1043
+ }
937
1044
  function normalizeShareItem(key, shareItem) {
938
1045
  let version;
939
1046
  if (!(typeof shareItem === "object" && shareItem.import === false)) try {
@@ -977,14 +1084,21 @@ function normalizeShareItem(key, shareItem) {
977
1084
  function normalizeShared(shared) {
978
1085
  if (!shared) return {};
979
1086
  const result = {};
980
- if (Array.isArray(shared)) {
981
- shared.forEach((key) => {
982
- result[key] = normalizeShareItem(key, key);
983
- });
984
- return result;
985
- }
986
- if (typeof shared === "object") Object.keys(shared).forEach((key) => {
987
- result[key] = normalizeShareItem(key, shared[key]);
1087
+ const sourceEntries = [];
1088
+ if (Array.isArray(shared)) shared.forEach((key) => {
1089
+ result[key] = normalizeShareItem(key, key);
1090
+ sourceEntries.push([key, key]);
1091
+ });
1092
+ else if (typeof shared === "object") Object.keys(shared).forEach((key) => {
1093
+ const value = shared[key];
1094
+ result[key] = normalizeShareItem(key, value);
1095
+ sourceEntries.push([key, value]);
1096
+ });
1097
+ sourceEntries.forEach(([key, value]) => {
1098
+ for (const subpathShare of getLitExportSubpathShares(key)) {
1099
+ if (result[subpathShare]) continue;
1100
+ result[subpathShare] = normalizeShareItem(subpathShare, value);
1101
+ }
988
1102
  });
989
1103
  return result;
990
1104
  }
@@ -1009,10 +1123,12 @@ function getNormalizeShareItem(key) {
1009
1123
  return options.shared[key] || options.shared[removePathFromNpmPackage(key)] || options.shared[removePathFromNpmPackage(key) + "/"];
1010
1124
  }
1011
1125
  function normalizeModuleFederationOptions(options) {
1126
+ warnOnReservedInternalNamePrefix(options.name, "containerName");
1012
1127
  if (options.virtualModuleDir && options.virtualModuleDir.includes("/")) throw createModuleFederationError(`Invalid virtualModuleDir: "${options.virtualModuleDir}". The virtualModuleDir option cannot contain slashes (/). Please use a single directory name like '__mf__virtual__your_app_name'.`);
1013
1128
  return config = {
1014
1129
  exposes: normalizeExposes(options.exposes),
1015
1130
  filename: options.filename || "remoteEntry-[hash]",
1131
+ internalName: toInternalModuleFederationName(options.name),
1016
1132
  library: normalizeLibrary(options.library),
1017
1133
  name: options.name,
1018
1134
  remotes: normalizeRemotes(options.remotes),
@@ -1187,7 +1303,7 @@ var VirtualModule = class {
1187
1303
  return resolve(getNodeModulesDir(), this.getImportId());
1188
1304
  }
1189
1305
  getImportId() {
1190
- const { name: mfName, virtualModuleDir } = getNormalizeModuleFederationOptions();
1306
+ const { internalName: mfName, virtualModuleDir } = getNormalizeModuleFederationOptions();
1191
1307
  return `${virtualModuleDir}/${packageNameEncode(`${mfName}${this.tag}${this.name}${this.tag}`)}${this.suffix}`;
1192
1308
  }
1193
1309
  writeSync(code, force) {
@@ -1210,7 +1326,7 @@ function getExposesCssMapPlaceholder() {
1210
1326
  return EXPOSES_CSS_MAP_PLACEHOLDER;
1211
1327
  }
1212
1328
  function getVirtualExposesId(options) {
1213
- return `virtual:mf-exposes:${`${options.name}__${options.filename}`.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
1329
+ return `virtual:mf-exposes:${`${options.internalName}__${options.filename}`.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
1214
1330
  }
1215
1331
  function generateExposes(options) {
1216
1332
  return `
@@ -1444,52 +1560,6 @@ function resolvePackageEntryFromProjectRoot(pkg) {
1444
1560
  return;
1445
1561
  }
1446
1562
  }
1447
- function getInstalledPackageJsonPath(pkg) {
1448
- try {
1449
- const packageName = removePathFromNpmPackage(pkg);
1450
- const projectRequire = createRequire$1(new URL(`file://${path.join(getPackageDetectionCwd(), "package.json")}`));
1451
- let resolvedPath;
1452
- try {
1453
- resolvedPath = projectRequire.resolve(pkg);
1454
- } catch {
1455
- resolvedPath = projectRequire.resolve(packageName);
1456
- }
1457
- let currentDir = path.dirname(resolvedPath);
1458
- const rootDir = path.parse(currentDir).root;
1459
- while (currentDir !== rootDir) {
1460
- const packageJsonPath = path.join(currentDir, "package.json");
1461
- if (existsSync(packageJsonPath)) {
1462
- const packageJsonContent = readFileSync(packageJsonPath, "utf-8");
1463
- try {
1464
- if (JSON.parse(packageJsonContent).name === packageName) return packageJsonPath;
1465
- } catch (error) {
1466
- if (!(error instanceof SyntaxError)) throw error;
1467
- }
1468
- }
1469
- currentDir = path.dirname(currentDir);
1470
- }
1471
- const rootPackageJsonPath = path.join(rootDir, "package.json");
1472
- if (existsSync(rootPackageJsonPath)) {
1473
- const rootPackageJsonContent = readFileSync(rootPackageJsonPath, "utf-8");
1474
- try {
1475
- if (JSON.parse(rootPackageJsonContent).name === packageName) return rootPackageJsonPath;
1476
- } catch (error) {
1477
- if (!(error instanceof SyntaxError)) throw error;
1478
- }
1479
- }
1480
- } catch {
1481
- const packageName = removePathFromNpmPackage(pkg);
1482
- let currentDir = getPackageDetectionCwd();
1483
- const rootDir = path.parse(currentDir).root;
1484
- while (currentDir !== rootDir) {
1485
- const packageJsonPath = path.join(currentDir, "node_modules", packageName, "package.json");
1486
- if (existsSync(packageJsonPath)) return packageJsonPath;
1487
- currentDir = path.dirname(currentDir);
1488
- }
1489
- const rootPackageJsonPath = path.join(rootDir, "node_modules", packageName, "package.json");
1490
- return existsSync(rootPackageJsonPath) ? rootPackageJsonPath : void 0;
1491
- }
1492
- }
1493
1563
  function resolveImportTarget(exportsField) {
1494
1564
  if (typeof exportsField === "string") return exportsField;
1495
1565
  if (!exportsField || typeof exportsField !== "object") return void 0;
@@ -1510,14 +1580,14 @@ function resolveImportTarget(exportsField) {
1510
1580
  function getPackageEsmEntryPath(pkg) {
1511
1581
  try {
1512
1582
  const resolvedEntryPath = resolvePackageEntryFromProjectRoot(pkg);
1513
- const packageJsonPath = getInstalledPackageJsonPath(pkg);
1514
- if (!packageJsonPath) return resolvedEntryPath;
1583
+ const installedPackageJson = getInstalledPackageJson(pkg);
1584
+ if (!installedPackageJson) return resolvedEntryPath;
1515
1585
  const packageName = removePathFromNpmPackage(pkg);
1516
- const packageJson = JSON.parse(readFileSync(packageJsonPath, "utf-8"));
1586
+ const packageJson = installedPackageJson.packageJson;
1517
1587
  const subpath = pkg === packageName ? "." : `.${pkg.slice(packageName.length)}`;
1518
1588
  const target = resolveImportTarget(typeof packageJson.exports === "string" ? subpath === "." ? packageJson.exports : void 0 : packageJson.exports?.[subpath] ?? (subpath === "." ? packageJson.exports?.["."] ?? (packageJson.exports && !Object.keys(packageJson.exports).some((key) => key.startsWith(".")) ? packageJson.exports : void 0) : void 0)) || packageJson.module;
1519
1589
  if (!target) return resolvedEntryPath;
1520
- return path.resolve(path.dirname(packageJsonPath), target);
1590
+ return path.resolve(installedPackageJson.dir, target);
1521
1591
  } catch {
1522
1592
  return resolvePackageEntryFromProjectRoot(pkg);
1523
1593
  }
@@ -1661,8 +1731,11 @@ function getSharedImportSource(pkg, shareItem) {
1661
1731
  }
1662
1732
  const LOAD_SHARE_TAG = "__loadShare__";
1663
1733
  const loadShareCacheMap = {};
1734
+ function shouldUseEsmLoadShare(pkg, command, isRolldown) {
1735
+ return command === "build" || !!isRolldown || pkg === "lit" || pkg.startsWith("lit/");
1736
+ }
1664
1737
  function getLoadShareImportId(pkg, isRolldown, command) {
1665
- if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, isRolldown || command === "build" ? ".mjs" : ".js");
1738
+ if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, shouldUseEsmLoadShare(pkg, command, isRolldown) ? ".mjs" : ".js");
1666
1739
  return loadShareCacheMap[pkg].getImportId();
1667
1740
  }
1668
1741
  function getLoadShareModulePath(pkg, isRolldown, command) {
@@ -1670,8 +1743,8 @@ function getLoadShareModulePath(pkg, isRolldown, command) {
1670
1743
  return loadShareCacheMap[pkg].getPath();
1671
1744
  }
1672
1745
  function writeLoadShareModule(pkg, shareItem, command, isRolldown) {
1673
- if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, isRolldown || command === "build" ? ".mjs" : ".js");
1674
- const useESM = command === "build" || isRolldown;
1746
+ if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, shouldUseEsmLoadShare(pkg, command, isRolldown) ? ".mjs" : ".js");
1747
+ const useESM = shouldUseEsmLoadShare(pkg, command, isRolldown);
1675
1748
  const importLine = command === "build" ? getRuntimeInitPromiseBootstrapCode() : useESM ? `${getRuntimeInitBootstrapCode()}
1676
1749
  const { initPromise } = globalThis[globalKey];` : `const {initPromise} = require("${virtualRuntimeInitStatus.getImportId()}")`;
1677
1750
  const awaitOrPlaceholder = useESM ? "await " : "/*mf top-level-await placeholder replacement mf*/";
@@ -1705,6 +1778,7 @@ function writeLoadShareModule(pkg, shareItem, command, isRolldown) {
1705
1778
  const devImportSource = concreteSharedImportSource || pkg;
1706
1779
  const localProviderPath = getLocalProviderImportPath(pkg);
1707
1780
  const isWorkspacePackage = isWorkspaceFilePath(localProviderPath) || isWorkspaceFilePath(concreteSharedImportSource);
1781
+ const skipServePrebuildWarmup = command !== "build" && (pkg === "lit" || pkg.startsWith("lit/"));
1708
1782
  const providerImportId = localProviderPath || concreteSharedImportSource || sharedImportSource;
1709
1783
  const namedExports = getPackageNamedExports(pkg);
1710
1784
  let exportLine;
@@ -1713,8 +1787,8 @@ function writeLoadShareModule(pkg, shareItem, command, isRolldown) {
1713
1787
  const namedExportLine = `export { ${namedExports.map((name, i) => `__mf_${i} as ${name}`).join(", ")} };`;
1714
1788
  exportLine = useESM ? `export default exportModule.default ?? exportModule;\n ${destructure}\n ${namedExportLine}` : `module.exports = exportModule;\n ${destructure}\n Object.assign(module.exports, { ${namedExports.map((name, i) => `"${name}": __mf_${i}`).join(", ")} });`;
1715
1789
  } else exportLine = useESM ? `export default exportModule.default ?? exportModule\n export * from ${escapeGeneratedStringLiteral(sharedImportSource)}` : "module.exports = exportModule";
1716
- const prebuildImportLine = isWorkspacePackage && command !== "build" ? "" : `import ${escapeGeneratedStringLiteral(sharedImportSource)};`;
1717
- const devDynamicImportLine = isWorkspacePackage ? "" : command !== "build" ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
1790
+ const prebuildImportLine = isWorkspacePackage && command !== "build" || skipServePrebuildWarmup ? "" : `import ${escapeGeneratedStringLiteral(sharedImportSource)};`;
1791
+ const devDynamicImportLine = isWorkspacePackage ? "" : command !== "build" && !skipServePrebuildWarmup ? `;() => import(${escapeGeneratedStringLiteral(devImportSource)}).catch(() => {});` : "";
1718
1792
  loadShareCacheMap[pkg].writeSync(`
1719
1793
  ${prebuildImportLine}
1720
1794
  ${devDynamicImportLine}
@@ -1788,7 +1862,7 @@ function generateLocalSharedImportMap() {
1788
1862
  version: ${JSON.stringify(shareItem.version)},
1789
1863
  scope: [${JSON.stringify(shareItem.scope)}],
1790
1864
  loaded: false,
1791
- from: ${JSON.stringify(options.name)},
1865
+ from: ${JSON.stringify(options.internalName)},
1792
1866
  async get () {
1793
1867
  if (${shareItem.shareConfig.import === false}) {
1794
1868
  throw new Error(\`[Module Federation] Shared module '\${${JSON.stringify(key)}}' must be provided by host\`);
@@ -1839,7 +1913,7 @@ function generateLocalSharedImportMap() {
1839
1913
  }
1840
1914
  const REMOTE_ENTRY_ID = "virtual:mf-REMOTE_ENTRY_ID";
1841
1915
  function getRemoteEntryId(options) {
1842
- return `${REMOTE_ENTRY_ID}:${`${options.name}__${options.filename}`.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
1916
+ return `${REMOTE_ENTRY_ID}:${`${options.internalName}__${options.filename}`.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
1843
1917
  }
1844
1918
  function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(options), command = "build") {
1845
1919
  const pluginImportNames = options.runtimePlugins.map((p, i) => {
@@ -1868,7 +1942,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1868
1942
  ${command === "build" ? getRuntimeInitResolveBootstrapCode() : getRuntimeInitBootstrapCode() + "\n const { initResolve } = globalThis[globalKey];"}
1869
1943
  const initTokens = {}
1870
1944
  const shareScopeName = ${JSON.stringify(options.shareScope)}
1871
- const mfName = ${JSON.stringify(options.name)}
1945
+ const mfName = ${JSON.stringify(options.internalName)}
1872
1946
  let localSharedImportMapPromise
1873
1947
  let exposesMapPromise
1874
1948
 
@@ -2435,7 +2509,7 @@ function pluginModuleParseEnd_default(excludeFn, options) {
2435
2509
  }
2436
2510
  //#endregion
2437
2511
  //#region src/plugins/pluginProxyRemoteEntry.ts
2438
- const filter = createFilter();
2512
+ const filter$1 = createFilter();
2439
2513
  function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposesId }) {
2440
2514
  let viteConfig, _command, root;
2441
2515
  return {
@@ -2475,7 +2549,7 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
2475
2549
  },
2476
2550
  transform(code, id) {
2477
2551
  return mapCodeToCodeWithSourcemap((() => {
2478
- if (!filter(id)) return;
2552
+ if (!filter$1(id)) return;
2479
2553
  if (id.includes(remoteEntryId)) return parsePromise.then((_) => generateRemoteEntry(options, virtualExposesId, _command));
2480
2554
  if (id === virtualExposesId) return generateExposes(options);
2481
2555
  if (id.includes(getHostAutoInitPath())) {
@@ -2548,25 +2622,47 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
2548
2622
  }
2549
2623
  //#endregion
2550
2624
  //#region src/plugins/pluginProxyRemotes.ts
2551
- createFilter();
2625
+ const filter = createFilter();
2626
+ function isNodeModulesImporter(importer) {
2627
+ return importer?.includes("/node_modules/") || importer?.includes("\\node_modules\\");
2628
+ }
2552
2629
  function pluginProxyRemotes_default(options) {
2630
+ let command;
2631
+ let root = process.cwd();
2553
2632
  const { remotes } = options;
2633
+ function resolveRemoteId(source, importer, remoteName, isRolldown) {
2634
+ if (source === remoteName) {
2635
+ const installedPackageEntry = getInstalledPackageEntry(source, { cwd: root });
2636
+ if (installedPackageEntry && (importer === void 0 || isNodeModulesImporter(importer))) return installedPackageEntry;
2637
+ }
2638
+ const remoteModule = getRemoteVirtualModule(source, command, isRolldown);
2639
+ addUsedRemote(remoteName, source);
2640
+ return remoteModule.getPath();
2641
+ }
2554
2642
  return {
2555
2643
  name: "proxyRemotes",
2556
2644
  config(config, { command: _command }) {
2645
+ command = _command;
2646
+ root = config.root || process.cwd();
2557
2647
  const isRolldown = getIsRolldown(this);
2558
2648
  Object.keys(remotes).forEach((key) => {
2559
2649
  const remote = remotes[key];
2560
2650
  config.resolve.alias.push({
2561
2651
  find: new RegExp(`^(${remote.name}(\/.*|$))`),
2562
2652
  replacement: "$1",
2563
- customResolver(source) {
2564
- const remoteModule = getRemoteVirtualModule(source, _command, isRolldown);
2565
- addUsedRemote(remote.name, source);
2566
- return remoteModule.getPath();
2653
+ customResolver(source, importer) {
2654
+ return resolveRemoteId(source, importer, remote.name, isRolldown);
2567
2655
  }
2568
2656
  });
2569
2657
  });
2658
+ },
2659
+ resolveId(source, importer) {
2660
+ if (!filter(source)) return;
2661
+ const isRolldown = getIsRolldown(this);
2662
+ for (const remote of Object.values(remotes)) {
2663
+ if (source !== remote.name) continue;
2664
+ return resolveRemoteId(source, importer, remote.name, isRolldown);
2665
+ }
2570
2666
  }
2571
2667
  };
2572
2668
  }
@@ -3042,24 +3138,31 @@ function collectFromRegex(code, isRemoteImport) {
3042
3138
  }
3043
3139
  function pluginRemoteNamedExports(options) {
3044
3140
  const remoteNames = Object.keys(options.remotes);
3045
- function isRemoteImport(source) {
3046
- return remoteNames.some((name) => source === name || source.startsWith(name + "/")) || source.includes("__loadRemote__");
3141
+ const isNodeModulesId = (id) => id.includes("/node_modules/") || id.includes("\\node_modules\\");
3142
+ function isRemoteImport(source, importerId) {
3143
+ return remoteNames.some((name) => {
3144
+ if (source.startsWith(name + "/")) return true;
3145
+ if (source !== name) return false;
3146
+ return !isNodeModulesId(importerId);
3147
+ }) || source.includes("__loadRemote__");
3047
3148
  }
3048
3149
  return {
3049
3150
  name: "module-federation-remote-named-exports",
3050
3151
  enforce: "post",
3051
3152
  async transform(code, id) {
3153
+ if (!getIsRolldown(this)) return;
3052
3154
  if (remoteNames.length === 0) return;
3053
3155
  if (id.includes("__loadRemote__") || id.includes("__loadShare__")) return;
3054
3156
  if (!JS_EXTENSIONS_RE.test(id)) return;
3055
3157
  if (!remoteNames.some((name) => code.includes(name))) return;
3158
+ const matchesRemoteImport = (source) => isRemoteImport(source, id);
3056
3159
  let imports;
3057
3160
  try {
3058
- imports = await collectFromAST(this.parse(code), code, isRemoteImport);
3161
+ imports = await collectFromAST(this.parse(code), code, matchesRemoteImport);
3059
3162
  } catch {
3060
- imports = await collectFromEsLexer(code, isRemoteImport);
3163
+ imports = await collectFromEsLexer(code, matchesRemoteImport);
3061
3164
  }
3062
- if ((!imports || imports.length === 0) && REGEX_FALLBACK_EXTENSIONS_RE.test(id)) imports = collectFromRegex(code, isRemoteImport);
3165
+ if ((!imports || imports.length === 0) && REGEX_FALLBACK_EXTENSIONS_RE.test(id)) imports = collectFromRegex(code, matchesRemoteImport);
3063
3166
  if (!imports) return;
3064
3167
  return applyRewrites(code, imports, id);
3065
3168
  }
@@ -3307,6 +3410,7 @@ function insertAfterLastTopLevelImport(code, snippet) {
3307
3410
  */
3308
3411
  function createEarlyVirtualModulesPlugin(options) {
3309
3412
  const { shared, remotes, virtualModuleDir } = options;
3413
+ const isLitShare = (pkg) => pkg === "lit" || pkg.startsWith("lit/");
3310
3414
  return {
3311
3415
  name: "vite:module-federation-early-init",
3312
3416
  enforce: "pre",
@@ -3319,16 +3423,23 @@ function createEarlyVirtualModulesPlugin(options) {
3319
3423
  VirtualModule.ensureVirtualPackageExists();
3320
3424
  initVirtualModules(_command, getRemoteEntryId(options));
3321
3425
  const isRolldown = getIsRolldown(this);
3322
- if (remotes && Object.keys(remotes).length > 0) for (const key of Object.keys(remotes)) addUsedRemote(key, key);
3426
+ if (remotes && Object.keys(remotes).length > 0) {
3427
+ for (const key of Object.keys(remotes)) addUsedRemote(key, key);
3428
+ if (_command === "serve" && isRolldown) {
3429
+ config.optimizeDeps = config.optimizeDeps || {};
3430
+ config.optimizeDeps.exclude = config.optimizeDeps.exclude || [];
3431
+ config.optimizeDeps.include = config.optimizeDeps.include || [];
3432
+ const collidingInstalledRemotes = Object.keys(remotes || {}).filter((remoteName) => getInstalledPackageJson(remoteName, { cwd: root }));
3433
+ const collidingInstalledRemoteEntries = collidingInstalledRemotes.map((remoteName) => getInstalledPackageEntry(remoteName, { cwd: root }) || remoteName);
3434
+ config.optimizeDeps.exclude.push(...Object.keys(remotes || {}).filter((remoteName) => !collidingInstalledRemotes.includes(remoteName)));
3435
+ config.optimizeDeps.include.push(...collidingInstalledRemoteEntries);
3436
+ }
3437
+ }
3323
3438
  if (shared && Object.keys(shared).length > 0) {
3324
3439
  if (_command === "serve") {
3325
3440
  config.optimizeDeps = config.optimizeDeps || {};
3326
3441
  config.optimizeDeps.include = config.optimizeDeps.include || [];
3327
3442
  config.optimizeDeps.include.push(virtualRuntimeInitStatus.getImportId());
3328
- if (isRolldown) {
3329
- config.optimizeDeps.exclude = config.optimizeDeps.exclude || [];
3330
- config.optimizeDeps.exclude.push(...Object.keys(remotes || {}));
3331
- }
3332
3443
  }
3333
3444
  for (const key of Object.keys(shared)) {
3334
3445
  if (key.endsWith("/")) continue;
@@ -3342,8 +3453,13 @@ function createEarlyVirtualModulesPlugin(options) {
3342
3453
  if (shareItem.shareConfig?.import !== false) writePreBuildLibPath(key, shareItem);
3343
3454
  addUsedShares(key);
3344
3455
  if (_command === "serve" && shareItem.shareConfig?.import !== false) {
3345
- if (!isRolldown) config.optimizeDeps.include.push(getLoadShareImportId(key, isRolldown, _command));
3346
- config.optimizeDeps.include.push(getPreBuildLibImportId(key));
3456
+ const optimizeDeps = config.optimizeDeps ??= {};
3457
+ optimizeDeps.include ??= [];
3458
+ optimizeDeps.exclude ??= [];
3459
+ const shouldBypassOptimizeDep = isLitShare(key);
3460
+ if (shouldBypassOptimizeDep) optimizeDeps.exclude.push(key);
3461
+ if (!isRolldown && !shouldBypassOptimizeDep) optimizeDeps.include.push(getLoadShareImportId(key, isRolldown, _command));
3462
+ optimizeDeps.include.push(getPreBuildLibImportId(key));
3347
3463
  }
3348
3464
  }
3349
3465
  writeLocalSharedImportMap();
@@ -3361,6 +3477,7 @@ function federation(mfUserOptions) {
3361
3477
  const virtualExposesId = getVirtualExposesId(options);
3362
3478
  let command;
3363
3479
  let depsDir = "/node_modules/.vite/deps/";
3480
+ let desiredRolldownOutput;
3364
3481
  return [
3365
3482
  createEarlyVirtualModulesPlugin(options),
3366
3483
  ...isVinext ? [{
@@ -3451,12 +3568,22 @@ function federation(mfUserOptions) {
3451
3568
  };
3452
3569
  }
3453
3570
  let warnedAboutCodeSplitting = false;
3571
+ let warnedAboutCodeSplittingGroups = false;
3454
3572
  const ensureCodeSplitting = (output) => {
3455
- if (output?.codeSplitting !== false) return;
3456
- delete output.codeSplitting;
3457
- if (warnedAboutCodeSplitting) return;
3458
- warnedAboutCodeSplitting = true;
3459
- mfWarn("Ignoring `build.rolldownOptions.output.codeSplitting = false` because module federation requires chunk splitting.");
3573
+ if (output?.codeSplitting === false) {
3574
+ delete output.codeSplitting;
3575
+ if (warnedAboutCodeSplitting) return;
3576
+ warnedAboutCodeSplitting = true;
3577
+ mfWarn("Ignoring `output.codeSplitting = false` because module federation requires chunk splitting.");
3578
+ return;
3579
+ }
3580
+ if (!output?.codeSplitting || typeof output.codeSplitting !== "object") return;
3581
+ if (!("groups" in output.codeSplitting)) return;
3582
+ delete output.codeSplitting.groups;
3583
+ if (Object.keys(output.codeSplitting).length === 0) delete output.codeSplitting;
3584
+ if (warnedAboutCodeSplittingGroups) return;
3585
+ warnedAboutCodeSplittingGroups = true;
3586
+ mfWarn("Ignoring `output.codeSplitting.groups` because it conflicts with module federation. Grouping shared dependency init wrappers with their dependent modules can break runtime init order and cause standalone remotes to fail before mount.");
3460
3587
  };
3461
3588
  let warnedAboutManualChunks = false;
3462
3589
  const applyManualChunks = (output) => {
@@ -3464,7 +3591,7 @@ function federation(mfUserOptions) {
3464
3591
  const isPatchedByPlugin = !!(output.manualChunks && patchedManualChunks.has(output.manualChunks));
3465
3592
  if (output.manualChunks && !isPatchedByPlugin && !warnedAboutManualChunks) {
3466
3593
  warnedAboutManualChunks = true;
3467
- mfWarn("Ignoring `build.rollupOptions.output.manualChunks` because it conflicts with module federation. Module federation transforms shared dependency imports with top-level await, and grouping these transformed modules into a single chunk creates circular async dependencies that cause the application to silently hang.");
3594
+ mfWarn("Ignoring `output.manualChunks` because it conflicts with module federation. Module federation transforms shared dependency imports with top-level await, and grouping these transformed modules into a single chunk creates circular async dependencies that cause the application to silently hang.");
3468
3595
  }
3469
3596
  const mfManualChunks = function(id) {
3470
3597
  if (id.includes(runtimeInitId)) return "runtimeInit";
@@ -3477,10 +3604,46 @@ function federation(mfUserOptions) {
3477
3604
  output.manualChunks = mfManualChunks;
3478
3605
  };
3479
3606
  config.build.rollupOptions = config.build.rollupOptions || {};
3480
- if (!Array.isArray(config.build.rollupOptions.output)) applyManualChunks(config.build.rollupOptions.output ||= {});
3607
+ const rollupOutput = config.build.rollupOptions.output;
3608
+ if (Array.isArray(rollupOutput)) rollupOutput.forEach((output) => applyManualChunks(output));
3609
+ else applyManualChunks(config.build.rollupOptions.output ||= {});
3481
3610
  const buildWithRolldown = config.build;
3482
3611
  buildWithRolldown.rolldownOptions = buildWithRolldown.rolldownOptions || {};
3483
- if (!Array.isArray(buildWithRolldown.rolldownOptions.output)) applyManualChunks(buildWithRolldown.rolldownOptions.output ||= {});
3612
+ const rolldownOutput = buildWithRolldown.rolldownOptions.output;
3613
+ const snapshotRolldownOutput = (output) => ({
3614
+ entryFileNames: output.entryFileNames,
3615
+ chunkFileNames: output.chunkFileNames,
3616
+ assetFileNames: output.assetFileNames
3617
+ });
3618
+ if (Array.isArray(rolldownOutput)) {
3619
+ rolldownOutput.forEach((output) => applyManualChunks(output));
3620
+ desiredRolldownOutput = rolldownOutput.map((output) => snapshotRolldownOutput(output));
3621
+ } else {
3622
+ applyManualChunks(buildWithRolldown.rolldownOptions.output ||= {});
3623
+ desiredRolldownOutput = [snapshotRolldownOutput(buildWithRolldown.rolldownOptions.output)];
3624
+ }
3625
+ },
3626
+ async buildApp(builder) {
3627
+ if (!desiredRolldownOutput) return;
3628
+ const applyRolldownOutput = (output, restoredOutput) => {
3629
+ if (!output || !restoredOutput) return;
3630
+ if (restoredOutput.entryFileNames !== void 0) output.entryFileNames = restoredOutput.entryFileNames;
3631
+ if (restoredOutput.chunkFileNames !== void 0) output.chunkFileNames = restoredOutput.chunkFileNames;
3632
+ if (restoredOutput.assetFileNames !== void 0) output.assetFileNames = restoredOutput.assetFileNames;
3633
+ };
3634
+ for (const environment of Object.values(builder.environments)) {
3635
+ const getRolldownOptions = environment?.getRolldownOptions;
3636
+ if (typeof getRolldownOptions !== "function") continue;
3637
+ environment.getRolldownOptions = async () => {
3638
+ const rolldownOptions = await getRolldownOptions.call(environment);
3639
+ if (Array.isArray(rolldownOptions.output)) rolldownOptions.output.forEach((output, index) => applyRolldownOutput(output, desiredRolldownOutput?.[index]));
3640
+ else {
3641
+ rolldownOptions.output ||= {};
3642
+ applyRolldownOutput(rolldownOptions.output, desiredRolldownOutput[0]);
3643
+ }
3644
+ return rolldownOptions;
3645
+ };
3646
+ }
3484
3647
  },
3485
3648
  load(id) {
3486
3649
  if (id.startsWith("\0")) return;
@@ -3739,12 +3902,12 @@ function federation(mfUserOptions) {
3739
3902
  const prefixToRoot = chunkDir === "." ? "" : `${path.relative(chunkDir, ".")}/`;
3740
3903
  const replacementExpr = prefixToRoot ? `${escapeUnsafeJsSourceChars(JSON.stringify(prefixToRoot))}+$1` : "$1";
3741
3904
  const replacement = `=function($1){return new URL(${replacementExpr},import.meta.url).href}`;
3742
- const replaced = chunk.code.replace(/=\(?(\w+)(?:,\w+)?\)?\s*=>\s*["'][./][^"']*["']\s*\+\s*\1/, replacement);
3905
+ const replaced = chunk.code.replace(/=\(?(\w+)(?:,\w+)?\)?\s*=>\s*[`"'][./][^`"']*[`"']\s*\+\s*\1/, replacement);
3743
3906
  if (replaced !== chunk.code) {
3744
3907
  chunk.code = replaced;
3745
3908
  continue;
3746
3909
  }
3747
- chunk.code = chunk.code.replace(/=function\((\w+)(?:,\w+)?\)\{return\s*["'][./][^"']*["']\s*\+\s*\1\s*\}/, replacement);
3910
+ chunk.code = chunk.code.replace(/=function\((\w+)(?:,\w+)?\)\{return\s*[`"'][./][^`"']*[`"']\s*\+\s*\1\s*\}/, replacement);
3748
3911
  chunk.code = chunk.code.replace(/=function\((\w+)(?:,\w+)?\)\{return new URL\("\.\.\/"\+\1,import\.meta\.url\)\.href\}/, replacement);
3749
3912
  chunk.code = chunk.code.replace(/new URL\("\.\.\/"\+(\w+),import\.meta\.url\)\.href/g, `new URL(${replacementExpr},import.meta.url).href`);
3750
3913
  }