@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.mjs CHANGED
@@ -59,6 +59,38 @@ function inlineEntryScripts(html, initSrc) {
59
59
  return html.replace("<head>", `<head><script type="module" src=${JSON.stringify(src)}><\/script>`);
60
60
  }
61
61
  //#endregion
62
+ //#region src/utils/logger.ts
63
+ const MODULE_FEDERATION_LOG_PREFIX = "[Module Federation]";
64
+ function formatModuleFederationMessage(message) {
65
+ return `${MODULE_FEDERATION_LOG_PREFIX} ${message}`;
66
+ }
67
+ function createModuleFederationError(message) {
68
+ return new Error(formatModuleFederationMessage(message));
69
+ }
70
+ function toConsoleArgs(message, rest = []) {
71
+ if (typeof message === "string") return [formatModuleFederationMessage(message), ...rest];
72
+ if (message === void 0) return [MODULE_FEDERATION_LOG_PREFIX, ...rest];
73
+ return [
74
+ MODULE_FEDERATION_LOG_PREFIX,
75
+ message,
76
+ ...rest
77
+ ];
78
+ }
79
+ const moduleFederationConsole = {
80
+ log(message, ...rest) {
81
+ console.log(...toConsoleArgs(message, rest));
82
+ },
83
+ warn(message, ...rest) {
84
+ console.warn(...toConsoleArgs(message, rest));
85
+ },
86
+ error(message, ...rest) {
87
+ console.error(...toConsoleArgs(message, rest));
88
+ }
89
+ };
90
+ moduleFederationConsole.log;
91
+ const mfWarn = moduleFederationConsole.warn;
92
+ const mfError = moduleFederationConsole.error;
93
+ //#endregion
62
94
  //#region src/utils/packageUtils.ts
63
95
  const dependencyPresenceCache = /* @__PURE__ */ new Map();
64
96
  let packageDetectionCwd;
@@ -82,7 +114,7 @@ function setPackageDetectionCwd(cwd) {
82
114
  * @returns {string} - The encoded file name.
83
115
  */
84
116
  function packageNameEncode(name) {
85
- if (typeof name !== "string") throw new Error("A string package name is required");
117
+ if (typeof name !== "string") throw createModuleFederationError("A string package name is required");
86
118
  return name.replace(/@/g, "_mf_0_").replace(/\//g, "_mf_1_").replace(/-/g, "_mf_2_").replace(/\./g, "_mf_3_");
87
119
  }
88
120
  /**
@@ -91,7 +123,7 @@ function packageNameEncode(name) {
91
123
  * @returns {string} - The decoded package name.
92
124
  */
93
125
  function packageNameDecode(encoded) {
94
- if (typeof encoded !== "string") throw new Error("A string encoded file name is required");
126
+ if (typeof encoded !== "string") throw createModuleFederationError("A string encoded file name is required");
95
127
  return encoded.replace(/_mf_0_/g, "@").replace(/_mf_1_/g, "/").replace(/_mf_2_/g, "-").replace(/_mf_3_/g, ".");
96
128
  }
97
129
  /**
@@ -103,6 +135,13 @@ function removePathFromNpmPackage(packageString) {
103
135
  const match = packageString.match(/^(?:@[^/]+\/)?[^/]+/);
104
136
  return match ? match[0] : packageString;
105
137
  }
138
+ /**
139
+ * Detect whether the current bundler is Rolldown (Vite 8+) by checking
140
+ * for `meta.rolldownVersion` on the plugin hook context.
141
+ */
142
+ function getIsRolldown(ctx) {
143
+ return !!ctx?.meta?.rolldownVersion;
144
+ }
106
145
  function hasPackageDependency(dependencyName, cwd = packageDetectionCwd || process.cwd()) {
107
146
  const cacheKey = getDependencyCacheKey(cwd, dependencyName);
108
147
  const cached = dependencyPresenceCache.get(cacheKey);
@@ -184,6 +223,12 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry" }) => {
184
223
  else if (Array.isArray(inputOptions)) entryFiles = inputOptions;
185
224
  else if (typeof inputOptions === "object") entryFiles = Object.values(inputOptions);
186
225
  if (entryFiles && entryFiles.length > 0) htmlFilePath = getFirstHtmlEntryFile(entryFiles);
226
+ if (_command === "serve" && htmlFilePath && fs.existsSync(htmlFilePath)) {
227
+ const htmlContent = fs.readFileSync(htmlFilePath, "utf-8");
228
+ const scriptRegex = /<script\s+[^>]*src=["']([^"']+)["'][^>]*>/gi;
229
+ let match;
230
+ while ((match = scriptRegex.exec(htmlContent)) !== null) entryFiles.push(match[1]);
231
+ }
187
232
  },
188
233
  buildStart() {
189
234
  if (_command === "serve") return;
@@ -217,7 +262,7 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry" }) => {
217
262
  if (typeof result === "string") return result;
218
263
  if (result && typeof result === "object") {
219
264
  if ("runtime" in result) {
220
- 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.");
265
+ mfWarn("renderBuiltUrl returned runtime code for HTML injection. Runtime code cannot be used in <script src=\"\">. Falling back to base path.");
221
266
  return viteConfig.base + file;
222
267
  }
223
268
  if (result.relative) return file;
@@ -282,11 +327,11 @@ function checkAliasConflicts(options) {
282
327
  });
283
328
  }
284
329
  if (conflicts.length > 0) {
285
- config.logger.warn("\n[Module Federation] Detected alias conflicts with shared modules:");
330
+ mfWarn("Detected alias conflicts with shared modules:");
286
331
  conflicts.forEach(({ sharedModule, alias, target }) => {
287
- config.logger.warn(` - Shared module "${sharedModule}" is aliased by "${alias}" to "${target}"`);
332
+ mfWarn(`Shared module "${sharedModule}" is aliased by "${alias}" to "${target}"`);
288
333
  });
289
- config.logger.warn(" This may cause runtime errors as the shared module will bypass Module Federation's sharing mechanism.");
334
+ mfWarn("This may cause runtime errors as the shared module will bypass Module Federation's sharing mechanism.");
290
335
  }
291
336
  }
292
337
  };
@@ -315,7 +360,7 @@ function PluginDevProxyModuleTopLevelAwait() {
315
360
  try {
316
361
  ast = this.parse(code, { allowReturnOutsideFunction: true });
317
362
  } catch (e) {
318
- throw new Error(`${id}: ${e}`);
363
+ throw createModuleFederationError(`${id}: ${e}`);
319
364
  }
320
365
  const magicString = new MagicString(code);
321
366
  const walk = await loadWalk();
@@ -443,7 +488,7 @@ const normalizeDevDtsOptions = (dts, context) => {
443
488
  const logDtsError = (error, dtsOptions) => {
444
489
  if (dtsOptions === false) return;
445
490
  if (typeof dtsOptions === "object" && dtsOptions && dtsOptions.displayErrorInTerminal === false) return;
446
- console.error(error);
491
+ mfError(error);
447
492
  };
448
493
  function pluginDts(options) {
449
494
  if (options.dts === false) return [];
@@ -471,7 +516,7 @@ function pluginDts(options) {
471
516
  if (!normalizedDevOptions || !resolvedConfig) return;
472
517
  const devOptions = normalizedDevOptions;
473
518
  if (devOptions.disableDynamicRemoteTypeHints && devOptions.disableHotTypesReload && devOptions.disableLiveReload) return;
474
- if (!options.name) throw new Error("name is required if you want to enable dev server!");
519
+ if (!options.name) throw createModuleFederationError("name is required if you want to enable dev server!");
475
520
  const outputDir = resolveOutputDir(resolvedConfig);
476
521
  const normalizedDtsOptions = normalizeDevDtsOptions(options.dts, resolvedConfig.root);
477
522
  if (typeof normalizedDtsOptions !== "object") return;
@@ -652,6 +697,10 @@ function searchPackageVersion(sharedName) {
652
697
  }
653
698
  } catch (_) {}
654
699
  }
700
+ function inferVersionFromRequiredVersion(requiredVersion) {
701
+ if (!requiredVersion) return void 0;
702
+ return requiredVersion.match(/\d+\.\d+\.\d+(?:[-+][0-9A-Za-z.-]+)?/)?.[0];
703
+ }
655
704
  function normalizeShareItem(key, shareItem) {
656
705
  let version;
657
706
  try {
@@ -662,11 +711,11 @@ function normalizeShareItem(key, shareItem) {
662
711
  version = __require(path$1.join(process.cwd(), "node_modules", removePathFromNpmPackage(key), "package.json")).version;
663
712
  } catch (e2) {
664
713
  version = searchPackageVersion(key);
665
- if (!version) console.error(e1);
714
+ if (!version) mfError(e1);
666
715
  }
667
716
  }
668
717
  } catch (e) {
669
- console.error(`Unexpected error resolving version for ${key}:`, e);
718
+ mfError(`Unexpected error resolving version for ${key}:`, e);
670
719
  }
671
720
  if (typeof shareItem === "string") return {
672
721
  name: shareItem,
@@ -682,7 +731,7 @@ function normalizeShareItem(key, shareItem) {
682
731
  return {
683
732
  name: key,
684
733
  from: "",
685
- version: shareItem.version || version,
734
+ version: shareItem.version || inferVersionFromRequiredVersion(shareItem.requiredVersion) || version,
686
735
  scope: shareItem.shareScope || "default",
687
736
  shareConfig: {
688
737
  import: typeof shareItem === "object" ? shareItem.import : void 0,
@@ -727,7 +776,7 @@ function getNormalizeShareItem(key) {
727
776
  return options.shared[key] || options.shared[removePathFromNpmPackage(key)] || options.shared[removePathFromNpmPackage(key) + "/"];
728
777
  }
729
778
  function normalizeModuleFederationOptions(options) {
730
- 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'.`);
779
+ 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'.`);
731
780
  return config = {
732
781
  exposes: normalizeExposes(options.exposes),
733
782
  filename: options.filename || "remoteEntry-[hash]",
@@ -862,7 +911,7 @@ const cacheMap = {};
862
911
  */
863
912
  function assertModuleFound(tag, str = "") {
864
913
  const module = VirtualModule.findModule(tag, str);
865
- if (!module) throw new Error(`Module Federation shared module '${str}' not found. Please ensure it's installed as a dependency in your package.json.`);
914
+ if (!module) throw createModuleFederationError(`Module Federation shared module '${str}' not found. Please ensure it's installed as a dependency in your package.json.`);
866
915
  return module;
867
916
  }
868
917
  var VirtualModule = class {
@@ -949,12 +998,12 @@ function generateExposes(options) {
949
998
  //#endregion
950
999
  //#region src/virtualModules/virtualRuntimeInitStatus.ts
951
1000
  const virtualRuntimeInitStatus = new VirtualModule("runtimeInit");
952
- function writeRuntimeInitStatus(command) {
953
- const globalKey = `__mf_init__${virtualRuntimeInitStatus.getImportId()}__`;
954
- const exportStatement = command === "build" ? `const { initPromise, initResolve, initReject } = globalThis[globalKey];
955
- export { initPromise, initResolve, initReject };` : `module.exports = globalThis[globalKey];`;
956
- virtualRuntimeInitStatus.writeSync(`
957
- const globalKey = ${JSON.stringify(globalKey)};
1001
+ function getRuntimeInitGlobalKey() {
1002
+ return `__mf_init__${virtualRuntimeInitStatus.getImportId()}__`;
1003
+ }
1004
+ function getRuntimeInitBootstrapCode() {
1005
+ return `
1006
+ const globalKey = ${JSON.stringify(getRuntimeInitGlobalKey())};
958
1007
  if (!globalThis[globalKey]) {
959
1008
  let initResolve, initReject;
960
1009
  const initPromise = new Promise((re, rj) => {
@@ -966,8 +1015,6 @@ if (!globalThis[globalKey]) {
966
1015
  initResolve,
967
1016
  initReject,
968
1017
  };
969
- // In SSR (no window), resolve immediately with a stub runtime
970
- // so modules don't hang waiting for browser-only init
971
1018
  if (typeof window === 'undefined') {
972
1019
  initResolve({
973
1020
  loadRemote: function() { return Promise.resolve(undefined); },
@@ -975,6 +1022,64 @@ if (!globalThis[globalKey]) {
975
1022
  });
976
1023
  }
977
1024
  }
1025
+ `;
1026
+ }
1027
+ function getRuntimeInitPromiseBootstrapCode() {
1028
+ return `
1029
+ const __mfPromiseGlobalKey = ${JSON.stringify(getRuntimeInitGlobalKey())};
1030
+ let __mfPromiseState = globalThis[__mfPromiseGlobalKey];
1031
+ if (!__mfPromiseState) {
1032
+ let initResolve, initReject;
1033
+ const initPromise = new Promise((re, rj) => {
1034
+ initResolve = re;
1035
+ initReject = rj;
1036
+ });
1037
+ __mfPromiseState = globalThis[__mfPromiseGlobalKey] = {
1038
+ initPromise,
1039
+ initResolve,
1040
+ initReject,
1041
+ };
1042
+ if (typeof window === 'undefined') {
1043
+ initResolve({
1044
+ loadRemote: function() { return Promise.resolve(undefined); },
1045
+ loadShare: function() { return Promise.resolve(undefined); },
1046
+ });
1047
+ }
1048
+ }
1049
+ const initPromise = __mfPromiseState.initPromise;
1050
+ `;
1051
+ }
1052
+ function getRuntimeInitResolveBootstrapCode() {
1053
+ return `
1054
+ const __mfResolveGlobalKey = ${JSON.stringify(getRuntimeInitGlobalKey())};
1055
+ let __mfResolveState = globalThis[__mfResolveGlobalKey];
1056
+ if (!__mfResolveState) {
1057
+ let initResolve, initReject;
1058
+ const initPromise = new Promise((re, rj) => {
1059
+ initResolve = re;
1060
+ initReject = rj;
1061
+ });
1062
+ __mfResolveState = globalThis[__mfResolveGlobalKey] = {
1063
+ initPromise,
1064
+ initResolve,
1065
+ initReject,
1066
+ };
1067
+ if (typeof window === 'undefined') {
1068
+ initResolve({
1069
+ loadRemote: function() { return Promise.resolve(undefined); },
1070
+ loadShare: function() { return Promise.resolve(undefined); },
1071
+ });
1072
+ }
1073
+ }
1074
+ const initResolve = __mfResolveState.initResolve;
1075
+ `;
1076
+ }
1077
+ function writeRuntimeInitStatus(command) {
1078
+ getRuntimeInitGlobalKey();
1079
+ const exportStatement = command === "build" ? `const { initPromise, initResolve, initReject } = globalThis[globalKey];
1080
+ export { initPromise, initResolve, initReject };` : `module.exports = globalThis[globalKey];`;
1081
+ virtualRuntimeInitStatus.writeSync(`
1082
+ ${getRuntimeInitBootstrapCode()}
978
1083
  ${exportStatement}
979
1084
  `);
980
1085
  }
@@ -999,7 +1104,8 @@ function getUsedRemotesMap() {
999
1104
  }
1000
1105
  function generateRemotes(id, command, isRolldown) {
1001
1106
  const useESM = command === "build" || isRolldown;
1002
- const importLine = useESM ? `import { initPromise } from "${virtualRuntimeInitStatus.getImportId()}"` : `const {initPromise} = require("${virtualRuntimeInitStatus.getImportId()}")`;
1107
+ const importLine = command === "build" ? getRuntimeInitPromiseBootstrapCode() : useESM ? `${getRuntimeInitBootstrapCode()}
1108
+ const { initPromise } = globalThis[globalKey];` : `const {initPromise} = require("${virtualRuntimeInitStatus.getImportId()}")`;
1003
1109
  const awaitOrPlaceholder = useESM ? "await " : "/*mf top-level-await placeholder replacement mf*/";
1004
1110
  const exportLine = command === "serve" && useESM ? "export default exportModule.default ?? exportModule" : useESM ? "export default exportModule" : "module.exports = exportModule";
1005
1111
  return `
@@ -1049,14 +1155,19 @@ function getPreBuildLibImportId(pkg) {
1049
1155
  }
1050
1156
  const LOAD_SHARE_TAG = "__loadShare__";
1051
1157
  const loadShareCacheMap = {};
1052
- function getLoadShareModulePath(pkg, isRolldown, command) {
1158
+ function getLoadShareImportId(pkg, isRolldown, command) {
1053
1159
  if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, isRolldown || command === "build" ? ".mjs" : ".js");
1160
+ return loadShareCacheMap[pkg].getImportId();
1161
+ }
1162
+ function getLoadShareModulePath(pkg, isRolldown, command) {
1163
+ if (!loadShareCacheMap[pkg]) getLoadShareImportId(pkg, isRolldown, command);
1054
1164
  return loadShareCacheMap[pkg].getPath();
1055
1165
  }
1056
1166
  function writeLoadShareModule(pkg, shareItem, command, isRolldown) {
1057
1167
  if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, isRolldown || command === "build" ? ".mjs" : ".js");
1058
1168
  const useESM = command === "build" || isRolldown;
1059
- const importLine = useESM ? `import { initPromise } from "${virtualRuntimeInitStatus.getImportId()}"` : `const {initPromise} = require("${virtualRuntimeInitStatus.getImportId()}")`;
1169
+ const importLine = command === "build" ? getRuntimeInitPromiseBootstrapCode() : useESM ? `${getRuntimeInitBootstrapCode()}
1170
+ const { initPromise } = globalThis[globalKey];` : `const {initPromise} = require("${virtualRuntimeInitStatus.getImportId()}")`;
1060
1171
  const awaitOrPlaceholder = useESM ? "await " : "/*mf top-level-await placeholder replacement mf*/";
1061
1172
  const useSsrProviderFallback = hasPackageDependency("vinext") && command === "build" && pkg === "react";
1062
1173
  const providerImportId = getLocalProviderImportPath(pkg) || getPreBuildLibImportId(pkg);
@@ -1065,8 +1176,8 @@ function writeLoadShareModule(pkg, shareItem, command, isRolldown) {
1065
1176
  if (namedExports.length > 0) {
1066
1177
  const destructure = `const { ${namedExports.map((name, i) => `${name}: __mf_${i}`).join(", ")} } = exportModule;`;
1067
1178
  const namedExportLine = `export { ${namedExports.map((name, i) => `__mf_${i} as ${name}`).join(", ")} };`;
1068
- 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(", ")} });`;
1069
- } else exportLine = useESM ? `export default exportModule\n export * from ${JSON.stringify(getPreBuildLibImportId(pkg))}` : "module.exports = exportModule";
1179
+ 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(", ")} });`;
1180
+ } else exportLine = useESM ? `export default exportModule.default ?? exportModule\n export * from ${JSON.stringify(getPreBuildLibImportId(pkg))}` : "module.exports = exportModule";
1070
1181
  loadShareCacheMap[pkg].writeSync(`
1071
1182
  import ${JSON.stringify(getPreBuildLibImportId(pkg))};
1072
1183
  ${command !== "build" ? `;() => import(${JSON.stringify(pkg)}).catch(() => {});` : ""}
@@ -1100,12 +1211,12 @@ new VirtualModule("localSharedImportMap");
1100
1211
  function getLocalSharedImportMapPath() {
1101
1212
  return getLocalSharedImportMapPath_temp();
1102
1213
  }
1103
- let prevSharedCount;
1214
+ let prevLocalSharedImportMapContent;
1104
1215
  function writeLocalSharedImportMap() {
1105
- const sharedCount = getUsedShares().size;
1106
- if (prevSharedCount !== sharedCount) {
1107
- prevSharedCount = sharedCount;
1108
- writeLocalSharedImportMap_temp(generateLocalSharedImportMap());
1216
+ const nextContent = generateLocalSharedImportMap();
1217
+ if (prevLocalSharedImportMapContent !== nextContent) {
1218
+ prevLocalSharedImportMapContent = nextContent;
1219
+ writeLocalSharedImportMap_temp(nextContent);
1109
1220
  }
1110
1221
  }
1111
1222
  function generateLocalSharedImportMap() {
@@ -1118,7 +1229,7 @@ function generateLocalSharedImportMap() {
1118
1229
  const shareItem = getNormalizeShareItem(pkg);
1119
1230
  return `
1120
1231
  ${JSON.stringify(pkg)}: async () => {
1121
- ${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");
1232
+ ${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");
1122
1233
  return pkg;` : `let pkg = await import("${getPreBuildLibImportId(pkg)}");
1123
1234
  return pkg;`}
1124
1235
  }
@@ -1138,7 +1249,7 @@ function generateLocalSharedImportMap() {
1138
1249
  from: ${JSON.stringify(options.name)},
1139
1250
  async get () {
1140
1251
  if (${shareItem.shareConfig.import === false}) {
1141
- throw new Error(\`Shared module '\${${JSON.stringify(key)}}' must be provided by host\`);
1252
+ throw new Error(\`[Module Federation] Shared module '\${${JSON.stringify(key)}}' must be provided by host\`);
1142
1253
  }
1143
1254
  usedShared[${JSON.stringify(key)}].loaded = true
1144
1255
  const {${JSON.stringify(key)}: pkgDynamicImport} = importMap
@@ -1188,7 +1299,7 @@ const REMOTE_ENTRY_ID = "virtual:mf-REMOTE_ENTRY_ID";
1188
1299
  function getRemoteEntryId(options) {
1189
1300
  return `${REMOTE_ENTRY_ID}:${`${options.name}__${options.filename}`.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
1190
1301
  }
1191
- function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(options)) {
1302
+ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(options), command = "build") {
1192
1303
  const pluginImportNames = options.runtimePlugins.map((p, i) => {
1193
1304
  if (typeof p === "string") return [
1194
1305
  `$runtimePlugin_${i}`,
@@ -1204,15 +1315,25 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1204
1315
  return `
1205
1316
  import {init as runtimeInit, loadRemote} from "@module-federation/runtime";
1206
1317
  ${pluginImportNames.map((item) => item[1]).join("\n")}
1207
- import exposesMap from "${virtualExposesId}"
1208
- import {usedShared, usedRemotes} from "${getLocalSharedImportMapPath()}"
1209
- import {
1210
- initResolve
1211
- } from "${virtualRuntimeInitStatus.getImportId()}"
1318
+ ${command === "build" ? getRuntimeInitResolveBootstrapCode() : getRuntimeInitBootstrapCode() + "\n const { initResolve } = globalThis[globalKey];"}
1212
1319
  const initTokens = {}
1213
1320
  const shareScopeName = ${JSON.stringify(options.shareScope)}
1214
1321
  const mfName = ${JSON.stringify(options.name)}
1322
+ let localSharedImportMapPromise
1323
+ let exposesMapPromise
1324
+
1325
+ async function getLocalSharedImportMap() {
1326
+ localSharedImportMapPromise ??= import("${getLocalSharedImportMapPath()}")
1327
+ return localSharedImportMapPromise
1328
+ }
1329
+
1330
+ async function getExposesMap() {
1331
+ exposesMapPromise ??= import("${virtualExposesId}").then((mod) => mod.default ?? mod)
1332
+ return exposesMapPromise
1333
+ }
1334
+
1215
1335
  async function init(shared = {}, initScope = []) {
1336
+ const {usedShared, usedRemotes} = await getLocalSharedImportMap()
1216
1337
  const initRes = runtimeInit({
1217
1338
  name: mfName,
1218
1339
  remotes: usedRemotes,
@@ -1235,13 +1356,14 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1235
1356
  initScope
1236
1357
  }));
1237
1358
  } catch (e) {
1238
- console.error(e)
1359
+ console.error('[Module Federation]', e)
1239
1360
  }
1240
1361
  return initRes
1241
1362
  }
1242
1363
 
1243
- function getExposes(moduleName) {
1244
- if (!(moduleName in exposesMap)) throw new Error(\`Module \${moduleName} does not exist in container.\`)
1364
+ async function getExposes(moduleName) {
1365
+ const exposesMap = await getExposesMap()
1366
+ if (!(moduleName in exposesMap)) throw new Error(\`[Module Federation] Module \${moduleName} does not exist in container.\`)
1245
1367
  return (exposesMap[moduleName])().then(res => () => res)
1246
1368
  }
1247
1369
  export {
@@ -1253,13 +1375,8 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1253
1375
  const hostAutoInitModule = new VirtualModule("hostAutoInit", "__H_A_I__");
1254
1376
  function writeHostAutoInit(remoteEntryId = REMOTE_ENTRY_ID) {
1255
1377
  hostAutoInitModule.writeSync(`
1256
- const remoteEntryPromise = import("${remoteEntryId}")
1257
- Promise.resolve(remoteEntryPromise)
1258
- .then(remoteEntry => {
1259
- return Promise.resolve(remoteEntry.__tla)
1260
- .then(remoteEntry.init)
1261
- .catch(remoteEntry.init)
1262
- })
1378
+ const remoteEntry = await import("${remoteEntryId}");
1379
+ await remoteEntry.init();
1263
1380
  `);
1264
1381
  }
1265
1382
  function getHostAutoInitImportId() {
@@ -1282,13 +1399,21 @@ function initVirtualModules(command, remoteEntryId) {
1282
1399
  * If Rollup's deconflict renamed the alias but didn't update references
1283
1400
  * in the code body, fall back to proxyLocal so they stay in sync.
1284
1401
  */
1285
- function resolveProxyAlias(binding, proxyLocal, code, fullImport) {
1402
+ function resolveProxyAlias(binding, proxyLocal, code, fullImport, claimedLocals = /* @__PURE__ */ new Set()) {
1286
1403
  const codeWithoutImport = code.replace(fullImport, "");
1287
1404
  const escapedLocal = binding.local.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
1288
1405
  const localUsedInCode = new RegExp(`\\b${escapedLocal}\\b`).test(codeWithoutImport);
1406
+ const claimedImportLocals = /* @__PURE__ */ new Set();
1407
+ const importRe = /import\s*\{([^}]+)\}\s*from\s*["'][^"']+["']\s*;?/g;
1408
+ let match;
1409
+ while ((match = importRe.exec(codeWithoutImport)) !== null) for (const spec of match[1].split(",")) {
1410
+ const parts = spec.trim().split(/\s+as\s+/);
1411
+ claimedImportLocals.add((parts[1] || parts[0]).trim());
1412
+ }
1413
+ const local = !localUsedInCode && !claimedLocals.has(proxyLocal) && !claimedImportLocals.has(proxyLocal) ? proxyLocal : binding.local;
1289
1414
  return {
1290
1415
  imported: binding.imported,
1291
- local: localUsedInCode ? binding.local : proxyLocal
1416
+ local
1292
1417
  };
1293
1418
  }
1294
1419
  function findRemoteEntryFile(filename, bundle) {
@@ -1655,14 +1780,14 @@ const promise = new Promise((resolve, reject) => {
1655
1780
  });
1656
1781
  function setParseTimeout(timeout) {
1657
1782
  if (!_parseTimeout) _parseTimeout = setTimeout(() => {
1658
- console.warn(`Parse timeout (${timeout}s) - forcing resolve`);
1783
+ mfWarn(`Parse timeout (${timeout}s) - forcing resolve`);
1659
1784
  _resolve(1);
1660
1785
  }, timeout * 1e3);
1661
1786
  }
1662
1787
  function resetIdleTimeout(timeout) {
1663
1788
  clearTimeout(_parseTimeout);
1664
1789
  _parseTimeout = setTimeout(() => {
1665
- console.warn(`moduleParseIdleTimeout: no module activity for ${timeout}s, forcing resolve. Some shared/remote dependencies may be missing. Consider increasing moduleParseIdleTimeout.`);
1790
+ mfWarn(`moduleParseIdleTimeout: no module activity for ${timeout}s, forcing resolve. Some shared/remote dependencies may be missing. Consider increasing moduleParseIdleTimeout.`);
1666
1791
  _resolve(1);
1667
1792
  }, timeout * 1e3);
1668
1793
  }
@@ -1743,14 +1868,14 @@ function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposes
1743
1868
  }
1744
1869
  },
1745
1870
  load(id) {
1746
- if (id === remoteEntryId) return parsePromise.then((_) => generateRemoteEntry(options, virtualExposesId));
1871
+ if (id === remoteEntryId) return parsePromise.then((_) => generateRemoteEntry(options, virtualExposesId, _command));
1747
1872
  if (id === virtualExposesId) return generateExposes(options);
1748
1873
  if (_command === "serve" && id.includes(getHostAutoInitPath())) return id;
1749
1874
  },
1750
1875
  transform(code, id) {
1751
1876
  return mapCodeToCodeWithSourcemap((() => {
1752
1877
  if (!filter(id)) return;
1753
- if (id.includes(remoteEntryId)) return parsePromise.then((_) => generateRemoteEntry(options, virtualExposesId));
1878
+ if (id.includes(remoteEntryId)) return parsePromise.then((_) => generateRemoteEntry(options, virtualExposesId, _command));
1754
1879
  if (id === virtualExposesId) return generateExposes(options);
1755
1880
  if (id.includes(getHostAutoInitPath())) {
1756
1881
  if (_command === "serve") {
@@ -1783,7 +1908,7 @@ function pluginProxyRemotes_default(options) {
1783
1908
  return {
1784
1909
  name: "proxyRemotes",
1785
1910
  config(config, { command: _command }) {
1786
- const isRolldown = !!this?.meta?.rolldownVersion;
1911
+ const isRolldown = getIsRolldown(this);
1787
1912
  Object.keys(remotes).forEach((key) => {
1788
1913
  const remote = remotes[key];
1789
1914
  config.resolve.alias.push({
@@ -1855,7 +1980,7 @@ function proxySharedModule(options) {
1855
1980
  config(config, { command }) {
1856
1981
  setPackageDetectionCwd(config.root || process.cwd());
1857
1982
  isVinext = hasPackageDependency("vinext");
1858
- const isRolldown = !!this?.meta?.rolldownVersion;
1983
+ const isRolldown = getIsRolldown(this);
1859
1984
  _command = command;
1860
1985
  config.resolve.alias.push(...Object.keys(shared).filter((key) => !(isVinext && key === "react")).map((key) => {
1861
1986
  const keyBase = key.endsWith("/") ? key.slice(0, -1) : key;
@@ -1935,7 +2060,6 @@ const VarRemoteEntry = () => {
1935
2060
  if (req.url?.replace(/\?.*/, "") === (viteConfig.base + varFilename).replace(/^\/?/, "/")) {
1936
2061
  res.setHeader("Content-Type", "text/javascript");
1937
2062
  res.setHeader("Access-Control-Allow-Origin", "*");
1938
- console.log({ filename });
1939
2063
  res.end(generateVarRemoteEntry(filename));
1940
2064
  } else next();
1941
2065
  });
@@ -1951,9 +2075,9 @@ const VarRemoteEntry = () => {
1951
2075
  },
1952
2076
  async generateBundle(options, bundle) {
1953
2077
  if (!varFilename) return;
1954
- 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).`);
2078
+ 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).`);
1955
2079
  const remoteEntryFile = findRemoteEntryFile(mfOptions.filename, bundle);
1956
- if (!remoteEntryFile) throw new Error(`Couldn't find a remoteEntry chunk file for ${mfOptions.filename}, can't generate varRemoteEntry file`);
2080
+ if (!remoteEntryFile) throw createModuleFederationError(`Couldn't find a remoteEntry chunk file for ${mfOptions.filename}, can't generate varRemoteEntry file`);
1957
2081
  this.emitFile({
1958
2082
  type: "asset",
1959
2083
  fileName: varFilename,
@@ -1978,7 +2102,7 @@ const VarRemoteEntry = () => {
1978
2102
  function getScriptUrl() {
1979
2103
  const currentScript = document.currentScript;
1980
2104
  if (!currentScript) {
1981
- console.error("[VarRemoteEntry] ${varFilename} script should be called from sync <script> tag (document.currentScript is undefined)")
2105
+ console.error("[Module Federation] ${varFilename} script should be called from sync <script> tag (document.currentScript is undefined)")
1982
2106
  return '/';
1983
2107
  }
1984
2108
  return document.currentScript.src.replace(/\\/[^/]*$/, '/');
@@ -2009,6 +2133,58 @@ var aliasToArrayPlugin_default = {
2009
2133
  }
2010
2134
  };
2011
2135
  //#endregion
2136
+ //#region src/utils/controlChunkSanitizer.ts
2137
+ const FEDERATION_CONTROL_CHUNK_HINTS = [
2138
+ "hostInit",
2139
+ "virtualExposes",
2140
+ "localSharedImportMap"
2141
+ ];
2142
+ function stripEmptyPreloadCalls(code) {
2143
+ const helperImportRegex = /import\s*\{\s*_\s*as\s*(\w+)\s*\}\s*from\s*["'][^"']+["']\s*;?/g;
2144
+ const helperAliases = [...code.matchAll(helperImportRegex)].map((match) => match[1]);
2145
+ let nextCode = code;
2146
+ for (const alias of helperAliases) {
2147
+ const marker = `${alias}(()=>`;
2148
+ let start = nextCode.indexOf(marker);
2149
+ while (start !== -1) {
2150
+ const exprStart = start + marker.length;
2151
+ let depth = 0;
2152
+ let cursor = exprStart;
2153
+ let replacementEnd = -1;
2154
+ while (cursor < nextCode.length) {
2155
+ const char = nextCode[cursor];
2156
+ if (char === "(") depth++;
2157
+ else if (char === ")") depth--;
2158
+ else if (depth === 0 && nextCode.startsWith(",[],import.meta.url)", cursor)) {
2159
+ replacementEnd = cursor;
2160
+ break;
2161
+ }
2162
+ cursor++;
2163
+ }
2164
+ if (replacementEnd === -1) break;
2165
+ const expression = nextCode.slice(exprStart, replacementEnd);
2166
+ nextCode = nextCode.slice(0, start) + expression + nextCode.slice(replacementEnd + 20);
2167
+ start = nextCode.indexOf(marker, start + expression.length);
2168
+ }
2169
+ }
2170
+ nextCode = nextCode.replace(/import\s*["'][^"']*__loadShare__[^"']*["']\s*;?/g, "");
2171
+ nextCode = nextCode.replace(helperImportRegex, (statement, local) => {
2172
+ return new RegExp(`\\b${local}\\s*\\(`).test(nextCode.replace(statement, "")) ? statement : "";
2173
+ });
2174
+ return nextCode;
2175
+ }
2176
+ function isFederationControlChunk(fileName, filename) {
2177
+ return fileName.includes(filename) || FEDERATION_CONTROL_CHUNK_HINTS.some((hint) => fileName.includes(hint));
2178
+ }
2179
+ function sanitizeFederationControlChunk(code, fileName, filename) {
2180
+ let nextCode = stripEmptyPreloadCalls(code);
2181
+ if (fileName.includes("localSharedImportMap")) {
2182
+ const remoteEntryImportRegex = new RegExp(`import\\s*["'][^"']*${filename.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}["']\\s*;?`, "g");
2183
+ nextCode = nextCode.replace(remoteEntryImportRegex, "");
2184
+ }
2185
+ return nextCode;
2186
+ }
2187
+ //#endregion
2012
2188
  //#region src/utils/normalizeOptimizeDeps.ts
2013
2189
  var normalizeOptimizeDeps_default = {
2014
2190
  name: "normalizeOptimizeDeps",
@@ -2025,6 +2201,25 @@ var normalizeOptimizeDeps_default = {
2025
2201
  };
2026
2202
  //#endregion
2027
2203
  //#region src/index.ts
2204
+ const UNSAFE_JS_SOURCE_CHAR_MAP = {
2205
+ "<": "\\u003C",
2206
+ ">": "\\u003E",
2207
+ "/": "\\u002F",
2208
+ "\\": "\\\\",
2209
+ "\b": "\\b",
2210
+ "\f": "\\f",
2211
+ "\n": "\\n",
2212
+ "\r": "\\r",
2213
+ " ": "\\t",
2214
+ "\0": "\\0",
2215
+ "\u2028": "\\u2028",
2216
+ "\u2029": "\\u2029"
2217
+ };
2218
+ function escapeUnsafeJsSourceChars(str) {
2219
+ return str.replace(/[<>/\\\b\f\n\r\t\0\u2028\u2029]/g, (char) => {
2220
+ return UNSAFE_JS_SOURCE_CHAR_MAP[char] ?? char;
2221
+ });
2222
+ }
2028
2223
  /**
2029
2224
  * Plugin that runs FIRST to create virtual module files in the config hook.
2030
2225
  * This prevents 504 "Outdated Optimize Dep" errors by ensuring files exist
@@ -2044,7 +2239,7 @@ function createEarlyVirtualModulesPlugin(options) {
2044
2239
  VirtualModule.ensureVirtualPackageExists();
2045
2240
  initVirtualModules(_command, getRemoteEntryId(options));
2046
2241
  if (_command !== "serve") return;
2047
- const isRolldown = !!this?.meta?.rolldownVersion;
2242
+ const isRolldown = getIsRolldown(this);
2048
2243
  if (remotes && Object.keys(remotes).length > 0) for (const key of Object.keys(remotes)) addUsedRemote(key, key);
2049
2244
  if (shared && Object.keys(shared).length > 0) {
2050
2245
  config.optimizeDeps = config.optimizeDeps || {};
@@ -2061,6 +2256,7 @@ function createEarlyVirtualModulesPlugin(options) {
2061
2256
  writeLoadShareModule(key, shareItem, _command, isRolldown);
2062
2257
  writePreBuildLibPath(key);
2063
2258
  addUsedShares(key);
2259
+ config.optimizeDeps.include.push(getLoadShareImportId(key, isRolldown, _command));
2064
2260
  config.optimizeDeps.include.push(getPreBuildLibImportId(key));
2065
2261
  }
2066
2262
  writeLocalSharedImportMap();
@@ -2072,7 +2268,7 @@ function federation(mfUserOptions) {
2072
2268
  const options = normalizeModuleFederationOptions(mfUserOptions);
2073
2269
  const isVinext = hasPackageDependency("vinext");
2074
2270
  const { name, remotes, shared, filename, hostInitInjectLocation } = options;
2075
- if (!name) throw new Error("name is required");
2271
+ if (!name) throw createModuleFederationError("name is required");
2076
2272
  const remoteEntryId = getRemoteEntryId(options);
2077
2273
  const virtualExposesId = getVirtualExposesId(options);
2078
2274
  let command;
@@ -2146,9 +2342,28 @@ function federation(mfUserOptions) {
2146
2342
  config(config) {
2147
2343
  const runtimeInitId = virtualRuntimeInitStatus.getImportId();
2148
2344
  config.build = config.build || {};
2149
- config.build.rollupOptions = config.build.rollupOptions || {};
2150
- if (!Array.isArray(config.build.rollupOptions.output)) {
2151
- const output = config.build.rollupOptions.output ||= {};
2345
+ if (config.build.modulePreload !== false) {
2346
+ const currentModulePreload = config.build.modulePreload && typeof config.build.modulePreload === "object" ? config.build.modulePreload : {};
2347
+ const existingResolveDependencies = currentModulePreload.resolveDependencies;
2348
+ config.build.modulePreload = {
2349
+ ...currentModulePreload,
2350
+ resolveDependencies(filename, deps, context) {
2351
+ const resolvedDeps = existingResolveDependencies ? existingResolveDependencies(filename, deps, context) : deps;
2352
+ const hostFile = path.basename(context.hostId);
2353
+ return context.hostType === "js" && (hostFile === options.filename || hostFile.includes("hostInit") || hostFile.includes("virtualExposes") || hostFile.includes("localSharedImportMap")) ? [] : resolvedDeps;
2354
+ }
2355
+ };
2356
+ }
2357
+ let warnedAboutCodeSplitting = false;
2358
+ const ensureCodeSplitting = (output) => {
2359
+ if (output?.codeSplitting !== false) return;
2360
+ delete output.codeSplitting;
2361
+ if (warnedAboutCodeSplitting) return;
2362
+ warnedAboutCodeSplitting = true;
2363
+ mfWarn("Ignoring `build.rolldownOptions.output.codeSplitting = false` because module federation requires chunk splitting.");
2364
+ };
2365
+ const applyManualChunks = (output) => {
2366
+ ensureCodeSplitting(output);
2152
2367
  const existingManualChunks = output.manualChunks;
2153
2368
  output.manualChunks = function(id) {
2154
2369
  if (id.includes(runtimeInitId)) return "runtimeInit";
@@ -2161,7 +2376,12 @@ function federation(mfUserOptions) {
2161
2376
  for (const [key, ids] of Object.entries(existingManualChunks)) if (Array.isArray(ids) && ids.some((v) => id.includes(v))) return key;
2162
2377
  }
2163
2378
  };
2164
- }
2379
+ };
2380
+ config.build.rollupOptions = config.build.rollupOptions || {};
2381
+ if (!Array.isArray(config.build.rollupOptions.output)) applyManualChunks(config.build.rollupOptions.output ||= {});
2382
+ const buildWithRolldown = config.build;
2383
+ buildWithRolldown.rolldownOptions = buildWithRolldown.rolldownOptions || {};
2384
+ if (!Array.isArray(buildWithRolldown.rolldownOptions.output)) applyManualChunks(buildWithRolldown.rolldownOptions.output ||= {});
2165
2385
  },
2166
2386
  load(id) {
2167
2387
  if (id.startsWith("\0")) return;
@@ -2193,6 +2413,11 @@ function federation(mfUserOptions) {
2193
2413
  }
2194
2414
  },
2195
2415
  generateBundle(_, bundle) {
2416
+ for (const [fileName, chunk] of Object.entries(bundle)) {
2417
+ if (chunk.type !== "chunk") continue;
2418
+ if (!isFederationControlChunk(fileName, filename)) continue;
2419
+ chunk.code = sanitizeFederationControlChunk(chunk.code, fileName, filename);
2420
+ }
2196
2421
  for (const [fileName, chunk] of Object.entries(bundle)) {
2197
2422
  if (chunk.type !== "chunk") continue;
2198
2423
  if (fileName.includes("__loadShare__")) continue;
@@ -2230,12 +2455,12 @@ function federation(mfUserOptions) {
2230
2455
  fileName
2231
2456
  });
2232
2457
  }
2233
- if (proxyChunks.size === 0) return;
2234
- for (const [fileName, chunk] of Object.entries(bundle)) {
2458
+ if (proxyChunks.size > 0) for (const [fileName, chunk] of Object.entries(bundle)) {
2235
2459
  if (chunk.type !== "chunk") continue;
2236
2460
  if (fileName.includes("__loadShare__")) continue;
2237
2461
  let code = chunk.code;
2238
2462
  let modified = false;
2463
+ const claimedLocals = /* @__PURE__ */ new Set();
2239
2464
  for (const [proxyFileName, proxyInfo] of proxyChunks) {
2240
2465
  const proxyBaseName = proxyFileName.replace(/^.*\//, "").replace(/\.js$/, "").replace(/-[A-Za-z0-9_-]+$/, "");
2241
2466
  const importMatch = new RegExp(`import\\s*\\{([^}]+)\\}\\s*from\\s*["']([^"']*${proxyBaseName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}[^"']*)["']\\s*;?`).exec(code);
@@ -2258,9 +2483,12 @@ function federation(mfUserOptions) {
2258
2483
  }
2259
2484
  const inlineable = [];
2260
2485
  const nonInlineable = [];
2486
+ const pendingLocals = new Set(bindings.map((binding) => binding.local));
2261
2487
  for (const b of bindings) {
2488
+ pendingLocals.delete(b.local);
2262
2489
  const proxyLocal = exportMap[b.imported];
2263
2490
  if (!proxyLocal) {
2491
+ claimedLocals.add(b.local);
2264
2492
  nonInlineable.push(b);
2265
2493
  continue;
2266
2494
  }
@@ -2282,7 +2510,14 @@ function federation(mfUserOptions) {
2282
2510
  local: b.local,
2283
2511
  funcBody: renamedFunc
2284
2512
  });
2285
- } else nonInlineable.push(resolveProxyAlias(b, proxyLocal, code, fullImport));
2513
+ claimedLocals.add(b.local);
2514
+ } else {
2515
+ const unavailableLocals = new Set(claimedLocals);
2516
+ pendingLocals.forEach((local) => unavailableLocals.add(local));
2517
+ const resolvedBinding = resolveProxyAlias(b, proxyLocal, code, fullImport, unavailableLocals);
2518
+ claimedLocals.add(resolvedBinding.local);
2519
+ nonInlineable.push(resolvedBinding);
2520
+ }
2286
2521
  }
2287
2522
  const hasRenamedAlias = nonInlineable.some((b) => bindings.find((ob) => ob.imported === b.imported)?.local !== b.local);
2288
2523
  if (inlineable.length === 0 && !hasRenamedAlias) continue;
@@ -2296,6 +2531,28 @@ function federation(mfUserOptions) {
2296
2531
  }
2297
2532
  }
2298
2533
  },
2534
+ {
2535
+ name: "module-federation-strip-empty-preload-helper",
2536
+ enforce: "post",
2537
+ apply: "build",
2538
+ renderChunk(code, chunk) {
2539
+ if (!isFederationControlChunk(chunk.fileName, filename)) return;
2540
+ const nextCode = sanitizeFederationControlChunk(code, chunk.fileName, filename);
2541
+ return nextCode === code ? null : {
2542
+ code: nextCode,
2543
+ map: null
2544
+ };
2545
+ },
2546
+ writeBundle(outputOptions, bundle) {
2547
+ if (!outputOptions.dir) return;
2548
+ for (const chunk of Object.values(bundle)) {
2549
+ if (chunk.type !== "chunk") continue;
2550
+ if (!isFederationControlChunk(chunk.fileName, filename)) continue;
2551
+ const outputPath = path.join(outputOptions.dir, chunk.fileName);
2552
+ writeFileSync(outputPath, sanitizeFederationControlChunk(readFileSync(outputPath, "utf-8"), chunk.fileName, filename));
2553
+ }
2554
+ }
2555
+ },
2299
2556
  {
2300
2557
  name: "module-federation-dev-await-shared-init",
2301
2558
  apply: "serve",
@@ -2328,9 +2585,9 @@ function federation(mfUserOptions) {
2328
2585
  enforce: "post",
2329
2586
  _options: options,
2330
2587
  config(config, { command: _command }) {
2331
- const isRolldown = !!this?.meta?.rolldownVersion;
2588
+ const isRolldown = getIsRolldown(this);
2332
2589
  let implementation = options.implementation;
2333
- if (isRolldown) implementation = implementation.replace(/\.cjs\.cjs$/, ".esm.js");
2590
+ if (isRolldown) implementation = implementation.replace(/\.cjs(\.js)?$/, ".js");
2334
2591
  config.resolve.alias.push({
2335
2592
  find: "@module-federation/runtime",
2336
2593
  replacement: implementation
@@ -2357,7 +2614,7 @@ function federation(mfUserOptions) {
2357
2614
  const resolvedTarget = options.target ?? (config.build?.ssr ? "node" : "web");
2358
2615
  if (!config.define) config.define = {};
2359
2616
  if (!("ENV_TARGET" in config.define)) config.define["ENV_TARGET"] = JSON.stringify(resolvedTarget);
2360
- 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.`);
2617
+ 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.`);
2361
2618
  }
2362
2619
  },
2363
2620
  ...Manifest(),
@@ -2370,13 +2627,18 @@ function federation(mfUserOptions) {
2370
2627
  for (const chunk of Object.values(bundle)) {
2371
2628
  if (chunk.type !== "chunk") continue;
2372
2629
  if (!chunk.code.includes("modulepreload")) continue;
2373
- const replacement = "=function($1){return new URL(\"../\"+$1,import.meta.url).href}";
2630
+ const chunkDir = path.dirname(chunk.fileName);
2631
+ const prefixToRoot = chunkDir === "." ? "" : `${path.relative(chunkDir, ".")}/`;
2632
+ const replacementExpr = prefixToRoot ? `${escapeUnsafeJsSourceChars(JSON.stringify(prefixToRoot))}+$1` : "$1";
2633
+ const replacement = `=function($1){return new URL(${replacementExpr},import.meta.url).href}`;
2374
2634
  const replaced = chunk.code.replace(/=\(?(\w+)(?:,\w+)?\)?\s*=>\s*["'`][^"'`]*["'`]\s*\+\s*\1/, replacement);
2375
2635
  if (replaced !== chunk.code) {
2376
2636
  chunk.code = replaced;
2377
2637
  continue;
2378
2638
  }
2379
2639
  chunk.code = chunk.code.replace(/=function\((\w+)(?:,\w+)?\)\{return\s*["'`][^"'`]*["'`]\s*\+\s*\1\s*\}/, replacement);
2640
+ chunk.code = chunk.code.replace(/=function\((\w+)(?:,\w+)?\)\{return new URL\("\.\.\/"\+\1,import\.meta\.url\)\.href\}/, replacement);
2641
+ chunk.code = chunk.code.replace(/new URL\("\.\.\/"\+(\w+),import\.meta\.url\)\.href/g, `new URL(${replacementExpr},import.meta.url).href`);
2380
2642
  }
2381
2643
  }
2382
2644
  }] : []