@module-federation/vite 1.14.0 → 1.14.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.
package/lib/index.cjs CHANGED
@@ -234,11 +234,11 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry" }) => {
234
234
  if (!injectHtml()) return;
235
235
  clientInjected = true;
236
236
  const base = viteConfig.base.replace(/\/$/, "");
237
- const stripBase = (p) => base && p.startsWith(base) ? p.slice(base.length) : p;
237
+ const stripBase = (p) => base && p.startsWith(base + "/") ? p.slice(base.length) : p;
238
238
  const html = rewriteEntryScripts(c, (originalSrc) => {
239
239
  return `/@id/${DEV_HTML_PROXY_PREFIX}${new URLSearchParams({
240
240
  init: sanitizeDevEntryPath(stripBase(devEntryPath)),
241
- entry: originalSrc
241
+ entry: sanitizeDevEntryPath(stripBase(originalSrc))
242
242
  }).toString()}`;
243
243
  });
244
244
  return html === c ? injectEntryScript(c, stripBase(devEntryPath)) : html;
@@ -253,11 +253,7 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry" }) => {
253
253
  const initSrc = params.get("init");
254
254
  const entrySrc = params.get("entry");
255
255
  if (!initSrc || !entrySrc) return;
256
- return `
257
- const baseUrl = document.baseURI || window.location.href;
258
- await import(new URL(${JSON.stringify(initSrc)}, baseUrl).href);
259
- await import(new URL(${JSON.stringify(entrySrc)}, baseUrl).href);
260
- `;
256
+ return `import ${JSON.stringify(initSrc)};\nimport ${JSON.stringify(entrySrc)};\n`;
261
257
  },
262
258
  transform(code, id) {
263
259
  if (id.includes("node_modules") || inject !== "html" || htmlFilePath) return;
@@ -640,6 +636,13 @@ function pluginDevRemoteHmr(options) {
640
636
  connections.length = 0;
641
637
  };
642
638
  for (const [remoteName, remote] of Object.entries(options.remotes)) connectRemote(remoteName, remote);
639
+ const triggerHostReload = (file) => {
640
+ if (shouldIgnoreFile(file, options)) return;
641
+ server.ws.send({ type: "full-reload" });
642
+ };
643
+ server.watcher.on("change", triggerHostReload);
644
+ server.watcher.on("add", triggerHostReload);
645
+ server.watcher.on("unlink", triggerHostReload);
643
646
  server.httpServer?.once("close", teardown);
644
647
  }
645
648
  }
@@ -898,11 +901,20 @@ function normalizeRemotes(remotes) {
898
901
  }
899
902
  function normalizeRemoteItem(key, remote) {
900
903
  if (typeof remote === "string") {
901
- const [entryGlobalName] = remote.split("@");
904
+ const separatorIndex = remote.startsWith("@") ? remote.indexOf("@", 1) : remote.indexOf("@");
905
+ let entryGlobalName;
906
+ let entry;
907
+ if (separatorIndex > 0) {
908
+ entryGlobalName = remote.slice(0, separatorIndex);
909
+ entry = remote.slice(separatorIndex + 1);
910
+ } else {
911
+ entryGlobalName = remote;
912
+ entry = remote;
913
+ }
902
914
  return {
903
915
  type: "var",
904
916
  name: key,
905
- entry: remote.replace(entryGlobalName + "@", ""),
917
+ entry,
906
918
  entryGlobalName,
907
919
  shareScope: "default"
908
920
  };
@@ -928,8 +940,13 @@ function searchPackageVersion(sharedName) {
928
940
  while (pathe.parse(potentialPackageJsonDir).base !== "node_modules" && potentialPackageJsonDir !== rootDir) {
929
941
  const potentialPackageJsonPath = pathe.join(potentialPackageJsonDir, "package.json");
930
942
  if (fs.existsSync(potentialPackageJsonPath)) {
931
- const potentialPackageJson = JSON.parse(fs.readFileSync(potentialPackageJsonPath, "utf-8"));
932
- if (typeof potentialPackageJson == "object" && potentialPackageJson !== null && typeof potentialPackageJson.version === "string" && potentialPackageJson.name === sharedName) return potentialPackageJson.version;
943
+ const potentialPackageJsonContent = fs.readFileSync(potentialPackageJsonPath, "utf-8");
944
+ try {
945
+ const potentialPackageJson = JSON.parse(potentialPackageJsonContent);
946
+ if (typeof potentialPackageJson == "object" && potentialPackageJson !== null && typeof potentialPackageJson.version === "string" && potentialPackageJson.name === sharedName) return potentialPackageJson.version;
947
+ } catch (error) {
948
+ if (!(error instanceof SyntaxError)) throw error;
949
+ }
933
950
  }
934
951
  potentialPackageJsonDir = pathe.dirname(potentialPackageJsonDir);
935
952
  }
@@ -1453,13 +1470,23 @@ function getInstalledPackageJsonPath(pkg) {
1453
1470
  while (currentDir !== rootDir) {
1454
1471
  const packageJsonPath = pathe.default.join(currentDir, "package.json");
1455
1472
  if ((0, fs.existsSync)(packageJsonPath)) {
1456
- if (JSON.parse((0, fs.readFileSync)(packageJsonPath, "utf-8")).name === packageName) return packageJsonPath;
1473
+ const packageJsonContent = (0, fs.readFileSync)(packageJsonPath, "utf-8");
1474
+ try {
1475
+ if (JSON.parse(packageJsonContent).name === packageName) return packageJsonPath;
1476
+ } catch (error) {
1477
+ if (!(error instanceof SyntaxError)) throw error;
1478
+ }
1457
1479
  }
1458
1480
  currentDir = pathe.default.dirname(currentDir);
1459
1481
  }
1460
1482
  const rootPackageJsonPath = pathe.default.join(rootDir, "package.json");
1461
1483
  if ((0, fs.existsSync)(rootPackageJsonPath)) {
1462
- if (JSON.parse((0, fs.readFileSync)(rootPackageJsonPath, "utf-8")).name === packageName) return rootPackageJsonPath;
1484
+ const rootPackageJsonContent = (0, fs.readFileSync)(rootPackageJsonPath, "utf-8");
1485
+ try {
1486
+ if (JSON.parse(rootPackageJsonContent).name === packageName) return rootPackageJsonPath;
1487
+ } catch (error) {
1488
+ if (!(error instanceof SyntaxError)) throw error;
1489
+ }
1463
1490
  }
1464
1491
  } catch {
1465
1492
  const packageName = removePathFromNpmPackage(pkg);
@@ -3111,6 +3138,16 @@ var aliasToArrayPlugin_default = {
3111
3138
  }
3112
3139
  };
3113
3140
  //#endregion
3141
+ //#region src/utils/isTestEnv.ts
3142
+ /**
3143
+ * Detects whether the current process is running in a test environment
3144
+ * Set `MFE_VITE_NO_TEST_ENV_CHECK=true` to load federation plugins during tests.
3145
+ */
3146
+ function isTestEnv() {
3147
+ if (process.env.MFE_VITE_NO_TEST_ENV_CHECK === "true") return false;
3148
+ return process.env.NODE_ENV === "test" || process.env.VITEST != null || process.env.JEST_WORKER_ID != null;
3149
+ }
3150
+ //#endregion
3114
3151
  //#region src/utils/controlChunkSanitizer.ts
3115
3152
  const FEDERATION_CONTROL_CHUNK_HINTS = [
3116
3153
  "hostInit",
@@ -3256,6 +3293,7 @@ function createEarlyVirtualModulesPlugin(options) {
3256
3293
  };
3257
3294
  }
3258
3295
  function federation(mfUserOptions) {
3296
+ if (isTestEnv()) return [];
3259
3297
  const options = normalizeModuleFederationOptions(mfUserOptions);
3260
3298
  const isVinext = hasPackageDependency("vinext");
3261
3299
  const { name, remotes, shared, filename, hostInitInjectLocation } = options;
@@ -3651,12 +3689,12 @@ function federation(mfUserOptions) {
3651
3689
  const prefixToRoot = chunkDir === "." ? "" : `${pathe.default.relative(chunkDir, ".")}/`;
3652
3690
  const replacementExpr = prefixToRoot ? `${escapeUnsafeJsSourceChars(JSON.stringify(prefixToRoot))}+$1` : "$1";
3653
3691
  const replacement = `=function($1){return new URL(${replacementExpr},import.meta.url).href}`;
3654
- const replaced = chunk.code.replace(/=\(?(\w+)(?:,\w+)?\)?\s*=>\s*["'`][^"'`]*["'`]\s*\+\s*\1/, replacement);
3692
+ const replaced = chunk.code.replace(/=\(?(\w+)(?:,\w+)?\)?\s*=>\s*["'][./][^"']*["']\s*\+\s*\1/, replacement);
3655
3693
  if (replaced !== chunk.code) {
3656
3694
  chunk.code = replaced;
3657
3695
  continue;
3658
3696
  }
3659
- chunk.code = chunk.code.replace(/=function\((\w+)(?:,\w+)?\)\{return\s*["'`][^"'`]*["'`]\s*\+\s*\1\s*\}/, replacement);
3697
+ chunk.code = chunk.code.replace(/=function\((\w+)(?:,\w+)?\)\{return\s*["'][./][^"']*["']\s*\+\s*\1\s*\}/, replacement);
3660
3698
  chunk.code = chunk.code.replace(/=function\((\w+)(?:,\w+)?\)\{return new URL\("\.\.\/"\+\1,import\.meta\.url\)\.href\}/, replacement);
3661
3699
  chunk.code = chunk.code.replace(/new URL\("\.\.\/"\+(\w+),import\.meta\.url\)\.href/g, `new URL(${replacementExpr},import.meta.url).href`);
3662
3700
  }
package/lib/index.mjs CHANGED
@@ -212,11 +212,11 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry" }) => {
212
212
  if (!injectHtml()) return;
213
213
  clientInjected = true;
214
214
  const base = viteConfig.base.replace(/\/$/, "");
215
- const stripBase = (p) => base && p.startsWith(base) ? p.slice(base.length) : p;
215
+ const stripBase = (p) => base && p.startsWith(base + "/") ? p.slice(base.length) : p;
216
216
  const html = rewriteEntryScripts(c, (originalSrc) => {
217
217
  return `/@id/${DEV_HTML_PROXY_PREFIX}${new URLSearchParams({
218
218
  init: sanitizeDevEntryPath(stripBase(devEntryPath)),
219
- entry: originalSrc
219
+ entry: sanitizeDevEntryPath(stripBase(originalSrc))
220
220
  }).toString()}`;
221
221
  });
222
222
  return html === c ? injectEntryScript(c, stripBase(devEntryPath)) : html;
@@ -231,11 +231,7 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry" }) => {
231
231
  const initSrc = params.get("init");
232
232
  const entrySrc = params.get("entry");
233
233
  if (!initSrc || !entrySrc) return;
234
- return `
235
- const baseUrl = document.baseURI || window.location.href;
236
- await import(new URL(${JSON.stringify(initSrc)}, baseUrl).href);
237
- await import(new URL(${JSON.stringify(entrySrc)}, baseUrl).href);
238
- `;
234
+ return `import ${JSON.stringify(initSrc)};\nimport ${JSON.stringify(entrySrc)};\n`;
239
235
  },
240
236
  transform(code, id) {
241
237
  if (id.includes("node_modules") || inject !== "html" || htmlFilePath) return;
@@ -618,6 +614,13 @@ function pluginDevRemoteHmr(options) {
618
614
  connections.length = 0;
619
615
  };
620
616
  for (const [remoteName, remote] of Object.entries(options.remotes)) connectRemote(remoteName, remote);
617
+ const triggerHostReload = (file) => {
618
+ if (shouldIgnoreFile(file, options)) return;
619
+ server.ws.send({ type: "full-reload" });
620
+ };
621
+ server.watcher.on("change", triggerHostReload);
622
+ server.watcher.on("add", triggerHostReload);
623
+ server.watcher.on("unlink", triggerHostReload);
621
624
  server.httpServer?.once("close", teardown);
622
625
  }
623
626
  }
@@ -876,11 +879,20 @@ function normalizeRemotes(remotes) {
876
879
  }
877
880
  function normalizeRemoteItem(key, remote) {
878
881
  if (typeof remote === "string") {
879
- const [entryGlobalName] = remote.split("@");
882
+ const separatorIndex = remote.startsWith("@") ? remote.indexOf("@", 1) : remote.indexOf("@");
883
+ let entryGlobalName;
884
+ let entry;
885
+ if (separatorIndex > 0) {
886
+ entryGlobalName = remote.slice(0, separatorIndex);
887
+ entry = remote.slice(separatorIndex + 1);
888
+ } else {
889
+ entryGlobalName = remote;
890
+ entry = remote;
891
+ }
880
892
  return {
881
893
  type: "var",
882
894
  name: key,
883
- entry: remote.replace(entryGlobalName + "@", ""),
895
+ entry,
884
896
  entryGlobalName,
885
897
  shareScope: "default"
886
898
  };
@@ -906,8 +918,13 @@ function searchPackageVersion(sharedName) {
906
918
  while (path$1.parse(potentialPackageJsonDir).base !== "node_modules" && potentialPackageJsonDir !== rootDir) {
907
919
  const potentialPackageJsonPath = path$1.join(potentialPackageJsonDir, "package.json");
908
920
  if (fs.existsSync(potentialPackageJsonPath)) {
909
- const potentialPackageJson = JSON.parse(fs.readFileSync(potentialPackageJsonPath, "utf-8"));
910
- if (typeof potentialPackageJson == "object" && potentialPackageJson !== null && typeof potentialPackageJson.version === "string" && potentialPackageJson.name === sharedName) return potentialPackageJson.version;
921
+ const potentialPackageJsonContent = fs.readFileSync(potentialPackageJsonPath, "utf-8");
922
+ try {
923
+ const potentialPackageJson = JSON.parse(potentialPackageJsonContent);
924
+ if (typeof potentialPackageJson == "object" && potentialPackageJson !== null && typeof potentialPackageJson.version === "string" && potentialPackageJson.name === sharedName) return potentialPackageJson.version;
925
+ } catch (error) {
926
+ if (!(error instanceof SyntaxError)) throw error;
927
+ }
911
928
  }
912
929
  potentialPackageJsonDir = path$1.dirname(potentialPackageJsonDir);
913
930
  }
@@ -1430,13 +1447,23 @@ function getInstalledPackageJsonPath(pkg) {
1430
1447
  while (currentDir !== rootDir) {
1431
1448
  const packageJsonPath = path.join(currentDir, "package.json");
1432
1449
  if (existsSync(packageJsonPath)) {
1433
- if (JSON.parse(readFileSync(packageJsonPath, "utf-8")).name === packageName) return packageJsonPath;
1450
+ const packageJsonContent = readFileSync(packageJsonPath, "utf-8");
1451
+ try {
1452
+ if (JSON.parse(packageJsonContent).name === packageName) return packageJsonPath;
1453
+ } catch (error) {
1454
+ if (!(error instanceof SyntaxError)) throw error;
1455
+ }
1434
1456
  }
1435
1457
  currentDir = path.dirname(currentDir);
1436
1458
  }
1437
1459
  const rootPackageJsonPath = path.join(rootDir, "package.json");
1438
1460
  if (existsSync(rootPackageJsonPath)) {
1439
- if (JSON.parse(readFileSync(rootPackageJsonPath, "utf-8")).name === packageName) return rootPackageJsonPath;
1461
+ const rootPackageJsonContent = readFileSync(rootPackageJsonPath, "utf-8");
1462
+ try {
1463
+ if (JSON.parse(rootPackageJsonContent).name === packageName) return rootPackageJsonPath;
1464
+ } catch (error) {
1465
+ if (!(error instanceof SyntaxError)) throw error;
1466
+ }
1440
1467
  }
1441
1468
  } catch {
1442
1469
  const packageName = removePathFromNpmPackage(pkg);
@@ -3088,6 +3115,16 @@ var aliasToArrayPlugin_default = {
3088
3115
  }
3089
3116
  };
3090
3117
  //#endregion
3118
+ //#region src/utils/isTestEnv.ts
3119
+ /**
3120
+ * Detects whether the current process is running in a test environment
3121
+ * Set `MFE_VITE_NO_TEST_ENV_CHECK=true` to load federation plugins during tests.
3122
+ */
3123
+ function isTestEnv() {
3124
+ if (process.env.MFE_VITE_NO_TEST_ENV_CHECK === "true") return false;
3125
+ return process.env.NODE_ENV === "test" || process.env.VITEST != null || process.env.JEST_WORKER_ID != null;
3126
+ }
3127
+ //#endregion
3091
3128
  //#region src/utils/controlChunkSanitizer.ts
3092
3129
  const FEDERATION_CONTROL_CHUNK_HINTS = [
3093
3130
  "hostInit",
@@ -3233,6 +3270,7 @@ function createEarlyVirtualModulesPlugin(options) {
3233
3270
  };
3234
3271
  }
3235
3272
  function federation(mfUserOptions) {
3273
+ if (isTestEnv()) return [];
3236
3274
  const options = normalizeModuleFederationOptions(mfUserOptions);
3237
3275
  const isVinext = hasPackageDependency("vinext");
3238
3276
  const { name, remotes, shared, filename, hostInitInjectLocation } = options;
@@ -3628,12 +3666,12 @@ function federation(mfUserOptions) {
3628
3666
  const prefixToRoot = chunkDir === "." ? "" : `${path.relative(chunkDir, ".")}/`;
3629
3667
  const replacementExpr = prefixToRoot ? `${escapeUnsafeJsSourceChars(JSON.stringify(prefixToRoot))}+$1` : "$1";
3630
3668
  const replacement = `=function($1){return new URL(${replacementExpr},import.meta.url).href}`;
3631
- const replaced = chunk.code.replace(/=\(?(\w+)(?:,\w+)?\)?\s*=>\s*["'`][^"'`]*["'`]\s*\+\s*\1/, replacement);
3669
+ const replaced = chunk.code.replace(/=\(?(\w+)(?:,\w+)?\)?\s*=>\s*["'][./][^"']*["']\s*\+\s*\1/, replacement);
3632
3670
  if (replaced !== chunk.code) {
3633
3671
  chunk.code = replaced;
3634
3672
  continue;
3635
3673
  }
3636
- chunk.code = chunk.code.replace(/=function\((\w+)(?:,\w+)?\)\{return\s*["'`][^"'`]*["'`]\s*\+\s*\1\s*\}/, replacement);
3674
+ chunk.code = chunk.code.replace(/=function\((\w+)(?:,\w+)?\)\{return\s*["'][./][^"']*["']\s*\+\s*\1\s*\}/, replacement);
3637
3675
  chunk.code = chunk.code.replace(/=function\((\w+)(?:,\w+)?\)\{return new URL\("\.\.\/"\+\1,import\.meta\.url\)\.href\}/, replacement);
3638
3676
  chunk.code = chunk.code.replace(/new URL\("\.\.\/"\+(\w+),import\.meta\.url\)\.href/g, `new URL(${replacementExpr},import.meta.url).href`);
3639
3677
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@module-federation/vite",
3
- "version": "1.14.0",
3
+ "version": "1.14.2",
4
4
  "description": "Vite plugin for Module Federation",
5
5
  "type": "module",
6
6
  "main": "./lib/index.cjs",