@module-federation/vite 1.13.4 → 1.13.6
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/README.md +42 -11
- package/lib/index.cjs +501 -82
- package/lib/index.d.cts +3 -3
- package/lib/index.d.mts +3 -3
- package/lib/index.mjs +501 -82
- package/package.json +10 -7
package/lib/index.cjs
CHANGED
|
@@ -36,6 +36,7 @@ let _module_federation_dts_plugin = require("@module-federation/dts-plugin");
|
|
|
36
36
|
let _module_federation_dts_plugin_core = require("@module-federation/dts-plugin/core");
|
|
37
37
|
let node_module = require("node:module");
|
|
38
38
|
let url = require("url");
|
|
39
|
+
let es_module_lexer = require("es-module-lexer");
|
|
39
40
|
//#region src/utils/mapCodeToCodeWithSourcemap.ts
|
|
40
41
|
async function mapCodeToCodeWithSourcemap(code) {
|
|
41
42
|
const resolvedCode = await code;
|
|
@@ -151,11 +152,13 @@ function removePathFromNpmPackage(packageString) {
|
|
|
151
152
|
return match ? match[0] : packageString;
|
|
152
153
|
}
|
|
153
154
|
/**
|
|
154
|
-
* Detect whether the current
|
|
155
|
-
*
|
|
155
|
+
* Detect whether the current runtime is Vite 8+ by checking for a Vite version flag
|
|
156
|
+
* on the plugin hook context, with Rolldown metadata kept as a compatibility fallback.
|
|
156
157
|
*/
|
|
157
158
|
function getIsRolldown(ctx) {
|
|
158
|
-
|
|
159
|
+
const viteVersion = ctx?.meta?.viteVersion;
|
|
160
|
+
const viteMajor = Number(String(viteVersion ?? "").split(".")[0]);
|
|
161
|
+
return Number.isFinite(viteMajor) && viteMajor >= 8 || !!ctx?.meta?.rolldownVersion;
|
|
159
162
|
}
|
|
160
163
|
function hasPackageDependency(dependencyName, cwd = packageDetectionCwd || process.cwd()) {
|
|
161
164
|
const cacheKey = getDependencyCacheKey(cwd, dependencyName);
|
|
@@ -380,15 +383,17 @@ function checkAliasConflicts(options) {
|
|
|
380
383
|
};
|
|
381
384
|
}
|
|
382
385
|
//#endregion
|
|
383
|
-
//#region src/
|
|
384
|
-
/**
|
|
385
|
-
* Solve the problem that dev mode dependency prebunding does not support top-level await syntax
|
|
386
|
-
*/
|
|
386
|
+
//#region src/utils/loadWalk.ts
|
|
387
387
|
let walkPromise = null;
|
|
388
388
|
function loadWalk() {
|
|
389
389
|
walkPromise ||= import("estree-walker").then(({ walk }) => walk);
|
|
390
390
|
return walkPromise;
|
|
391
391
|
}
|
|
392
|
+
//#endregion
|
|
393
|
+
//#region src/plugins/pluginDevProxyModuleTopLevelAwait.ts
|
|
394
|
+
/**
|
|
395
|
+
* Solve the problem that dev mode dependency prebunding does not support top-level await syntax
|
|
396
|
+
*/
|
|
392
397
|
function PluginDevProxyModuleTopLevelAwait() {
|
|
393
398
|
const filterFunction = (0, _rollup_pluginutils.createFilter)();
|
|
394
399
|
const processedFlag = "/* already-processed-by-dev-proxy-module-top-level-await */";
|
|
@@ -803,13 +808,13 @@ function normalizeLibrary(library) {
|
|
|
803
808
|
if (!library) return void 0;
|
|
804
809
|
return library;
|
|
805
810
|
}
|
|
806
|
-
function normalizeManifest(manifest
|
|
811
|
+
function normalizeManifest(manifest) {
|
|
812
|
+
if (manifest === void 0) return;
|
|
807
813
|
if (typeof manifest === "boolean") return manifest;
|
|
808
|
-
return
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
|
|
812
|
-
}, manifest);
|
|
814
|
+
return {
|
|
815
|
+
...manifest,
|
|
816
|
+
fileName: manifest.fileName || "mf-manifest.json"
|
|
817
|
+
};
|
|
813
818
|
}
|
|
814
819
|
let config;
|
|
815
820
|
function getNormalizeModuleFederationOptions() {
|
|
@@ -1197,7 +1202,7 @@ function generateRemotes(id, command, isRolldown) {
|
|
|
1197
1202
|
const importLine = command === "build" ? getRuntimeInitPromiseBootstrapCode() : useESM ? `${getRuntimeInitBootstrapCode()}
|
|
1198
1203
|
const { initPromise } = globalThis[globalKey];` : `const {initPromise} = require("${virtualRuntimeInitStatus.getImportId()}")`;
|
|
1199
1204
|
const awaitOrPlaceholder = useESM ? "await " : "/*mf top-level-await placeholder replacement mf*/";
|
|
1200
|
-
const exportLine = command === "serve" && useESM ? "export default exportModule.default ?? exportModule" : useESM ? "export default exportModule" : "module.exports = exportModule";
|
|
1205
|
+
const exportLine = command === "serve" && useESM ? "export const __moduleExports = exportModule;\nexport default exportModule.default ?? exportModule" : useESM ? "export default exportModule" : "module.exports = exportModule";
|
|
1201
1206
|
return `
|
|
1202
1207
|
${importLine}
|
|
1203
1208
|
const res = initPromise.then(runtime => runtime.loadRemote(${JSON.stringify(id)}))
|
|
@@ -1228,6 +1233,9 @@ function escapeGeneratedStringLiteral(value) {
|
|
|
1228
1233
|
}
|
|
1229
1234
|
});
|
|
1230
1235
|
}
|
|
1236
|
+
function isValidJsIdentifier(name) {
|
|
1237
|
+
return /^[$_\p{ID_Start}][$_\u200C\u200D\p{ID_Continue}]*$/u.test(name);
|
|
1238
|
+
}
|
|
1231
1239
|
const localRequire = (0, module$1.createRequire)(require("url").pathToFileURL(__filename).href);
|
|
1232
1240
|
function resolvePackageEntryFromProjectRoot(pkg) {
|
|
1233
1241
|
try {
|
|
@@ -1311,7 +1319,7 @@ function getEsmNamedExports(pkg) {
|
|
|
1311
1319
|
const { initSync, parse } = localRequire("es-module-lexer");
|
|
1312
1320
|
initSync();
|
|
1313
1321
|
const [, exports] = parse((0, fs.readFileSync)(entryPath, "utf-8"), entryPath);
|
|
1314
|
-
return exports.map((item) => item.n).filter((name) => !!name && name !== "default" && name !== "__esModule" &&
|
|
1322
|
+
return exports.map((item) => item.n).filter((name) => !!name && name !== "default" && name !== "__esModule" && isValidJsIdentifier(name));
|
|
1315
1323
|
} catch {
|
|
1316
1324
|
return [];
|
|
1317
1325
|
}
|
|
@@ -1319,7 +1327,7 @@ function getEsmNamedExports(pkg) {
|
|
|
1319
1327
|
function getPackageNamedExports(pkg) {
|
|
1320
1328
|
try {
|
|
1321
1329
|
const mod = (0, module$1.createRequire)(new URL(`file://${pathe.default.join(getPackageDetectionCwd(), "package.json")}`))(pkg);
|
|
1322
|
-
return Object.keys(mod).filter((k) => k !== "default" && k !== "__esModule" &&
|
|
1330
|
+
return Object.keys(mod).filter((k) => k !== "default" && k !== "__esModule" && isValidJsIdentifier(k));
|
|
1323
1331
|
} catch {
|
|
1324
1332
|
return getEsmNamedExports(pkg);
|
|
1325
1333
|
}
|
|
@@ -1408,7 +1416,9 @@ function writeLoadShareModule(pkg, shareItem, command, isRolldown) {
|
|
|
1408
1416
|
`, true);
|
|
1409
1417
|
return;
|
|
1410
1418
|
}
|
|
1411
|
-
const
|
|
1419
|
+
const isVinext = hasPackageDependency("vinext");
|
|
1420
|
+
const isAstro = hasPackageDependency("astro");
|
|
1421
|
+
const useSsrProviderFallback = (isVinext || isAstro) && command === "build" && pkg === "react";
|
|
1412
1422
|
const concreteSharedImportSource = getConcreteSharedImportSource(pkg, shareItem);
|
|
1413
1423
|
const sharedImportSource = concreteSharedImportSource || getPreBuildLibImportId(pkg);
|
|
1414
1424
|
const devImportSource = concreteSharedImportSource || pkg;
|
|
@@ -1463,6 +1473,8 @@ function writeLocalSharedImportMap() {
|
|
|
1463
1473
|
}
|
|
1464
1474
|
function generateLocalSharedImportMap() {
|
|
1465
1475
|
const isVinext = hasPackageDependency("vinext");
|
|
1476
|
+
const isAstro = hasPackageDependency("astro");
|
|
1477
|
+
const useDirectReactImport = isVinext || isAstro;
|
|
1466
1478
|
const options = getNormalizeModuleFederationOptions();
|
|
1467
1479
|
return `
|
|
1468
1480
|
import {loadShare} from "@module-federation/runtime";
|
|
@@ -1471,7 +1483,7 @@ function generateLocalSharedImportMap() {
|
|
|
1471
1483
|
const shareItem = getNormalizeShareItem(pkg);
|
|
1472
1484
|
return `
|
|
1473
1485
|
${JSON.stringify(pkg)}: async () => {
|
|
1474
|
-
${shareItem?.shareConfig.import === false ? `throw new Error(\`[Module Federation] Shared module '\${${JSON.stringify(pkg)}}' must be provided by host\`);` :
|
|
1486
|
+
${shareItem?.shareConfig.import === false ? `throw new Error(\`[Module Federation] Shared module '\${${JSON.stringify(pkg)}}' must be provided by host\`);` : useDirectReactImport && pkg === "react" ? `let pkg = await import("react");
|
|
1475
1487
|
return pkg;` : `let pkg = await import(${JSON.stringify(getSharedImportSource(pkg, shareItem))});
|
|
1476
1488
|
return pkg;`}
|
|
1477
1489
|
}
|
|
@@ -1496,7 +1508,7 @@ function generateLocalSharedImportMap() {
|
|
|
1496
1508
|
usedShared[${JSON.stringify(key)}].loaded = true
|
|
1497
1509
|
const {${JSON.stringify(key)}: pkgDynamicImport} = importMap
|
|
1498
1510
|
const res = await pkgDynamicImport()
|
|
1499
|
-
const exportModule = ${JSON.stringify(
|
|
1511
|
+
const exportModule = ${JSON.stringify(useDirectReactImport)} && ${JSON.stringify(key)} === "react"
|
|
1500
1512
|
? (res?.default ?? res)
|
|
1501
1513
|
: {...res}
|
|
1502
1514
|
// All npm packages pre-built by vite will be converted to esm
|
|
@@ -1811,7 +1823,7 @@ const buildFileToShareKeyMap = async (shareKeys, resolveFn) => {
|
|
|
1811
1823
|
* @returns The resolved public path
|
|
1812
1824
|
*/
|
|
1813
1825
|
function resolvePublicPath(options, viteBase, originalBase) {
|
|
1814
|
-
if (options.publicPath) return options.publicPath;
|
|
1826
|
+
if (options.publicPath && options.publicPath !== "auto") return options.publicPath;
|
|
1815
1827
|
if (originalBase === "") return "auto";
|
|
1816
1828
|
if (viteBase) return viteBase.replace(/\/?$/, "/");
|
|
1817
1829
|
return "auto";
|
|
@@ -1821,9 +1833,17 @@ function resolvePublicPath(options, viteBase, originalBase) {
|
|
|
1821
1833
|
const Manifest = () => {
|
|
1822
1834
|
const mfOptions = getNormalizeModuleFederationOptions();
|
|
1823
1835
|
const { name, filename, getPublicPath, manifest: manifestOptions, varFilename } = mfOptions;
|
|
1824
|
-
let mfManifestName = "";
|
|
1825
|
-
|
|
1826
|
-
|
|
1836
|
+
let mfManifestName = manifestOptions === true ? "mf-manifest.json" : typeof manifestOptions === "object" ? pathe.join(manifestOptions?.filePath || "", manifestOptions?.fileName || "mf-manifest.json") : void 0;
|
|
1837
|
+
let mfManifestStatsName = mfManifestName ? getStatsFileName(mfManifestName) : void 0;
|
|
1838
|
+
const isConsumerProject = Object.keys(mfOptions.exposes).length === 0;
|
|
1839
|
+
let disableAssetsAnalyze = false;
|
|
1840
|
+
const getDefaultDisableAssetsAnalyze = (command) => command === "serve" && isConsumerProject && (typeof manifestOptions !== "object" || !Object.prototype.hasOwnProperty.call(manifestOptions, "disableAssetsAnalyze"));
|
|
1841
|
+
const getConfiguredDisableAssetsAnalyze = (command) => {
|
|
1842
|
+
if (typeof manifestOptions === "object" && manifestOptions !== null) {
|
|
1843
|
+
if (Object.prototype.hasOwnProperty.call(manifestOptions, "disableAssetsAnalyze")) return manifestOptions.disableAssetsAnalyze === true;
|
|
1844
|
+
}
|
|
1845
|
+
return getDefaultDisableAssetsAnalyze(command);
|
|
1846
|
+
};
|
|
1827
1847
|
let root;
|
|
1828
1848
|
let remoteEntryFile;
|
|
1829
1849
|
let publicPath;
|
|
@@ -1858,7 +1878,7 @@ const Manifest = () => {
|
|
|
1858
1878
|
res.setHeader("Content-Type", "application/json");
|
|
1859
1879
|
res.setHeader("Access-Control-Allow-Origin", "*");
|
|
1860
1880
|
res.end(JSON.stringify({
|
|
1861
|
-
...generateMFManifest({}),
|
|
1881
|
+
...generateMFManifest({}, disableAssetsAnalyze),
|
|
1862
1882
|
id: name,
|
|
1863
1883
|
name,
|
|
1864
1884
|
metaData: {
|
|
@@ -1899,9 +1919,10 @@ const Manifest = () => {
|
|
|
1899
1919
|
name: "module-federation-manifest",
|
|
1900
1920
|
enforce: "post",
|
|
1901
1921
|
config(config, { command }) {
|
|
1902
|
-
if (!config.build) config.build = {};
|
|
1903
|
-
if (!config.build.manifest) config.build.manifest = config.build.manifest || !!manifestOptions;
|
|
1904
1922
|
_command = command;
|
|
1923
|
+
if (!config.build) config.build = {};
|
|
1924
|
+
if (!config.build.manifest) config.build.manifest = config.build.manifest || !!mfManifestName;
|
|
1925
|
+
disableAssetsAnalyze = getConfiguredDisableAssetsAnalyze(command);
|
|
1905
1926
|
_originalConfigBase = config.base;
|
|
1906
1927
|
},
|
|
1907
1928
|
configResolved(config) {
|
|
@@ -1915,28 +1936,35 @@ const Manifest = () => {
|
|
|
1915
1936
|
let filesMap = {};
|
|
1916
1937
|
const foundRemoteEntryFile = findRemoteEntryFile(mfOptions.filename, bundle);
|
|
1917
1938
|
if (foundRemoteEntryFile) remoteEntryFile = foundRemoteEntryFile;
|
|
1918
|
-
const allCssAssets = mfOptions.bundleAllCSS ? collectCssAssets(bundle) : /* @__PURE__ */ new Set();
|
|
1919
|
-
|
|
1920
|
-
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
const
|
|
1927
|
-
|
|
1928
|
-
|
|
1929
|
-
|
|
1939
|
+
const allCssAssets = mfOptions.bundleAllCSS && !disableAssetsAnalyze ? collectCssAssets(bundle) : /* @__PURE__ */ new Set();
|
|
1940
|
+
if (!disableAssetsAnalyze) {
|
|
1941
|
+
const exposesModules = Object.keys(mfOptions.exposes).map((item) => mfOptions.exposes[item].import);
|
|
1942
|
+
processModuleAssets(bundle, filesMap, (modulePath) => {
|
|
1943
|
+
const absoluteModulePath = pathe.resolve(root, modulePath);
|
|
1944
|
+
return exposesModules.find((exposeModule) => {
|
|
1945
|
+
const exposePath = pathe.resolve(root, exposeModule);
|
|
1946
|
+
if (absoluteModulePath === exposePath) return true;
|
|
1947
|
+
const getPathWithoutKnownExt = (filePath) => {
|
|
1948
|
+
const ext = pathe.extname(filePath);
|
|
1949
|
+
return JS_EXTENSIONS.includes(ext) ? pathe.join(pathe.dirname(filePath), pathe.basename(filePath, ext)) : filePath;
|
|
1950
|
+
};
|
|
1951
|
+
return getPathWithoutKnownExt(absoluteModulePath) === getPathWithoutKnownExt(exposePath);
|
|
1952
|
+
});
|
|
1930
1953
|
});
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1935
|
-
|
|
1954
|
+
const fileToShareKey = await buildFileToShareKeyMap(getUsedShares(), this.resolve.bind(this));
|
|
1955
|
+
processModuleAssets(bundle, filesMap, (modulePath) => fileToShareKey.get(modulePath));
|
|
1956
|
+
if (mfOptions.bundleAllCSS) addCssAssetsToAllExports(filesMap, allCssAssets);
|
|
1957
|
+
filesMap = deduplicateAssets(filesMap);
|
|
1958
|
+
}
|
|
1936
1959
|
this.emitFile({
|
|
1937
1960
|
type: "asset",
|
|
1938
1961
|
fileName: mfManifestName,
|
|
1939
|
-
source: JSON.stringify(generateMFManifest(filesMap))
|
|
1962
|
+
source: JSON.stringify(generateMFManifest(filesMap, disableAssetsAnalyze))
|
|
1963
|
+
});
|
|
1964
|
+
if (mfManifestStatsName) this.emitFile({
|
|
1965
|
+
type: "asset",
|
|
1966
|
+
fileName: mfManifestStatsName,
|
|
1967
|
+
source: JSON.stringify(generateMFStats(filesMap, bundle, disableAssetsAnalyze))
|
|
1940
1968
|
});
|
|
1941
1969
|
}
|
|
1942
1970
|
}];
|
|
@@ -1945,7 +1973,7 @@ const Manifest = () => {
|
|
|
1945
1973
|
* @param preloadMap - Map of module assets to include
|
|
1946
1974
|
* @returns Complete manifest object
|
|
1947
1975
|
*/
|
|
1948
|
-
function generateMFManifest(preloadMap) {
|
|
1976
|
+
function generateMFManifest(preloadMap, disableAssetsAnalyze = false) {
|
|
1949
1977
|
const options = getNormalizeModuleFederationOptions();
|
|
1950
1978
|
const { name, varFilename } = options;
|
|
1951
1979
|
const remoteEntry = {
|
|
@@ -1971,6 +1999,7 @@ const Manifest = () => {
|
|
|
1971
1999
|
id: `${name}:${shareKey}`,
|
|
1972
2000
|
name: shareKey,
|
|
1973
2001
|
version: shareItem.version,
|
|
2002
|
+
singleton: shareItem.shareConfig.singleton,
|
|
1974
2003
|
requiredVersion: shareItem.shareConfig.requiredVersion,
|
|
1975
2004
|
assets: {
|
|
1976
2005
|
js: {
|
|
@@ -2024,12 +2053,33 @@ const Manifest = () => {
|
|
|
2024
2053
|
pluginVersion: "0.2.5",
|
|
2025
2054
|
...!!getPublicPath ? { getPublicPath } : { publicPath }
|
|
2026
2055
|
},
|
|
2027
|
-
shared,
|
|
2056
|
+
...disableAssetsAnalyze ? {} : { shared },
|
|
2028
2057
|
remotes,
|
|
2029
|
-
exposes
|
|
2058
|
+
...disableAssetsAnalyze ? {} : { exposes }
|
|
2059
|
+
};
|
|
2060
|
+
}
|
|
2061
|
+
function generateMFStats(preloadMap, bundle, disableAssetsAnalyze = false) {
|
|
2062
|
+
const baseManifest = generateMFManifest(preloadMap, disableAssetsAnalyze);
|
|
2063
|
+
const bundleSummary = Object.entries(bundle).map(([fileName, chunkOrAsset]) => ({
|
|
2064
|
+
fileName,
|
|
2065
|
+
type: chunkOrAsset.type,
|
|
2066
|
+
isEntry: chunkOrAsset.isEntry || false,
|
|
2067
|
+
size: typeof chunkOrAsset.code === "string" ? chunkOrAsset.code.length : chunkOrAsset.source?.length || chunkOrAsset.source?.byteLength || void 0
|
|
2068
|
+
}));
|
|
2069
|
+
return {
|
|
2070
|
+
...baseManifest,
|
|
2071
|
+
buildOutput: bundleSummary,
|
|
2072
|
+
...disableAssetsAnalyze ? {} : { assetAnalysis: preloadMap }
|
|
2030
2073
|
};
|
|
2031
2074
|
}
|
|
2032
2075
|
};
|
|
2076
|
+
function getStatsFileName(manifestFileName) {
|
|
2077
|
+
const parsed = pathe.parse(manifestFileName);
|
|
2078
|
+
const fileExt = parsed.ext || ".json";
|
|
2079
|
+
const baseName = parsed.ext ? parsed.name : parsed.base;
|
|
2080
|
+
const fileName = `${baseName === "mf-manifest" ? "mf" : baseName}-stats${fileExt}`;
|
|
2081
|
+
return parsed.dir ? pathe.join(parsed.dir, fileName) : fileName;
|
|
2082
|
+
}
|
|
2033
2083
|
//#endregion
|
|
2034
2084
|
//#region src/plugins/pluginModuleParseEnd.ts
|
|
2035
2085
|
let _resolve, _parseTimeout;
|
|
@@ -2274,7 +2324,7 @@ function proxySharedModule(options) {
|
|
|
2274
2324
|
const { shared = {} } = options;
|
|
2275
2325
|
let _config;
|
|
2276
2326
|
let _command = "serve";
|
|
2277
|
-
let
|
|
2327
|
+
let useDirectReactImport = false;
|
|
2278
2328
|
const savePrebuild = new PromiseStore();
|
|
2279
2329
|
return [{
|
|
2280
2330
|
name: "generateLocalSharedImportMap",
|
|
@@ -2290,10 +2340,12 @@ function proxySharedModule(options) {
|
|
|
2290
2340
|
enforce: "post",
|
|
2291
2341
|
config(config, { command }) {
|
|
2292
2342
|
setPackageDetectionCwd(config.root || process.cwd());
|
|
2293
|
-
isVinext = hasPackageDependency("vinext");
|
|
2343
|
+
const isVinext = hasPackageDependency("vinext");
|
|
2344
|
+
const isAstro = hasPackageDependency("astro");
|
|
2294
2345
|
const isRolldown = getIsRolldown(this);
|
|
2295
2346
|
_command = command;
|
|
2296
|
-
|
|
2347
|
+
useDirectReactImport = isVinext || isAstro;
|
|
2348
|
+
config.resolve.alias.push(...Object.keys(shared).filter((key) => !(useDirectReactImport && key === "react")).map((key) => {
|
|
2297
2349
|
const keyBase = key.endsWith("/") ? key.slice(0, -1) : key;
|
|
2298
2350
|
const escapeRegex = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
2299
2351
|
const escapedKeyBase = escapeRegex(keyBase);
|
|
@@ -2303,7 +2355,7 @@ function proxySharedModule(options) {
|
|
|
2303
2355
|
replacement: "$1",
|
|
2304
2356
|
customResolver(source, importer) {
|
|
2305
2357
|
if (/\.css$/.test(source)) return;
|
|
2306
|
-
if (
|
|
2358
|
+
if (useDirectReactImport && source === "react") return;
|
|
2307
2359
|
if (importer && importer.includes("localSharedImportMap")) return;
|
|
2308
2360
|
if (key.endsWith("/") && source !== key.slice(0, -1)) return;
|
|
2309
2361
|
const loadSharePath = getLoadShareModulePath(source, isRolldown, command);
|
|
@@ -2315,7 +2367,7 @@ function proxySharedModule(options) {
|
|
|
2315
2367
|
}
|
|
2316
2368
|
};
|
|
2317
2369
|
}));
|
|
2318
|
-
config.resolve.alias.push(...Object.keys(shared).filter((key) => !(
|
|
2370
|
+
config.resolve.alias.push(...Object.keys(shared).filter((key) => !(useDirectReactImport && key === "react")).map((key) => {
|
|
2319
2371
|
return command === "build" ? {
|
|
2320
2372
|
find: new RegExp(`(.*${PREBUILD_TAG}.*)`),
|
|
2321
2373
|
replacement: function($1) {
|
|
@@ -2339,10 +2391,10 @@ function proxySharedModule(options) {
|
|
|
2339
2391
|
},
|
|
2340
2392
|
configResolved(config) {
|
|
2341
2393
|
_config = config;
|
|
2342
|
-
const isRolldown =
|
|
2394
|
+
const isRolldown = getIsRolldown(this);
|
|
2343
2395
|
Object.keys(shared).forEach((key) => {
|
|
2344
2396
|
if (key.endsWith("/")) return;
|
|
2345
|
-
if (
|
|
2397
|
+
if (useDirectReactImport && key === "react") {
|
|
2346
2398
|
addUsedShares(key);
|
|
2347
2399
|
return;
|
|
2348
2400
|
}
|
|
@@ -2355,6 +2407,345 @@ function proxySharedModule(options) {
|
|
|
2355
2407
|
}];
|
|
2356
2408
|
}
|
|
2357
2409
|
//#endregion
|
|
2410
|
+
//#region src/plugins/pluginRemoteNamedExports.ts
|
|
2411
|
+
/**
|
|
2412
|
+
* Transforms consumer-side imports of remote modules so that named exports
|
|
2413
|
+
* are accessible even when the bundler does not support syntheticNamedExports
|
|
2414
|
+
* (Rolldown / Vite 8+).
|
|
2415
|
+
*
|
|
2416
|
+
* The remote proxy module exports:
|
|
2417
|
+
* export const __moduleExports = exportModule; // full namespace
|
|
2418
|
+
* export default exportModule.default ?? exportModule; // unwrapped default
|
|
2419
|
+
*
|
|
2420
|
+
* This plugin rewrites consumer code:
|
|
2421
|
+
* import { foo } from "remote/xxx"
|
|
2422
|
+
* → import { __moduleExports as __mf_ns_0 } from "remote/xxx"; const { foo } = __mf_ns_0;
|
|
2423
|
+
*
|
|
2424
|
+
* import("remote/xxx")
|
|
2425
|
+
* → import("remote/xxx").then(…) // spreads __moduleExports into namespace
|
|
2426
|
+
*
|
|
2427
|
+
* NOTE: `export * from "remote/xxx"` is not supported — Rolldown cannot
|
|
2428
|
+
* statically resolve the set of exported names from a federated remote at
|
|
2429
|
+
* build time. Use explicit named re-exports instead.
|
|
2430
|
+
*/
|
|
2431
|
+
const JS_EXTENSIONS_RE = /\.(?:[mc]?[jt]sx?|vue|svelte)(?:\?|$)/;
|
|
2432
|
+
const REGEX_FALLBACK_EXTENSIONS_RE = /\.(?:[mc]?[jt]sx?)(?:\?|$)/;
|
|
2433
|
+
function wrapDynamicImport(original) {
|
|
2434
|
+
return `${original}.then(function(__mf_m__) {\n if (!__mf_m__ || !__mf_m__.__moduleExports) return __mf_m__;\n var __mf_ns__ = Object.create(null);\n Object.defineProperty(__mf_ns__, Symbol.toStringTag, { value: "Module" });\n var __mf_e__ = __mf_m__.__moduleExports;\n Object.keys(__mf_e__).forEach(function(k) { if (k !== "__esModule") __mf_ns__[k] = __mf_e__[k] });\n if ("default" in __mf_m__) __mf_ns__.default = __mf_m__.default;\n return __mf_ns__;\n})`;
|
|
2435
|
+
}
|
|
2436
|
+
function applyRewrites(code, imports, id) {
|
|
2437
|
+
if (imports.length === 0) return;
|
|
2438
|
+
const ms = new magic_string.default(code);
|
|
2439
|
+
let changed = false;
|
|
2440
|
+
let counter = 0;
|
|
2441
|
+
for (const imp of imports) switch (imp.kind) {
|
|
2442
|
+
case "static": {
|
|
2443
|
+
const src = JSON.stringify(imp.source);
|
|
2444
|
+
if (imp.namespaceLocal && !imp.defaultLocal && imp.named.length === 0) ms.overwrite(imp.start, imp.end, `import { __moduleExports as ${imp.namespaceLocal} } from ${src};`);
|
|
2445
|
+
else {
|
|
2446
|
+
const nsId = `__mf_ns_${counter++}`;
|
|
2447
|
+
const importParts = [];
|
|
2448
|
+
if (imp.defaultLocal) importParts.push(`default as ${imp.defaultLocal}`);
|
|
2449
|
+
importParts.push(`__moduleExports as ${nsId}`);
|
|
2450
|
+
const destructParts = imp.named.map((s) => s.imported === s.local ? s.local : `${s.imported}: ${s.local}`);
|
|
2451
|
+
let rewrite = `import { ${importParts.join(", ")} } from ${src};`;
|
|
2452
|
+
if (destructParts.length > 0) rewrite += `\nconst { ${destructParts.join(", ")} } = ${nsId};`;
|
|
2453
|
+
ms.overwrite(imp.start, imp.end, rewrite);
|
|
2454
|
+
}
|
|
2455
|
+
changed = true;
|
|
2456
|
+
break;
|
|
2457
|
+
}
|
|
2458
|
+
case "reexport": {
|
|
2459
|
+
const src = JSON.stringify(imp.source);
|
|
2460
|
+
const nsId = `__mf_ns_${counter++}`;
|
|
2461
|
+
const vars = imp.specifiers.map((s) => {
|
|
2462
|
+
const tmp = `__mf_re_${counter++}`;
|
|
2463
|
+
return {
|
|
2464
|
+
...s,
|
|
2465
|
+
tmp
|
|
2466
|
+
};
|
|
2467
|
+
});
|
|
2468
|
+
const importLine = `import { __moduleExports as ${nsId} } from ${src};`;
|
|
2469
|
+
const varLines = vars.map((v) => `const ${v.tmp} = ${nsId}[${JSON.stringify(v.local)}];`).join("\n");
|
|
2470
|
+
const exportLine = `export { ${vars.map((v) => `${v.tmp} as ${v.exported}`).join(", ")} };`;
|
|
2471
|
+
ms.overwrite(imp.start, imp.end, `${importLine}\n${varLines}\n${exportLine}`);
|
|
2472
|
+
changed = true;
|
|
2473
|
+
break;
|
|
2474
|
+
}
|
|
2475
|
+
case "export-all":
|
|
2476
|
+
console.warn(`[module-federation] "export * from '${imp.source}'" is not supported with Rolldown — use explicit named re-exports instead. (${id})`);
|
|
2477
|
+
break;
|
|
2478
|
+
case "dynamic":
|
|
2479
|
+
ms.overwrite(imp.start, imp.end, wrapDynamicImport(imp.originalText));
|
|
2480
|
+
changed = true;
|
|
2481
|
+
break;
|
|
2482
|
+
}
|
|
2483
|
+
if (!changed) return;
|
|
2484
|
+
return {
|
|
2485
|
+
code: ms.toString(),
|
|
2486
|
+
map: ms.generateMap({ hires: true })
|
|
2487
|
+
};
|
|
2488
|
+
}
|
|
2489
|
+
async function collectFromAST(ast, code, isRemoteImport) {
|
|
2490
|
+
const walk = await loadWalk();
|
|
2491
|
+
const result = [];
|
|
2492
|
+
walk(ast, { enter(node) {
|
|
2493
|
+
if (node.type === "ImportDeclaration" && node.source?.value) {
|
|
2494
|
+
if (!isRemoteImport(node.source.value)) return;
|
|
2495
|
+
const specifiers = node.specifiers || [];
|
|
2496
|
+
const named = specifiers.filter((s) => s.type === "ImportSpecifier" && s.importKind !== "type").map((s) => ({
|
|
2497
|
+
imported: s.imported.name ?? s.imported.value,
|
|
2498
|
+
local: s.local.name
|
|
2499
|
+
}));
|
|
2500
|
+
const defaultSpec = specifiers.find((s) => s.type === "ImportDefaultSpecifier");
|
|
2501
|
+
const nsSpec = specifiers.find((s) => s.type === "ImportNamespaceSpecifier");
|
|
2502
|
+
if (named.length === 0 && !nsSpec) return;
|
|
2503
|
+
result.push({
|
|
2504
|
+
kind: "static",
|
|
2505
|
+
source: node.source.value,
|
|
2506
|
+
start: node.start,
|
|
2507
|
+
end: node.end,
|
|
2508
|
+
named,
|
|
2509
|
+
defaultLocal: defaultSpec?.local.name,
|
|
2510
|
+
namespaceLocal: nsSpec?.local.name
|
|
2511
|
+
});
|
|
2512
|
+
}
|
|
2513
|
+
if (node.type === "ExportNamedDeclaration" && node.source?.value && isRemoteImport(node.source.value)) {
|
|
2514
|
+
const specifiers = (node.specifiers || []).filter((s) => s.exportKind !== "type").map((s) => ({
|
|
2515
|
+
local: s.local.name ?? s.local.value,
|
|
2516
|
+
exported: s.exported.name ?? s.exported.value
|
|
2517
|
+
}));
|
|
2518
|
+
if (specifiers.length === 0) return;
|
|
2519
|
+
result.push({
|
|
2520
|
+
kind: "reexport",
|
|
2521
|
+
source: node.source.value,
|
|
2522
|
+
start: node.start,
|
|
2523
|
+
end: node.end,
|
|
2524
|
+
specifiers
|
|
2525
|
+
});
|
|
2526
|
+
}
|
|
2527
|
+
if (node.type === "ExportAllDeclaration" && node.source?.value && isRemoteImport(node.source.value)) {
|
|
2528
|
+
this.skip();
|
|
2529
|
+
result.push({
|
|
2530
|
+
kind: "export-all",
|
|
2531
|
+
source: node.source.value,
|
|
2532
|
+
start: node.start,
|
|
2533
|
+
end: node.end
|
|
2534
|
+
});
|
|
2535
|
+
}
|
|
2536
|
+
if (node.type === "ImportExpression") {
|
|
2537
|
+
const source = node.source;
|
|
2538
|
+
if (source.type !== "Literal" && source.type !== "StringLiteral" && source.type !== "TemplateLiteral") return;
|
|
2539
|
+
const value = source.type === "TemplateLiteral" ? source.quasis?.length === 1 ? source.quasis[0].value?.cooked : void 0 : source.value;
|
|
2540
|
+
if (!value || !isRemoteImport(value)) return;
|
|
2541
|
+
result.push({
|
|
2542
|
+
kind: "dynamic",
|
|
2543
|
+
start: node.start,
|
|
2544
|
+
end: node.end,
|
|
2545
|
+
originalText: code.slice(node.start, node.end)
|
|
2546
|
+
});
|
|
2547
|
+
}
|
|
2548
|
+
} });
|
|
2549
|
+
return result;
|
|
2550
|
+
}
|
|
2551
|
+
async function collectFromEsLexer(code, isRemoteImport) {
|
|
2552
|
+
await es_module_lexer.init;
|
|
2553
|
+
let imports;
|
|
2554
|
+
try {
|
|
2555
|
+
[imports] = (0, es_module_lexer.parse)(code);
|
|
2556
|
+
} catch {
|
|
2557
|
+
return;
|
|
2558
|
+
}
|
|
2559
|
+
const result = [];
|
|
2560
|
+
for (const imp of imports) {
|
|
2561
|
+
if (imp.d === -2) continue;
|
|
2562
|
+
if (!imp.n || !isRemoteImport(imp.n)) continue;
|
|
2563
|
+
const stmtText = code.slice(imp.ss, imp.se);
|
|
2564
|
+
if (imp.d >= 0) {
|
|
2565
|
+
result.push({
|
|
2566
|
+
kind: "dynamic",
|
|
2567
|
+
start: imp.ss,
|
|
2568
|
+
end: imp.se,
|
|
2569
|
+
originalText: stmtText
|
|
2570
|
+
});
|
|
2571
|
+
continue;
|
|
2572
|
+
}
|
|
2573
|
+
if (/^\s*export\s*\*\s/.test(stmtText)) {
|
|
2574
|
+
result.push({
|
|
2575
|
+
kind: "export-all",
|
|
2576
|
+
source: imp.n,
|
|
2577
|
+
start: imp.ss,
|
|
2578
|
+
end: imp.se
|
|
2579
|
+
});
|
|
2580
|
+
continue;
|
|
2581
|
+
}
|
|
2582
|
+
if (/^\s*export\s/.test(stmtText)) {
|
|
2583
|
+
const braceMatch = stmtText.match(/\{([^}]*)\}/);
|
|
2584
|
+
if (!braceMatch) continue;
|
|
2585
|
+
const specs = braceMatch[1].split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
2586
|
+
if (specs.length === 0) continue;
|
|
2587
|
+
const specifiers = specs.map((s) => {
|
|
2588
|
+
const asMatch = s.match(/^(\w+)\s+as\s+(\w+)$/);
|
|
2589
|
+
return {
|
|
2590
|
+
local: asMatch ? asMatch[1] : s,
|
|
2591
|
+
exported: asMatch ? asMatch[2] : s
|
|
2592
|
+
};
|
|
2593
|
+
});
|
|
2594
|
+
result.push({
|
|
2595
|
+
kind: "reexport",
|
|
2596
|
+
source: imp.n,
|
|
2597
|
+
start: imp.ss,
|
|
2598
|
+
end: imp.se,
|
|
2599
|
+
specifiers
|
|
2600
|
+
});
|
|
2601
|
+
continue;
|
|
2602
|
+
}
|
|
2603
|
+
const importMatch = stmtText.match(/^import\s+([\s\S]*?)\s+from\s/);
|
|
2604
|
+
if (!importMatch) continue;
|
|
2605
|
+
const specifiersPart = importMatch[1].trim();
|
|
2606
|
+
if (/^type\s/.test(specifiersPart)) continue;
|
|
2607
|
+
const nsMatch = specifiersPart.match(/^\*\s+as\s+(\w+)$/);
|
|
2608
|
+
if (nsMatch) {
|
|
2609
|
+
result.push({
|
|
2610
|
+
kind: "static",
|
|
2611
|
+
source: imp.n,
|
|
2612
|
+
start: imp.ss,
|
|
2613
|
+
end: imp.se,
|
|
2614
|
+
named: [],
|
|
2615
|
+
namespaceLocal: nsMatch[1]
|
|
2616
|
+
});
|
|
2617
|
+
continue;
|
|
2618
|
+
}
|
|
2619
|
+
const braceMatch = specifiersPart.match(/\{([^}]*)\}/);
|
|
2620
|
+
if (!braceMatch) continue;
|
|
2621
|
+
const namedSpecifiers = braceMatch[1].split(",").map((s) => s.trim()).filter((s) => s.length > 0 && !s.startsWith("type "));
|
|
2622
|
+
if (namedSpecifiers.length === 0) continue;
|
|
2623
|
+
const defaultMatch = specifiersPart.match(/^(\w+)\s*,/);
|
|
2624
|
+
const named = namedSpecifiers.map((s) => {
|
|
2625
|
+
const asMatch = s.match(/^(\w+)\s+as\s+(\w+)$/);
|
|
2626
|
+
return {
|
|
2627
|
+
imported: asMatch ? asMatch[1] : s,
|
|
2628
|
+
local: asMatch ? asMatch[2] : s
|
|
2629
|
+
};
|
|
2630
|
+
});
|
|
2631
|
+
result.push({
|
|
2632
|
+
kind: "static",
|
|
2633
|
+
source: imp.n,
|
|
2634
|
+
start: imp.ss,
|
|
2635
|
+
end: imp.se,
|
|
2636
|
+
named,
|
|
2637
|
+
defaultLocal: defaultMatch?.[1]
|
|
2638
|
+
});
|
|
2639
|
+
}
|
|
2640
|
+
return result;
|
|
2641
|
+
}
|
|
2642
|
+
function collectFromRegex(code, isRemoteImport) {
|
|
2643
|
+
const result = [];
|
|
2644
|
+
for (const match of code.matchAll(/^\s*import\s+([\s\S]*?)\s+from\s+(['"])([^'"]+)\2\s*;?/gm)) {
|
|
2645
|
+
const [full, specifiersPartRaw, , source] = match;
|
|
2646
|
+
if (!isRemoteImport(source)) continue;
|
|
2647
|
+
const specifiersPart = specifiersPartRaw.trim();
|
|
2648
|
+
if (/^type\s/.test(specifiersPart)) continue;
|
|
2649
|
+
const nsMatch = specifiersPart.match(/^\*\s+as\s+(\w+)$/);
|
|
2650
|
+
if (nsMatch) {
|
|
2651
|
+
result.push({
|
|
2652
|
+
kind: "static",
|
|
2653
|
+
source,
|
|
2654
|
+
start: match.index,
|
|
2655
|
+
end: match.index + full.length,
|
|
2656
|
+
named: [],
|
|
2657
|
+
namespaceLocal: nsMatch[1]
|
|
2658
|
+
});
|
|
2659
|
+
continue;
|
|
2660
|
+
}
|
|
2661
|
+
const braceMatch = specifiersPart.match(/\{([^}]*)\}/);
|
|
2662
|
+
if (!braceMatch) continue;
|
|
2663
|
+
const namedSpecifiers = braceMatch[1].split(",").map((s) => s.trim()).filter((s) => s.length > 0 && !s.startsWith("type "));
|
|
2664
|
+
if (namedSpecifiers.length === 0) continue;
|
|
2665
|
+
const defaultMatch = specifiersPart.match(/^(\w+)\s*,/);
|
|
2666
|
+
const named = namedSpecifiers.map((s) => {
|
|
2667
|
+
const asMatch = s.match(/^(\w+)\s+as\s+(\w+)$/);
|
|
2668
|
+
return {
|
|
2669
|
+
imported: asMatch ? asMatch[1] : s,
|
|
2670
|
+
local: asMatch ? asMatch[2] : s
|
|
2671
|
+
};
|
|
2672
|
+
});
|
|
2673
|
+
result.push({
|
|
2674
|
+
kind: "static",
|
|
2675
|
+
source,
|
|
2676
|
+
start: match.index,
|
|
2677
|
+
end: match.index + full.length,
|
|
2678
|
+
named,
|
|
2679
|
+
defaultLocal: defaultMatch?.[1]
|
|
2680
|
+
});
|
|
2681
|
+
}
|
|
2682
|
+
for (const match of code.matchAll(/^\s*export\s+\{([\s\S]*?)\}\s+from\s+(['"])([^'"]+)\2\s*;?/gm)) {
|
|
2683
|
+
const [full, specifiersRaw, , source] = match;
|
|
2684
|
+
if (!isRemoteImport(source)) continue;
|
|
2685
|
+
const specs = specifiersRaw.split(",").map((s) => s.trim()).filter((s) => s.length > 0);
|
|
2686
|
+
if (specs.length === 0) continue;
|
|
2687
|
+
result.push({
|
|
2688
|
+
kind: "reexport",
|
|
2689
|
+
source,
|
|
2690
|
+
start: match.index,
|
|
2691
|
+
end: match.index + full.length,
|
|
2692
|
+
specifiers: specs.map((s) => {
|
|
2693
|
+
const asMatch = s.match(/^(\w+)\s+as\s+(\w+)$/);
|
|
2694
|
+
return {
|
|
2695
|
+
local: asMatch ? asMatch[1] : s,
|
|
2696
|
+
exported: asMatch ? asMatch[2] : s
|
|
2697
|
+
};
|
|
2698
|
+
})
|
|
2699
|
+
});
|
|
2700
|
+
}
|
|
2701
|
+
for (const match of code.matchAll(/^\s*export\s+\*\s+from\s+(['"])([^'"]+)\1\s*;?/gm)) {
|
|
2702
|
+
const [full, , source] = match;
|
|
2703
|
+
if (!isRemoteImport(source)) continue;
|
|
2704
|
+
result.push({
|
|
2705
|
+
kind: "export-all",
|
|
2706
|
+
source,
|
|
2707
|
+
start: match.index,
|
|
2708
|
+
end: match.index + full.length
|
|
2709
|
+
});
|
|
2710
|
+
}
|
|
2711
|
+
for (const match of code.matchAll(/import\(\s*(['"])([^'"]+)\1\s*\)/g)) {
|
|
2712
|
+
const [full, , source] = match;
|
|
2713
|
+
if (!isRemoteImport(source)) continue;
|
|
2714
|
+
result.push({
|
|
2715
|
+
kind: "dynamic",
|
|
2716
|
+
start: match.index,
|
|
2717
|
+
end: match.index + full.length,
|
|
2718
|
+
originalText: full
|
|
2719
|
+
});
|
|
2720
|
+
}
|
|
2721
|
+
return result.length > 0 ? result : void 0;
|
|
2722
|
+
}
|
|
2723
|
+
function pluginRemoteNamedExports(options) {
|
|
2724
|
+
const remoteNames = Object.keys(options.remotes);
|
|
2725
|
+
function isRemoteImport(source) {
|
|
2726
|
+
return remoteNames.some((name) => source === name || source.startsWith(name + "/")) || source.includes("__loadRemote__");
|
|
2727
|
+
}
|
|
2728
|
+
return {
|
|
2729
|
+
name: "module-federation-remote-named-exports",
|
|
2730
|
+
enforce: "post",
|
|
2731
|
+
async transform(code, id) {
|
|
2732
|
+
if (remoteNames.length === 0) return;
|
|
2733
|
+
if (id.includes("__loadRemote__") || id.includes("__loadShare__")) return;
|
|
2734
|
+
if (!JS_EXTENSIONS_RE.test(id)) return;
|
|
2735
|
+
if (!remoteNames.some((name) => code.includes(name))) return;
|
|
2736
|
+
let imports;
|
|
2737
|
+
try {
|
|
2738
|
+
imports = await collectFromAST(this.parse(code), code, isRemoteImport);
|
|
2739
|
+
} catch {
|
|
2740
|
+
imports = await collectFromEsLexer(code, isRemoteImport);
|
|
2741
|
+
}
|
|
2742
|
+
if ((!imports || imports.length === 0) && REGEX_FALLBACK_EXTENSIONS_RE.test(id)) imports = collectFromRegex(code, isRemoteImport);
|
|
2743
|
+
if (!imports) return;
|
|
2744
|
+
return applyRewrites(code, imports, id);
|
|
2745
|
+
}
|
|
2746
|
+
};
|
|
2747
|
+
}
|
|
2748
|
+
//#endregion
|
|
2358
2749
|
//#region src/plugins/pluginVarRemoteEntry.ts
|
|
2359
2750
|
const VarRemoteEntry = () => {
|
|
2360
2751
|
const mfOptions = getNormalizeModuleFederationOptions();
|
|
@@ -2521,6 +2912,7 @@ var normalizeOptimizeDeps_default = {
|
|
|
2521
2912
|
};
|
|
2522
2913
|
//#endregion
|
|
2523
2914
|
//#region src/index.ts
|
|
2915
|
+
const patchedManualChunks = /* @__PURE__ */ new WeakSet();
|
|
2524
2916
|
const UNSAFE_JS_SOURCE_CHAR_MAP = {
|
|
2525
2917
|
"<": "\\u003C",
|
|
2526
2918
|
">": "\\u003E",
|
|
@@ -2565,6 +2957,10 @@ function createEarlyVirtualModulesPlugin(options) {
|
|
|
2565
2957
|
config.optimizeDeps = config.optimizeDeps || {};
|
|
2566
2958
|
config.optimizeDeps.include = config.optimizeDeps.include || [];
|
|
2567
2959
|
config.optimizeDeps.include.push(virtualRuntimeInitStatus.getImportId());
|
|
2960
|
+
if (isRolldown) {
|
|
2961
|
+
config.optimizeDeps.exclude = config.optimizeDeps.exclude || [];
|
|
2962
|
+
config.optimizeDeps.exclude.push(...Object.keys(remotes || {}));
|
|
2963
|
+
}
|
|
2568
2964
|
}
|
|
2569
2965
|
for (const key of Object.keys(shared)) {
|
|
2570
2966
|
if (key.endsWith("/")) continue;
|
|
@@ -2650,6 +3046,7 @@ function federation(mfUserOptions) {
|
|
|
2650
3046
|
virtualExposesId
|
|
2651
3047
|
}),
|
|
2652
3048
|
pluginProxyRemotes_default(options),
|
|
3049
|
+
pluginRemoteNamedExports(options),
|
|
2653
3050
|
...pluginModuleParseEnd_default((id) => {
|
|
2654
3051
|
return id.includes(getHostAutoInitImportId()) || id.includes(remoteEntryId) || id.includes(virtualExposesId) || id.includes(getLocalSharedImportMapPath());
|
|
2655
3052
|
}, {
|
|
@@ -2685,20 +3082,23 @@ function federation(mfUserOptions) {
|
|
|
2685
3082
|
warnedAboutCodeSplitting = true;
|
|
2686
3083
|
mfWarn("Ignoring `build.rolldownOptions.output.codeSplitting = false` because module federation requires chunk splitting.");
|
|
2687
3084
|
};
|
|
3085
|
+
let warnedAboutManualChunks = false;
|
|
2688
3086
|
const applyManualChunks = (output) => {
|
|
2689
3087
|
ensureCodeSplitting(output);
|
|
2690
|
-
const
|
|
2691
|
-
output.manualChunks
|
|
3088
|
+
const isPatchedByPlugin = !!(output.manualChunks && patchedManualChunks.has(output.manualChunks));
|
|
3089
|
+
if (output.manualChunks && !isPatchedByPlugin && !warnedAboutManualChunks) {
|
|
3090
|
+
warnedAboutManualChunks = true;
|
|
3091
|
+
mfWarn("Ignoring `build.rollupOptions.output.manualChunks` because it conflicts with module federation. Module federation transforms shared dependency imports with top-level await, and grouping these transformed modules into a single chunk creates circular async dependencies that cause the application to silently hang.");
|
|
3092
|
+
}
|
|
3093
|
+
const mfManualChunks = function(id) {
|
|
2692
3094
|
if (id.includes(runtimeInitId)) return "runtimeInit";
|
|
2693
3095
|
if (id.includes("__loadShare__")) {
|
|
2694
3096
|
const match = id.match(/([^/\\]+__loadShare__[^/\\]+)/);
|
|
2695
3097
|
return match ? match[1] : "loadShare";
|
|
2696
3098
|
}
|
|
2697
|
-
if (typeof existingManualChunks === "function") return existingManualChunks.apply(this, arguments);
|
|
2698
|
-
if (existingManualChunks && typeof existingManualChunks === "object") {
|
|
2699
|
-
for (const [key, ids] of Object.entries(existingManualChunks)) if (Array.isArray(ids) && ids.some((v) => id.includes(v))) return key;
|
|
2700
|
-
}
|
|
2701
3099
|
};
|
|
3100
|
+
patchedManualChunks.add(mfManualChunks);
|
|
3101
|
+
output.manualChunks = mfManualChunks;
|
|
2702
3102
|
};
|
|
2703
3103
|
config.build.rollupOptions = config.build.rollupOptions || {};
|
|
2704
3104
|
if (!Array.isArray(config.build.rollupOptions.output)) applyManualChunks(config.build.rollupOptions.output ||= {});
|
|
@@ -2729,6 +3129,7 @@ function federation(mfUserOptions) {
|
|
|
2729
3129
|
* @see https://rollupjs.org/plugin-development/#synthetic-named-exports
|
|
2730
3130
|
*/
|
|
2731
3131
|
code = code.replace("export default exportModule", "export const __moduleExports = exportModule;\nexport default exportModule.__esModule ? exportModule.default : exportModule");
|
|
3132
|
+
if (getIsRolldown(this)) return { code };
|
|
2732
3133
|
return {
|
|
2733
3134
|
code,
|
|
2734
3135
|
syntheticNamedExports: "__moduleExports"
|
|
@@ -2934,37 +3335,55 @@ function federation(mfUserOptions) {
|
|
|
2934
3335
|
config.optimizeDeps.needsInterop.push(virtualDir);
|
|
2935
3336
|
config.optimizeDeps.needsInterop.push(getLocalSharedImportMapPath());
|
|
2936
3337
|
}
|
|
3338
|
+
const isAstro = hasPackageDependency("astro");
|
|
2937
3339
|
const resolvedTarget = options.target ?? (config.build?.ssr ? "node" : "web");
|
|
3340
|
+
const envTargetDefineValue = !options.target && isAstro ? "undefined" : JSON.stringify(resolvedTarget);
|
|
2938
3341
|
if (!config.define) config.define = {};
|
|
2939
|
-
if (!("ENV_TARGET" in config.define)) config.define["ENV_TARGET"] =
|
|
3342
|
+
if (!("ENV_TARGET" in config.define)) config.define["ENV_TARGET"] = envTargetDefineValue;
|
|
2940
3343
|
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.`);
|
|
2941
3344
|
}
|
|
2942
3345
|
},
|
|
2943
3346
|
...Manifest(),
|
|
2944
3347
|
...VarRemoteEntry(),
|
|
2945
|
-
...
|
|
2946
|
-
|
|
2947
|
-
|
|
2948
|
-
|
|
2949
|
-
|
|
2950
|
-
|
|
2951
|
-
|
|
2952
|
-
|
|
2953
|
-
const
|
|
2954
|
-
const
|
|
2955
|
-
const
|
|
2956
|
-
|
|
2957
|
-
|
|
2958
|
-
|
|
2959
|
-
|
|
2960
|
-
|
|
3348
|
+
...(function() {
|
|
3349
|
+
let disablePreload = false;
|
|
3350
|
+
return Object.keys(options.exposes).length > 0 ? [{
|
|
3351
|
+
name: "module-federation-fix-preload",
|
|
3352
|
+
enforce: "post",
|
|
3353
|
+
apply: "build",
|
|
3354
|
+
config(_config, { command }) {
|
|
3355
|
+
const manifest = options.manifest;
|
|
3356
|
+
const isConsumerProject = Object.keys(options.exposes).length === 0;
|
|
3357
|
+
const getDefaultDisableAssetsAnalyze = (cfgCommand) => cfgCommand === "serve" && isConsumerProject && (typeof manifest !== "object" || !Object.prototype.hasOwnProperty.call(manifest, "disableAssetsAnalyze"));
|
|
3358
|
+
const getConfiguredDisableAssetsAnalyze = (cfgCommand) => {
|
|
3359
|
+
if (typeof manifest === "object" && manifest !== null) {
|
|
3360
|
+
if (Object.prototype.hasOwnProperty.call(manifest, "disableAssetsAnalyze")) return manifest.disableAssetsAnalyze === true;
|
|
3361
|
+
}
|
|
3362
|
+
return getDefaultDisableAssetsAnalyze(cfgCommand);
|
|
3363
|
+
};
|
|
3364
|
+
disablePreload = getConfiguredDisableAssetsAnalyze(command);
|
|
3365
|
+
},
|
|
3366
|
+
generateBundle(_, bundle) {
|
|
3367
|
+
if (disablePreload) return;
|
|
3368
|
+
for (const chunk of Object.values(bundle)) {
|
|
3369
|
+
if (chunk.type !== "chunk") continue;
|
|
3370
|
+
if (!chunk.code.includes("modulepreload")) continue;
|
|
3371
|
+
const chunkDir = pathe.default.dirname(chunk.fileName);
|
|
3372
|
+
const prefixToRoot = chunkDir === "." ? "" : `${pathe.default.relative(chunkDir, ".")}/`;
|
|
3373
|
+
const replacementExpr = prefixToRoot ? `${escapeUnsafeJsSourceChars(JSON.stringify(prefixToRoot))}+$1` : "$1";
|
|
3374
|
+
const replacement = `=function($1){return new URL(${replacementExpr},import.meta.url).href}`;
|
|
3375
|
+
const replaced = chunk.code.replace(/=\(?(\w+)(?:,\w+)?\)?\s*=>\s*["'`][^"'`]*["'`]\s*\+\s*\1/, replacement);
|
|
3376
|
+
if (replaced !== chunk.code) {
|
|
3377
|
+
chunk.code = replaced;
|
|
3378
|
+
continue;
|
|
3379
|
+
}
|
|
3380
|
+
chunk.code = chunk.code.replace(/=function\((\w+)(?:,\w+)?\)\{return\s*["'`][^"'`]*["'`]\s*\+\s*\1\s*\}/, replacement);
|
|
3381
|
+
chunk.code = chunk.code.replace(/=function\((\w+)(?:,\w+)?\)\{return new URL\("\.\.\/"\+\1,import\.meta\.url\)\.href\}/, replacement);
|
|
3382
|
+
chunk.code = chunk.code.replace(/new URL\("\.\.\/"\+(\w+),import\.meta\.url\)\.href/g, `new URL(${replacementExpr},import.meta.url).href`);
|
|
2961
3383
|
}
|
|
2962
|
-
chunk.code = chunk.code.replace(/=function\((\w+)(?:,\w+)?\)\{return\s*["'`][^"'`]*["'`]\s*\+\s*\1\s*\}/, replacement);
|
|
2963
|
-
chunk.code = chunk.code.replace(/=function\((\w+)(?:,\w+)?\)\{return new URL\("\.\.\/"\+\1,import\.meta\.url\)\.href\}/, replacement);
|
|
2964
|
-
chunk.code = chunk.code.replace(/new URL\("\.\.\/"\+(\w+),import\.meta\.url\)\.href/g, `new URL(${replacementExpr},import.meta.url).href`);
|
|
2965
3384
|
}
|
|
2966
|
-
}
|
|
2967
|
-
}
|
|
3385
|
+
}] : [];
|
|
3386
|
+
})()
|
|
2968
3387
|
];
|
|
2969
3388
|
}
|
|
2970
3389
|
//#endregion
|