@module-federation/vite 1.13.0 → 1.13.2

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.
Files changed (3) hide show
  1. package/lib/index.cjs +337 -75
  2. package/lib/index.mjs +337 -75
  3. package/package.json +7 -6
package/lib/index.cjs CHANGED
@@ -81,6 +81,38 @@ function inlineEntryScripts(html, initSrc) {
81
81
  return html.replace("<head>", `<head><script type="module" src=${JSON.stringify(src)}><\/script>`);
82
82
  }
83
83
  //#endregion
84
+ //#region src/utils/logger.ts
85
+ const MODULE_FEDERATION_LOG_PREFIX = "[Module Federation]";
86
+ function formatModuleFederationMessage(message) {
87
+ return `${MODULE_FEDERATION_LOG_PREFIX} ${message}`;
88
+ }
89
+ function createModuleFederationError(message) {
90
+ return new Error(formatModuleFederationMessage(message));
91
+ }
92
+ function toConsoleArgs(message, rest = []) {
93
+ if (typeof message === "string") return [formatModuleFederationMessage(message), ...rest];
94
+ if (message === void 0) return [MODULE_FEDERATION_LOG_PREFIX, ...rest];
95
+ return [
96
+ MODULE_FEDERATION_LOG_PREFIX,
97
+ message,
98
+ ...rest
99
+ ];
100
+ }
101
+ const moduleFederationConsole = {
102
+ log(message, ...rest) {
103
+ console.log(...toConsoleArgs(message, rest));
104
+ },
105
+ warn(message, ...rest) {
106
+ console.warn(...toConsoleArgs(message, rest));
107
+ },
108
+ error(message, ...rest) {
109
+ console.error(...toConsoleArgs(message, rest));
110
+ }
111
+ };
112
+ moduleFederationConsole.log;
113
+ const mfWarn = moduleFederationConsole.warn;
114
+ const mfError = moduleFederationConsole.error;
115
+ //#endregion
84
116
  //#region src/utils/packageUtils.ts
85
117
  const dependencyPresenceCache = /* @__PURE__ */ new Map();
86
118
  let packageDetectionCwd;
@@ -104,7 +136,7 @@ function setPackageDetectionCwd(cwd) {
104
136
  * @returns {string} - The encoded file name.
105
137
  */
106
138
  function packageNameEncode(name) {
107
- if (typeof name !== "string") throw new Error("A string package name is required");
139
+ if (typeof name !== "string") throw createModuleFederationError("A string package name is required");
108
140
  return name.replace(/@/g, "_mf_0_").replace(/\//g, "_mf_1_").replace(/-/g, "_mf_2_").replace(/\./g, "_mf_3_");
109
141
  }
110
142
  /**
@@ -113,7 +145,7 @@ function packageNameEncode(name) {
113
145
  * @returns {string} - The decoded package name.
114
146
  */
115
147
  function packageNameDecode(encoded) {
116
- if (typeof encoded !== "string") throw new Error("A string encoded file name is required");
148
+ if (typeof encoded !== "string") throw createModuleFederationError("A string encoded file name is required");
117
149
  return encoded.replace(/_mf_0_/g, "@").replace(/_mf_1_/g, "/").replace(/_mf_2_/g, "-").replace(/_mf_3_/g, ".");
118
150
  }
119
151
  /**
@@ -125,6 +157,13 @@ function removePathFromNpmPackage(packageString) {
125
157
  const match = packageString.match(/^(?:@[^/]+\/)?[^/]+/);
126
158
  return match ? match[0] : packageString;
127
159
  }
160
+ /**
161
+ * Detect whether the current bundler is Rolldown (Vite 8+) by checking
162
+ * for `meta.rolldownVersion` on the plugin hook context.
163
+ */
164
+ function getIsRolldown(ctx) {
165
+ return !!ctx?.meta?.rolldownVersion;
166
+ }
128
167
  function hasPackageDependency(dependencyName, cwd = packageDetectionCwd || process.cwd()) {
129
168
  const cacheKey = getDependencyCacheKey(cwd, dependencyName);
130
169
  const cached = dependencyPresenceCache.get(cacheKey);
@@ -206,6 +245,12 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry" }) => {
206
245
  else if (Array.isArray(inputOptions)) entryFiles = inputOptions;
207
246
  else if (typeof inputOptions === "object") entryFiles = Object.values(inputOptions);
208
247
  if (entryFiles && entryFiles.length > 0) htmlFilePath = getFirstHtmlEntryFile(entryFiles);
248
+ if (_command === "serve" && htmlFilePath && fs.existsSync(htmlFilePath)) {
249
+ const htmlContent = fs.readFileSync(htmlFilePath, "utf-8");
250
+ const scriptRegex = /<script\s+[^>]*src=["']([^"']+)["'][^>]*>/gi;
251
+ let match;
252
+ while ((match = scriptRegex.exec(htmlContent)) !== null) entryFiles.push(match[1]);
253
+ }
209
254
  },
210
255
  buildStart() {
211
256
  if (_command === "serve") return;
@@ -239,7 +284,7 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry" }) => {
239
284
  if (typeof result === "string") return result;
240
285
  if (result && typeof result === "object") {
241
286
  if ("runtime" in result) {
242
- console.warn("[vite-plugin-federation] renderBuiltUrl returned runtime code for HTML injection. Runtime code cannot be used in <script src=\"\">. Falling back to base path.");
287
+ mfWarn("renderBuiltUrl returned runtime code for HTML injection. Runtime code cannot be used in <script src=\"\">. Falling back to base path.");
243
288
  return viteConfig.base + file;
244
289
  }
245
290
  if (result.relative) return file;
@@ -304,11 +349,11 @@ function checkAliasConflicts(options) {
304
349
  });
305
350
  }
306
351
  if (conflicts.length > 0) {
307
- config.logger.warn("\n[Module Federation] Detected alias conflicts with shared modules:");
352
+ mfWarn("Detected alias conflicts with shared modules:");
308
353
  conflicts.forEach(({ sharedModule, alias, target }) => {
309
- config.logger.warn(` - Shared module "${sharedModule}" is aliased by "${alias}" to "${target}"`);
354
+ mfWarn(`Shared module "${sharedModule}" is aliased by "${alias}" to "${target}"`);
310
355
  });
311
- config.logger.warn(" This may cause runtime errors as the shared module will bypass Module Federation's sharing mechanism.");
356
+ mfWarn("This may cause runtime errors as the shared module will bypass Module Federation's sharing mechanism.");
312
357
  }
313
358
  }
314
359
  };
@@ -337,7 +382,7 @@ function PluginDevProxyModuleTopLevelAwait() {
337
382
  try {
338
383
  ast = this.parse(code, { allowReturnOutsideFunction: true });
339
384
  } catch (e) {
340
- throw new Error(`${id}: ${e}`);
385
+ throw createModuleFederationError(`${id}: ${e}`);
341
386
  }
342
387
  const magicString = new magic_string.default(code);
343
388
  const walk = await loadWalk();
@@ -465,7 +510,7 @@ const normalizeDevDtsOptions = (dts, context) => {
465
510
  const logDtsError = (error, dtsOptions) => {
466
511
  if (dtsOptions === false) return;
467
512
  if (typeof dtsOptions === "object" && dtsOptions && dtsOptions.displayErrorInTerminal === false) return;
468
- console.error(error);
513
+ mfError(error);
469
514
  };
470
515
  function pluginDts(options) {
471
516
  if (options.dts === false) return [];
@@ -493,7 +538,7 @@ function pluginDts(options) {
493
538
  if (!normalizedDevOptions || !resolvedConfig) return;
494
539
  const devOptions = normalizedDevOptions;
495
540
  if (devOptions.disableDynamicRemoteTypeHints && devOptions.disableHotTypesReload && devOptions.disableLiveReload) return;
496
- if (!options.name) throw new Error("name is required if you want to enable dev server!");
541
+ if (!options.name) throw createModuleFederationError("name is required if you want to enable dev server!");
497
542
  const outputDir = resolveOutputDir(resolvedConfig);
498
543
  const normalizedDtsOptions = normalizeDevDtsOptions(options.dts, resolvedConfig.root);
499
544
  if (typeof normalizedDtsOptions !== "object") return;
@@ -674,6 +719,10 @@ function searchPackageVersion(sharedName) {
674
719
  }
675
720
  } catch (_) {}
676
721
  }
722
+ function inferVersionFromRequiredVersion(requiredVersion) {
723
+ if (!requiredVersion) return void 0;
724
+ return requiredVersion.match(/\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?/)?.[0];
725
+ }
677
726
  function normalizeShareItem(key, shareItem) {
678
727
  let version;
679
728
  try {
@@ -685,11 +734,11 @@ function normalizeShareItem(key, shareItem) {
685
734
  version = require(localPath).version;
686
735
  } catch (e2) {
687
736
  version = searchPackageVersion(key);
688
- if (!version) console.error(e1);
737
+ if (!version) mfError(e1);
689
738
  }
690
739
  }
691
740
  } catch (e) {
692
- console.error(`Unexpected error resolving version for ${key}:`, e);
741
+ mfError(`Unexpected error resolving version for ${key}:`, e);
693
742
  }
694
743
  if (typeof shareItem === "string") return {
695
744
  name: shareItem,
@@ -705,7 +754,7 @@ function normalizeShareItem(key, shareItem) {
705
754
  return {
706
755
  name: key,
707
756
  from: "",
708
- version: shareItem.version || version,
757
+ version: shareItem.version || inferVersionFromRequiredVersion(shareItem.requiredVersion) || version,
709
758
  scope: shareItem.shareScope || "default",
710
759
  shareConfig: {
711
760
  import: typeof shareItem === "object" ? shareItem.import : void 0,
@@ -750,7 +799,7 @@ function getNormalizeShareItem(key) {
750
799
  return options.shared[key] || options.shared[removePathFromNpmPackage(key)] || options.shared[removePathFromNpmPackage(key) + "/"];
751
800
  }
752
801
  function normalizeModuleFederationOptions(options) {
753
- if (options.virtualModuleDir && options.virtualModuleDir.includes("/")) throw new Error(`Invalid virtualModuleDir: "${options.virtualModuleDir}". The virtualModuleDir option cannot contain slashes (/). Please use a single directory name like '__mf__virtual__your_app_name'.`);
802
+ 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'.`);
754
803
  return config = {
755
804
  exposes: normalizeExposes(options.exposes),
756
805
  filename: options.filename || "remoteEntry-[hash]",
@@ -885,7 +934,7 @@ const cacheMap = {};
885
934
  */
886
935
  function assertModuleFound(tag, str = "") {
887
936
  const module = VirtualModule.findModule(tag, str);
888
- if (!module) throw new Error(`Module Federation shared module '${str}' not found. Please ensure it's installed as a dependency in your package.json.`);
937
+ if (!module) throw createModuleFederationError(`Module Federation shared module '${str}' not found. Please ensure it's installed as a dependency in your package.json.`);
889
938
  return module;
890
939
  }
891
940
  var VirtualModule = class {
@@ -972,12 +1021,12 @@ function generateExposes(options) {
972
1021
  //#endregion
973
1022
  //#region src/virtualModules/virtualRuntimeInitStatus.ts
974
1023
  const virtualRuntimeInitStatus = new VirtualModule("runtimeInit");
975
- function writeRuntimeInitStatus(command) {
976
- const globalKey = `__mf_init__${virtualRuntimeInitStatus.getImportId()}__`;
977
- const exportStatement = command === "build" ? `const { initPromise, initResolve, initReject } = globalThis[globalKey];
978
- export { initPromise, initResolve, initReject };` : `module.exports = globalThis[globalKey];`;
979
- virtualRuntimeInitStatus.writeSync(`
980
- const globalKey = ${JSON.stringify(globalKey)};
1024
+ function getRuntimeInitGlobalKey() {
1025
+ return `__mf_init__${virtualRuntimeInitStatus.getImportId()}__`;
1026
+ }
1027
+ function getRuntimeInitBootstrapCode() {
1028
+ return `
1029
+ const globalKey = ${JSON.stringify(getRuntimeInitGlobalKey())};
981
1030
  if (!globalThis[globalKey]) {
982
1031
  let initResolve, initReject;
983
1032
  const initPromise = new Promise((re, rj) => {
@@ -989,8 +1038,6 @@ if (!globalThis[globalKey]) {
989
1038
  initResolve,
990
1039
  initReject,
991
1040
  };
992
- // In SSR (no window), resolve immediately with a stub runtime
993
- // so modules don't hang waiting for browser-only init
994
1041
  if (typeof window === 'undefined') {
995
1042
  initResolve({
996
1043
  loadRemote: function() { return Promise.resolve(undefined); },
@@ -998,6 +1045,64 @@ if (!globalThis[globalKey]) {
998
1045
  });
999
1046
  }
1000
1047
  }
1048
+ `;
1049
+ }
1050
+ function getRuntimeInitPromiseBootstrapCode() {
1051
+ return `
1052
+ const __mfPromiseGlobalKey = ${JSON.stringify(getRuntimeInitGlobalKey())};
1053
+ let __mfPromiseState = globalThis[__mfPromiseGlobalKey];
1054
+ if (!__mfPromiseState) {
1055
+ let initResolve, initReject;
1056
+ const initPromise = new Promise((re, rj) => {
1057
+ initResolve = re;
1058
+ initReject = rj;
1059
+ });
1060
+ __mfPromiseState = globalThis[__mfPromiseGlobalKey] = {
1061
+ initPromise,
1062
+ initResolve,
1063
+ initReject,
1064
+ };
1065
+ if (typeof window === 'undefined') {
1066
+ initResolve({
1067
+ loadRemote: function() { return Promise.resolve(undefined); },
1068
+ loadShare: function() { return Promise.resolve(undefined); },
1069
+ });
1070
+ }
1071
+ }
1072
+ const initPromise = __mfPromiseState.initPromise;
1073
+ `;
1074
+ }
1075
+ function getRuntimeInitResolveBootstrapCode() {
1076
+ return `
1077
+ const __mfResolveGlobalKey = ${JSON.stringify(getRuntimeInitGlobalKey())};
1078
+ let __mfResolveState = globalThis[__mfResolveGlobalKey];
1079
+ if (!__mfResolveState) {
1080
+ let initResolve, initReject;
1081
+ const initPromise = new Promise((re, rj) => {
1082
+ initResolve = re;
1083
+ initReject = rj;
1084
+ });
1085
+ __mfResolveState = globalThis[__mfResolveGlobalKey] = {
1086
+ initPromise,
1087
+ initResolve,
1088
+ initReject,
1089
+ };
1090
+ if (typeof window === 'undefined') {
1091
+ initResolve({
1092
+ loadRemote: function() { return Promise.resolve(undefined); },
1093
+ loadShare: function() { return Promise.resolve(undefined); },
1094
+ });
1095
+ }
1096
+ }
1097
+ const initResolve = __mfResolveState.initResolve;
1098
+ `;
1099
+ }
1100
+ function writeRuntimeInitStatus(command) {
1101
+ getRuntimeInitGlobalKey();
1102
+ const exportStatement = command === "build" ? `const { initPromise, initResolve, initReject } = globalThis[globalKey];
1103
+ export { initPromise, initResolve, initReject };` : `module.exports = globalThis[globalKey];`;
1104
+ virtualRuntimeInitStatus.writeSync(`
1105
+ ${getRuntimeInitBootstrapCode()}
1001
1106
  ${exportStatement}
1002
1107
  `);
1003
1108
  }
@@ -1022,7 +1127,8 @@ function getUsedRemotesMap() {
1022
1127
  }
1023
1128
  function generateRemotes(id, command, isRolldown) {
1024
1129
  const useESM = command === "build" || isRolldown;
1025
- const importLine = useESM ? `import { initPromise } from "${virtualRuntimeInitStatus.getImportId()}"` : `const {initPromise} = require("${virtualRuntimeInitStatus.getImportId()}")`;
1130
+ const importLine = command === "build" ? getRuntimeInitPromiseBootstrapCode() : useESM ? `${getRuntimeInitBootstrapCode()}
1131
+ const { initPromise } = globalThis[globalKey];` : `const {initPromise} = require("${virtualRuntimeInitStatus.getImportId()}")`;
1026
1132
  const awaitOrPlaceholder = useESM ? "await " : "/*mf top-level-await placeholder replacement mf*/";
1027
1133
  const exportLine = command === "serve" && useESM ? "export default exportModule.default ?? exportModule" : useESM ? "export default exportModule" : "module.exports = exportModule";
1028
1134
  return `
@@ -1072,14 +1178,19 @@ function getPreBuildLibImportId(pkg) {
1072
1178
  }
1073
1179
  const LOAD_SHARE_TAG = "__loadShare__";
1074
1180
  const loadShareCacheMap = {};
1075
- function getLoadShareModulePath(pkg, isRolldown, command) {
1181
+ function getLoadShareImportId(pkg, isRolldown, command) {
1076
1182
  if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, isRolldown || command === "build" ? ".mjs" : ".js");
1183
+ return loadShareCacheMap[pkg].getImportId();
1184
+ }
1185
+ function getLoadShareModulePath(pkg, isRolldown, command) {
1186
+ if (!loadShareCacheMap[pkg]) getLoadShareImportId(pkg, isRolldown, command);
1077
1187
  return loadShareCacheMap[pkg].getPath();
1078
1188
  }
1079
1189
  function writeLoadShareModule(pkg, shareItem, command, isRolldown) {
1080
1190
  if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, isRolldown || command === "build" ? ".mjs" : ".js");
1081
1191
  const useESM = command === "build" || isRolldown;
1082
- const importLine = useESM ? `import { initPromise } from "${virtualRuntimeInitStatus.getImportId()}"` : `const {initPromise} = require("${virtualRuntimeInitStatus.getImportId()}")`;
1192
+ const importLine = command === "build" ? getRuntimeInitPromiseBootstrapCode() : useESM ? `${getRuntimeInitBootstrapCode()}
1193
+ const { initPromise } = globalThis[globalKey];` : `const {initPromise} = require("${virtualRuntimeInitStatus.getImportId()}")`;
1083
1194
  const awaitOrPlaceholder = useESM ? "await " : "/*mf top-level-await placeholder replacement mf*/";
1084
1195
  const useSsrProviderFallback = hasPackageDependency("vinext") && command === "build" && pkg === "react";
1085
1196
  const providerImportId = getLocalProviderImportPath(pkg) || getPreBuildLibImportId(pkg);
@@ -1088,8 +1199,8 @@ function writeLoadShareModule(pkg, shareItem, command, isRolldown) {
1088
1199
  if (namedExports.length > 0) {
1089
1200
  const destructure = `const { ${namedExports.map((name, i) => `${name}: __mf_${i}`).join(", ")} } = exportModule;`;
1090
1201
  const namedExportLine = `export { ${namedExports.map((name, i) => `__mf_${i} as ${name}`).join(", ")} };`;
1091
- exportLine = useESM ? `export default exportModule;\n ${destructure}\n ${namedExportLine}` : `module.exports = exportModule;\n ${destructure}\n Object.assign(module.exports, { ${namedExports.map((name, i) => `"${name}": __mf_${i}`).join(", ")} });`;
1092
- } else exportLine = useESM ? `export default exportModule\n export * from ${JSON.stringify(getPreBuildLibImportId(pkg))}` : "module.exports = exportModule";
1202
+ 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(", ")} });`;
1203
+ } else exportLine = useESM ? `export default exportModule.default ?? exportModule\n export * from ${JSON.stringify(getPreBuildLibImportId(pkg))}` : "module.exports = exportModule";
1093
1204
  loadShareCacheMap[pkg].writeSync(`
1094
1205
  import ${JSON.stringify(getPreBuildLibImportId(pkg))};
1095
1206
  ${command !== "build" ? `;() => import(${JSON.stringify(pkg)}).catch(() => {});` : ""}
@@ -1123,12 +1234,12 @@ new VirtualModule("localSharedImportMap");
1123
1234
  function getLocalSharedImportMapPath() {
1124
1235
  return getLocalSharedImportMapPath_temp();
1125
1236
  }
1126
- let prevSharedCount;
1237
+ let prevLocalSharedImportMapContent;
1127
1238
  function writeLocalSharedImportMap() {
1128
- const sharedCount = getUsedShares().size;
1129
- if (prevSharedCount !== sharedCount) {
1130
- prevSharedCount = sharedCount;
1131
- writeLocalSharedImportMap_temp(generateLocalSharedImportMap());
1239
+ const nextContent = generateLocalSharedImportMap();
1240
+ if (prevLocalSharedImportMapContent !== nextContent) {
1241
+ prevLocalSharedImportMapContent = nextContent;
1242
+ writeLocalSharedImportMap_temp(nextContent);
1132
1243
  }
1133
1244
  }
1134
1245
  function generateLocalSharedImportMap() {
@@ -1141,7 +1252,7 @@ function generateLocalSharedImportMap() {
1141
1252
  const shareItem = getNormalizeShareItem(pkg);
1142
1253
  return `
1143
1254
  ${JSON.stringify(pkg)}: async () => {
1144
- ${shareItem?.shareConfig.import === false ? `throw new Error(\`Shared module '\${${JSON.stringify(pkg)}}' must be provided by host\`);` : isVinext && pkg === "react" ? `let pkg = await import("react");
1255
+ ${shareItem?.shareConfig.import === false ? `throw new Error(\`[Module Federation] Shared module '\${${JSON.stringify(pkg)}}' must be provided by host\`);` : isVinext && pkg === "react" ? `let pkg = await import("react");
1145
1256
  return pkg;` : `let pkg = await import("${getPreBuildLibImportId(pkg)}");
1146
1257
  return pkg;`}
1147
1258
  }
@@ -1161,7 +1272,7 @@ function generateLocalSharedImportMap() {
1161
1272
  from: ${JSON.stringify(options.name)},
1162
1273
  async get () {
1163
1274
  if (${shareItem.shareConfig.import === false}) {
1164
- throw new Error(\`Shared module '\${${JSON.stringify(key)}}' must be provided by host\`);
1275
+ throw new Error(\`[Module Federation] Shared module '\${${JSON.stringify(key)}}' must be provided by host\`);
1165
1276
  }
1166
1277
  usedShared[${JSON.stringify(key)}].loaded = true
1167
1278
  const {${JSON.stringify(key)}: pkgDynamicImport} = importMap
@@ -1211,7 +1322,7 @@ const REMOTE_ENTRY_ID = "virtual:mf-REMOTE_ENTRY_ID";
1211
1322
  function getRemoteEntryId(options) {
1212
1323
  return `${REMOTE_ENTRY_ID}:${`${options.name}__${options.filename}`.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
1213
1324
  }
1214
- function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(options)) {
1325
+ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(options), command = "build") {
1215
1326
  const pluginImportNames = options.runtimePlugins.map((p, i) => {
1216
1327
  if (typeof p === "string") return [
1217
1328
  `$runtimePlugin_${i}`,
@@ -1227,15 +1338,25 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1227
1338
  return `
1228
1339
  import {init as runtimeInit, loadRemote} from "@module-federation/runtime";
1229
1340
  ${pluginImportNames.map((item) => item[1]).join("\n")}
1230
- import exposesMap from "${virtualExposesId}"
1231
- import {usedShared, usedRemotes} from "${getLocalSharedImportMapPath()}"
1232
- import {
1233
- initResolve
1234
- } from "${virtualRuntimeInitStatus.getImportId()}"
1341
+ ${command === "build" ? getRuntimeInitResolveBootstrapCode() : getRuntimeInitBootstrapCode() + "\n const { initResolve } = globalThis[globalKey];"}
1235
1342
  const initTokens = {}
1236
1343
  const shareScopeName = ${JSON.stringify(options.shareScope)}
1237
1344
  const mfName = ${JSON.stringify(options.name)}
1345
+ let localSharedImportMapPromise
1346
+ let exposesMapPromise
1347
+
1348
+ async function getLocalSharedImportMap() {
1349
+ localSharedImportMapPromise ??= import("${getLocalSharedImportMapPath()}")
1350
+ return localSharedImportMapPromise
1351
+ }
1352
+
1353
+ async function getExposesMap() {
1354
+ exposesMapPromise ??= import("${virtualExposesId}").then((mod) => mod.default ?? mod)
1355
+ return exposesMapPromise
1356
+ }
1357
+
1238
1358
  async function init(shared = {}, initScope = []) {
1359
+ const {usedShared, usedRemotes} = await getLocalSharedImportMap()
1239
1360
  const initRes = runtimeInit({
1240
1361
  name: mfName,
1241
1362
  remotes: usedRemotes,
@@ -1258,13 +1379,14 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1258
1379
  initScope
1259
1380
  }));
1260
1381
  } catch (e) {
1261
- console.error(e)
1382
+ console.error('[Module Federation]', e)
1262
1383
  }
1263
1384
  return initRes
1264
1385
  }
1265
1386
 
1266
- function getExposes(moduleName) {
1267
- if (!(moduleName in exposesMap)) throw new Error(\`Module \${moduleName} does not exist in container.\`)
1387
+ async function getExposes(moduleName) {
1388
+ const exposesMap = await getExposesMap()
1389
+ if (!(moduleName in exposesMap)) throw new Error(\`[Module Federation] Module \${moduleName} does not exist in container.\`)
1268
1390
  return (exposesMap[moduleName])().then(res => () => res)
1269
1391
  }
1270
1392
  export {
@@ -1276,13 +1398,8 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1276
1398
  const hostAutoInitModule = new VirtualModule("hostAutoInit", "__H_A_I__");
1277
1399
  function writeHostAutoInit(remoteEntryId = REMOTE_ENTRY_ID) {
1278
1400
  hostAutoInitModule.writeSync(`
1279
- const remoteEntryPromise = import("${remoteEntryId}")
1280
- Promise.resolve(remoteEntryPromise)
1281
- .then(remoteEntry => {
1282
- return Promise.resolve(remoteEntry.__tla)
1283
- .then(remoteEntry.init)
1284
- .catch(remoteEntry.init)
1285
- })
1401
+ const remoteEntry = await import("${remoteEntryId}");
1402
+ await remoteEntry.init();
1286
1403
  `);
1287
1404
  }
1288
1405
  function getHostAutoInitImportId() {
@@ -1305,13 +1422,21 @@ function initVirtualModules(command, remoteEntryId) {
1305
1422
  * If Rollup's deconflict renamed the alias but didn't update references
1306
1423
  * in the code body, fall back to proxyLocal so they stay in sync.
1307
1424
  */
1308
- function resolveProxyAlias(binding, proxyLocal, code, fullImport) {
1425
+ function resolveProxyAlias(binding, proxyLocal, code, fullImport, claimedLocals = /* @__PURE__ */ new Set()) {
1309
1426
  const codeWithoutImport = code.replace(fullImport, "");
1310
1427
  const escapedLocal = binding.local.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1311
1428
  const localUsedInCode = new RegExp(`\\b${escapedLocal}\\b`).test(codeWithoutImport);
1429
+ const claimedImportLocals = /* @__PURE__ */ new Set();
1430
+ const importRe = /import\s*\{([^}]+)\}\s*from\s*["'][^"']+["']\s*;?/g;
1431
+ let match;
1432
+ while ((match = importRe.exec(codeWithoutImport)) !== null) for (const spec of match[1].split(",")) {
1433
+ const parts = spec.trim().split(/\s+as\s+/);
1434
+ claimedImportLocals.add((parts[1] || parts[0]).trim());
1435
+ }
1436
+ const local = !localUsedInCode && !claimedLocals.has(proxyLocal) && !claimedImportLocals.has(proxyLocal) ? proxyLocal : binding.local;
1312
1437
  return {
1313
1438
  imported: binding.imported,
1314
- local: localUsedInCode ? binding.local : proxyLocal
1439
+ local
1315
1440
  };
1316
1441
  }
1317
1442
  function findRemoteEntryFile(filename, bundle) {
@@ -1678,14 +1803,14 @@ const promise = new Promise((resolve, reject) => {
1678
1803
  });
1679
1804
  function setParseTimeout(timeout) {
1680
1805
  if (!_parseTimeout) _parseTimeout = setTimeout(() => {
1681
- console.warn(`Parse timeout (${timeout}s) - forcing resolve`);
1806
+ mfWarn(`Parse timeout (${timeout}s) - forcing resolve`);
1682
1807
  _resolve(1);
1683
1808
  }, timeout * 1e3);
1684
1809
  }
1685
1810
  function resetIdleTimeout(timeout) {
1686
1811
  clearTimeout(_parseTimeout);
1687
1812
  _parseTimeout = setTimeout(() => {
1688
- console.warn(`moduleParseIdleTimeout: no module activity for ${timeout}s, forcing resolve. Some shared/remote dependencies may be missing. Consider increasing moduleParseIdleTimeout.`);
1813
+ mfWarn(`moduleParseIdleTimeout: no module activity for ${timeout}s, forcing resolve. Some shared/remote dependencies may be missing. Consider increasing moduleParseIdleTimeout.`);
1689
1814
  _resolve(1);
1690
1815
  }, timeout * 1e3);
1691
1816
  }
@@ -1766,14 +1891,14 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
1766
1891
  }
1767
1892
  },
1768
1893
  load(id) {
1769
- if (id === remoteEntryId) return parsePromise.then((_) => generateRemoteEntry(options, virtualExposesId));
1894
+ if (id === remoteEntryId) return parsePromise.then((_) => generateRemoteEntry(options, virtualExposesId, _command));
1770
1895
  if (id === virtualExposesId) return generateExposes(options);
1771
1896
  if (_command === "serve" && id.includes(getHostAutoInitPath())) return id;
1772
1897
  },
1773
1898
  transform(code, id) {
1774
1899
  return mapCodeToCodeWithSourcemap((() => {
1775
1900
  if (!filter(id)) return;
1776
- if (id.includes(remoteEntryId)) return parsePromise.then((_) => generateRemoteEntry(options, virtualExposesId));
1901
+ if (id.includes(remoteEntryId)) return parsePromise.then((_) => generateRemoteEntry(options, virtualExposesId, _command));
1777
1902
  if (id === virtualExposesId) return generateExposes(options);
1778
1903
  if (id.includes(getHostAutoInitPath())) {
1779
1904
  if (_command === "serve") {
@@ -1806,7 +1931,7 @@ function pluginProxyRemotes_default(options) {
1806
1931
  return {
1807
1932
  name: "proxyRemotes",
1808
1933
  config(config, { command: _command }) {
1809
- const isRolldown = !!this?.meta?.rolldownVersion;
1934
+ const isRolldown = getIsRolldown(this);
1810
1935
  Object.keys(remotes).forEach((key) => {
1811
1936
  const remote = remotes[key];
1812
1937
  config.resolve.alias.push({
@@ -1878,7 +2003,7 @@ function proxySharedModule(options) {
1878
2003
  config(config, { command }) {
1879
2004
  setPackageDetectionCwd(config.root || process.cwd());
1880
2005
  isVinext = hasPackageDependency("vinext");
1881
- const isRolldown = !!this?.meta?.rolldownVersion;
2006
+ const isRolldown = getIsRolldown(this);
1882
2007
  _command = command;
1883
2008
  config.resolve.alias.push(...Object.keys(shared).filter((key) => !(isVinext && key === "react")).map((key) => {
1884
2009
  const keyBase = key.endsWith("/") ? key.slice(0, -1) : key;
@@ -1958,7 +2083,6 @@ const VarRemoteEntry = () => {
1958
2083
  if (req.url?.replace(/\?.*/, "") === (viteConfig.base + varFilename).replace(/^\/?/, "/")) {
1959
2084
  res.setHeader("Content-Type", "text/javascript");
1960
2085
  res.setHeader("Access-Control-Allow-Origin", "*");
1961
- console.log({ filename });
1962
2086
  res.end(generateVarRemoteEntry(filename));
1963
2087
  } else next();
1964
2088
  });
@@ -1974,9 +2098,9 @@ const VarRemoteEntry = () => {
1974
2098
  },
1975
2099
  async generateBundle(options, bundle) {
1976
2100
  if (!varFilename) return;
1977
- if (!isValidVarName(name)) viteConfig.logger.warn(`Provided remote name "${name}" is not valid for "var" remoteEntry type, thus it's placed in globalThis['${name}'].\nIt may cause problems, so you would better want to use valid var name (see https://www.w3schools.com/js/js_variables.asp).`);
2101
+ if (!isValidVarName(name)) mfWarn(`Provided remote name "${name}" is not valid for "var" remoteEntry type, thus it's placed in globalThis['${name}'].\nIt may cause problems, so you would better want to use valid var name (see https://www.w3schools.com/js/js_variables.asp).`);
1978
2102
  const remoteEntryFile = findRemoteEntryFile(mfOptions.filename, bundle);
1979
- if (!remoteEntryFile) throw new Error(`Couldn't find a remoteEntry chunk file for ${mfOptions.filename}, can't generate varRemoteEntry file`);
2103
+ if (!remoteEntryFile) throw createModuleFederationError(`Couldn't find a remoteEntry chunk file for ${mfOptions.filename}, can't generate varRemoteEntry file`);
1980
2104
  this.emitFile({
1981
2105
  type: "asset",
1982
2106
  fileName: varFilename,
@@ -2001,7 +2125,7 @@ const VarRemoteEntry = () => {
2001
2125
  function getScriptUrl() {
2002
2126
  const currentScript = document.currentScript;
2003
2127
  if (!currentScript) {
2004
- console.error("[VarRemoteEntry] ${varFilename} script should be called from sync <script> tag (document.currentScript is undefined)")
2128
+ console.error("[Module Federation] ${varFilename} script should be called from sync <script> tag (document.currentScript is undefined)")
2005
2129
  return '/';
2006
2130
  }
2007
2131
  return document.currentScript.src.replace(/\\/[^/]*$/, '/');
@@ -2032,6 +2156,58 @@ var aliasToArrayPlugin_default = {
2032
2156
  }
2033
2157
  };
2034
2158
  //#endregion
2159
+ //#region src/utils/controlChunkSanitizer.ts
2160
+ const FEDERATION_CONTROL_CHUNK_HINTS = [
2161
+ "hostInit",
2162
+ "virtualExposes",
2163
+ "localSharedImportMap"
2164
+ ];
2165
+ function stripEmptyPreloadCalls(code) {
2166
+ const helperImportRegex = /import\s*\{\s*_\s*as\s*(\w+)\s*\}\s*from\s*["'][^"']+["']\s*;?/g;
2167
+ const helperAliases = [...code.matchAll(helperImportRegex)].map((match) => match[1]);
2168
+ let nextCode = code;
2169
+ for (const alias of helperAliases) {
2170
+ const marker = `${alias}(()=>`;
2171
+ let start = nextCode.indexOf(marker);
2172
+ while (start !== -1) {
2173
+ const exprStart = start + marker.length;
2174
+ let depth = 0;
2175
+ let cursor = exprStart;
2176
+ let replacementEnd = -1;
2177
+ while (cursor < nextCode.length) {
2178
+ const char = nextCode[cursor];
2179
+ if (char === "(") depth++;
2180
+ else if (char === ")") depth--;
2181
+ else if (depth === 0 && nextCode.startsWith(",[],import.meta.url)", cursor)) {
2182
+ replacementEnd = cursor;
2183
+ break;
2184
+ }
2185
+ cursor++;
2186
+ }
2187
+ if (replacementEnd === -1) break;
2188
+ const expression = nextCode.slice(exprStart, replacementEnd);
2189
+ nextCode = nextCode.slice(0, start) + expression + nextCode.slice(replacementEnd + 20);
2190
+ start = nextCode.indexOf(marker, start + expression.length);
2191
+ }
2192
+ }
2193
+ nextCode = nextCode.replace(/import\s*["'][^"']*__loadShare__[^"']*["']\s*;?/g, "");
2194
+ nextCode = nextCode.replace(helperImportRegex, (statement, local) => {
2195
+ return new RegExp(`\\b${local}\\s*\\(`).test(nextCode.replace(statement, "")) ? statement : "";
2196
+ });
2197
+ return nextCode;
2198
+ }
2199
+ function isFederationControlChunk(fileName, filename) {
2200
+ return fileName.includes(filename) || FEDERATION_CONTROL_CHUNK_HINTS.some((hint) => fileName.includes(hint));
2201
+ }
2202
+ function sanitizeFederationControlChunk(code, fileName, filename) {
2203
+ let nextCode = stripEmptyPreloadCalls(code);
2204
+ if (fileName.includes("localSharedImportMap")) {
2205
+ const remoteEntryImportRegex = new RegExp(`import\\s*["'][^"']*${filename.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}["']\\s*;?`, "g");
2206
+ nextCode = nextCode.replace(remoteEntryImportRegex, "");
2207
+ }
2208
+ return nextCode;
2209
+ }
2210
+ //#endregion
2035
2211
  //#region src/utils/normalizeOptimizeDeps.ts
2036
2212
  var normalizeOptimizeDeps_default = {
2037
2213
  name: "normalizeOptimizeDeps",
@@ -2048,6 +2224,25 @@ var normalizeOptimizeDeps_default = {
2048
2224
  };
2049
2225
  //#endregion
2050
2226
  //#region src/index.ts
2227
+ const UNSAFE_JS_SOURCE_CHAR_MAP = {
2228
+ "<": "\\u003C",
2229
+ ">": "\\u003E",
2230
+ "/": "\\u002F",
2231
+ "\\": "\\\\",
2232
+ "\b": "\\b",
2233
+ "\f": "\\f",
2234
+ "\n": "\\n",
2235
+ "\r": "\\r",
2236
+ " ": "\\t",
2237
+ "\0": "\\0",
2238
+ "\u2028": "\\u2028",
2239
+ "\u2029": "\\u2029"
2240
+ };
2241
+ function escapeUnsafeJsSourceChars(str) {
2242
+ return str.replace(/[<>/\\\b\f\n\r\t\0\u2028\u2029]/g, (char) => {
2243
+ return UNSAFE_JS_SOURCE_CHAR_MAP[char] ?? char;
2244
+ });
2245
+ }
2051
2246
  /**
2052
2247
  * Plugin that runs FIRST to create virtual module files in the config hook.
2053
2248
  * This prevents 504 "Outdated Optimize Dep" errors by ensuring files exist
@@ -2067,7 +2262,7 @@ function createEarlyVirtualModulesPlugin(options) {
2067
2262
  VirtualModule.ensureVirtualPackageExists();
2068
2263
  initVirtualModules(_command, getRemoteEntryId(options));
2069
2264
  if (_command !== "serve") return;
2070
- const isRolldown = !!this?.meta?.rolldownVersion;
2265
+ const isRolldown = getIsRolldown(this);
2071
2266
  if (remotes && Object.keys(remotes).length > 0) for (const key of Object.keys(remotes)) addUsedRemote(key, key);
2072
2267
  if (shared && Object.keys(shared).length > 0) {
2073
2268
  config.optimizeDeps = config.optimizeDeps || {};
@@ -2084,6 +2279,7 @@ function createEarlyVirtualModulesPlugin(options) {
2084
2279
  writeLoadShareModule(key, shareItem, _command, isRolldown);
2085
2280
  writePreBuildLibPath(key);
2086
2281
  addUsedShares(key);
2282
+ config.optimizeDeps.include.push(getLoadShareImportId(key, isRolldown, _command));
2087
2283
  config.optimizeDeps.include.push(getPreBuildLibImportId(key));
2088
2284
  }
2089
2285
  writeLocalSharedImportMap();
@@ -2095,7 +2291,7 @@ function federation(mfUserOptions) {
2095
2291
  const options = normalizeModuleFederationOptions(mfUserOptions);
2096
2292
  const isVinext = hasPackageDependency("vinext");
2097
2293
  const { name, remotes, shared, filename, hostInitInjectLocation } = options;
2098
- if (!name) throw new Error("name is required");
2294
+ if (!name) throw createModuleFederationError("name is required");
2099
2295
  const remoteEntryId = getRemoteEntryId(options);
2100
2296
  const virtualExposesId = getVirtualExposesId(options);
2101
2297
  let command;
@@ -2169,9 +2365,28 @@ function federation(mfUserOptions) {
2169
2365
  config(config) {
2170
2366
  const runtimeInitId = virtualRuntimeInitStatus.getImportId();
2171
2367
  config.build = config.build || {};
2172
- config.build.rollupOptions = config.build.rollupOptions || {};
2173
- if (!Array.isArray(config.build.rollupOptions.output)) {
2174
- const output = config.build.rollupOptions.output ||= {};
2368
+ if (config.build.modulePreload !== false) {
2369
+ const currentModulePreload = config.build.modulePreload && typeof config.build.modulePreload === "object" ? config.build.modulePreload : {};
2370
+ const existingResolveDependencies = currentModulePreload.resolveDependencies;
2371
+ config.build.modulePreload = {
2372
+ ...currentModulePreload,
2373
+ resolveDependencies(filename, deps, context) {
2374
+ const resolvedDeps = existingResolveDependencies ? existingResolveDependencies(filename, deps, context) : deps;
2375
+ const hostFile = pathe.default.basename(context.hostId);
2376
+ return context.hostType === "js" && (hostFile === options.filename || hostFile.includes("hostInit") || hostFile.includes("virtualExposes") || hostFile.includes("localSharedImportMap")) ? [] : resolvedDeps;
2377
+ }
2378
+ };
2379
+ }
2380
+ let warnedAboutCodeSplitting = false;
2381
+ const ensureCodeSplitting = (output) => {
2382
+ if (output?.codeSplitting !== false) return;
2383
+ delete output.codeSplitting;
2384
+ if (warnedAboutCodeSplitting) return;
2385
+ warnedAboutCodeSplitting = true;
2386
+ mfWarn("Ignoring `build.rolldownOptions.output.codeSplitting = false` because module federation requires chunk splitting.");
2387
+ };
2388
+ const applyManualChunks = (output) => {
2389
+ ensureCodeSplitting(output);
2175
2390
  const existingManualChunks = output.manualChunks;
2176
2391
  output.manualChunks = function(id) {
2177
2392
  if (id.includes(runtimeInitId)) return "runtimeInit";
@@ -2184,7 +2399,12 @@ function federation(mfUserOptions) {
2184
2399
  for (const [key, ids] of Object.entries(existingManualChunks)) if (Array.isArray(ids) && ids.some((v) => id.includes(v))) return key;
2185
2400
  }
2186
2401
  };
2187
- }
2402
+ };
2403
+ config.build.rollupOptions = config.build.rollupOptions || {};
2404
+ if (!Array.isArray(config.build.rollupOptions.output)) applyManualChunks(config.build.rollupOptions.output ||= {});
2405
+ const buildWithRolldown = config.build;
2406
+ buildWithRolldown.rolldownOptions = buildWithRolldown.rolldownOptions || {};
2407
+ if (!Array.isArray(buildWithRolldown.rolldownOptions.output)) applyManualChunks(buildWithRolldown.rolldownOptions.output ||= {});
2188
2408
  },
2189
2409
  load(id) {
2190
2410
  if (id.startsWith("\0")) return;
@@ -2216,6 +2436,11 @@ function federation(mfUserOptions) {
2216
2436
  }
2217
2437
  },
2218
2438
  generateBundle(_, bundle) {
2439
+ for (const [fileName, chunk] of Object.entries(bundle)) {
2440
+ if (chunk.type !== "chunk") continue;
2441
+ if (!isFederationControlChunk(fileName, filename)) continue;
2442
+ chunk.code = sanitizeFederationControlChunk(chunk.code, fileName, filename);
2443
+ }
2219
2444
  for (const [fileName, chunk] of Object.entries(bundle)) {
2220
2445
  if (chunk.type !== "chunk") continue;
2221
2446
  if (fileName.includes("__loadShare__")) continue;
@@ -2253,12 +2478,12 @@ function federation(mfUserOptions) {
2253
2478
  fileName
2254
2479
  });
2255
2480
  }
2256
- if (proxyChunks.size === 0) return;
2257
- for (const [fileName, chunk] of Object.entries(bundle)) {
2481
+ if (proxyChunks.size > 0) for (const [fileName, chunk] of Object.entries(bundle)) {
2258
2482
  if (chunk.type !== "chunk") continue;
2259
2483
  if (fileName.includes("__loadShare__")) continue;
2260
2484
  let code = chunk.code;
2261
2485
  let modified = false;
2486
+ const claimedLocals = /* @__PURE__ */ new Set();
2262
2487
  for (const [proxyFileName, proxyInfo] of proxyChunks) {
2263
2488
  const proxyBaseName = proxyFileName.replace(/^.*\//, "").replace(/\.js$/, "").replace(/-[A-Za-z0-9_-]+$/, "");
2264
2489
  const importMatch = new RegExp(`import\\s*\\{([^}]+)\\}\\s*from\\s*["']([^"']*${proxyBaseName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}[^"']*)["']\\s*;?`).exec(code);
@@ -2281,9 +2506,12 @@ function federation(mfUserOptions) {
2281
2506
  }
2282
2507
  const inlineable = [];
2283
2508
  const nonInlineable = [];
2509
+ const pendingLocals = new Set(bindings.map((binding) => binding.local));
2284
2510
  for (const b of bindings) {
2511
+ pendingLocals.delete(b.local);
2285
2512
  const proxyLocal = exportMap[b.imported];
2286
2513
  if (!proxyLocal) {
2514
+ claimedLocals.add(b.local);
2287
2515
  nonInlineable.push(b);
2288
2516
  continue;
2289
2517
  }
@@ -2305,7 +2533,14 @@ function federation(mfUserOptions) {
2305
2533
  local: b.local,
2306
2534
  funcBody: renamedFunc
2307
2535
  });
2308
- } else nonInlineable.push(resolveProxyAlias(b, proxyLocal, code, fullImport));
2536
+ claimedLocals.add(b.local);
2537
+ } else {
2538
+ const unavailableLocals = new Set(claimedLocals);
2539
+ pendingLocals.forEach((local) => unavailableLocals.add(local));
2540
+ const resolvedBinding = resolveProxyAlias(b, proxyLocal, code, fullImport, unavailableLocals);
2541
+ claimedLocals.add(resolvedBinding.local);
2542
+ nonInlineable.push(resolvedBinding);
2543
+ }
2309
2544
  }
2310
2545
  const hasRenamedAlias = nonInlineable.some((b) => bindings.find((ob) => ob.imported === b.imported)?.local !== b.local);
2311
2546
  if (inlineable.length === 0 && !hasRenamedAlias) continue;
@@ -2319,6 +2554,28 @@ function federation(mfUserOptions) {
2319
2554
  }
2320
2555
  }
2321
2556
  },
2557
+ {
2558
+ name: "module-federation-strip-empty-preload-helper",
2559
+ enforce: "post",
2560
+ apply: "build",
2561
+ renderChunk(code, chunk) {
2562
+ if (!isFederationControlChunk(chunk.fileName, filename)) return;
2563
+ const nextCode = sanitizeFederationControlChunk(code, chunk.fileName, filename);
2564
+ return nextCode === code ? null : {
2565
+ code: nextCode,
2566
+ map: null
2567
+ };
2568
+ },
2569
+ writeBundle(outputOptions, bundle) {
2570
+ if (!outputOptions.dir) return;
2571
+ for (const chunk of Object.values(bundle)) {
2572
+ if (chunk.type !== "chunk") continue;
2573
+ if (!isFederationControlChunk(chunk.fileName, filename)) continue;
2574
+ const outputPath = pathe.default.join(outputOptions.dir, chunk.fileName);
2575
+ (0, fs.writeFileSync)(outputPath, sanitizeFederationControlChunk((0, fs.readFileSync)(outputPath, "utf-8"), chunk.fileName, filename));
2576
+ }
2577
+ }
2578
+ },
2322
2579
  {
2323
2580
  name: "module-federation-dev-await-shared-init",
2324
2581
  apply: "serve",
@@ -2351,9 +2608,9 @@ function federation(mfUserOptions) {
2351
2608
  enforce: "post",
2352
2609
  _options: options,
2353
2610
  config(config, { command: _command }) {
2354
- const isRolldown = !!this?.meta?.rolldownVersion;
2611
+ const isRolldown = getIsRolldown(this);
2355
2612
  let implementation = options.implementation;
2356
- if (isRolldown) implementation = implementation.replace(/\.cjs\.cjs$/, ".esm.js");
2613
+ if (isRolldown) implementation = implementation.replace(/\.cjs(\.js)?$/, ".js");
2357
2614
  config.resolve.alias.push({
2358
2615
  find: "@module-federation/runtime",
2359
2616
  replacement: implementation
@@ -2380,7 +2637,7 @@ function federation(mfUserOptions) {
2380
2637
  const resolvedTarget = options.target ?? (config.build?.ssr ? "node" : "web");
2381
2638
  if (!config.define) config.define = {};
2382
2639
  if (!("ENV_TARGET" in config.define)) config.define["ENV_TARGET"] = JSON.stringify(resolvedTarget);
2383
- if (options.target && "ENV_TARGET" in config.define && config.define["ENV_TARGET"] !== JSON.stringify(options.target)) console.warn(`[module-federation] ENV_TARGET define (${config.define["ENV_TARGET"]}) differs from target option ("${options.target}"). ENV_TARGET will not be overridden.`);
2640
+ if (options.target && "ENV_TARGET" in config.define && config.define["ENV_TARGET"] !== JSON.stringify(options.target)) mfWarn(`ENV_TARGET define (${config.define["ENV_TARGET"]}) differs from target option ("${options.target}"). ENV_TARGET will not be overridden.`);
2384
2641
  }
2385
2642
  },
2386
2643
  ...Manifest(),
@@ -2393,13 +2650,18 @@ function federation(mfUserOptions) {
2393
2650
  for (const chunk of Object.values(bundle)) {
2394
2651
  if (chunk.type !== "chunk") continue;
2395
2652
  if (!chunk.code.includes("modulepreload")) continue;
2396
- const replacement = "=function($1){return new URL(\"../\"+$1,import.meta.url).href}";
2653
+ const chunkDir = pathe.default.dirname(chunk.fileName);
2654
+ const prefixToRoot = chunkDir === "." ? "" : `${pathe.default.relative(chunkDir, ".")}/`;
2655
+ const replacementExpr = prefixToRoot ? `${escapeUnsafeJsSourceChars(JSON.stringify(prefixToRoot))}+$1` : "$1";
2656
+ const replacement = `=function($1){return new URL(${replacementExpr},import.meta.url).href}`;
2397
2657
  const replaced = chunk.code.replace(/=\(?(\w+)(?:,\w+)?\)?\s*=>\s*["'`][^"'`]*["'`]\s*\+\s*\1/, replacement);
2398
2658
  if (replaced !== chunk.code) {
2399
2659
  chunk.code = replaced;
2400
2660
  continue;
2401
2661
  }
2402
2662
  chunk.code = chunk.code.replace(/=function\((\w+)(?:,\w+)?\)\{return\s*["'`][^"'`]*["'`]\s*\+\s*\1\s*\}/, replacement);
2663
+ chunk.code = chunk.code.replace(/=function\((\w+)(?:,\w+)?\)\{return new URL\("\.\.\/"\+\1,import\.meta\.url\)\.href\}/, replacement);
2664
+ chunk.code = chunk.code.replace(/new URL\("\.\.\/"\+(\w+),import\.meta\.url\)\.href/g, `new URL(${replacementExpr},import.meta.url).href`);
2403
2665
  }
2404
2666
  }
2405
2667
  }] : []