@module-federation/vite 1.16.9 → 1.16.11
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 +154 -15
- package/lib/utils/ssrEntryLoader.js +25 -3
- package/package.json +5 -5
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
|
-
|
|
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
|
|
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;
|
|
@@ -2163,6 +2221,12 @@ function getFirstHtmlEntryFile(entryFiles) {
|
|
|
2163
2221
|
function stripQueryAndHash(file) {
|
|
2164
2222
|
return file.split(/[?#]/)[0];
|
|
2165
2223
|
}
|
|
2224
|
+
function resolveDevHashEntryFileName(fileName) {
|
|
2225
|
+
if (!fileName.includes("[hash")) return fileName;
|
|
2226
|
+
const normalized = fileName.replace(/(?:[._-]?\[hash(?::\d+)?\])/g, "");
|
|
2227
|
+
const baseName = path$1.basename(normalized);
|
|
2228
|
+
return path$1.extname(baseName) ? normalized : `${normalized}.js`;
|
|
2229
|
+
}
|
|
2166
2230
|
function getBuildInput(config) {
|
|
2167
2231
|
return config.build?.rollupOptions?.input ?? config.build?.rolldownOptions?.input;
|
|
2168
2232
|
}
|
|
@@ -2386,6 +2450,8 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry", forceClien
|
|
|
2386
2450
|
next();
|
|
2387
2451
|
return;
|
|
2388
2452
|
}
|
|
2453
|
+
const devFileName = resolveDevHashEntryFileName(fileName);
|
|
2454
|
+
if (devFileName !== fileName && req.url?.startsWith((viteConfig.base + devFileName).replace(/^\/?/, "/"))) req.url = req.url.replace(devFileName, fileName);
|
|
2389
2455
|
if (req.url && req.url.startsWith((viteConfig.base + fileName).replace(/^\/?/, "/"))) req.url = devEntryPath;
|
|
2390
2456
|
next();
|
|
2391
2457
|
});
|
|
@@ -3291,7 +3357,13 @@ function rewriteSystemProxyConsumers(code, systemProxyInfo) {
|
|
|
3291
3357
|
return nextCode;
|
|
3292
3358
|
}
|
|
3293
3359
|
function findRemoteEntryFile(filename, bundle) {
|
|
3294
|
-
|
|
3360
|
+
const strippedName = filename.replace(/[\[\]]/g, "_").replace(/\.[^/.]+$/, "");
|
|
3361
|
+
let fallback;
|
|
3362
|
+
for (const fileData of Object.values(bundle)) {
|
|
3363
|
+
if (fileData.fileName === filename) return fileData.fileName;
|
|
3364
|
+
if (fallback === void 0 && (strippedName === fileData.name || fileData.name === "remoteEntry")) fallback = fileData.fileName;
|
|
3365
|
+
}
|
|
3366
|
+
return fallback;
|
|
3295
3367
|
}
|
|
3296
3368
|
//#endregion
|
|
3297
3369
|
//#region src/utils/cssModuleHelpers.ts
|
|
@@ -3641,13 +3713,13 @@ const Manifest = () => {
|
|
|
3641
3713
|
},
|
|
3642
3714
|
configureServer(server) {
|
|
3643
3715
|
server.middlewares.use((req, res, next) => {
|
|
3644
|
-
|
|
3716
|
+
const devRemoteEntryFile = resolveDevRemoteEntryFileName(filename);
|
|
3717
|
+
if (devRemoteEntryFile !== filename && Object.keys(mfOptions.exposes).length > 0 && req.url?.startsWith((viteConfig.base + devRemoteEntryFile).replace(/^\/?/, "/"))) {
|
|
3718
|
+
req.url = req.url.replace(devRemoteEntryFile, filename);
|
|
3645
3719
|
next();
|
|
3646
3720
|
return;
|
|
3647
3721
|
}
|
|
3648
|
-
|
|
3649
|
-
if (devRemoteEntryFile !== filename && req.url?.startsWith((viteConfig.base + devRemoteEntryFile).replace(/^\/?/, "/"))) {
|
|
3650
|
-
req.url = req.url.replace(devRemoteEntryFile, filename);
|
|
3722
|
+
if (!mfManifestName) {
|
|
3651
3723
|
next();
|
|
3652
3724
|
return;
|
|
3653
3725
|
}
|
|
@@ -4424,7 +4496,6 @@ function proxySharedModule(options) {
|
|
|
4424
4496
|
//#endregion
|
|
4425
4497
|
//#region src/plugins/pluginRemoteNamedExports.ts
|
|
4426
4498
|
const JS_EXTENSIONS_RE = /\.(?:[mc]?[jt]sx?|vue|svelte)(?:\?|$)/;
|
|
4427
|
-
const REGEX_FALLBACK_EXTENSIONS_RE = /\.(?:[mc]?[jt]sx?)(?:\?|$)/;
|
|
4428
4499
|
function isAstNode(value) {
|
|
4429
4500
|
return !!value && typeof value === "object" && typeof value.type === "string";
|
|
4430
4501
|
}
|
|
@@ -4621,10 +4692,12 @@ async function collectFromAST(ast, code, isRemoteImport) {
|
|
|
4621
4692
|
}
|
|
4622
4693
|
function collectFromRegex(code, isRemoteImport) {
|
|
4623
4694
|
const result = [];
|
|
4695
|
+
const codePositions = createCodePositionMap(code);
|
|
4624
4696
|
const importAttributes = String.raw`(?:\s+(?:with|assert)\s+\{[^;]*\})?`;
|
|
4625
4697
|
const staticRe = new RegExp(String.raw`^\s*import\s+([\s\S]*?)\s+from\s+(['"])([^'"]+)\2${importAttributes}\s*;?`, "gm");
|
|
4626
4698
|
for (const match of code.matchAll(staticRe)) {
|
|
4627
4699
|
const [full, specifiersPartRaw, , source] = match;
|
|
4700
|
+
if (!codePositions[match.index]) continue;
|
|
4628
4701
|
if (!isRemoteImport(source)) continue;
|
|
4629
4702
|
const specifiersPart = specifiersPartRaw.trim();
|
|
4630
4703
|
if (/^type\s/.test(specifiersPart)) continue;
|
|
@@ -4657,6 +4730,7 @@ function collectFromRegex(code, isRemoteImport) {
|
|
|
4657
4730
|
const reexportRe = new RegExp(String.raw`^\s*export\s+\{([\s\S]*?)\}\s+from\s+(['"])([^'"]+)\2${importAttributes}\s*;?`, "gm");
|
|
4658
4731
|
for (const match of code.matchAll(reexportRe)) {
|
|
4659
4732
|
const [full, specifiersRaw, , source] = match;
|
|
4733
|
+
if (!codePositions[match.index]) continue;
|
|
4660
4734
|
if (!isRemoteImport(source)) continue;
|
|
4661
4735
|
const specifiers = parseNamedSpecifiers(specifiersRaw, "export");
|
|
4662
4736
|
if (specifiers.length === 0) continue;
|
|
@@ -4671,6 +4745,7 @@ function collectFromRegex(code, isRemoteImport) {
|
|
|
4671
4745
|
const exportAllRe = new RegExp(String.raw`^\s*export\s+\*\s+from\s+(['"])([^'"]+)\1${importAttributes}\s*;?`, "gm");
|
|
4672
4746
|
for (const match of code.matchAll(exportAllRe)) {
|
|
4673
4747
|
const [full, , source] = match;
|
|
4748
|
+
if (!codePositions[match.index]) continue;
|
|
4674
4749
|
if (!isRemoteImport(source)) continue;
|
|
4675
4750
|
result.push({
|
|
4676
4751
|
kind: "export-all",
|
|
@@ -4681,6 +4756,7 @@ function collectFromRegex(code, isRemoteImport) {
|
|
|
4681
4756
|
}
|
|
4682
4757
|
for (const match of code.matchAll(/import\(\s*(?:\/\*[\s\S]*?\*\/\s*)?(['"])([^'"]+)\1\s*\)/g)) {
|
|
4683
4758
|
const [full, , source] = match;
|
|
4759
|
+
if (!codePositions[match.index]) continue;
|
|
4684
4760
|
if (!isRemoteImport(source)) continue;
|
|
4685
4761
|
result.push({
|
|
4686
4762
|
kind: "dynamic",
|
|
@@ -4691,6 +4767,50 @@ function collectFromRegex(code, isRemoteImport) {
|
|
|
4691
4767
|
}
|
|
4692
4768
|
return result.length > 0 ? result : void 0;
|
|
4693
4769
|
}
|
|
4770
|
+
function createCodePositionMap(code) {
|
|
4771
|
+
const positions = Array(code.length).fill(true);
|
|
4772
|
+
function mask(start, end) {
|
|
4773
|
+
for (let i = start; i < end; i++) positions[i] = false;
|
|
4774
|
+
}
|
|
4775
|
+
for (let i = 0; i < code.length;) {
|
|
4776
|
+
const char = code[i];
|
|
4777
|
+
const next = code[i + 1];
|
|
4778
|
+
if (char === "/" && next === "/") {
|
|
4779
|
+
const start = i;
|
|
4780
|
+
i += 2;
|
|
4781
|
+
while (i < code.length && code[i] !== "\n" && code[i] !== "\r") i++;
|
|
4782
|
+
mask(start, i);
|
|
4783
|
+
continue;
|
|
4784
|
+
}
|
|
4785
|
+
if (char === "/" && next === "*") {
|
|
4786
|
+
const start = i;
|
|
4787
|
+
i += 2;
|
|
4788
|
+
while (i < code.length && !(code[i] === "*" && code[i + 1] === "/")) i++;
|
|
4789
|
+
i = Math.min(code.length, i + 2);
|
|
4790
|
+
mask(start, i);
|
|
4791
|
+
continue;
|
|
4792
|
+
}
|
|
4793
|
+
if (char === "\"" || char === "'" || char === "`") {
|
|
4794
|
+
const quote = char;
|
|
4795
|
+
const start = i++;
|
|
4796
|
+
while (i < code.length) {
|
|
4797
|
+
if (code[i] === "\\") {
|
|
4798
|
+
i += 2;
|
|
4799
|
+
continue;
|
|
4800
|
+
}
|
|
4801
|
+
if (code[i] === quote) {
|
|
4802
|
+
i++;
|
|
4803
|
+
break;
|
|
4804
|
+
}
|
|
4805
|
+
i++;
|
|
4806
|
+
}
|
|
4807
|
+
mask(start, i);
|
|
4808
|
+
continue;
|
|
4809
|
+
}
|
|
4810
|
+
i++;
|
|
4811
|
+
}
|
|
4812
|
+
return positions;
|
|
4813
|
+
}
|
|
4694
4814
|
function pluginRemoteNamedExports(options) {
|
|
4695
4815
|
const remoteNames = Object.keys(options.remotes);
|
|
4696
4816
|
const isNodeModulesId = (id) => id.includes("/node_modules/") || id.includes("\\node_modules\\");
|
|
@@ -4717,7 +4837,6 @@ function pluginRemoteNamedExports(options) {
|
|
|
4717
4837
|
if ((id.includes(".vue") || id.includes(".svelte")) && /^\s*</.test(code)) return;
|
|
4718
4838
|
imports = collectFromRegex(code, matchesRemoteImport);
|
|
4719
4839
|
}
|
|
4720
|
-
if ((!imports || imports.length === 0) && REGEX_FALLBACK_EXTENSIONS_RE.test(id)) imports = collectFromRegex(code, matchesRemoteImport);
|
|
4721
4840
|
if (!imports) return;
|
|
4722
4841
|
return applyRewrites(code, imports, id);
|
|
4723
4842
|
}
|
|
@@ -5122,18 +5241,21 @@ function normalizeVinextRscPreloadHints(code) {
|
|
|
5122
5241
|
}
|
|
5123
5242
|
function ignoreFederationGeneratedFiles(config, options) {
|
|
5124
5243
|
config.server ??= {};
|
|
5125
|
-
config.server.watch
|
|
5244
|
+
const watch = config.server.watch;
|
|
5245
|
+
if (watch === false || watch === null) return;
|
|
5246
|
+
const watchOptions = watch === true || watch === void 0 ? {} : watch;
|
|
5247
|
+
config.server.watch = watchOptions;
|
|
5126
5248
|
const federationIgnore = (file) => shouldIgnoreFile(file, options);
|
|
5127
|
-
const ignored =
|
|
5249
|
+
const ignored = watchOptions.ignored;
|
|
5128
5250
|
if (!ignored) {
|
|
5129
|
-
|
|
5251
|
+
watchOptions.ignored = federationIgnore;
|
|
5130
5252
|
return;
|
|
5131
5253
|
}
|
|
5132
5254
|
if (Array.isArray(ignored)) {
|
|
5133
5255
|
ignored.push(federationIgnore);
|
|
5134
5256
|
return;
|
|
5135
5257
|
}
|
|
5136
|
-
|
|
5258
|
+
watchOptions.ignored = [ignored, federationIgnore];
|
|
5137
5259
|
}
|
|
5138
5260
|
function isSharedResolverInternalImporter(importer) {
|
|
5139
5261
|
return !!importer && (importer.includes("__loadShare__") || importer.includes("__prebuild__"));
|
|
@@ -5160,6 +5282,17 @@ function appendResolveAlias(config, alias) {
|
|
|
5160
5282
|
replacement
|
|
5161
5283
|
})), alias];
|
|
5162
5284
|
}
|
|
5285
|
+
function hasImportFalseShared(options) {
|
|
5286
|
+
return Object.values(options.shared ?? {}).some((share) => share?.shareConfig?.import === false);
|
|
5287
|
+
}
|
|
5288
|
+
function getRuntimeHelpersImplementation(runtimeImplementation) {
|
|
5289
|
+
const indexEntryMatch = runtimeImplementation.match(/^(.*[\\/])index(\.[cm]?js)$/);
|
|
5290
|
+
if (indexEntryMatch) return `${indexEntryMatch[1]}helpers${indexEntryMatch[2]}`;
|
|
5291
|
+
const extension = path$1.extname(runtimeImplementation);
|
|
5292
|
+
if (extension) return path$1.join(path$1.dirname(runtimeImplementation), `helpers${extension}`);
|
|
5293
|
+
if (path$1.isAbsolute(runtimeImplementation) || runtimeImplementation.startsWith(".")) return path$1.join(runtimeImplementation, "helpers");
|
|
5294
|
+
return `${runtimeImplementation.replace(/\/$/, "")}/helpers`;
|
|
5295
|
+
}
|
|
5163
5296
|
const UNSAFE_JS_SOURCE_CHAR_MAP = {
|
|
5164
5297
|
"<": "\\u003C",
|
|
5165
5298
|
">": "\\u003E",
|
|
@@ -5687,8 +5820,13 @@ function federation(mfUserOptions) {
|
|
|
5687
5820
|
config(config, { command: _command }) {
|
|
5688
5821
|
const isRolldown = getIsRolldown(this);
|
|
5689
5822
|
isSsrBuild = _command === "build" && config.build?.ssr === true;
|
|
5823
|
+
const needsSharedProviderSelectionHelper = hasImportFalseShared(options);
|
|
5824
|
+
if (needsSharedProviderSelectionHelper) appendResolveAlias(config, {
|
|
5825
|
+
find: /^@module-federation\/runtime\/helpers$/,
|
|
5826
|
+
replacement: getRuntimeHelpersImplementation(options.implementation)
|
|
5827
|
+
});
|
|
5690
5828
|
appendResolveAlias(config, {
|
|
5691
|
-
find:
|
|
5829
|
+
find: /^@module-federation\/runtime$/,
|
|
5692
5830
|
replacement: options.implementation
|
|
5693
5831
|
});
|
|
5694
5832
|
config.build ||= {};
|
|
@@ -5697,6 +5835,7 @@ function federation(mfUserOptions) {
|
|
|
5697
5835
|
config.optimizeDeps ||= {};
|
|
5698
5836
|
config.optimizeDeps.include ||= [];
|
|
5699
5837
|
config.optimizeDeps.include.push("@module-federation/runtime");
|
|
5838
|
+
if (needsSharedProviderSelectionHelper) config.optimizeDeps.include.push("@module-federation/runtime/helpers");
|
|
5700
5839
|
options.runtimePlugins.forEach((p) => {
|
|
5701
5840
|
const pluginPath = typeof p === "string" ? p : p[0];
|
|
5702
5841
|
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
|
-
|
|
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.
|
|
3
|
+
"version": "1.16.11",
|
|
4
4
|
"description": "Vite plugin for Module Federation",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./lib/index.js",
|
|
@@ -70,9 +70,9 @@
|
|
|
70
70
|
"vite": "^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0"
|
|
71
71
|
},
|
|
72
72
|
"dependencies": {
|
|
73
|
-
"@module-federation/dts-plugin": "2.
|
|
74
|
-
"@module-federation/runtime": "2.
|
|
75
|
-
"@module-federation/sdk": "2.
|
|
73
|
+
"@module-federation/dts-plugin": "2.6.0",
|
|
74
|
+
"@module-federation/runtime": "2.6.0",
|
|
75
|
+
"@module-federation/sdk": "2.6.0"
|
|
76
76
|
},
|
|
77
77
|
"devDependencies": {
|
|
78
78
|
"@playwright/test": "1.58.2",
|
|
@@ -83,7 +83,7 @@
|
|
|
83
83
|
"rollup": "4.47.1",
|
|
84
84
|
"tsdown": "0.21.0",
|
|
85
85
|
"typescript": "5.9.3",
|
|
86
|
-
"vite": "8.0
|
|
86
|
+
"vite": "8.1.0",
|
|
87
87
|
"vitest": "4.0.18"
|
|
88
88
|
}
|
|
89
89
|
}
|