@module-federation/vite 1.20.2 → 1.20.3

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.
@@ -0,0 +1,47 @@
1
+ //#region src/utils/buildPaths.ts
2
+ /**
3
+ * Rebase an import path for a bootstrap file that moved from root into `dir`.
4
+ *
5
+ * When entryFileNames places entries in a subdirectory (e.g. `static/js/`),
6
+ * the bootstrap file moves there too. Paths that resolved from the HTML root
7
+ * must resolve from the new directory instead.
8
+ *
9
+ * Cases: `/static/js/hostInit.js` → `./hostInit.js` (strip dir prefix)
10
+ * `./src/main.tsx` → `../../src/main.tsx` (climb back up for each dir level)
11
+ * `https://cdn.example.com` → unchanged (absolute URL)
12
+ */
13
+ function rebaseImport(importSrc, dir) {
14
+ if (!dir) return importSrc;
15
+ if (isAbsoluteUrl(importSrc)) return importSrc;
16
+ const normalizedDir = dir.replace(/^\/+|\/+$/g, "");
17
+ if (!normalizedDir) return importSrc;
18
+ const stripDirPrefix = (src, prefix) => {
19
+ if (src === prefix) return "";
20
+ if (src.startsWith(prefix + "/")) return src.slice(prefix.length);
21
+ };
22
+ const absoluteRemainder = stripDirPrefix(importSrc, "/" + normalizedDir);
23
+ if (absoluteRemainder !== void 0) {
24
+ const remainder = absoluteRemainder.replace(/^\/+/, "");
25
+ return remainder ? "./" + remainder : "./";
26
+ }
27
+ const relativeRemainder = stripDirPrefix(importSrc, normalizedDir);
28
+ if (relativeRemainder !== void 0) {
29
+ const remainder = relativeRemainder.replace(/^\/+/, "");
30
+ return remainder ? "./" + remainder : "./";
31
+ }
32
+ const upLevels = normalizedDir.split("/").filter(Boolean).length;
33
+ const prefix = upLevels > 0 ? "../".repeat(upLevels) : "./";
34
+ if (importSrc.startsWith("./")) return prefix + importSrc.slice(2);
35
+ if (importSrc.startsWith("/")) return prefix + importSrc.slice(1);
36
+ return prefix + importSrc;
37
+ }
38
+ function normalizePathForImport(path) {
39
+ return path.replace(/\\/g, "/");
40
+ }
41
+ const EXTERNAL_URL_RE = /^(?:[a-z]+:|\/\/)/i;
42
+ function isAbsoluteUrl(src) {
43
+ if (/^[a-z]:[\\/]/i.test(src)) return false;
44
+ return EXTERNAL_URL_RE.test(src);
45
+ }
46
+ //#endregion
47
+ export { normalizePathForImport as n, rebaseImport as r, EXTERNAL_URL_RE as t };
package/lib/index.js CHANGED
@@ -1,3 +1,5 @@
1
+ import { n as normalizePathForImport, r as rebaseImport } from "./buildPaths-BkaQHrd2.js";
2
+ import { a as getMatchingNodeModuleSubpath, c as isNuxtClientBase, d as resolvePublicPath, i as getCommonSharedSubpaths, l as isViteOptimizableEntry, n as getBasePath$2, o as isAssetLikeImport, r as getCommonSharedSubpathFromNodeModulePath, s as isNodeModulePath, t as filterId, u as normalizeNodeModulePath } from "./pathNormalization-CLDIcf9-.js";
1
3
  import { createRequire } from "node:module";
2
4
  import * as fs$2 from "fs";
3
5
  import fs, { existsSync, readFileSync, readdirSync, realpathSync, statSync, writeFileSync } from "fs";
@@ -25,52 +27,6 @@ var __exportAll = (all, no_symbols) => {
25
27
  return target;
26
28
  };
27
29
  //#endregion
28
- //#region src/utils/buildPaths.ts
29
- /**
30
- * Rebase an import path for a bootstrap file that moved from root into `dir`.
31
- *
32
- * When entryFileNames places entries in a subdirectory (e.g. `static/js/`),
33
- * the bootstrap file moves there too. Paths that resolved from the HTML root
34
- * must resolve from the new directory instead.
35
- *
36
- * Cases: `/static/js/hostInit.js` → `./hostInit.js` (strip dir prefix)
37
- * `./src/main.tsx` → `../../src/main.tsx` (climb back up for each dir level)
38
- * `https://cdn.example.com` → unchanged (absolute URL)
39
- */
40
- function rebaseImport(importSrc, dir) {
41
- if (!dir) return importSrc;
42
- if (isAbsoluteUrl(importSrc)) return importSrc;
43
- const normalizedDir = dir.replace(/^\/+|\/+$/g, "");
44
- if (!normalizedDir) return importSrc;
45
- const stripDirPrefix = (src, prefix) => {
46
- if (src === prefix) return "";
47
- if (src.startsWith(prefix + "/")) return src.slice(prefix.length);
48
- };
49
- const absoluteRemainder = stripDirPrefix(importSrc, "/" + normalizedDir);
50
- if (absoluteRemainder !== void 0) {
51
- const remainder = absoluteRemainder.replace(/^\/+/, "");
52
- return remainder ? "./" + remainder : "./";
53
- }
54
- const relativeRemainder = stripDirPrefix(importSrc, normalizedDir);
55
- if (relativeRemainder !== void 0) {
56
- const remainder = relativeRemainder.replace(/^\/+/, "");
57
- return remainder ? "./" + remainder : "./";
58
- }
59
- const upLevels = normalizedDir.split("/").filter(Boolean).length;
60
- const prefix = upLevels > 0 ? "../".repeat(upLevels) : "./";
61
- if (importSrc.startsWith("./")) return prefix + importSrc.slice(2);
62
- if (importSrc.startsWith("/")) return prefix + importSrc.slice(1);
63
- return prefix + importSrc;
64
- }
65
- function normalizePathForImport(path) {
66
- return path.replace(/\\/g, "/");
67
- }
68
- const EXTERNAL_URL_RE = /^(?:[a-z]+:|\/\/)/i;
69
- function isAbsoluteUrl(src) {
70
- if (/^[a-z]:[\\/]/i.test(src)) return false;
71
- return EXTERNAL_URL_RE.test(src);
72
- }
73
- //#endregion
74
30
  //#region src/utils/codeRewriter.ts
75
31
  const BASE64_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
76
32
  var CodeRewriter = class {
@@ -851,124 +807,6 @@ function hasPackageDependency(dependencyName, cwd = packageDetectionCwd || proce
851
807
  }
852
808
  }
853
809
  //#endregion
854
- //#region src/utils/pathNormalization.ts
855
- const COMMON_SHARED_SUBPATHS = {
856
- react: [
857
- "react/jsx-runtime",
858
- "react/jsx-dev-runtime",
859
- "react/compiler-runtime"
860
- ],
861
- "react-dom": [
862
- "react-dom/client",
863
- "react-dom/server",
864
- "react-dom/server.browser"
865
- ],
866
- "solid-js": [
867
- "solid-js/web",
868
- "solid-js/store",
869
- "solid-js/html",
870
- "solid-js/h"
871
- ],
872
- zustand: ["zustand/vanilla", "zustand/react"]
873
- };
874
- const VITE_DEFAULT_ASSET_TYPES = [
875
- "apng",
876
- "bmp",
877
- "png",
878
- "jpe?g",
879
- "jfif",
880
- "pjpeg",
881
- "pjp",
882
- "gif",
883
- "svg",
884
- "ico",
885
- "webp",
886
- "avif",
887
- "cur",
888
- "jxl",
889
- "mp4",
890
- "webm",
891
- "ogg",
892
- "mp3",
893
- "wav",
894
- "flac",
895
- "aac",
896
- "opus",
897
- "mov",
898
- "m4a",
899
- "vtt",
900
- "woff2?",
901
- "eot",
902
- "ttf",
903
- "otf",
904
- "webmanifest",
905
- "pdf",
906
- "txt"
907
- ];
908
- const ASSET_LIKE_IMPORT_RE = new RegExp(`\\.(${[...[
909
- "css",
910
- "scss",
911
- "sass",
912
- "less",
913
- "styl",
914
- "stylus"
915
- ], ...VITE_DEFAULT_ASSET_TYPES].join("|")})(?:[?#].*)?$`, "i");
916
- function isAssetLikeImport(source) {
917
- return ASSET_LIKE_IMPORT_RE.test(source);
918
- }
919
- const VITE_OPTIMIZABLE_ENTRY_RE = /\.[cm]?[jt]s$/;
920
- function isViteOptimizableEntry(resolvedPath) {
921
- return VITE_OPTIMIZABLE_ENTRY_RE.test(resolvedPath);
922
- }
923
- function removeTrailingSlash(value) {
924
- return value.endsWith("/") ? value.slice(0, -1) : value;
925
- }
926
- function ensureTrailingSlash(value) {
927
- return `${removeTrailingSlash(value)}/`;
928
- }
929
- function getBasePath$2(base) {
930
- return removeTrailingSlash(base || "/");
931
- }
932
- function isNuxtClientBase(base) {
933
- return getBasePath$2(base).endsWith("/_nuxt");
934
- }
935
- function normalizeNodeModulePath(source) {
936
- const queryIndex = source.indexOf("?");
937
- return (queryIndex === -1 ? source : source.slice(0, queryIndex)).replace(/\\/g, "/");
938
- }
939
- function isNodeModulePath(source) {
940
- return source.includes("/node_modules/") || source.includes("\\node_modules\\");
941
- }
942
- function filterId(id) {
943
- return typeof id === "string" && !id.includes("\0");
944
- }
945
- function getMatchingNodeModuleSubpath(source, candidates) {
946
- const normalized = normalizeNodeModulePath(source);
947
- return [...candidates].sort((a, b) => b.length - a.length).find((candidate) => normalized.includes(`/node_modules/${candidate}/`) || normalized.includes(`/node_modules/${candidate}.`));
948
- }
949
- function getCommonSharedSubpaths(sharedKey) {
950
- return COMMON_SHARED_SUBPATHS[removeTrailingSlash(sharedKey)] || [];
951
- }
952
- function getCommonSharedSubpathFromNodeModulePath(source, sharedKey) {
953
- return getMatchingNodeModuleSubpath(source, getCommonSharedSubpaths(removeTrailingSlash(sharedKey)));
954
- }
955
- /**
956
- * Resolves the public path for remote entries
957
- * @param options - Module Federation options
958
- * @param viteBase - Vite's base config value
959
- * @param originalBase - Original base config before any transformations
960
- * @returns The resolved public path
961
- */
962
- function resolvePublicPath(options, viteBase, originalBase) {
963
- if (options.publicPath && options.publicPath !== "auto") return options.publicPath;
964
- if (!originalBase) return "auto";
965
- if (viteBase) {
966
- if (viteBase === "./") return "auto";
967
- return ensureTrailingSlash(viteBase);
968
- }
969
- return "auto";
970
- }
971
- //#endregion
972
810
  //#region src/utils/normalizeModuleFederationOptions.ts
973
811
  const INTERNAL_NAME_PREFIX = "__mfe_internal__";
974
812
  function toInternalModuleFederationName(name) {
@@ -2476,32 +2314,55 @@ function resolveReExportModule(filePath, specifier, exportConditions) {
2476
2314
  return;
2477
2315
  }
2478
2316
  }
2479
- function hasTopLevelDeclaratorComma(source, start, codePositions) {
2317
+ /** Marks a template-literal frame whose text (not its interpolation) is being scanned. */
2318
+ const TEMPLATE_TEXT = Symbol("templateText");
2319
+ function getAdditionalTopLevelDeclaratorNames(source, start, codePositions) {
2320
+ const names = [];
2480
2321
  let depth = 0;
2481
2322
  let quote;
2482
2323
  let escaped = false;
2483
2324
  let canStartRegex = true;
2325
+ const templateFrames = [];
2326
+ const inTemplateText = () => templateFrames[templateFrames.length - 1] === TEMPLATE_TEXT;
2484
2327
  for (let index = start; index < source.length; index++) {
2485
2328
  const char = source[index];
2329
+ if (inTemplateText()) {
2330
+ if (escaped) escaped = false;
2331
+ else if (char === "\\") escaped = true;
2332
+ else if (char === "$" && source[index + 1] === "{") {
2333
+ templateFrames.push(depth);
2334
+ index++;
2335
+ canStartRegex = true;
2336
+ } else if (char === "`") {
2337
+ templateFrames.pop();
2338
+ canStartRegex = false;
2339
+ }
2340
+ continue;
2341
+ }
2486
2342
  if (quote) {
2487
2343
  if (escaped) escaped = false;
2488
2344
  else if (char === "\\") escaped = true;
2489
2345
  else if (char === quote) quote = void 0;
2490
2346
  continue;
2491
2347
  }
2492
- if (char === "\"" || char === "'" || char === "`") {
2348
+ if (char === "`") {
2349
+ templateFrames.push(TEMPLATE_TEXT);
2350
+ canStartRegex = false;
2351
+ continue;
2352
+ }
2353
+ if (char === "\"" || char === "'") {
2493
2354
  quote = char;
2494
2355
  canStartRegex = false;
2495
2356
  continue;
2496
2357
  }
2497
2358
  if (char === "/" && source[index + 1] === "/") {
2498
2359
  index = source.indexOf("\n", index + 2);
2499
- if (index === -1) return false;
2360
+ if (index === -1) return names;
2500
2361
  continue;
2501
2362
  }
2502
2363
  if (char === "/" && source[index + 1] === "*") {
2503
2364
  const commentEnd = source.indexOf("*/", index + 2);
2504
- if (commentEnd === -1) return true;
2365
+ if (commentEnd === -1) return void 0;
2505
2366
  index = commentEnd + 1;
2506
2367
  continue;
2507
2368
  }
@@ -2532,9 +2393,9 @@ function hasTopLevelDeclaratorComma(source, start, codePositions) {
2532
2393
  while (/[$_\p{ID_Continue}]/u.test(source[index + 1] || "")) index++;
2533
2394
  break;
2534
2395
  }
2535
- if (regexChar === "\n" || regexChar === "\r") return true;
2396
+ if (regexChar === "\n" || regexChar === "\r") return void 0;
2536
2397
  }
2537
- if (!closed) return true;
2398
+ if (!closed) return void 0;
2538
2399
  canStartRegex = false;
2539
2400
  continue;
2540
2401
  }
@@ -2573,15 +2434,29 @@ function hasTopLevelDeclaratorComma(source, start, codePositions) {
2573
2434
  continue;
2574
2435
  }
2575
2436
  if (char === ")" || char === "]" || char === "}") {
2437
+ if (char === "}" && templateFrames.length > 0 && templateFrames[templateFrames.length - 1] === depth) {
2438
+ templateFrames.pop();
2439
+ canStartRegex = false;
2440
+ continue;
2441
+ }
2576
2442
  depth = Math.max(0, depth - 1);
2577
2443
  canStartRegex = false;
2578
2444
  continue;
2579
2445
  }
2580
- if (depth === 0 && char === ",") return true;
2581
- if (depth === 0 && char === ";") return false;
2446
+ if (templateFrames.length === 0 && depth === 0 && char === ",") {
2447
+ let bindingStart = index + 1;
2448
+ while (/\s/.test(source[bindingStart] || "")) bindingStart++;
2449
+ const binding = source.slice(bindingStart).match(new RegExp(`^(${JS_IDENTIFIER_PATTERN})`, "u"));
2450
+ if (!binding || !isValidEsmExportName(binding[1])) return void 0;
2451
+ names.push(binding[1]);
2452
+ index = bindingStart + binding[1].length - 1;
2453
+ canStartRegex = false;
2454
+ continue;
2455
+ }
2456
+ if (templateFrames.length === 0 && depth === 0 && char === ";") return names;
2582
2457
  if (!/\s/.test(char)) canStartRegex = char !== ".";
2583
2458
  }
2584
- return false;
2459
+ return names;
2585
2460
  }
2586
2461
  function hasUnsupportedBindingPattern(source, start) {
2587
2462
  const opening = source[start];
@@ -2624,7 +2499,9 @@ function getNamedExportsViaRegex(source, filePath, visited, scanState = { comple
2624
2499
  const exportedVariableDeclarationRegex = /export\s+(?:const|let|var)\s+/g;
2625
2500
  while ((match = exportedVariableDeclarationRegex.exec(source)) !== null) {
2626
2501
  if (!codePositions[match.index]) continue;
2627
- if (hasTopLevelDeclaratorComma(source, exportedVariableDeclarationRegex.lastIndex, codePositions)) scanState.complete = false;
2502
+ const additionalNames = getAdditionalTopLevelDeclaratorNames(source, exportedVariableDeclarationRegex.lastIndex, codePositions);
2503
+ if (additionalNames === void 0) scanState.complete = false;
2504
+ else for (const name of additionalNames) names.add(name);
2628
2505
  if (hasUnsupportedBindingPattern(source, exportedVariableDeclarationRegex.lastIndex)) scanState.complete = false;
2629
2506
  }
2630
2507
  if (hasCodeMatch(source, /export\s+import\s+/g, codePositions) || hasCodeMatch(source, /export\s*=/g, codePositions)) scanState.complete = false;
@@ -4193,7 +4070,6 @@ function generateTreeShakingSnapshotPluginCode(enabled) {
4193
4070
  function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(options), command = "build") {
4194
4071
  const needsSharedProviderSelectionHelper = Object.keys(options.shared ?? {}).length > 0;
4195
4072
  const hasTreeShakingShared = Object.values(options.shared ?? {}).some((share) => !!share?.shareConfig.treeShaking);
4196
- const hasEagerShared = Object.values(options.shared ?? {}).some((share) => share?.shareConfig.eager === true && share.shareConfig.import !== false);
4197
4073
  const hasMultipleShareScopes = Array.isArray(options.shareScope);
4198
4074
  const runtimeImports = [
4199
4075
  "init as runtimeInit",
@@ -4246,7 +4122,6 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
4246
4122
  globalThis.__VUE_HMR_RUNTIME__ = { createRecord() {}, rerender() {}, reload() {} };
4247
4123
  }
4248
4124
  import {${runtimeImports}} from "@module-federation/runtime";
4249
- ${hasEagerShared ? `import * as __mfLocalSharedImportMap from "${getLocalSharedImportMapPath(options)}";` : ""}
4250
4125
  ${runtimeHelperImports.length ? `import {${runtimeHelperImports.join(", ")}} from "@module-federation/runtime/helpers";` : ""}
4251
4126
  ${pluginImportNames.filter((item) => !isSsrOnlyPlugin(item[1])).map((item) => item[1]).join("\n")}
4252
4127
  ${command === "build" ? getRuntimeInitResolveBootstrapCode(false, options ? getRuntimeInitStatusImportId(options) : void 0) : getRuntimeInitBootstrapCode(false, options ? getRuntimeInitStatusImportId(options) : void 0) + "\n const { initResolve } = globalThis[globalKey];"}
@@ -4281,12 +4156,11 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
4281
4156
  ${needsSharedProviderSelectionHelper ? externalSharedProviderSelectionHelperCode : ""}
4282
4157
 
4283
4158
  async function getLocalSharedImportMap() {
4284
- ${hasEagerShared ? "return __mfLocalSharedImportMap;" : ""}
4285
- ${hasEagerShared ? "" : `if (!localSharedImportMapPromise) {
4159
+ if (!localSharedImportMapPromise) {
4286
4160
  localSharedImportMapPromise = retrySharedInit(() => import("${getLocalSharedImportMapPath(options)}"))
4287
4161
  .catch((e) => { localSharedImportMapPromise = undefined; throw e; });
4288
4162
  }
4289
- return localSharedImportMapPromise`}
4163
+ return localSharedImportMapPromise
4290
4164
  }
4291
4165
 
4292
4166
  async function getExposesMap() {
@@ -9481,7 +9355,7 @@ function stripEmptyPreloadCalls(code) {
9481
9355
  }
9482
9356
  nextCode = nextCode.replace(/import\s*["'][^"']*__loadShare__[^"']*["']\s*;?/g, "");
9483
9357
  nextCode = nextCode.replace(helperImportRegex, (statement, local) => {
9484
- return new RegExp(`\\b${local}\\s*\\(`).test(nextCode.replace(statement, "")) ? statement : "";
9358
+ return new RegExp(`\\b${local}\\b`).test(nextCode.replace(statement, "")) ? statement : "";
9485
9359
  });
9486
9360
  return nextCode;
9487
9361
  }
@@ -9935,7 +9809,7 @@ export default __mfShared.default ?? __mfShared;`
9935
9809
  else optimizeDeps.include.push(key);
9936
9810
  for (const subpath of getCommonSharedSubpaths(key)) {
9937
9811
  const canResolveSubpath = canResolveSharedSubpath(subpath, root);
9938
- if (subpath === "react/compiler-runtime" && !canResolveSubpath) {
9812
+ if (["react/compiler-runtime", "react-dom/client"].includes(subpath) && !canResolveSubpath) {
9939
9813
  optimizeDeps.exclude.push(subpath);
9940
9814
  continue;
9941
9815
  }
@@ -0,0 +1,119 @@
1
+ //#region src/utils/pathNormalization.ts
2
+ const COMMON_SHARED_SUBPATHS = {
3
+ react: [
4
+ "react/jsx-runtime",
5
+ "react/jsx-dev-runtime",
6
+ "react/compiler-runtime"
7
+ ],
8
+ "react-dom": [
9
+ "react-dom/client",
10
+ "react-dom/server",
11
+ "react-dom/server.browser"
12
+ ],
13
+ "solid-js": [
14
+ "solid-js/web",
15
+ "solid-js/store",
16
+ "solid-js/html",
17
+ "solid-js/h"
18
+ ],
19
+ zustand: ["zustand/vanilla", "zustand/react"]
20
+ };
21
+ const VITE_DEFAULT_ASSET_TYPES = [
22
+ "apng",
23
+ "bmp",
24
+ "png",
25
+ "jpe?g",
26
+ "jfif",
27
+ "pjpeg",
28
+ "pjp",
29
+ "gif",
30
+ "svg",
31
+ "ico",
32
+ "webp",
33
+ "avif",
34
+ "cur",
35
+ "jxl",
36
+ "mp4",
37
+ "webm",
38
+ "ogg",
39
+ "mp3",
40
+ "wav",
41
+ "flac",
42
+ "aac",
43
+ "opus",
44
+ "mov",
45
+ "m4a",
46
+ "vtt",
47
+ "woff2?",
48
+ "eot",
49
+ "ttf",
50
+ "otf",
51
+ "webmanifest",
52
+ "pdf",
53
+ "txt"
54
+ ];
55
+ const ASSET_LIKE_IMPORT_RE = new RegExp(`\\.(${[...[
56
+ "css",
57
+ "scss",
58
+ "sass",
59
+ "less",
60
+ "styl",
61
+ "stylus"
62
+ ], ...VITE_DEFAULT_ASSET_TYPES].join("|")})(?:[?#].*)?$`, "i");
63
+ function isAssetLikeImport(source) {
64
+ return ASSET_LIKE_IMPORT_RE.test(source);
65
+ }
66
+ const VITE_OPTIMIZABLE_ENTRY_RE = /\.[cm]?[jt]s$/;
67
+ function isViteOptimizableEntry(resolvedPath) {
68
+ return VITE_OPTIMIZABLE_ENTRY_RE.test(resolvedPath);
69
+ }
70
+ function removeTrailingSlash(value) {
71
+ return value.endsWith("/") ? value.slice(0, -1) : value;
72
+ }
73
+ function ensureTrailingSlash(value) {
74
+ return `${removeTrailingSlash(value)}/`;
75
+ }
76
+ function getBasePath(base) {
77
+ return removeTrailingSlash(base || "/");
78
+ }
79
+ function isNuxtClientBase(base) {
80
+ return getBasePath(base).endsWith("/_nuxt");
81
+ }
82
+ function normalizeNodeModulePath(source) {
83
+ const queryIndex = source.indexOf("?");
84
+ return (queryIndex === -1 ? source : source.slice(0, queryIndex)).replace(/\\/g, "/");
85
+ }
86
+ function isNodeModulePath(source) {
87
+ return source.includes("/node_modules/") || source.includes("\\node_modules\\");
88
+ }
89
+ function filterId(id) {
90
+ return typeof id === "string" && !id.includes("\0");
91
+ }
92
+ function getMatchingNodeModuleSubpath(source, candidates) {
93
+ const normalized = normalizeNodeModulePath(source);
94
+ return [...candidates].sort((a, b) => b.length - a.length).find((candidate) => normalized.includes(`/node_modules/${candidate}/`) || normalized.includes(`/node_modules/${candidate}.`));
95
+ }
96
+ function getCommonSharedSubpaths(sharedKey) {
97
+ return COMMON_SHARED_SUBPATHS[removeTrailingSlash(sharedKey)] || [];
98
+ }
99
+ function getCommonSharedSubpathFromNodeModulePath(source, sharedKey) {
100
+ return getMatchingNodeModuleSubpath(source, getCommonSharedSubpaths(removeTrailingSlash(sharedKey)));
101
+ }
102
+ /**
103
+ * Resolves the public path for remote entries
104
+ * @param options - Module Federation options
105
+ * @param viteBase - Vite's base config value
106
+ * @param originalBase - Original base config before any transformations
107
+ * @returns The resolved public path
108
+ */
109
+ function resolvePublicPath(options, viteBase, originalBase) {
110
+ if (options.publicPath && options.publicPath !== "auto") return options.publicPath;
111
+ if (!originalBase) return "auto";
112
+ if (viteBase) {
113
+ if (viteBase === "./") return "auto";
114
+ return ensureTrailingSlash(viteBase);
115
+ }
116
+ return "auto";
117
+ }
118
+ //#endregion
119
+ export { getMatchingNodeModuleSubpath as a, isNuxtClientBase as c, resolvePublicPath as d, getCommonSharedSubpaths as i, isViteOptimizableEntry as l, getBasePath as n, isAssetLikeImport as o, getCommonSharedSubpathFromNodeModulePath as r, isNodeModulePath as s, filterId as t, normalizeNodeModulePath as u };
@@ -1,3 +1,4 @@
1
+ import { t as EXTERNAL_URL_RE } from "./buildPaths-BkaQHrd2.js";
1
2
  //#region src/utils/fetchWithTimeout.ts
2
3
  const DEFAULT_SSR_FETCH_TIMEOUT_MS = 1e4;
3
4
  const DEFAULT_SSR_FETCH_MAX_BYTES = 10 * 1024 * 1024;
@@ -116,11 +117,10 @@ async function readResponseTextBounded(res, maxBytes = DEFAULT_SSR_FETCH_MAX_BYT
116
117
  * module source through Vite's plugin pipeline, avoiding serialisation which
117
118
  * cannot faithfully represent React components or closures.
118
119
  *
119
- * Dev mode on Vite < 8 is NOT supported `ModuleRunner` and
120
- * `FetchableDevEnvironment` are Vite 8+ APIs. If you need dev-mode SSR on
121
- * an older Vite version, implement an alternative loader in `loadSSRRemoteEntry`
122
- * for the `isDevSsrEntry` branch and expose a corresponding server endpoint
123
- * from `pluginSSRRemoteEntry.configureServer`.
120
+ * Dev mode on Vite < 8 is NOT supported by this integration because the
121
+ * cross-process `fetchModule` proxy uses Vite 8's environment APIs.
122
+ * `ModuleRunner` itself is available in earlier Vite versions, but an older
123
+ * remote needs a different transport and server endpoint.
124
124
  *
125
125
  * Exported as a plain factory function so it can be serialised into the
126
126
  * generated runtimePlugins list in virtualRemotes.ts.
@@ -135,9 +135,12 @@ async function nodeImport(id) {
135
135
  }
136
136
  const isNodeServer = () => typeof globalThis.process?.versions?.node === "string";
137
137
  const runnerCache = /* @__PURE__ */ new Map();
138
+ function getSortedRecordEntries(record) {
139
+ return Object.entries(record).sort(([left], [right]) => left.localeCompare(right));
140
+ }
138
141
  /**
139
- * Load `vite/module-runner`. Returns null on Vite < 8 where the subpath doesn't
140
- * exist.
142
+ * Load `vite/module-runner`. Returns null when the installed Vite does not
143
+ * expose the module-runner entry point.
141
144
  */
142
145
  async function getModuleRunnerModule() {
143
146
  const moduleRunnerId = ["vite", "module-runner"].join("/");
@@ -156,11 +159,33 @@ async function getModuleRunnerModule() {
156
159
  * `/__mf_runner__` endpoint. Each HTTP POST carries a `fetchModule` invoke
157
160
  * payload; the remote responds with the transformed module source as JSON.
158
161
  *
159
- * This is Vite 8+ only older versions don't expose `vite/module-runner` or
160
- * the `/__mf_runner__` proxy endpoint.
162
+ * The cross-process transport is Vite 8+ only because older versions do not
163
+ * expose the `/__mf_runner__` environment proxy used here.
161
164
  */
162
- async function getOrCreateRunner(remoteOrigin, fetchTimeoutMs, fetchMaxBytes) {
163
- const cacheKey = `${fetchTimeoutMs}::${fetchMaxBytes}::${remoteOrigin}`;
165
+ function getRunnerCacheKey(remoteOrigin, resolvedShared, fetchTimeoutMs, fetchMaxBytes) {
166
+ return JSON.stringify([
167
+ remoteOrigin,
168
+ fetchTimeoutMs,
169
+ fetchMaxBytes,
170
+ getSortedRecordEntries(resolvedShared)
171
+ ]);
172
+ }
173
+ async function resolveSharedExternal(id, resolvedShared) {
174
+ if (typeof id !== "string") return null;
175
+ const resolved = resolvedShared[id];
176
+ if (!resolved) return null;
177
+ if (EXTERNAL_URL_RE.test(resolved)) return {
178
+ externalize: resolved,
179
+ type: "module"
180
+ };
181
+ const { pathToFileURL } = await _url();
182
+ return {
183
+ externalize: pathToFileURL(resolved).href,
184
+ type: "module"
185
+ };
186
+ }
187
+ async function getOrCreateRunner(remoteOrigin, resolvedShared, fetchTimeoutMs, fetchMaxBytes) {
188
+ const cacheKey = getRunnerCacheKey(remoteOrigin, resolvedShared, fetchTimeoutMs, fetchMaxBytes);
164
189
  if (runnerCache.has(cacheKey)) return runnerCache.get(cacheKey);
165
190
  const promise = (async () => {
166
191
  const viteRunner = await getModuleRunnerModule();
@@ -171,6 +196,10 @@ async function getOrCreateRunner(remoteOrigin, fetchTimeoutMs, fetchMaxBytes) {
171
196
  return new ModuleRunner({
172
197
  hmr: false,
173
198
  transport: { async invoke(payload) {
199
+ if (payload.data.name === "fetchModule") {
200
+ const sharedExternal = await resolveSharedExternal(payload.data.data[0], resolvedShared);
201
+ if (sharedExternal) return { result: sharedExternal };
202
+ }
174
203
  const text = await readResponseTextBounded(await fetchWithTimeout(runnerEndpoint, {
175
204
  method: "POST",
176
205
  headers: { "Content-Type": "application/json" },
@@ -190,6 +219,7 @@ const _path = () => nodeImport("path");
190
219
  const _fs = () => nodeImport("fs");
191
220
  const _crypto = () => nodeImport("crypto");
192
221
  const _module = () => nodeImport("module");
222
+ const _url = () => nodeImport("url");
193
223
  /**
194
224
  * Version key for a resolved SSR entry. Derived from the remote's manifest
195
225
  * content so a redeploy at the same URL produces a different key, which in
@@ -449,7 +479,7 @@ function revalidate(remoteEntryUrl) {
449
479
  const tempFileCache = /* @__PURE__ */ new Map();
450
480
  const tempFilePathCache = /* @__PURE__ */ new Map();
451
481
  function getSsrTransformContextKey(resolvedShared, shareScopeName) {
452
- return JSON.stringify([shareScopeName, Object.entries(resolvedShared).sort(([left], [right]) => left.localeCompare(right))]);
482
+ return JSON.stringify([shareScopeName, getSortedRecordEntries(resolvedShared)]);
453
483
  }
454
484
  let ssrCacheDirPromise;
455
485
  async function getSSRCacheDir() {
@@ -573,7 +603,7 @@ async function importTempModule(filePath, versionKey) {
573
603
  }
574
604
  let warnedVmUnavailable = false;
575
605
  async function tryVmStrategy(ssrEntry, options) {
576
- const { loadViaVmStrategy, isVmStrategyAvailable } = await import("./ssrVmStrategy-B34y11HE.js");
606
+ const { loadViaVmStrategy, isVmStrategyAvailable } = await import("./ssrVmStrategy-BkEp3YIv.js");
577
607
  if (!await isVmStrategyAvailable()) {
578
608
  if (!warnedVmUnavailable) {
579
609
  warnedVmUnavailable = true;
@@ -605,7 +635,7 @@ async function loadSSRRemoteEntry(ssrEntry, options) {
605
635
  const urlObj = new URL(url);
606
636
  if (urlObj.pathname.includes("/__mf_ssr__/")) {
607
637
  const remoteOrigin = urlObj.origin;
608
- const runner = await getOrCreateRunner(remoteOrigin, options.fetchTimeoutMs, options.fetchMaxBytes);
638
+ const runner = await getOrCreateRunner(remoteOrigin, resolvedShared, options.fetchTimeoutMs, options.fetchMaxBytes);
609
639
  if (!runner) {
610
640
  if (process.env.NODE_ENV !== "production") return null;
611
641
  } else try {
@@ -1,4 +1,5 @@
1
- import { c as readResponseTextBounded, n as neutralizeBrowserPreloadHelpers, s as fetchWithTimeout, t as SsrEntryHttpError } from "./ssrEntryLoader-gVPDPAE8.js";
1
+ import { i as getCommonSharedSubpaths } from "./pathNormalization-CLDIcf9-.js";
2
+ import { c as readResponseTextBounded, n as neutralizeBrowserPreloadHelpers, s as fetchWithTimeout, t as SsrEntryHttpError } from "./ssrEntryLoader-7v0Do_g5.js";
2
3
  //#region src/utils/ssrVmStrategy.ts
3
4
  /**
4
5
  * vm.SourceTextModule strategy for loading remote SSR entries.
@@ -39,6 +40,22 @@ async function getVmApi() {
39
40
  async function isVmStrategyAvailable() {
40
41
  return await getVmApi() !== null;
41
42
  }
43
+ function findVmSharedKey(specifier, shared) {
44
+ if (!shared) return;
45
+ const keys = Object.keys(shared);
46
+ if (Object.prototype.hasOwnProperty.call(shared, specifier)) return specifier;
47
+ const vueKey = keys.find((key) => key.endsWith("/") ? key.slice(0, -1) === "vue" : key === "vue");
48
+ if (vueKey && (specifier === "vue/dist/vue.esm-bundler.js" || specifier === "vue/dist/vue.runtime.esm-bundler.js")) return vueKey;
49
+ const commonSubpathKey = keys.find((key) => {
50
+ return getCommonSharedSubpaths(key.endsWith("/") ? key.slice(0, -1) : key).includes(specifier);
51
+ });
52
+ if (commonSubpathKey) return commonSubpathKey;
53
+ return keys.find((key) => {
54
+ if (!key.endsWith("/")) return false;
55
+ const keyBase = key.slice(0, -1);
56
+ return specifier === keyBase || specifier.startsWith(`${keyBase}/`);
57
+ });
58
+ }
42
59
  function getFederationInstances() {
43
60
  return globalThis.__FEDERATION__?.__INSTANCES__ ?? [];
44
61
  }
@@ -51,9 +68,11 @@ async function loadBareModule(specifier, options) {
51
68
  const instances = owner ? [owner] : getFederationInstances();
52
69
  for (const instance of instances) {
53
70
  if (typeof instance?.loadShare !== "function") continue;
54
- const shared = instance.options?.shared?.[specifier];
55
- if (!shared) continue;
56
- if (!(Array.isArray(shared.scope) ? shared.scope : [shared.scope ?? "default"]).includes(options.shareScopeName)) continue;
71
+ const shared = instance.options?.shared;
72
+ const sharedKey = findVmSharedKey(specifier, shared);
73
+ const shareConfig = sharedKey ? shared?.[sharedKey] : void 0;
74
+ if (!shareConfig) continue;
75
+ if (!(Array.isArray(shareConfig.scope) ? shareConfig.scope : [shareConfig.scope ?? "default"]).includes(options.shareScopeName)) continue;
57
76
  try {
58
77
  const factory = await instance.loadShare(specifier);
59
78
  if (typeof factory === "function") {
@@ -17,11 +17,10 @@
17
17
  * module source through Vite's plugin pipeline, avoiding serialisation which
18
18
  * cannot faithfully represent React components or closures.
19
19
  *
20
- * Dev mode on Vite < 8 is NOT supported `ModuleRunner` and
21
- * `FetchableDevEnvironment` are Vite 8+ APIs. If you need dev-mode SSR on
22
- * an older Vite version, implement an alternative loader in `loadSSRRemoteEntry`
23
- * for the `isDevSsrEntry` branch and expose a corresponding server endpoint
24
- * from `pluginSSRRemoteEntry.configureServer`.
20
+ * Dev mode on Vite < 8 is NOT supported by this integration because the
21
+ * cross-process `fetchModule` proxy uses Vite 8's environment APIs.
22
+ * `ModuleRunner` itself is available in earlier Vite versions, but an older
23
+ * remote needs a different transport and server endpoint.
25
24
  *
26
25
  * Exported as a plain factory function so it can be serialised into the
27
26
  * generated runtimePlugins list in virtualRemotes.ts.
@@ -1,2 +1,2 @@
1
- import { i as ssrEntryLoaderPlugin, n as neutralizeBrowserPreloadHelpers, r as revalidate, t as SsrEntryHttpError } from "../ssrEntryLoader-gVPDPAE8.js";
1
+ import { i as ssrEntryLoaderPlugin, n as neutralizeBrowserPreloadHelpers, r as revalidate, t as SsrEntryHttpError } from "../ssrEntryLoader-7v0Do_g5.js";
2
2
  export { SsrEntryHttpError, ssrEntryLoaderPlugin as default, neutralizeBrowserPreloadHelpers, revalidate };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@module-federation/vite",
3
- "version": "1.20.2",
3
+ "version": "1.20.3",
4
4
  "description": "Vite plugin for Module Federation",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",
@@ -92,39 +92,5 @@
92
92
  "typescript": "7.0.2",
93
93
  "vite": "8.2.0",
94
94
  "vitest": "4.1.10"
95
- },
96
- "pnpm": {
97
- "overrides": {
98
- "@babel/core@<7.29.6": "7.29.6",
99
- "@babel/helpers@<7.26.10": "7.29.7",
100
- "@babel/plugin-transform-modules-systemjs@<7.29.4": "7.29.4",
101
- "@babel/runtime@<7.26.10": "7.29.7",
102
- "adm-zip@<0.6.0": "0.6.0",
103
- "ajv@>=6.0.0 <6.14.0": "6.14.0",
104
- "ajv@>=8.0.0 <8.18.0": "8.20.0",
105
- "body-parser@<1.20.6": "1.20.6",
106
- "cross-spawn@<7.0.5": "7.0.6",
107
- "esbuild@<0.28.1": "0.28.1",
108
- "fast-uri@>=3.0.0 <3.1.4": "3.1.4",
109
- "follow-redirects@<1.16.0": "1.16.0",
110
- "http-proxy-middleware@>=2.0.0 <2.0.10": "2.0.10",
111
- "immutable@<4.3.9": "4.3.9",
112
- "js-yaml@>=4.0.0 <4.3.0": "4.3.0",
113
- "lodash@<4.18.0": "4.18.1",
114
- "path-to-regexp@<0.1.13": "0.1.13",
115
- "postcss@<8.5.18": "8.5.25",
116
- "qs@>=6.0.0 <6.15.2": "6.15.2",
117
- "serialize-javascript@<7.0.5": "7.0.5",
118
- "shell-quote@<1.9.0": "1.10.0",
119
- "sucrase@<3.35.1": "3.35.1",
120
- "undici@>=7.0.0 <7.28.0": "7.28.0",
121
- "uuid@<11.1.1": "11.1.1",
122
- "webpack-dev-server@<5.2.6": "5.2.6",
123
- "webpack@<5.104.1": "5.109.2",
124
- "websocket-driver@<0.7.5": "0.7.5",
125
- "ws@>=8.0.0 <8.21.0": "8.21.0",
126
- "yaml@>=1.0.0 <1.10.3": "1.10.3",
127
- "yaml@>=2.0.0 <2.8.3": "2.8.3"
128
- }
129
95
  }
130
96
  }