@module-federation/vite 1.16.9 → 1.16.10

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.js CHANGED
@@ -797,6 +797,19 @@ globalThis[__mfCacheGlobalKey] ||= { share: {}, remote: {} };
797
797
  globalThis[__mfCacheGlobalKey].share ||= {};
798
798
  globalThis[__mfCacheGlobalKey].remote ||= {};
799
799
  const __mfModuleCache = globalThis[__mfCacheGlobalKey];
800
+ for (const __mfShareKey of Object.keys(__mfModuleCache.share)) {
801
+ if (__mfShareKey.startsWith("default:")) {
802
+ const __mfLegacyShareKey = __mfShareKey.slice("default:".length);
803
+ if (__mfModuleCache.share[__mfLegacyShareKey] === undefined) {
804
+ __mfModuleCache.share[__mfLegacyShareKey] = __mfModuleCache.share[__mfShareKey];
805
+ }
806
+ } else if (!__mfShareKey.includes(":")) {
807
+ const __mfDefaultShareKey = "default:" + __mfShareKey;
808
+ if (__mfModuleCache.share[__mfDefaultShareKey] === undefined) {
809
+ __mfModuleCache.share[__mfDefaultShareKey] = __mfModuleCache.share[__mfShareKey];
810
+ }
811
+ }
812
+ }
800
813
  `;
801
814
  }
802
815
  function getRuntimeInitPromiseBootstrapCode(enableSsrInit = false) {
@@ -1489,6 +1502,7 @@ function generateLocalSharedImportMap() {
1489
1502
  shareConfig: {
1490
1503
  singleton: ${shareItem.shareConfig.singleton},
1491
1504
  requiredVersion: ${JSON.stringify(shareItem.shareConfig.requiredVersion)},
1505
+ strictVersion: ${shareItem.shareConfig.strictVersion},
1492
1506
  ${shareItem.shareConfig.import === false ? "import: false," : ""}
1493
1507
  }
1494
1508
  }
@@ -1526,6 +1540,7 @@ function generateUsedSharedPreloadConfig() {
1526
1540
  shareConfig: {
1527
1541
  singleton: ${shareItem.shareConfig.singleton},
1528
1542
  requiredVersion: ${JSON.stringify(shareItem.shareConfig.requiredVersion)},
1543
+ strictVersion: ${shareItem.shareConfig.strictVersion},
1529
1544
  ${shareItem.shareConfig.import === false ? "import: false," : ""}
1530
1545
  }
1531
1546
  }`;
@@ -1610,6 +1625,40 @@ const normalizeRuntimeShareCode = `const __mfNormalizeRuntimeShare = (mod) => {
1610
1625
  }
1611
1626
  return current;
1612
1627
  };`;
1628
+ const sharedProviderSelectionHelperCode = `const __mfOriginalProviderKey = Symbol("mf.originalSharedProvider");
1629
+ const __mfResolveShareHook = { emit: (params) => params };
1630
+ const __mfCreateProviderSelectionVersions = (versions, strategy) => {
1631
+ if (strategy !== "version-first") return versions;
1632
+ const selectionVersions = {};
1633
+ for (const [version, provider] of Object.entries(versions)) {
1634
+ selectionVersions[version] = Object.assign({}, provider, {
1635
+ loaded: false,
1636
+ loading: undefined,
1637
+ lib: undefined,
1638
+ [__mfOriginalProviderKey]: provider
1639
+ });
1640
+ }
1641
+ return selectionVersions;
1642
+ };
1643
+ const __mfSelectSharedProvider = (versions, pkg, share, strategy) => {
1644
+ if (!versions || !share) return undefined;
1645
+ const scopes = Array.isArray(share.scope) ? share.scope : [share.scope || "default"];
1646
+ const selectionVersions = __mfCreateProviderSelectionVersions(versions, strategy);
1647
+ const shareScopeMap = {};
1648
+ for (const scope of scopes) {
1649
+ shareScopeMap[scope || "default"] = { [pkg]: selectionVersions };
1650
+ }
1651
+ const selected = runtimeShare.getRegisteredShare(
1652
+ shareScopeMap,
1653
+ pkg,
1654
+ { ...share, scope: scopes, strategy },
1655
+ __mfResolveShareHook
1656
+ )?.shared;
1657
+ return selected?.[__mfOriginalProviderKey] || selected;
1658
+ };`;
1659
+ function hasImportFalseShared$1(options) {
1660
+ return Object.values(options.shared ?? {}).some((share) => share?.shareConfig?.import === false);
1661
+ }
1613
1662
  function generateDirectSharedCacheSeedCode(command = "build") {
1614
1663
  return getOrderedUsedShares().map((pkg) => {
1615
1664
  const shareItem = getShareItemForPreload(pkg);
@@ -1647,6 +1696,7 @@ const SSR_ONLY_PLUGIN_SPECIFIERS = new Set(["@module-federation/vite/ssrEntryLoa
1647
1696
  const isSsrOnlyPlugin = (importStatement) => [...SSR_ONLY_PLUGIN_SPECIFIERS].some((s) => importStatement.includes(s));
1648
1697
  const getSsrOnlyPluginSpecifier = (importStatement) => [...SSR_ONLY_PLUGIN_SPECIFIERS].find((s) => importStatement.includes(s));
1649
1698
  function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(options), command = "build") {
1699
+ const needsSharedProviderSelectionHelper = hasImportFalseShared$1(options);
1650
1700
  const pluginImportNames = options.runtimePlugins.map((p, i) => {
1651
1701
  if (typeof p === "string") return [
1652
1702
  `$runtimePlugin_${i}`,
@@ -1669,6 +1719,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1669
1719
  globalThis.__VUE_HMR_RUNTIME__ = { createRecord() {}, rerender() {}, reload() {} };
1670
1720
  }
1671
1721
  import {init as runtimeInit, loadRemote} from "@module-federation/runtime";
1722
+ ${needsSharedProviderSelectionHelper ? "import {share as runtimeShare} from \"@module-federation/runtime/helpers\";" : ""}
1672
1723
  ${pluginImportNames.filter((item) => !isSsrOnlyPlugin(item[1])).map((item) => item[1]).join("\n")}
1673
1724
  ${command === "build" ? getRuntimeInitResolveBootstrapCode() : getRuntimeInitBootstrapCode() + "\n const { initResolve } = globalThis[globalKey];"}
1674
1725
  ${getRuntimeModuleCacheBootstrapCode()}
@@ -1696,6 +1747,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1696
1747
  }
1697
1748
  }
1698
1749
  }
1750
+ ${needsSharedProviderSelectionHelper ? sharedProviderSelectionHelperCode : ""}
1699
1751
 
1700
1752
  async function getLocalSharedImportMap() {
1701
1753
  if (!localSharedImportMapPromise) {
@@ -1725,7 +1777,14 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1725
1777
  const scopeShare = scopes?.['${options.shareScope}'];
1726
1778
  if (!scopeShare) continue;
1727
1779
  for (const [pkg, versionMap] of Object.entries(scopeShare)) {
1728
- for (const [version, provider] of Object.entries(versionMap)) {
1780
+ const usedShare = usedShared?.[pkg];
1781
+ const selectedProvider = usedShare?.shareConfig?.import === false
1782
+ ? __mfSelectSharedProvider(versionMap, pkg, usedShare, '${options.shareStrategy}')
1783
+ : undefined;
1784
+ const providerEntries = usedShare?.shareConfig?.import === false
1785
+ ? Object.entries(versionMap).filter(([, provider]) => provider === selectedProvider)
1786
+ : Object.entries(versionMap);
1787
+ for (const [version, provider] of providerEntries) {
1729
1788
  if (!provider.lib) continue;
1730
1789
  const cacheKey = __mfGetSharedCacheKey(pkg, provider.shareConfig?.singleton, version, ${JSON.stringify(options.shareScope)});
1731
1790
  if (__mfModuleCache.share[cacheKey] !== undefined) continue;
@@ -1733,7 +1792,6 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1733
1792
  const resolved = await Promise.resolve(mod);
1734
1793
  const normalized = __mfNormalizeRuntimeShare(resolved);
1735
1794
  __mfModuleCache.share[cacheKey] = normalized;
1736
- const usedShare = usedShared?.[pkg];
1737
1795
  if (provider.shareConfig?.singleton && usedShare) {
1738
1796
  const usedCacheKey = __mfGetSharedCacheKey(pkg, usedShare.shareConfig?.singleton, usedShare.version, usedShare.scope);
1739
1797
  if (__mfModuleCache.share[usedCacheKey] === undefined) {
@@ -1795,7 +1853,7 @@ function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(opt
1795
1853
  if (share.shareConfig?.import !== false || __mfModuleCache.share[cacheKey] !== undefined) continue;
1796
1854
  ${normalizeRuntimeShareCode}
1797
1855
  const versions = shared?.[pkg];
1798
- const provider = versions && versions[Object.keys(versions)[0]];
1856
+ const provider = __mfSelectSharedProvider(versions, pkg, share, '${options.shareStrategy}');
1799
1857
  if (!provider) continue;
1800
1858
  const factory = provider.lib || (provider.loading ? await provider.loading : await provider.get?.());
1801
1859
  const mod = typeof factory === "function" ? factory() : factory;
@@ -5160,6 +5218,17 @@ function appendResolveAlias(config, alias) {
5160
5218
  replacement
5161
5219
  })), alias];
5162
5220
  }
5221
+ function hasImportFalseShared(options) {
5222
+ return Object.values(options.shared ?? {}).some((share) => share?.shareConfig?.import === false);
5223
+ }
5224
+ function getRuntimeHelpersImplementation(runtimeImplementation) {
5225
+ const indexEntryMatch = runtimeImplementation.match(/^(.*[\\/])index(\.[cm]?js)$/);
5226
+ if (indexEntryMatch) return `${indexEntryMatch[1]}helpers${indexEntryMatch[2]}`;
5227
+ const extension = path$1.extname(runtimeImplementation);
5228
+ if (extension) return path$1.join(path$1.dirname(runtimeImplementation), `helpers${extension}`);
5229
+ if (path$1.isAbsolute(runtimeImplementation) || runtimeImplementation.startsWith(".")) return path$1.join(runtimeImplementation, "helpers");
5230
+ return `${runtimeImplementation.replace(/\/$/, "")}/helpers`;
5231
+ }
5163
5232
  const UNSAFE_JS_SOURCE_CHAR_MAP = {
5164
5233
  "<": "\\u003C",
5165
5234
  ">": "\\u003E",
@@ -5687,8 +5756,13 @@ function federation(mfUserOptions) {
5687
5756
  config(config, { command: _command }) {
5688
5757
  const isRolldown = getIsRolldown(this);
5689
5758
  isSsrBuild = _command === "build" && config.build?.ssr === true;
5759
+ const needsSharedProviderSelectionHelper = hasImportFalseShared(options);
5760
+ if (needsSharedProviderSelectionHelper) appendResolveAlias(config, {
5761
+ find: /^@module-federation\/runtime\/helpers$/,
5762
+ replacement: getRuntimeHelpersImplementation(options.implementation)
5763
+ });
5690
5764
  appendResolveAlias(config, {
5691
- find: "@module-federation/runtime",
5765
+ find: /^@module-federation\/runtime$/,
5692
5766
  replacement: options.implementation
5693
5767
  });
5694
5768
  config.build ||= {};
@@ -5697,6 +5771,7 @@ function federation(mfUserOptions) {
5697
5771
  config.optimizeDeps ||= {};
5698
5772
  config.optimizeDeps.include ||= [];
5699
5773
  config.optimizeDeps.include.push("@module-federation/runtime");
5774
+ if (needsSharedProviderSelectionHelper) config.optimizeDeps.include.push("@module-federation/runtime/helpers");
5700
5775
  options.runtimePlugins.forEach((p) => {
5701
5776
  const pluginPath = typeof p === "string" ? p : p[0];
5702
5777
  if (SSR_ONLY_PLUGINS.has(pluginPath)) return;
@@ -89,6 +89,22 @@ const _crypto = () => nodeImport("crypto");
89
89
  const _module = () => nodeImport("module");
90
90
  const ssrEntryCache = /* @__PURE__ */ new Map();
91
91
  const manifestFetchCache = /* @__PURE__ */ new Map();
92
+ var SsrEntryHttpError = class extends Error {
93
+ constructor(url, status, statusText, bodyPreview) {
94
+ super(`Failed to fetch SSR module "${url}": ${status} ${statusText}` + (bodyPreview ? `\npreview: ${bodyPreview}` : ""));
95
+ this.url = url;
96
+ this.status = status;
97
+ this.statusText = statusText;
98
+ this.bodyPreview = bodyPreview;
99
+ this.name = "SsrEntryHttpError";
100
+ }
101
+ };
102
+ function getBodyPreview(body) {
103
+ return body.slice(0, 240).replace(/\s+/g, " ").trim();
104
+ }
105
+ function isSsrEntryHttpError(error) {
106
+ return error instanceof SsrEntryHttpError;
107
+ }
92
108
  async function fetchManifest(manifestUrl) {
93
109
  try {
94
110
  const res = await fetch(manifestUrl);
@@ -253,6 +269,9 @@ function transformSsrCode(code, base, sharedPkgMap) {
253
269
  code = code.replace(/\b([A-Za-z_$][\w$]*)\s*\(\s*\(\s*\)\s*=>\s*import\(([^)]*)\)\s*,\s*\[\]\s*\)/g, "import($2)");
254
270
  return code;
255
271
  }
272
+ function isVitePreloadHelperSpecifier(specifier) {
273
+ return specifier.includes("preload-helper");
274
+ }
256
275
  /**
257
276
  * Fetch an HTTP ESM module, transform it, write it to a temp .js file and
258
277
  * return the file path. Recursively does the same for HTTP transitive imports
@@ -262,12 +281,14 @@ async function fetchEsmToTempFile(url, tmpDir, visited, sharedPkgMap) {
262
281
  if (visited.has(url)) return visited.get(url);
263
282
  if (tempFileCache.has(url)) return tempFileCache.get(url);
264
283
  const promise = (async () => {
265
- let code = await (await fetch(url)).text();
284
+ const res = await fetch(url);
285
+ let code = await res.text();
286
+ if (!res.ok) throw new SsrEntryHttpError(url, res.status, res.statusText, getBodyPreview(code));
266
287
  const base = url.replace(/\/[^/]*$/, "/");
267
288
  const relImports = [];
268
289
  const relRegex = /(?:from|export\s*\*\s*from|import\s*(?:\(|\s))\s*["'`]([^"'`\s]+)["'`]/g;
269
290
  let m;
270
- while ((m = relRegex.exec(code)) !== null) if (m[1].startsWith("./") || m[1].startsWith("../")) relImports.push(new URL(m[1], base).href);
291
+ while ((m = relRegex.exec(code)) !== null) if ((m[1].startsWith("./") || m[1].startsWith("../")) && !isVitePreloadHelperSpecifier(m[1])) relImports.push(new URL(m[1], base).href);
271
292
  const subMap = /* @__PURE__ */ new Map();
272
293
  await Promise.all([...new Set(relImports)].filter((u) => u.startsWith("http://") || u.startsWith("https://")).map(async (u) => {
273
294
  const tmpPath = await fetchEsmToTempFile(u, tmpDir, visited, sharedPkgMap);
@@ -322,7 +343,8 @@ async function loadSSRRemoteEntry(ssrEntry, resolvedShared = {}) {
322
343
  const sharedPkgMap = new Map(Object.entries(resolvedShared));
323
344
  try {
324
345
  return await importTempModule(await fetchEsmToTempFile(url, cacheDir, /* @__PURE__ */ new Map(), sharedPkgMap));
325
- } catch {
346
+ } catch (error) {
347
+ if (isSsrEntryHttpError(error)) throw error;
326
348
  return null;
327
349
  }
328
350
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@module-federation/vite",
3
- "version": "1.16.9",
3
+ "version": "1.16.10",
4
4
  "description": "Vite plugin for Module Federation",
5
5
  "type": "module",
6
6
  "main": "./lib/index.js",