@module-federation/vite 1.11.1 → 1.12.1-next.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/lib/index.mjs CHANGED
@@ -6,15 +6,13 @@ import * as path$1 from "pathe";
6
6
  import path, { basename, dirname, join, parse, resolve } from "pathe";
7
7
  import MagicString from "magic-string";
8
8
  import { createFilter } from "@rollup/pluginutils";
9
- import { walk } from "estree-walker";
10
9
  import { normalizeOptions } from "@module-federation/sdk";
11
10
  import { consumeTypesAPI, generateTypesAPI, isTSProject, normalizeConsumeTypesOptions, normalizeDtsOptions, normalizeGenerateTypesOptions } from "@module-federation/dts-plugin";
12
11
  import { rpc } from "@module-federation/dts-plugin/core";
12
+ import { createRequire as createRequire$1 } from "module";
13
13
  import { fileURLToPath } from "url";
14
-
15
14
  //#region \0rolldown/runtime.js
16
15
  var __require = /* @__PURE__ */ createRequire(import.meta.url);
17
-
18
16
  //#endregion
19
17
  //#region src/utils/mapCodeToCodeWithSourcemap.ts
20
18
  async function mapCodeToCodeWithSourcemap(code) {
@@ -26,14 +24,14 @@ async function mapCodeToCodeWithSourcemap(code) {
26
24
  map: s.generateMap({ hires: true })
27
25
  };
28
26
  }
29
-
30
27
  //#endregion
31
28
  //#region src/plugins/pluginAddEntry.ts
32
29
  function getFirstHtmlEntryFile(entryFiles) {
33
30
  return entryFiles.find((file) => file.endsWith(".html"));
34
31
  }
35
32
  const addEntry = ({ entryName, entryPath, fileName, inject = "entry" }) => {
36
- let devEntryPath = entryPath.startsWith("virtual:mf") ? "@id/" + entryPath : entryPath;
33
+ const getEntryPath = () => typeof entryPath === "function" ? entryPath() : entryPath;
34
+ let devEntryPath = "";
37
35
  let entryFiles = [];
38
36
  let htmlFilePath;
39
37
  let _command;
@@ -53,6 +51,8 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry" }) => {
53
51
  },
54
52
  configResolved(config) {
55
53
  viteConfig = config;
54
+ const resolvedEntryPath = getEntryPath();
55
+ devEntryPath = resolvedEntryPath.startsWith("virtual:mf") ? "@id/" + resolvedEntryPath : resolvedEntryPath;
56
56
  devEntryPath = config.base + devEntryPath.replace(/\\\\?/g, "/").replace(/.+?\:([/\\])[/\\]?/, "$1").replace(/^\//, "");
57
57
  },
58
58
  configureServer(server) {
@@ -94,7 +94,7 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry" }) => {
94
94
  const emitFileOptions = {
95
95
  name: entryName,
96
96
  type: "chunk",
97
- id: entryPath,
97
+ id: getEntryPath(),
98
98
  preserveSignature: "strict"
99
99
  };
100
100
  if (!hasHash) emitFileOptions.fileName = fileName;
@@ -140,12 +140,11 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry" }) => {
140
140
  },
141
141
  transform(code, id) {
142
142
  if (injectEntry() && entryFiles.some((file) => id.endsWith(file))) return mapCodeToCodeWithSourcemap(`
143
- import ${JSON.stringify(entryPath)};
143
+ import ${JSON.stringify(getEntryPath())};
144
144
  ` + code);
145
145
  }
146
146
  }];
147
147
  };
148
-
149
148
  //#endregion
150
149
  //#region src/plugins/pluginCheckAliasConflicts.ts
151
150
  /**
@@ -185,19 +184,23 @@ function checkAliasConflicts(options) {
185
184
  }
186
185
  };
187
186
  }
188
-
189
187
  //#endregion
190
188
  //#region src/plugins/pluginDevProxyModuleTopLevelAwait.ts
191
189
  /**
192
190
  * Solve the problem that dev mode dependency prebunding does not support top-level await syntax
193
191
  */
192
+ let walkPromise = null;
193
+ function loadWalk() {
194
+ walkPromise ||= import("estree-walker").then(({ walk }) => walk);
195
+ return walkPromise;
196
+ }
194
197
  function PluginDevProxyModuleTopLevelAwait() {
195
198
  const filterFunction = createFilter();
196
199
  const processedFlag = "/* already-processed-by-dev-proxy-module-top-level-await */";
197
200
  return {
198
201
  name: "dev-proxy-module-top-level-await",
199
202
  apply: "serve",
200
- transform(code, id) {
203
+ async transform(code, id) {
201
204
  if (code.includes(processedFlag)) return null;
202
205
  if (!code.includes("/*mf top-level-await placeholder replacement mf*/")) return null;
203
206
  if (!filterFunction(id)) return null;
@@ -208,7 +211,7 @@ function PluginDevProxyModuleTopLevelAwait() {
208
211
  throw new Error(`${id}: ${e}`);
209
212
  }
210
213
  const magicString = new MagicString(code);
211
- walk(ast, { enter(node) {
214
+ (await loadWalk())(ast, { enter(node) {
212
215
  if (node.type === "ExportNamedDeclaration" && node.specifiers) {
213
216
  const exportSpecifiers = node.specifiers.map((specifier) => specifier.exported.name);
214
217
  const proxyStatements = exportSpecifiers.map((name) => `
@@ -250,7 +253,6 @@ function PluginDevProxyModuleTopLevelAwait() {
250
253
  }
251
254
  };
252
255
  }
253
-
254
256
  //#endregion
255
257
  //#region src/plugins/pluginDts.ts
256
258
  const DEFAULT_DEV_OPTIONS = {
@@ -478,7 +480,6 @@ function pluginDts(options) {
478
480
  }
479
481
  }];
480
482
  }
481
-
482
483
  //#endregion
483
484
  //#region src/utils/normalizeModuleFederationOptions.ts
484
485
  function normalizeExposesItem(key, item) {
@@ -553,8 +554,7 @@ function normalizeShareItem(key, shareItem) {
553
554
  version = __require(path$1.join(removePathFromNpmPackage(key), "package.json")).version;
554
555
  } catch (e1) {
555
556
  try {
556
- const localPath = path$1.join(process.cwd(), "node_modules", removePathFromNpmPackage(key), "package.json");
557
- version = __require(localPath).version;
557
+ version = __require(path$1.join(process.cwd(), "node_modules", removePathFromNpmPackage(key), "package.json")).version;
558
558
  } catch (e2) {
559
559
  version = searchPackageVersion(key);
560
560
  if (!version) console.error(e1);
@@ -645,11 +645,11 @@ function normalizeModuleFederationOptions(options) {
645
645
  hostInitInjectLocation: options.hostInitInjectLocation || "html",
646
646
  bundleAllCSS: options.bundleAllCSS || false,
647
647
  moduleParseTimeout: options.moduleParseTimeout || 10,
648
+ moduleParseIdleTimeout: options.moduleParseIdleTimeout,
648
649
  varFilename: options.varFilename,
649
650
  target: options.target
650
651
  };
651
652
  }
652
-
653
653
  //#endregion
654
654
  //#region src/utils/packageNameUtils.ts
655
655
  /**
@@ -678,7 +678,6 @@ function packageNameDecode(encoded) {
678
678
  if (typeof encoded !== "string") throw new Error("A string encoded file name is required");
679
679
  return encoded.replace(/_mf_0_/g, "@").replace(/_mf_1_/g, "/").replace(/_mf_2_/g, "-").replace(/_mf_3_/g, ".");
680
680
  }
681
-
682
681
  //#endregion
683
682
  //#region src/utils/localSharedImportMap_temp.ts
684
683
  /**
@@ -695,7 +694,6 @@ function createFile(filePath, content) {
695
694
  mkdirSync(path.dirname(filePath), { recursive: true });
696
695
  writeFileSync(filePath, content);
697
696
  }
698
-
699
697
  //#endregion
700
698
  //#region src/utils/serializeRuntimeOptions.ts
701
699
  /**
@@ -743,9 +741,22 @@ function serializeRuntimeOptions(options) {
743
741
  for (const key in options) if (Object.prototype.hasOwnProperty.call(options, key)) topLevelProps.push(`${JSON.stringify(key)}: ${valueToCode(options[key])}`);
744
742
  return `{${topLevelProps.join(", ")}}`;
745
743
  }
746
-
747
744
  //#endregion
748
745
  //#region src/utils/VirtualModule.ts
746
+ /**
747
+ * Initialize virtual module infrastructure BEFORE VirtualModule class is used.
748
+ * This must be called in the config hook to ensure the directory exists
749
+ * before Vite's optimization phase.
750
+ */
751
+ function initVirtualModuleInfrastructure(root, virtualModuleDir = "__mf__virtual") {
752
+ const virtualPackagePath = join(join(root, "node_modules"), virtualModuleDir);
753
+ mkdirSync(virtualPackagePath, { recursive: true });
754
+ writeFileSync(join(virtualPackagePath, "empty.js"), "");
755
+ writeFileSync(join(virtualPackagePath, "package.json"), JSON.stringify({
756
+ name: virtualModuleDir,
757
+ main: "empty.js"
758
+ }));
759
+ }
749
760
  let rootDir;
750
761
  function findNodeModulesDir(root = process.cwd()) {
751
762
  let currentDir = root;
@@ -793,14 +804,12 @@ var VirtualModule = class {
793
804
  const nodeModulesDir = getNodeModulesDir();
794
805
  const { virtualModuleDir } = getNormalizeModuleFederationOptions();
795
806
  const virtualPackagePath = resolve(nodeModulesDir, virtualModuleDir);
796
- if (!existsSync(virtualPackagePath)) {
797
- mkdirSync(virtualPackagePath);
798
- writeFileSync(resolve(virtualPackagePath, "empty.js"), "");
799
- writeFileSync(resolve(virtualPackagePath, "package.json"), JSON.stringify({
800
- name: virtualModuleDir,
801
- main: "empty.js"
802
- }));
803
- }
807
+ mkdirSync(virtualPackagePath, { recursive: true });
808
+ writeFileSync(resolve(virtualPackagePath, "empty.js"), "");
809
+ writeFileSync(resolve(virtualPackagePath, "package.json"), JSON.stringify({
810
+ name: virtualModuleDir,
811
+ main: "empty.js"
812
+ }));
804
813
  }
805
814
  static findModule(tag, str = "") {
806
815
  if (!patternMap[tag]) patternMap[tag] = new RegExp(`(.*${packageNameEncode(tag)}(.+?)${packageNameEncode(tag)}.*)`);
@@ -831,12 +840,12 @@ var VirtualModule = class {
831
840
  writeFile(this.getPath(), code, function() {});
832
841
  }
833
842
  };
834
-
835
843
  //#endregion
836
844
  //#region src/virtualModules/virtualExposes.ts
837
- const VIRTUAL_EXPOSES = "virtual:mf-exposes";
838
- function generateExposes() {
839
- const options = getNormalizeModuleFederationOptions();
845
+ function getVirtualExposesId(options) {
846
+ return `virtual:mf-exposes:${`${options.name}__${options.filename}`.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
847
+ }
848
+ function generateExposes(options) {
840
849
  return `
841
850
  export default {
842
851
  ${Object.keys(options.exposes).map((key) => {
@@ -856,7 +865,6 @@ function generateExposes() {
856
865
  }
857
866
  `;
858
867
  }
859
-
860
868
  //#endregion
861
869
  //#region src/virtualModules/virtualRuntimeInitStatus.ts
862
870
  const virtualRuntimeInitStatus = new VirtualModule("runtimeInit");
@@ -881,15 +889,14 @@ if (!globalThis[globalKey]) {
881
889
  ${exportStatement}
882
890
  `);
883
891
  }
884
-
885
892
  //#endregion
886
893
  //#region src/virtualModules/virtualRemotes.ts
887
894
  const cacheRemoteMap = {};
888
895
  const LOAD_REMOTE_TAG = "__loadRemote__";
889
- function getRemoteVirtualModule(remote, command) {
896
+ function getRemoteVirtualModule(remote, command, isRolldown) {
890
897
  if (!cacheRemoteMap[remote]) {
891
- cacheRemoteMap[remote] = new VirtualModule(remote, LOAD_REMOTE_TAG, ".js");
892
- cacheRemoteMap[remote].writeSync(generateRemotes(remote, command));
898
+ cacheRemoteMap[remote] = new VirtualModule(remote, LOAD_REMOTE_TAG, isRolldown ? ".mjs" : ".js");
899
+ cacheRemoteMap[remote].writeSync(generateRemotes(remote, command, isRolldown));
893
900
  }
894
901
  return cacheRemoteMap[remote];
895
902
  }
@@ -901,11 +908,11 @@ function addUsedRemote(remoteKey, remoteModule) {
901
908
  function getUsedRemotesMap() {
902
909
  return usedRemotesMap;
903
910
  }
904
- function generateRemotes(id, command) {
905
- const isBuild = command === "build";
906
- const importLine = isBuild ? `import { initPromise } from "${virtualRuntimeInitStatus.getImportId()}"` : `const {initPromise} = require("${virtualRuntimeInitStatus.getImportId()}")`;
907
- const awaitOrPlaceholder = isBuild ? "await " : "/*mf top-level-await placeholder replacement mf*/";
908
- const exportLine = isBuild ? "export default exportModule" : "module.exports = exportModule";
911
+ function generateRemotes(id, command, isRolldown) {
912
+ const useESM = command === "build" || isRolldown;
913
+ const importLine = useESM ? `import { initPromise } from "${virtualRuntimeInitStatus.getImportId()}"` : `const {initPromise} = require("${virtualRuntimeInitStatus.getImportId()}")`;
914
+ const awaitOrPlaceholder = useESM ? "await " : "/*mf top-level-await placeholder replacement mf*/";
915
+ const exportLine = command === "serve" && useESM ? "export default exportModule.default ?? exportModule" : useESM ? "export default exportModule" : "module.exports = exportModule";
909
916
  return `
910
917
  ${importLine}
911
918
  const res = initPromise.then(runtime => runtime.loadRemote(${JSON.stringify(id)}))
@@ -913,9 +920,26 @@ function generateRemotes(id, command) {
913
920
  ${exportLine}
914
921
  `;
915
922
  }
916
-
917
923
  //#endregion
918
924
  //#region src/virtualModules/virtualShared_preBuild.ts
925
+ /**
926
+ * Even the resolveId hook cannot interfere with vite pre-build,
927
+ * and adding query parameter virtual modules will also fail.
928
+ * You can only proxy to the real file through alias
929
+ */
930
+ /**
931
+ * shared will be proxied:
932
+ * 1. __prebuild__: export shareModule (pre-built source code of modules such as vue, react, etc.)
933
+ * 2. __loadShare__: load shareModule (mfRuntime.loadShare('vue'))
934
+ */
935
+ function getPackageNamedExports(pkg) {
936
+ try {
937
+ const mod = createRequire$1(new URL("file://" + process.cwd() + "/package.json"))(pkg);
938
+ return Object.keys(mod).filter((k) => k !== "default" && k !== "__esModule");
939
+ } catch {
940
+ return [];
941
+ }
942
+ }
919
943
  const preBuildCacheMap = {};
920
944
  const PREBUILD_TAG = "__prebuild__";
921
945
  function writePreBuildLibPath(pkg) {
@@ -928,17 +952,24 @@ function getPreBuildLibImportId(pkg) {
928
952
  }
929
953
  const LOAD_SHARE_TAG = "__loadShare__";
930
954
  const loadShareCacheMap = {};
931
- function getLoadShareModulePath(pkg) {
932
- if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, ".js");
955
+ function getLoadShareModulePath(pkg, isRolldown, command) {
956
+ if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, isRolldown || command === "build" ? ".mjs" : ".js");
933
957
  return loadShareCacheMap[pkg].getPath();
934
958
  }
935
- function writeLoadShareModule(pkg, shareItem, command) {
936
- const isBuild = command === "build";
937
- const importLine = isBuild ? `import { initPromise } from "${virtualRuntimeInitStatus.getImportId()}"` : `const {initPromise} = require("${virtualRuntimeInitStatus.getImportId()}")`;
938
- const awaitOrPlaceholder = isBuild ? "await " : "/*mf top-level-await placeholder replacement mf*/";
939
- const exportLine = isBuild ? "export default exportModule" : "module.exports = exportModule";
959
+ function writeLoadShareModule(pkg, shareItem, command, isRolldown) {
960
+ if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, isRolldown || command === "build" ? ".mjs" : ".js");
961
+ const useESM = command === "build" || isRolldown;
962
+ const importLine = useESM ? `import { initPromise } from "${virtualRuntimeInitStatus.getImportId()}"` : `const {initPromise} = require("${virtualRuntimeInitStatus.getImportId()}")`;
963
+ const awaitOrPlaceholder = useESM ? "await " : "/*mf top-level-await placeholder replacement mf*/";
964
+ const namedExports = getPackageNamedExports(pkg);
965
+ let exportLine;
966
+ if (namedExports.length > 0) {
967
+ const destructure = `const { ${namedExports.join(", ")} } = exportModule;`;
968
+ const namedExportLine = `export { ${namedExports.join(", ")} };`;
969
+ exportLine = useESM ? `export default exportModule;\n ${destructure}\n ${namedExportLine}` : `module.exports = exportModule;\n ${destructure}\n Object.assign(module.exports, { ${namedExports.join(", ")} });`;
970
+ } else exportLine = useESM ? `export default exportModule\n export * from ${JSON.stringify(getPreBuildLibImportId(pkg))}` : "module.exports = exportModule";
940
971
  loadShareCacheMap[pkg].writeSync(`
941
- ;() => import(${JSON.stringify(getPreBuildLibImportId(pkg))}).catch(() => {});
972
+ import ${JSON.stringify(getPreBuildLibImportId(pkg))};
942
973
  ${command !== "build" ? `;() => import(${JSON.stringify(pkg)}).catch(() => {});` : ""}
943
974
  ${importLine}
944
975
  const res = initPromise.then(runtime => runtime.loadShare(${JSON.stringify(pkg)}, {
@@ -948,11 +979,10 @@ function writeLoadShareModule(pkg, shareItem, command) {
948
979
  requiredVersion: ${JSON.stringify(shareItem.shareConfig.requiredVersion)}
949
980
  }}
950
981
  }))
951
- const exportModule = ${awaitOrPlaceholder}res.then(factory => factory())
982
+ const exportModule = ${awaitOrPlaceholder}res.then((factory) => (typeof factory === "function" ? factory() : factory))
952
983
  ${exportLine}
953
984
  `);
954
985
  }
955
-
956
986
  //#endregion
957
987
  //#region src/virtualModules/virtualRemoteEntry.ts
958
988
  let usedShares = /* @__PURE__ */ new Set();
@@ -1047,7 +1077,10 @@ function generateLocalSharedImportMap() {
1047
1077
  `;
1048
1078
  }
1049
1079
  const REMOTE_ENTRY_ID = "virtual:mf-REMOTE_ENTRY_ID";
1050
- function generateRemoteEntry(options) {
1080
+ function getRemoteEntryId(options) {
1081
+ return `${REMOTE_ENTRY_ID}:${`${options.name}__${options.filename}`.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
1082
+ }
1083
+ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(options)) {
1051
1084
  const pluginImportNames = options.runtimePlugins.map((p, i) => {
1052
1085
  if (typeof p === "string") return [
1053
1086
  `$runtimePlugin_${i}`,
@@ -1063,7 +1096,7 @@ function generateRemoteEntry(options) {
1063
1096
  return `
1064
1097
  import {init as runtimeInit, loadRemote} from "@module-federation/runtime";
1065
1098
  ${pluginImportNames.map((item) => item[1]).join("\n")}
1066
- import exposesMap from "${VIRTUAL_EXPOSES}"
1099
+ import exposesMap from "${virtualExposesId}"
1067
1100
  import {usedShared, usedRemotes} from "${getLocalSharedImportMapPath()}"
1068
1101
  import {
1069
1102
  initResolve
@@ -1109,15 +1142,10 @@ function generateRemoteEntry(options) {
1109
1142
  }
1110
1143
  `;
1111
1144
  }
1112
- /**
1113
- * Inject entry file, automatically init when used as host,
1114
- * and will not inject remoteEntry
1115
- */
1116
- const HOST_AUTO_INIT_TAG = "__H_A_I__";
1117
- const hostAutoInitModule = new VirtualModule("hostAutoInit", HOST_AUTO_INIT_TAG);
1118
- function writeHostAutoInit() {
1145
+ const hostAutoInitModule = new VirtualModule("hostAutoInit", "__H_A_I__");
1146
+ function writeHostAutoInit(remoteEntryId = REMOTE_ENTRY_ID) {
1119
1147
  hostAutoInitModule.writeSync(`
1120
- const remoteEntryPromise = import("${REMOTE_ENTRY_ID}")
1148
+ const remoteEntryPromise = import("${remoteEntryId}")
1121
1149
  // __tla only serves as a hack for vite-plugin-top-level-await.
1122
1150
  Promise.resolve(remoteEntryPromise)
1123
1151
  .then(remoteEntry => {
@@ -1132,21 +1160,18 @@ function getHostAutoInitImportId() {
1132
1160
  function getHostAutoInitPath() {
1133
1161
  return hostAutoInitModule.getPath();
1134
1162
  }
1135
-
1136
1163
  //#endregion
1137
1164
  //#region src/virtualModules/index.ts
1138
- function initVirtualModules(command) {
1165
+ function initVirtualModules(command, remoteEntryId) {
1139
1166
  writeLocalSharedImportMap();
1140
- writeHostAutoInit();
1167
+ writeHostAutoInit(remoteEntryId);
1141
1168
  writeRuntimeInitStatus(command);
1142
1169
  }
1143
-
1144
1170
  //#endregion
1145
1171
  //#region src/utils/bundleHelpers.ts
1146
1172
  function findRemoteEntryFile(filename, bundle) {
1147
1173
  for (const [_, fileData] of Object.entries(bundle)) if (filename.replace(/[\[\]]/g, "_").replace(/\.[^/.]+$/, "") === fileData.name || fileData.name === "remoteEntry") return fileData.fileName;
1148
1174
  }
1149
-
1150
1175
  //#endregion
1151
1176
  //#region src/utils/cssModuleHelpers.ts
1152
1177
  const ASSET_TYPES = ["js", "css"];
@@ -1267,7 +1292,6 @@ const buildFileToShareKeyMap = async (shareKeys, resolveFn) => {
1267
1292
  for (const resolution of resolutions) if (resolution?.file) fileToShareKey.set(resolution.file, resolution.shareKey);
1268
1293
  return fileToShareKey;
1269
1294
  };
1270
-
1271
1295
  //#endregion
1272
1296
  //#region src/utils/publicPath.ts
1273
1297
  /**
@@ -1283,7 +1307,6 @@ function resolvePublicPath(options, viteBase, originalBase) {
1283
1307
  if (viteBase) return viteBase.replace(/\/?$/, "/");
1284
1308
  return "auto";
1285
1309
  }
1286
-
1287
1310
  //#endregion
1288
1311
  //#region src/plugins/pluginMFManifest.ts
1289
1312
  const Manifest = () => {
@@ -1498,7 +1521,6 @@ const Manifest = () => {
1498
1521
  };
1499
1522
  }
1500
1523
  };
1501
-
1502
1524
  //#endregion
1503
1525
  //#region src/plugins/pluginModuleParseEnd.ts
1504
1526
  let _resolve, _parseTimeout;
@@ -1515,12 +1537,19 @@ function setParseTimeout(timeout) {
1515
1537
  _resolve(1);
1516
1538
  }, timeout * 1e3);
1517
1539
  }
1540
+ function resetIdleTimeout(timeout) {
1541
+ clearTimeout(_parseTimeout);
1542
+ _parseTimeout = setTimeout(() => {
1543
+ console.warn(`moduleParseIdleTimeout: no module activity for ${timeout}s, forcing resolve. Some shared/remote dependencies may be missing. Consider increasing moduleParseIdleTimeout.`);
1544
+ _resolve(1);
1545
+ }, timeout * 1e3);
1546
+ }
1518
1547
  let parsePromise = promise;
1519
1548
  let exposesParseEnd = false;
1520
1549
  const parseStartSet = /* @__PURE__ */ new Set();
1521
1550
  const parseEndSet = /* @__PURE__ */ new Set();
1522
1551
  function pluginModuleParseEnd_default(excludeFn, options) {
1523
- setParseTimeout(options.moduleParseTimeout);
1552
+ const idleTimeout = options.moduleParseIdleTimeout;
1524
1553
  return [
1525
1554
  {
1526
1555
  name: "_",
@@ -1533,6 +1562,10 @@ function pluginModuleParseEnd_default(excludeFn, options) {
1533
1562
  enforce: "pre",
1534
1563
  name: "parseStart",
1535
1564
  apply: "build",
1565
+ buildStart() {
1566
+ if (idleTimeout) resetIdleTimeout(idleTimeout);
1567
+ else setParseTimeout(options.moduleParseTimeout);
1568
+ },
1536
1569
  load(id) {
1537
1570
  if (excludeFn(id)) return;
1538
1571
  parseStartSet.add(id);
@@ -1544,7 +1577,8 @@ function pluginModuleParseEnd_default(excludeFn, options) {
1544
1577
  apply: "build",
1545
1578
  moduleParsed(module) {
1546
1579
  const id = module.id;
1547
- if (id === VIRTUAL_EXPOSES) exposesParseEnd = true;
1580
+ if (id === options.virtualExposesId) exposesParseEnd = true;
1581
+ if (idleTimeout) resetIdleTimeout(idleTimeout);
1548
1582
  if (excludeFn(id)) return;
1549
1583
  parseEndSet.add(id);
1550
1584
  if (exposesParseEnd && parseStartSet.size === parseEndSet.size) _resolve(1);
@@ -1552,11 +1586,10 @@ function pluginModuleParseEnd_default(excludeFn, options) {
1552
1586
  }
1553
1587
  ];
1554
1588
  }
1555
-
1556
1589
  //#endregion
1557
1590
  //#region src/plugins/pluginProxyRemoteEntry.ts
1558
1591
  const filter = createFilter();
1559
- function pluginProxyRemoteEntry_default() {
1592
+ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposesId }) {
1560
1593
  let viteConfig, _command;
1561
1594
  return {
1562
1595
  name: "proxyRemoteEntry",
@@ -1567,28 +1600,37 @@ function pluginProxyRemoteEntry_default() {
1567
1600
  config(config, { command }) {
1568
1601
  _command = command;
1569
1602
  },
1603
+ async buildStart() {
1604
+ if (_command !== "build") return;
1605
+ for (const expose of Object.values(options.exposes)) {
1606
+ const resolved = await this.resolve(expose.import);
1607
+ if (resolved) this.emitFile({
1608
+ type: "chunk",
1609
+ id: resolved.id
1610
+ });
1611
+ }
1612
+ },
1570
1613
  async resolveId(id, importer) {
1571
- if (id === REMOTE_ENTRY_ID) return REMOTE_ENTRY_ID;
1572
- if (id === VIRTUAL_EXPOSES) return VIRTUAL_EXPOSES;
1614
+ if (id === remoteEntryId) return remoteEntryId;
1615
+ if (id === virtualExposesId) return virtualExposesId;
1573
1616
  if (_command === "serve" && id.includes(getHostAutoInitPath())) return id;
1574
- if (importer === REMOTE_ENTRY_ID && !id.startsWith(".") && !id.startsWith("/") && !id.startsWith("\0") && !id.startsWith("virtual:")) {
1575
- typeof __filename === "string" ? __filename : fileURLToPath(import.meta.url);
1576
- const resolved = await this.resolve(id, __filename, { skipSelf: true });
1617
+ if (importer === remoteEntryId && !id.startsWith(".") && !id.startsWith("/") && !id.startsWith("\0") && !id.startsWith("virtual:")) {
1618
+ const importPath = typeof __filename === "string" ? __filename : fileURLToPath(import.meta.url);
1619
+ const resolved = await this.resolve(id, importPath, { skipSelf: true });
1577
1620
  if (resolved) return resolved;
1578
1621
  }
1579
1622
  },
1580
1623
  load(id) {
1581
- if (id === REMOTE_ENTRY_ID) return parsePromise.then((_) => generateRemoteEntry(getNormalizeModuleFederationOptions()));
1582
- if (id === VIRTUAL_EXPOSES) return generateExposes();
1624
+ if (id === remoteEntryId) return parsePromise.then((_) => generateRemoteEntry(options, virtualExposesId));
1625
+ if (id === virtualExposesId) return generateExposes(options);
1583
1626
  if (_command === "serve" && id.includes(getHostAutoInitPath())) return id;
1584
1627
  },
1585
1628
  transform(code, id) {
1586
1629
  return mapCodeToCodeWithSourcemap((() => {
1587
1630
  if (!filter(id)) return;
1588
- if (id.includes(REMOTE_ENTRY_ID)) return parsePromise.then((_) => generateRemoteEntry(getNormalizeModuleFederationOptions()));
1589
- if (id === VIRTUAL_EXPOSES) return generateExposes();
1631
+ if (id.includes(remoteEntryId)) return parsePromise.then((_) => generateRemoteEntry(options, virtualExposesId));
1632
+ if (id === virtualExposesId) return generateExposes(options);
1590
1633
  if (id.includes(getHostAutoInitPath())) {
1591
- const options = getNormalizeModuleFederationOptions();
1592
1634
  if (_command === "serve") {
1593
1635
  const host = typeof viteConfig.server?.host === "string" && viteConfig.server.host !== "0.0.0.0" ? viteConfig.server.host : "localhost";
1594
1636
  const publicPath = JSON.stringify(resolvePublicPath(options, viteConfig.base) + options.filename);
@@ -1609,7 +1651,6 @@ function pluginProxyRemoteEntry_default() {
1609
1651
  }
1610
1652
  };
1611
1653
  }
1612
-
1613
1654
  //#endregion
1614
1655
  //#region src/plugins/pluginProxyRemotes.ts
1615
1656
  createFilter();
@@ -1618,13 +1659,14 @@ function pluginProxyRemotes_default(options) {
1618
1659
  return {
1619
1660
  name: "proxyRemotes",
1620
1661
  config(config, { command: _command }) {
1662
+ const isRolldown = !!this?.meta?.rolldownVersion;
1621
1663
  Object.keys(remotes).forEach((key) => {
1622
1664
  const remote = remotes[key];
1623
1665
  config.resolve.alias.push({
1624
1666
  find: new RegExp(`^(${remote.name}(\/.*|$))`),
1625
1667
  replacement: "$1",
1626
1668
  customResolver(source) {
1627
- const remoteModule = getRemoteVirtualModule(source, _command);
1669
+ const remoteModule = getRemoteVirtualModule(source, _command, isRolldown);
1628
1670
  addUsedRemote(remote.name, source);
1629
1671
  return remoteModule.getPath();
1630
1672
  }
@@ -1633,7 +1675,6 @@ function pluginProxyRemotes_default(options) {
1633
1675
  }
1634
1676
  };
1635
1677
  }
1636
-
1637
1678
  //#endregion
1638
1679
  //#region src/utils/PromiseStore.ts
1639
1680
  /**
@@ -1667,12 +1708,13 @@ var PromiseStore = class {
1667
1708
  return pendingPromise;
1668
1709
  }
1669
1710
  };
1670
-
1671
1711
  //#endregion
1672
1712
  //#region src/plugins/pluginProxySharedModule_preBuild.ts
1673
1713
  function proxySharedModule(options) {
1674
- let { shared = {}, include, exclude } = options;
1714
+ const { shared = {} } = options;
1675
1715
  let _config;
1716
+ let _command = "serve";
1717
+ const savePrebuild = new PromiseStore();
1676
1718
  return [{
1677
1719
  name: "generateLocalSharedImportMap",
1678
1720
  enforce: "post",
@@ -1685,19 +1727,23 @@ function proxySharedModule(options) {
1685
1727
  }, {
1686
1728
  name: "proxyPreBuildShared",
1687
1729
  enforce: "post",
1688
- configResolved(config) {
1689
- _config = config;
1690
- },
1691
1730
  config(config, { command }) {
1731
+ const isRolldown = !!this?.meta?.rolldownVersion;
1732
+ _command = command;
1692
1733
  config.resolve.alias.push(...Object.keys(shared).map((key) => {
1693
- const pattern = key.endsWith("/") ? `(^${key.replace(/\/$/, "")}(\/.+)?$)` : `(^${key}$)`;
1734
+ const keyBase = key.endsWith("/") ? key.slice(0, -1) : key;
1735
+ const escapeRegex = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1736
+ const escapedKeyBase = escapeRegex(keyBase);
1737
+ const pattern = key.endsWith("/") ? `^(${escapedKeyBase}(?:\\/.*)?)$` : `^(${escapedKeyBase})$`;
1694
1738
  return {
1695
1739
  find: new RegExp(pattern),
1696
1740
  replacement: "$1",
1697
1741
  customResolver(source, importer) {
1698
1742
  if (/\.css$/.test(source)) return;
1699
- const loadSharePath = getLoadShareModulePath(source);
1700
- writeLoadShareModule(source, shared[key], command);
1743
+ if (importer && importer.includes("localSharedImportMap")) return;
1744
+ if (key.endsWith("/") && source !== key.slice(0, -1)) return;
1745
+ const loadSharePath = getLoadShareModulePath(source, isRolldown, command);
1746
+ writeLoadShareModule(source, shared[key], command, isRolldown);
1701
1747
  writePreBuildLibPath(source);
1702
1748
  addUsedShares(source);
1703
1749
  writeLocalSharedImportMap();
@@ -1705,7 +1751,6 @@ function proxySharedModule(options) {
1705
1751
  }
1706
1752
  };
1707
1753
  }));
1708
- const savePrebuild = new PromiseStore();
1709
1754
  config.resolve.alias.push(...Object.keys(shared).map((key) => {
1710
1755
  return command === "build" ? {
1711
1756
  find: new RegExp(`(.*${PREBUILD_TAG}.*)`),
@@ -1718,15 +1763,25 @@ function proxySharedModule(options) {
1718
1763
  async customResolver(source, importer) {
1719
1764
  const pkgName = assertModuleFound(PREBUILD_TAG, source).name;
1720
1765
  const result = await this.resolve(pkgName, importer).then((item) => item.id);
1721
- if (!result.includes(_config.cacheDir)) savePrebuild.set(pkgName, Promise.resolve(result));
1766
+ if (_config && !result.includes(_config.cacheDir)) savePrebuild.set(pkgName, Promise.resolve(result));
1722
1767
  return await this.resolve(await savePrebuild.get(pkgName), importer);
1723
1768
  }
1724
1769
  };
1725
1770
  }));
1771
+ },
1772
+ configResolved(config) {
1773
+ _config = config;
1774
+ const isRolldown = !!config.experimental?.rolldownDev;
1775
+ Object.keys(shared).forEach((key) => {
1776
+ if (key.endsWith("/")) return;
1777
+ writeLoadShareModule(key, shared[key], _command, isRolldown);
1778
+ writePreBuildLibPath(key);
1779
+ addUsedShares(key);
1780
+ });
1781
+ writeLocalSharedImportMap();
1726
1782
  }
1727
1783
  }];
1728
1784
  }
1729
-
1730
1785
  //#endregion
1731
1786
  //#region src/plugins/pluginVarRemoteEntry.ts
1732
1787
  const VarRemoteEntry = () => {
@@ -1807,7 +1862,6 @@ const VarRemoteEntry = () => {
1807
1862
  `;
1808
1863
  }
1809
1864
  };
1810
-
1811
1865
  //#endregion
1812
1866
  //#region src/utils/aliasToArrayPlugin.ts
1813
1867
  var aliasToArrayPlugin_default = {
@@ -1822,7 +1876,6 @@ var aliasToArrayPlugin_default = {
1822
1876
  }));
1823
1877
  }
1824
1878
  };
1825
-
1826
1879
  //#endregion
1827
1880
  //#region src/utils/normalizeOptimizeDeps.ts
1828
1881
  var normalizeOptimizeDeps_default = {
@@ -1833,20 +1886,59 @@ var normalizeOptimizeDeps_default = {
1833
1886
  config.optimizeDeps = {};
1834
1887
  optimizeDeps = config.optimizeDeps;
1835
1888
  }
1836
- optimizeDeps.force = true;
1837
1889
  if (!optimizeDeps.include) optimizeDeps.include = [];
1890
+ if (!optimizeDeps.exclude) optimizeDeps.exclude = [];
1838
1891
  if (!optimizeDeps.needsInterop) optimizeDeps.needsInterop = [];
1839
1892
  }
1840
1893
  };
1841
-
1842
1894
  //#endregion
1843
1895
  //#region src/index.ts
1896
+ /**
1897
+ * Plugin that runs FIRST to create virtual module files in the config hook.
1898
+ * This prevents 504 "Outdated Optimize Dep" errors by ensuring files exist
1899
+ * before Vite's optimization phase.
1900
+ */
1901
+ function createEarlyVirtualModulesPlugin(options) {
1902
+ const { shared, remotes, virtualModuleDir } = options;
1903
+ return {
1904
+ name: "vite:module-federation-early-init",
1905
+ enforce: "pre",
1906
+ config(config, { command: _command }) {
1907
+ if (_command !== "serve") return;
1908
+ const isRolldown = !!this?.meta?.rolldownVersion;
1909
+ const root = config.root || process.cwd();
1910
+ initVirtualModuleInfrastructure(root, virtualModuleDir);
1911
+ VirtualModule.setRoot(root);
1912
+ VirtualModule.ensureVirtualPackageExists();
1913
+ initVirtualModules(_command, getRemoteEntryId(options));
1914
+ if (remotes && Object.keys(remotes).length > 0) for (const key of Object.keys(remotes)) addUsedRemote(key, key);
1915
+ if (shared && Object.keys(shared).length > 0) {
1916
+ config.optimizeDeps = config.optimizeDeps || {};
1917
+ config.optimizeDeps.include = config.optimizeDeps.include || [];
1918
+ config.optimizeDeps.include.push(virtualRuntimeInitStatus.getImportId());
1919
+ for (const key of Object.keys(shared)) {
1920
+ if (key.endsWith("/")) continue;
1921
+ const shareItem = shared[key];
1922
+ getLoadShareModulePath(key, isRolldown);
1923
+ writeLoadShareModule(key, shareItem, _command, isRolldown);
1924
+ writePreBuildLibPath(key);
1925
+ addUsedShares(key);
1926
+ config.optimizeDeps.include.push(getPreBuildLibImportId(key));
1927
+ }
1928
+ writeLocalSharedImportMap();
1929
+ }
1930
+ }
1931
+ };
1932
+ }
1844
1933
  function federation(mfUserOptions) {
1845
1934
  const options = normalizeModuleFederationOptions(mfUserOptions);
1846
1935
  const { name, remotes, shared, filename, hostInitInjectLocation } = options;
1847
1936
  if (!name) throw new Error("name is required");
1937
+ const remoteEntryId = getRemoteEntryId(options);
1938
+ const virtualExposesId = getVirtualExposesId(options);
1848
1939
  let command;
1849
1940
  return [
1941
+ createEarlyVirtualModulesPlugin(options),
1850
1942
  {
1851
1943
  name: "vite:module-federation-config",
1852
1944
  enforce: "pre",
@@ -1856,7 +1948,7 @@ function federation(mfUserOptions) {
1856
1948
  configResolved(config) {
1857
1949
  VirtualModule.setRoot(config.root);
1858
1950
  VirtualModule.ensureVirtualPackageExists();
1859
- initVirtualModules(command);
1951
+ initVirtualModules(command, remoteEntryId);
1860
1952
  }
1861
1953
  },
1862
1954
  aliasToArrayPlugin_default,
@@ -1865,32 +1957,62 @@ function federation(mfUserOptions) {
1865
1957
  ...pluginDts(options),
1866
1958
  ...addEntry({
1867
1959
  entryName: "remoteEntry",
1868
- entryPath: REMOTE_ENTRY_ID,
1960
+ entryPath: remoteEntryId,
1869
1961
  fileName: filename
1870
1962
  }),
1871
1963
  ...addEntry({
1872
1964
  entryName: "hostInit",
1873
- entryPath: getHostAutoInitPath(),
1965
+ entryPath: () => getHostAutoInitPath(),
1874
1966
  inject: hostInitInjectLocation
1875
1967
  }),
1876
1968
  ...addEntry({
1877
1969
  entryName: "virtualExposes",
1878
- entryPath: VIRTUAL_EXPOSES
1970
+ entryPath: virtualExposesId
1971
+ }),
1972
+ pluginProxyRemoteEntry_default({
1973
+ options,
1974
+ remoteEntryId,
1975
+ virtualExposesId
1879
1976
  }),
1880
- pluginProxyRemoteEntry_default(),
1881
1977
  pluginProxyRemotes_default(options),
1882
1978
  ...pluginModuleParseEnd_default((id) => {
1883
- return id.includes(getHostAutoInitImportId()) || id.includes(REMOTE_ENTRY_ID) || id.includes(VIRTUAL_EXPOSES) || id.includes(getLocalSharedImportMapPath());
1884
- }, { moduleParseTimeout: options.moduleParseTimeout }),
1979
+ return id.includes(getHostAutoInitImportId()) || id.includes(remoteEntryId) || id.includes(virtualExposesId) || id.includes(getLocalSharedImportMapPath());
1980
+ }, {
1981
+ moduleParseTimeout: options.moduleParseTimeout,
1982
+ moduleParseIdleTimeout: options.moduleParseIdleTimeout,
1983
+ virtualExposesId
1984
+ }),
1885
1985
  ...proxySharedModule({ shared }),
1886
1986
  {
1887
1987
  name: "module-federation-esm-shims",
1888
1988
  enforce: "pre",
1889
1989
  apply: "build",
1990
+ config(config) {
1991
+ const runtimeInitId = virtualRuntimeInitStatus.getImportId();
1992
+ config.build = config.build || {};
1993
+ config.build.rollupOptions = config.build.rollupOptions || {};
1994
+ if (!Array.isArray(config.build.rollupOptions.output)) {
1995
+ const output = config.build.rollupOptions.output ||= {};
1996
+ const existingManualChunks = output.manualChunks;
1997
+ output.manualChunks = function(id) {
1998
+ if (id.includes(runtimeInitId)) return "runtimeInit";
1999
+ if (id.includes("__loadShare__")) {
2000
+ const match = id.match(/([^/\\]+__loadShare__[^/\\]+)/);
2001
+ return match ? match[1] : "loadShare";
2002
+ }
2003
+ if (typeof existingManualChunks === "function") return existingManualChunks.apply(this, arguments);
2004
+ if (existingManualChunks && typeof existingManualChunks === "object") {
2005
+ for (const [key, ids] of Object.entries(existingManualChunks)) if (Array.isArray(ids) && ids.some((v) => id.includes(v))) return key;
2006
+ }
2007
+ };
2008
+ }
2009
+ },
1890
2010
  load(id) {
1891
2011
  if (id.startsWith("\0")) return;
1892
- if (id.includes(LOAD_SHARE_TAG) || id.includes(LOAD_REMOTE_TAG)) {
2012
+ if (id.includes("__loadShare__") || id.includes("__loadRemote__")) {
1893
2013
  let code = readFileSync(id, "utf-8");
2014
+ code = code.replace(/import\s+["'][^"']*__prebuild__[^"']*["']\s*;?/g, "");
2015
+ code = code.replace(/export\s+\*\s+from\s+["'][^"']*__prebuild__[^"']*["']\s*;?/g, "");
1894
2016
  /**
1895
2017
  * Shared/remote shims only have `export default exportModule`.
1896
2018
  *
@@ -1913,6 +2035,134 @@ function federation(mfUserOptions) {
1913
2035
  syntheticNamedExports: "__moduleExports"
1914
2036
  };
1915
2037
  }
2038
+ },
2039
+ generateBundle(_, bundle) {
2040
+ for (const [fileName, chunk] of Object.entries(bundle)) {
2041
+ if (chunk.type !== "chunk") continue;
2042
+ if (fileName.includes("__loadShare__")) continue;
2043
+ let code = chunk.code;
2044
+ let m;
2045
+ const importedFromLoadShare = /* @__PURE__ */ new Set();
2046
+ const importRegex = /import\s*\{([^}]+)\}\s*from\s*["'][^"']*__loadShare__[^"']*["']/g;
2047
+ while ((m = importRegex.exec(code)) !== null) for (const spec of m[1].split(",")) {
2048
+ const parts = spec.trim().split(/\s+as\s+/);
2049
+ const local = (parts[1] || parts[0]).trim();
2050
+ if (local) importedFromLoadShare.add(local);
2051
+ }
2052
+ const allInits = [];
2053
+ for (const v of importedFromLoadShare) if (new RegExp("\\(" + v + "\\(\\)\\s*,\\s*\\w+\\(\\w+\\)\\)").test(code)) allInits.push(v);
2054
+ if (allInits.length === 0) continue;
2055
+ const awaits = allInits.map((v) => `await ${v}();`).join("");
2056
+ const lastFromRegex = /\bfrom\s*["'][^"']*["']\s*;?/g;
2057
+ let lastFromEnd = -1;
2058
+ while ((m = lastFromRegex.exec(code)) !== null) lastFromEnd = m.index + m[0].length;
2059
+ if (lastFromEnd !== -1) {
2060
+ chunk.code = code.slice(0, lastFromEnd) + awaits + code.slice(lastFromEnd);
2061
+ continue;
2062
+ }
2063
+ const exportIdx = code.search(/\bexport\s*[{d]/);
2064
+ if (exportIdx !== -1) {
2065
+ chunk.code = code.slice(0, exportIdx) + awaits + code.slice(exportIdx);
2066
+ continue;
2067
+ }
2068
+ }
2069
+ const proxyChunks = /* @__PURE__ */ new Map();
2070
+ for (const [fileName, chunk] of Object.entries(bundle)) {
2071
+ if (chunk.type !== "chunk") continue;
2072
+ if (fileName.includes("__loadShare__") && fileName.includes("commonjs-proxy")) proxyChunks.set(fileName, {
2073
+ code: chunk.code,
2074
+ fileName
2075
+ });
2076
+ }
2077
+ if (proxyChunks.size === 0) return;
2078
+ for (const [fileName, chunk] of Object.entries(bundle)) {
2079
+ if (chunk.type !== "chunk") continue;
2080
+ if (fileName.includes("__loadShare__")) continue;
2081
+ let code = chunk.code;
2082
+ let modified = false;
2083
+ for (const [proxyFileName, proxyInfo] of proxyChunks) {
2084
+ const proxyBaseName = proxyFileName.replace(/^.*\//, "").replace(/\.js$/, "").replace(/-[A-Za-z0-9_-]+$/, "");
2085
+ const importMatch = new RegExp(`import\\s*\\{([^}]+)\\}\\s*from\\s*["']([^"']*${proxyBaseName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}[^"']*)["']\\s*;?`).exec(code);
2086
+ if (!importMatch) continue;
2087
+ const fullImport = importMatch[0];
2088
+ const bindings = importMatch[1].split(",").map((s) => {
2089
+ const parts = s.trim().split(/\s+as\s+/);
2090
+ return {
2091
+ imported: parts[0].trim(),
2092
+ local: (parts[1] || parts[0]).trim()
2093
+ };
2094
+ });
2095
+ const proxyCode = proxyInfo.code;
2096
+ const exportMapMatch = proxyCode.match(/export\s*\{([^}]+)\}/);
2097
+ if (!exportMapMatch) continue;
2098
+ const exportMap = {};
2099
+ for (const entry of exportMapMatch[1].split(",")) {
2100
+ const parts = entry.trim().split(/\s+as\s+/);
2101
+ if (parts.length === 2) exportMap[parts[1].trim()] = parts[0].trim();
2102
+ }
2103
+ const inlineable = [];
2104
+ const nonInlineable = [];
2105
+ for (const b of bindings) {
2106
+ const proxyLocal = exportMap[b.imported];
2107
+ if (!proxyLocal) {
2108
+ nonInlineable.push(b);
2109
+ continue;
2110
+ }
2111
+ const funcRe = new RegExp(`function\\s+${proxyLocal}\\s*\\([^)]*\\)\\s*\\{`);
2112
+ if (funcRe.test(proxyCode)) {
2113
+ const funcStart = proxyCode.search(funcRe);
2114
+ let depth = 0;
2115
+ let funcEnd = funcStart;
2116
+ for (let i = proxyCode.indexOf("{", funcStart); i < proxyCode.length; i++) if (proxyCode[i] === "{") depth++;
2117
+ else if (proxyCode[i] === "}") {
2118
+ depth--;
2119
+ if (depth === 0) {
2120
+ funcEnd = i + 1;
2121
+ break;
2122
+ }
2123
+ }
2124
+ const renamedFunc = proxyCode.slice(funcStart, funcEnd).replace(new RegExp(`function\\s+${proxyLocal}\\s*\\(`), `function ${b.local}(`);
2125
+ inlineable.push({
2126
+ local: b.local,
2127
+ funcBody: renamedFunc
2128
+ });
2129
+ } else nonInlineable.push(b);
2130
+ }
2131
+ if (inlineable.length === 0) continue;
2132
+ let replacement = "";
2133
+ if (nonInlineable.length > 0) replacement = `import{${nonInlineable.map((b) => b.imported === b.local ? b.imported : `${b.imported} as ${b.local}`).join(",")}}from"${importMatch[2]}";`;
2134
+ replacement += inlineable.map((f) => f.funcBody).join("");
2135
+ code = code.replace(fullImport, replacement);
2136
+ modified = true;
2137
+ }
2138
+ if (modified) chunk.code = code;
2139
+ }
2140
+ }
2141
+ },
2142
+ {
2143
+ name: "module-federation-dev-await-shared-init",
2144
+ apply: "serve",
2145
+ enforce: "post",
2146
+ transform(code, id) {
2147
+ if (!id.includes(".vite/deps/")) return;
2148
+ const initPattern = /\b(init_\w+__loadShare__\w+)\b/g;
2149
+ const initFns = /* @__PURE__ */ new Set();
2150
+ let match;
2151
+ while ((match = initPattern.exec(code)) !== null) initFns.add(match[1]);
2152
+ if (initFns.size === 0) return;
2153
+ if (![...initFns].some((fn) => {
2154
+ return code.includes(`${fn}(),`) || code.includes(`${fn}()`);
2155
+ })) return;
2156
+ if (/await\s+init_\w+__loadShare__/.test(code)) return;
2157
+ if (code.includes("__esmMin")) return;
2158
+ const awaits = [...initFns].map((fn) => `await ${fn}();`).join("\n");
2159
+ const topLevelImportRe = /^import\s/gm;
2160
+ let lastImportIdx = -1;
2161
+ let importMatch;
2162
+ while ((importMatch = topLevelImportRe.exec(code)) !== null) lastImportIdx = importMatch.index;
2163
+ if (lastImportIdx === -1) return;
2164
+ const lineEnd = code.indexOf("\n", lastImportIdx);
2165
+ return code.slice(0, lineEnd + 1) + awaits + "\n" + code.slice(lineEnd + 1);
1916
2166
  }
1917
2167
  },
1918
2168
  PluginDevProxyModuleTopLevelAwait(),
@@ -1921,16 +2171,29 @@ function federation(mfUserOptions) {
1921
2171
  enforce: "post",
1922
2172
  _options: options,
1923
2173
  config(config, { command: _command }) {
2174
+ const isRolldown = !!this?.meta?.rolldownVersion;
2175
+ let implementation = options.implementation;
2176
+ if (isRolldown) implementation = implementation.replace(/\.cjs\.cjs$/, ".esm.js");
1924
2177
  config.resolve.alias.push({
1925
2178
  find: "@module-federation/runtime",
1926
- replacement: options.implementation
2179
+ replacement: implementation
1927
2180
  });
1928
2181
  config.build = defu(config.build || {}, { commonjsOptions: { strictRequires: "auto" } });
1929
2182
  const virtualDir = options.virtualModuleDir || "__mf__virtual";
1930
- config.optimizeDeps?.include?.push("@module-federation/runtime");
1931
- config.optimizeDeps?.include?.push(virtualDir);
1932
- config.optimizeDeps?.needsInterop?.push(virtualDir);
1933
- config.optimizeDeps?.needsInterop?.push(getLocalSharedImportMapPath());
2183
+ config.optimizeDeps ||= {};
2184
+ config.optimizeDeps.include ||= [];
2185
+ config.optimizeDeps.include.push("@module-federation/runtime");
2186
+ config.optimizeDeps.include.push(virtualDir);
2187
+ options.runtimePlugins.forEach((p) => {
2188
+ const pluginPath = typeof p === "string" ? p : p[0];
2189
+ if (pluginPath && !pluginPath.startsWith(".") && !pluginPath.startsWith("/") && !pluginPath.startsWith("\0") && !pluginPath.startsWith("virtual:")) config.optimizeDeps.include.push(pluginPath);
2190
+ });
2191
+ if (isRolldown) config.build = defu(config.build || {}, { target: "esnext" });
2192
+ else {
2193
+ config.optimizeDeps.needsInterop ||= [];
2194
+ config.optimizeDeps.needsInterop.push(virtualDir);
2195
+ config.optimizeDeps.needsInterop.push(getLocalSharedImportMapPath());
2196
+ }
1934
2197
  const resolvedTarget = options.target ?? (config.build?.ssr ? "node" : "web");
1935
2198
  if (!config.define) config.define = {};
1936
2199
  if (!("ENV_TARGET" in config.define)) config.define["ENV_TARGET"] = JSON.stringify(resolvedTarget);
@@ -1938,9 +2201,26 @@ function federation(mfUserOptions) {
1938
2201
  }
1939
2202
  },
1940
2203
  ...Manifest(),
1941
- ...VarRemoteEntry()
2204
+ ...VarRemoteEntry(),
2205
+ ...Object.keys(options.exposes).length > 0 ? [{
2206
+ name: "module-federation-fix-preload",
2207
+ enforce: "post",
2208
+ apply: "build",
2209
+ generateBundle(_, bundle) {
2210
+ for (const chunk of Object.values(bundle)) {
2211
+ if (chunk.type !== "chunk") continue;
2212
+ if (!chunk.code.includes("modulepreload")) continue;
2213
+ const replacement = "=function($1){return new URL(\"../\"+$1,import.meta.url).href}";
2214
+ const replaced = chunk.code.replace(/=\(?(\w+)(?:,\w+)?\)?\s*=>\s*["'`][^"'`]*["'`]\s*\+\s*\1/, replacement);
2215
+ if (replaced !== chunk.code) {
2216
+ chunk.code = replaced;
2217
+ continue;
2218
+ }
2219
+ chunk.code = chunk.code.replace(/=function\((\w+)(?:,\w+)?\)\{return\s*["'`][^"'`]*["'`]\s*\+\s*\1\s*\}/, replacement);
2220
+ }
2221
+ }
2222
+ }] : []
1942
2223
  ];
1943
2224
  }
1944
-
1945
2225
  //#endregion
1946
- export { federation };
2226
+ export { federation };