@module-federation/vite 1.11.1 → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/index.cjs +352 -59
- package/lib/index.mjs +352 -59
- package/package.json +13 -12
package/lib/index.cjs
CHANGED
|
@@ -39,6 +39,7 @@ let estree_walker = require("estree-walker");
|
|
|
39
39
|
let _module_federation_sdk = require("@module-federation/sdk");
|
|
40
40
|
let _module_federation_dts_plugin = require("@module-federation/dts-plugin");
|
|
41
41
|
let _module_federation_dts_plugin_core = require("@module-federation/dts-plugin/core");
|
|
42
|
+
let module$1 = require("module");
|
|
42
43
|
let url = require("url");
|
|
43
44
|
|
|
44
45
|
//#region src/utils/mapCodeToCodeWithSourcemap.ts
|
|
@@ -771,6 +772,22 @@ function serializeRuntimeOptions(options) {
|
|
|
771
772
|
|
|
772
773
|
//#endregion
|
|
773
774
|
//#region src/utils/VirtualModule.ts
|
|
775
|
+
/**
|
|
776
|
+
* Initialize virtual module infrastructure BEFORE VirtualModule class is used.
|
|
777
|
+
* This must be called in the config hook to ensure the directory exists
|
|
778
|
+
* before Vite's optimization phase.
|
|
779
|
+
*/
|
|
780
|
+
function initVirtualModuleInfrastructure(root, virtualModuleDir = "__mf__virtual") {
|
|
781
|
+
const virtualPackagePath = (0, pathe.join)((0, pathe.join)(root, "node_modules"), virtualModuleDir);
|
|
782
|
+
if (!(0, fs.existsSync)(virtualPackagePath)) {
|
|
783
|
+
(0, fs.mkdirSync)(virtualPackagePath, { recursive: true });
|
|
784
|
+
(0, fs.writeFileSync)((0, pathe.join)(virtualPackagePath, "empty.js"), "");
|
|
785
|
+
(0, fs.writeFileSync)((0, pathe.join)(virtualPackagePath, "package.json"), JSON.stringify({
|
|
786
|
+
name: virtualModuleDir,
|
|
787
|
+
main: "empty.js"
|
|
788
|
+
}));
|
|
789
|
+
}
|
|
790
|
+
}
|
|
774
791
|
let rootDir;
|
|
775
792
|
function findNodeModulesDir(root = process.cwd()) {
|
|
776
793
|
let currentDir = root;
|
|
@@ -859,9 +876,10 @@ var VirtualModule = class {
|
|
|
859
876
|
|
|
860
877
|
//#endregion
|
|
861
878
|
//#region src/virtualModules/virtualExposes.ts
|
|
862
|
-
|
|
863
|
-
|
|
864
|
-
|
|
879
|
+
function getVirtualExposesId(options) {
|
|
880
|
+
return `virtual:mf-exposes:${`${options.name}__${options.filename}`.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
|
|
881
|
+
}
|
|
882
|
+
function generateExposes(options) {
|
|
865
883
|
return `
|
|
866
884
|
export default {
|
|
867
885
|
${Object.keys(options.exposes).map((key) => {
|
|
@@ -911,10 +929,10 @@ ${exportStatement}
|
|
|
911
929
|
//#region src/virtualModules/virtualRemotes.ts
|
|
912
930
|
const cacheRemoteMap = {};
|
|
913
931
|
const LOAD_REMOTE_TAG = "__loadRemote__";
|
|
914
|
-
function getRemoteVirtualModule(remote, command) {
|
|
932
|
+
function getRemoteVirtualModule(remote, command, isRolldown) {
|
|
915
933
|
if (!cacheRemoteMap[remote]) {
|
|
916
|
-
cacheRemoteMap[remote] = new VirtualModule(remote, LOAD_REMOTE_TAG, ".js");
|
|
917
|
-
cacheRemoteMap[remote].writeSync(generateRemotes(remote, command));
|
|
934
|
+
cacheRemoteMap[remote] = new VirtualModule(remote, LOAD_REMOTE_TAG, isRolldown ? ".mjs" : ".js");
|
|
935
|
+
cacheRemoteMap[remote].writeSync(generateRemotes(remote, command, isRolldown));
|
|
918
936
|
}
|
|
919
937
|
return cacheRemoteMap[remote];
|
|
920
938
|
}
|
|
@@ -926,11 +944,11 @@ function addUsedRemote(remoteKey, remoteModule) {
|
|
|
926
944
|
function getUsedRemotesMap() {
|
|
927
945
|
return usedRemotesMap;
|
|
928
946
|
}
|
|
929
|
-
function generateRemotes(id, command) {
|
|
930
|
-
const
|
|
931
|
-
const importLine =
|
|
932
|
-
const awaitOrPlaceholder =
|
|
933
|
-
const exportLine =
|
|
947
|
+
function generateRemotes(id, command, isRolldown) {
|
|
948
|
+
const useESM = command === "build" || isRolldown;
|
|
949
|
+
const importLine = useESM ? `import { initPromise } from "${virtualRuntimeInitStatus.getImportId()}"` : `const {initPromise} = require("${virtualRuntimeInitStatus.getImportId()}")`;
|
|
950
|
+
const awaitOrPlaceholder = useESM ? "await " : "/*mf top-level-await placeholder replacement mf*/";
|
|
951
|
+
const exportLine = command === "serve" && useESM ? "export default exportModule.default ?? exportModule" : useESM ? "export default exportModule" : "module.exports = exportModule";
|
|
934
952
|
return `
|
|
935
953
|
${importLine}
|
|
936
954
|
const res = initPromise.then(runtime => runtime.loadRemote(${JSON.stringify(id)}))
|
|
@@ -941,6 +959,24 @@ function generateRemotes(id, command) {
|
|
|
941
959
|
|
|
942
960
|
//#endregion
|
|
943
961
|
//#region src/virtualModules/virtualShared_preBuild.ts
|
|
962
|
+
/**
|
|
963
|
+
* Even the resolveId hook cannot interfere with vite pre-build,
|
|
964
|
+
* and adding query parameter virtual modules will also fail.
|
|
965
|
+
* You can only proxy to the real file through alias
|
|
966
|
+
*/
|
|
967
|
+
/**
|
|
968
|
+
* shared will be proxied:
|
|
969
|
+
* 1. __prebuild__: export shareModule (pre-built source code of modules such as vue, react, etc.)
|
|
970
|
+
* 2. __loadShare__: load shareModule (mfRuntime.loadShare('vue'))
|
|
971
|
+
*/
|
|
972
|
+
function getPackageNamedExports(pkg) {
|
|
973
|
+
try {
|
|
974
|
+
const mod = (0, module$1.createRequire)(new URL("file://" + process.cwd() + "/package.json"))(pkg);
|
|
975
|
+
return Object.keys(mod).filter((k) => k !== "default" && k !== "__esModule");
|
|
976
|
+
} catch {
|
|
977
|
+
return [];
|
|
978
|
+
}
|
|
979
|
+
}
|
|
944
980
|
const preBuildCacheMap = {};
|
|
945
981
|
const PREBUILD_TAG = "__prebuild__";
|
|
946
982
|
function writePreBuildLibPath(pkg) {
|
|
@@ -953,17 +989,24 @@ function getPreBuildLibImportId(pkg) {
|
|
|
953
989
|
}
|
|
954
990
|
const LOAD_SHARE_TAG = "__loadShare__";
|
|
955
991
|
const loadShareCacheMap = {};
|
|
956
|
-
function getLoadShareModulePath(pkg) {
|
|
957
|
-
if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, ".js");
|
|
992
|
+
function getLoadShareModulePath(pkg, isRolldown, command) {
|
|
993
|
+
if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, isRolldown || command === "build" ? ".mjs" : ".js");
|
|
958
994
|
return loadShareCacheMap[pkg].getPath();
|
|
959
995
|
}
|
|
960
|
-
function writeLoadShareModule(pkg, shareItem, command) {
|
|
961
|
-
|
|
962
|
-
const
|
|
963
|
-
const
|
|
964
|
-
const
|
|
996
|
+
function writeLoadShareModule(pkg, shareItem, command, isRolldown) {
|
|
997
|
+
if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, isRolldown || command === "build" ? ".mjs" : ".js");
|
|
998
|
+
const useESM = command === "build" || isRolldown;
|
|
999
|
+
const importLine = useESM ? `import { initPromise } from "${virtualRuntimeInitStatus.getImportId()}"` : `const {initPromise} = require("${virtualRuntimeInitStatus.getImportId()}")`;
|
|
1000
|
+
const awaitOrPlaceholder = useESM ? "await " : "/*mf top-level-await placeholder replacement mf*/";
|
|
1001
|
+
const namedExports = getPackageNamedExports(pkg);
|
|
1002
|
+
let exportLine;
|
|
1003
|
+
if (namedExports.length > 0) {
|
|
1004
|
+
const destructure = `const { ${namedExports.join(", ")} } = exportModule;`;
|
|
1005
|
+
const namedExportLine = `export { ${namedExports.join(", ")} };`;
|
|
1006
|
+
exportLine = useESM ? `export default exportModule;\n ${destructure}\n ${namedExportLine}` : `module.exports = exportModule;\n ${destructure}\n Object.assign(module.exports, { ${namedExports.join(", ")} });`;
|
|
1007
|
+
} else exportLine = useESM ? `export default exportModule\n export * from ${JSON.stringify(getPreBuildLibImportId(pkg))}` : "module.exports = exportModule";
|
|
965
1008
|
loadShareCacheMap[pkg].writeSync(`
|
|
966
|
-
|
|
1009
|
+
import ${JSON.stringify(getPreBuildLibImportId(pkg))};
|
|
967
1010
|
${command !== "build" ? `;() => import(${JSON.stringify(pkg)}).catch(() => {});` : ""}
|
|
968
1011
|
${importLine}
|
|
969
1012
|
const res = initPromise.then(runtime => runtime.loadShare(${JSON.stringify(pkg)}, {
|
|
@@ -973,7 +1016,7 @@ function writeLoadShareModule(pkg, shareItem, command) {
|
|
|
973
1016
|
requiredVersion: ${JSON.stringify(shareItem.shareConfig.requiredVersion)}
|
|
974
1017
|
}}
|
|
975
1018
|
}))
|
|
976
|
-
const exportModule = ${awaitOrPlaceholder}res.then(factory => factory())
|
|
1019
|
+
const exportModule = ${awaitOrPlaceholder}res.then((factory) => (typeof factory === "function" ? factory() : factory))
|
|
977
1020
|
${exportLine}
|
|
978
1021
|
`);
|
|
979
1022
|
}
|
|
@@ -1072,7 +1115,10 @@ function generateLocalSharedImportMap() {
|
|
|
1072
1115
|
`;
|
|
1073
1116
|
}
|
|
1074
1117
|
const REMOTE_ENTRY_ID = "virtual:mf-REMOTE_ENTRY_ID";
|
|
1075
|
-
function
|
|
1118
|
+
function getRemoteEntryId(options) {
|
|
1119
|
+
return `${REMOTE_ENTRY_ID}:${`${options.name}__${options.filename}`.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
|
|
1120
|
+
}
|
|
1121
|
+
function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(options)) {
|
|
1076
1122
|
const pluginImportNames = options.runtimePlugins.map((p, i) => {
|
|
1077
1123
|
if (typeof p === "string") return [
|
|
1078
1124
|
`$runtimePlugin_${i}`,
|
|
@@ -1088,7 +1134,7 @@ function generateRemoteEntry(options) {
|
|
|
1088
1134
|
return `
|
|
1089
1135
|
import {init as runtimeInit, loadRemote} from "@module-federation/runtime";
|
|
1090
1136
|
${pluginImportNames.map((item) => item[1]).join("\n")}
|
|
1091
|
-
import exposesMap from "${
|
|
1137
|
+
import exposesMap from "${virtualExposesId}"
|
|
1092
1138
|
import {usedShared, usedRemotes} from "${getLocalSharedImportMapPath()}"
|
|
1093
1139
|
import {
|
|
1094
1140
|
initResolve
|
|
@@ -1140,9 +1186,9 @@ function generateRemoteEntry(options) {
|
|
|
1140
1186
|
*/
|
|
1141
1187
|
const HOST_AUTO_INIT_TAG = "__H_A_I__";
|
|
1142
1188
|
const hostAutoInitModule = new VirtualModule("hostAutoInit", HOST_AUTO_INIT_TAG);
|
|
1143
|
-
function writeHostAutoInit() {
|
|
1189
|
+
function writeHostAutoInit(remoteEntryId = REMOTE_ENTRY_ID) {
|
|
1144
1190
|
hostAutoInitModule.writeSync(`
|
|
1145
|
-
const remoteEntryPromise = import("${
|
|
1191
|
+
const remoteEntryPromise = import("${remoteEntryId}")
|
|
1146
1192
|
// __tla only serves as a hack for vite-plugin-top-level-await.
|
|
1147
1193
|
Promise.resolve(remoteEntryPromise)
|
|
1148
1194
|
.then(remoteEntry => {
|
|
@@ -1160,9 +1206,9 @@ function getHostAutoInitPath() {
|
|
|
1160
1206
|
|
|
1161
1207
|
//#endregion
|
|
1162
1208
|
//#region src/virtualModules/index.ts
|
|
1163
|
-
function initVirtualModules(command) {
|
|
1209
|
+
function initVirtualModules(command, remoteEntryId) {
|
|
1164
1210
|
writeLocalSharedImportMap();
|
|
1165
|
-
writeHostAutoInit();
|
|
1211
|
+
writeHostAutoInit(remoteEntryId);
|
|
1166
1212
|
writeRuntimeInitStatus(command);
|
|
1167
1213
|
}
|
|
1168
1214
|
|
|
@@ -1569,7 +1615,7 @@ function pluginModuleParseEnd_default(excludeFn, options) {
|
|
|
1569
1615
|
apply: "build",
|
|
1570
1616
|
moduleParsed(module) {
|
|
1571
1617
|
const id = module.id;
|
|
1572
|
-
if (id ===
|
|
1618
|
+
if (id === options.virtualExposesId) exposesParseEnd = true;
|
|
1573
1619
|
if (excludeFn(id)) return;
|
|
1574
1620
|
parseEndSet.add(id);
|
|
1575
1621
|
if (exposesParseEnd && parseStartSet.size === parseEndSet.size) _resolve(1);
|
|
@@ -1581,7 +1627,7 @@ function pluginModuleParseEnd_default(excludeFn, options) {
|
|
|
1581
1627
|
//#endregion
|
|
1582
1628
|
//#region src/plugins/pluginProxyRemoteEntry.ts
|
|
1583
1629
|
const filter = (0, _rollup_pluginutils.createFilter)();
|
|
1584
|
-
function pluginProxyRemoteEntry_default() {
|
|
1630
|
+
function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposesId }) {
|
|
1585
1631
|
let viteConfig, _command;
|
|
1586
1632
|
return {
|
|
1587
1633
|
name: "proxyRemoteEntry",
|
|
@@ -1592,28 +1638,37 @@ function pluginProxyRemoteEntry_default() {
|
|
|
1592
1638
|
config(config, { command }) {
|
|
1593
1639
|
_command = command;
|
|
1594
1640
|
},
|
|
1641
|
+
async buildStart() {
|
|
1642
|
+
if (_command !== "build") return;
|
|
1643
|
+
for (const expose of Object.values(options.exposes)) {
|
|
1644
|
+
const resolved = await this.resolve(expose.import);
|
|
1645
|
+
if (resolved) this.emitFile({
|
|
1646
|
+
type: "chunk",
|
|
1647
|
+
id: resolved.id
|
|
1648
|
+
});
|
|
1649
|
+
}
|
|
1650
|
+
},
|
|
1595
1651
|
async resolveId(id, importer) {
|
|
1596
|
-
if (id ===
|
|
1597
|
-
if (id ===
|
|
1652
|
+
if (id === remoteEntryId) return remoteEntryId;
|
|
1653
|
+
if (id === virtualExposesId) return virtualExposesId;
|
|
1598
1654
|
if (_command === "serve" && id.includes(getHostAutoInitPath())) return id;
|
|
1599
|
-
if (importer ===
|
|
1600
|
-
typeof __filename === "string" ? __filename : (0, url.fileURLToPath)(require("url").pathToFileURL(__filename).href);
|
|
1601
|
-
const resolved = await this.resolve(id,
|
|
1655
|
+
if (importer === remoteEntryId && !id.startsWith(".") && !id.startsWith("/") && !id.startsWith("\0") && !id.startsWith("virtual:")) {
|
|
1656
|
+
const importPath = typeof __filename === "string" ? __filename : (0, url.fileURLToPath)(require("url").pathToFileURL(__filename).href);
|
|
1657
|
+
const resolved = await this.resolve(id, importPath, { skipSelf: true });
|
|
1602
1658
|
if (resolved) return resolved;
|
|
1603
1659
|
}
|
|
1604
1660
|
},
|
|
1605
1661
|
load(id) {
|
|
1606
|
-
if (id ===
|
|
1607
|
-
if (id ===
|
|
1662
|
+
if (id === remoteEntryId) return parsePromise.then((_) => generateRemoteEntry(options, virtualExposesId));
|
|
1663
|
+
if (id === virtualExposesId) return generateExposes(options);
|
|
1608
1664
|
if (_command === "serve" && id.includes(getHostAutoInitPath())) return id;
|
|
1609
1665
|
},
|
|
1610
1666
|
transform(code, id) {
|
|
1611
1667
|
return mapCodeToCodeWithSourcemap((() => {
|
|
1612
1668
|
if (!filter(id)) return;
|
|
1613
|
-
if (id.includes(
|
|
1614
|
-
if (id ===
|
|
1669
|
+
if (id.includes(remoteEntryId)) return parsePromise.then((_) => generateRemoteEntry(options, virtualExposesId));
|
|
1670
|
+
if (id === virtualExposesId) return generateExposes(options);
|
|
1615
1671
|
if (id.includes(getHostAutoInitPath())) {
|
|
1616
|
-
const options = getNormalizeModuleFederationOptions();
|
|
1617
1672
|
if (_command === "serve") {
|
|
1618
1673
|
const host = typeof viteConfig.server?.host === "string" && viteConfig.server.host !== "0.0.0.0" ? viteConfig.server.host : "localhost";
|
|
1619
1674
|
const publicPath = JSON.stringify(resolvePublicPath(options, viteConfig.base) + options.filename);
|
|
@@ -1643,13 +1698,14 @@ function pluginProxyRemotes_default(options) {
|
|
|
1643
1698
|
return {
|
|
1644
1699
|
name: "proxyRemotes",
|
|
1645
1700
|
config(config, { command: _command }) {
|
|
1701
|
+
const isRolldown = !!this?.meta?.rolldownVersion;
|
|
1646
1702
|
Object.keys(remotes).forEach((key) => {
|
|
1647
1703
|
const remote = remotes[key];
|
|
1648
1704
|
config.resolve.alias.push({
|
|
1649
1705
|
find: new RegExp(`^(${remote.name}(\/.*|$))`),
|
|
1650
1706
|
replacement: "$1",
|
|
1651
1707
|
customResolver(source) {
|
|
1652
|
-
const remoteModule = getRemoteVirtualModule(source, _command);
|
|
1708
|
+
const remoteModule = getRemoteVirtualModule(source, _command, isRolldown);
|
|
1653
1709
|
addUsedRemote(remote.name, source);
|
|
1654
1710
|
return remoteModule.getPath();
|
|
1655
1711
|
}
|
|
@@ -1696,8 +1752,10 @@ var PromiseStore = class {
|
|
|
1696
1752
|
//#endregion
|
|
1697
1753
|
//#region src/plugins/pluginProxySharedModule_preBuild.ts
|
|
1698
1754
|
function proxySharedModule(options) {
|
|
1699
|
-
|
|
1755
|
+
const { shared = {} } = options;
|
|
1700
1756
|
let _config;
|
|
1757
|
+
let _command = "serve";
|
|
1758
|
+
const savePrebuild = new PromiseStore();
|
|
1701
1759
|
return [{
|
|
1702
1760
|
name: "generateLocalSharedImportMap",
|
|
1703
1761
|
enforce: "post",
|
|
@@ -1710,19 +1768,23 @@ function proxySharedModule(options) {
|
|
|
1710
1768
|
}, {
|
|
1711
1769
|
name: "proxyPreBuildShared",
|
|
1712
1770
|
enforce: "post",
|
|
1713
|
-
configResolved(config) {
|
|
1714
|
-
_config = config;
|
|
1715
|
-
},
|
|
1716
1771
|
config(config, { command }) {
|
|
1772
|
+
const isRolldown = !!this?.meta?.rolldownVersion;
|
|
1773
|
+
_command = command;
|
|
1717
1774
|
config.resolve.alias.push(...Object.keys(shared).map((key) => {
|
|
1718
|
-
const
|
|
1775
|
+
const keyBase = key.endsWith("/") ? key.slice(0, -1) : key;
|
|
1776
|
+
const escapeRegex = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1777
|
+
const escapedKeyBase = escapeRegex(keyBase);
|
|
1778
|
+
const pattern = key.endsWith("/") ? `^(${escapedKeyBase}(?:\\/.*)?)$` : `^(${escapedKeyBase})$`;
|
|
1719
1779
|
return {
|
|
1720
1780
|
find: new RegExp(pattern),
|
|
1721
1781
|
replacement: "$1",
|
|
1722
1782
|
customResolver(source, importer) {
|
|
1723
1783
|
if (/\.css$/.test(source)) return;
|
|
1724
|
-
|
|
1725
|
-
|
|
1784
|
+
if (importer && importer.includes("localSharedImportMap")) return;
|
|
1785
|
+
if (key.endsWith("/") && source !== key.slice(0, -1)) return;
|
|
1786
|
+
const loadSharePath = getLoadShareModulePath(source, isRolldown, command);
|
|
1787
|
+
writeLoadShareModule(source, shared[key], command, isRolldown);
|
|
1726
1788
|
writePreBuildLibPath(source);
|
|
1727
1789
|
addUsedShares(source);
|
|
1728
1790
|
writeLocalSharedImportMap();
|
|
@@ -1730,7 +1792,6 @@ function proxySharedModule(options) {
|
|
|
1730
1792
|
}
|
|
1731
1793
|
};
|
|
1732
1794
|
}));
|
|
1733
|
-
const savePrebuild = new PromiseStore();
|
|
1734
1795
|
config.resolve.alias.push(...Object.keys(shared).map((key) => {
|
|
1735
1796
|
return command === "build" ? {
|
|
1736
1797
|
find: new RegExp(`(.*${PREBUILD_TAG}.*)`),
|
|
@@ -1743,11 +1804,22 @@ function proxySharedModule(options) {
|
|
|
1743
1804
|
async customResolver(source, importer) {
|
|
1744
1805
|
const pkgName = assertModuleFound(PREBUILD_TAG, source).name;
|
|
1745
1806
|
const result = await this.resolve(pkgName, importer).then((item) => item.id);
|
|
1746
|
-
if (!result.includes(_config.cacheDir)) savePrebuild.set(pkgName, Promise.resolve(result));
|
|
1807
|
+
if (_config && !result.includes(_config.cacheDir)) savePrebuild.set(pkgName, Promise.resolve(result));
|
|
1747
1808
|
return await this.resolve(await savePrebuild.get(pkgName), importer);
|
|
1748
1809
|
}
|
|
1749
1810
|
};
|
|
1750
1811
|
}));
|
|
1812
|
+
},
|
|
1813
|
+
configResolved(config) {
|
|
1814
|
+
_config = config;
|
|
1815
|
+
const isRolldown = !!config.experimental?.rolldownDev;
|
|
1816
|
+
Object.keys(shared).forEach((key) => {
|
|
1817
|
+
if (key.endsWith("/")) return;
|
|
1818
|
+
writeLoadShareModule(key, shared[key], _command, isRolldown);
|
|
1819
|
+
writePreBuildLibPath(key);
|
|
1820
|
+
addUsedShares(key);
|
|
1821
|
+
});
|
|
1822
|
+
writeLocalSharedImportMap();
|
|
1751
1823
|
}
|
|
1752
1824
|
}];
|
|
1753
1825
|
}
|
|
@@ -1858,20 +1930,60 @@ var normalizeOptimizeDeps_default = {
|
|
|
1858
1930
|
config.optimizeDeps = {};
|
|
1859
1931
|
optimizeDeps = config.optimizeDeps;
|
|
1860
1932
|
}
|
|
1861
|
-
optimizeDeps.force = true;
|
|
1862
1933
|
if (!optimizeDeps.include) optimizeDeps.include = [];
|
|
1934
|
+
if (!optimizeDeps.exclude) optimizeDeps.exclude = [];
|
|
1863
1935
|
if (!optimizeDeps.needsInterop) optimizeDeps.needsInterop = [];
|
|
1864
1936
|
}
|
|
1865
1937
|
};
|
|
1866
1938
|
|
|
1867
1939
|
//#endregion
|
|
1868
1940
|
//#region src/index.ts
|
|
1941
|
+
/**
|
|
1942
|
+
* Plugin that runs FIRST to create virtual module files in the config hook.
|
|
1943
|
+
* This prevents 504 "Outdated Optimize Dep" errors by ensuring files exist
|
|
1944
|
+
* before Vite's optimization phase.
|
|
1945
|
+
*/
|
|
1946
|
+
function createEarlyVirtualModulesPlugin(options) {
|
|
1947
|
+
const { shared, remotes, virtualModuleDir } = options;
|
|
1948
|
+
return {
|
|
1949
|
+
name: "vite:module-federation-early-init",
|
|
1950
|
+
enforce: "pre",
|
|
1951
|
+
config(config, { command: _command }) {
|
|
1952
|
+
if (_command !== "serve") return;
|
|
1953
|
+
const isRolldown = !!this?.meta?.rolldownVersion;
|
|
1954
|
+
const root = config.root || process.cwd();
|
|
1955
|
+
initVirtualModuleInfrastructure(root, virtualModuleDir);
|
|
1956
|
+
VirtualModule.setRoot(root);
|
|
1957
|
+
VirtualModule.ensureVirtualPackageExists();
|
|
1958
|
+
initVirtualModules(_command, getRemoteEntryId(options));
|
|
1959
|
+
if (remotes && Object.keys(remotes).length > 0) for (const key of Object.keys(remotes)) addUsedRemote(key, key);
|
|
1960
|
+
if (shared && Object.keys(shared).length > 0) {
|
|
1961
|
+
config.optimizeDeps = config.optimizeDeps || {};
|
|
1962
|
+
config.optimizeDeps.include = config.optimizeDeps.include || [];
|
|
1963
|
+
config.optimizeDeps.include.push(virtualRuntimeInitStatus.getImportId());
|
|
1964
|
+
for (const key of Object.keys(shared)) {
|
|
1965
|
+
if (key.endsWith("/")) continue;
|
|
1966
|
+
const shareItem = shared[key];
|
|
1967
|
+
getLoadShareModulePath(key, isRolldown);
|
|
1968
|
+
writeLoadShareModule(key, shareItem, _command, isRolldown);
|
|
1969
|
+
writePreBuildLibPath(key);
|
|
1970
|
+
addUsedShares(key);
|
|
1971
|
+
config.optimizeDeps.include.push(getPreBuildLibImportId(key));
|
|
1972
|
+
}
|
|
1973
|
+
writeLocalSharedImportMap();
|
|
1974
|
+
}
|
|
1975
|
+
}
|
|
1976
|
+
};
|
|
1977
|
+
}
|
|
1869
1978
|
function federation(mfUserOptions) {
|
|
1870
1979
|
const options = normalizeModuleFederationOptions(mfUserOptions);
|
|
1871
1980
|
const { name, remotes, shared, filename, hostInitInjectLocation } = options;
|
|
1872
1981
|
if (!name) throw new Error("name is required");
|
|
1982
|
+
const remoteEntryId = getRemoteEntryId(options);
|
|
1983
|
+
const virtualExposesId = getVirtualExposesId(options);
|
|
1873
1984
|
let command;
|
|
1874
1985
|
return [
|
|
1986
|
+
createEarlyVirtualModulesPlugin(options),
|
|
1875
1987
|
{
|
|
1876
1988
|
name: "vite:module-federation-config",
|
|
1877
1989
|
enforce: "pre",
|
|
@@ -1881,7 +1993,7 @@ function federation(mfUserOptions) {
|
|
|
1881
1993
|
configResolved(config) {
|
|
1882
1994
|
VirtualModule.setRoot(config.root);
|
|
1883
1995
|
VirtualModule.ensureVirtualPackageExists();
|
|
1884
|
-
initVirtualModules(command);
|
|
1996
|
+
initVirtualModules(command, remoteEntryId);
|
|
1885
1997
|
}
|
|
1886
1998
|
},
|
|
1887
1999
|
aliasToArrayPlugin_default,
|
|
@@ -1890,7 +2002,7 @@ function federation(mfUserOptions) {
|
|
|
1890
2002
|
...pluginDts(options),
|
|
1891
2003
|
...addEntry({
|
|
1892
2004
|
entryName: "remoteEntry",
|
|
1893
|
-
entryPath:
|
|
2005
|
+
entryPath: remoteEntryId,
|
|
1894
2006
|
fileName: filename
|
|
1895
2007
|
}),
|
|
1896
2008
|
...addEntry({
|
|
@@ -1900,22 +2012,51 @@ function federation(mfUserOptions) {
|
|
|
1900
2012
|
}),
|
|
1901
2013
|
...addEntry({
|
|
1902
2014
|
entryName: "virtualExposes",
|
|
1903
|
-
entryPath:
|
|
2015
|
+
entryPath: virtualExposesId
|
|
2016
|
+
}),
|
|
2017
|
+
pluginProxyRemoteEntry_default({
|
|
2018
|
+
options,
|
|
2019
|
+
remoteEntryId,
|
|
2020
|
+
virtualExposesId
|
|
1904
2021
|
}),
|
|
1905
|
-
pluginProxyRemoteEntry_default(),
|
|
1906
2022
|
pluginProxyRemotes_default(options),
|
|
1907
2023
|
...pluginModuleParseEnd_default((id) => {
|
|
1908
|
-
return id.includes(getHostAutoInitImportId()) || id.includes(
|
|
1909
|
-
}, {
|
|
2024
|
+
return id.includes(getHostAutoInitImportId()) || id.includes(remoteEntryId) || id.includes(virtualExposesId) || id.includes(getLocalSharedImportMapPath());
|
|
2025
|
+
}, {
|
|
2026
|
+
moduleParseTimeout: options.moduleParseTimeout,
|
|
2027
|
+
virtualExposesId
|
|
2028
|
+
}),
|
|
1910
2029
|
...proxySharedModule({ shared }),
|
|
1911
2030
|
{
|
|
1912
2031
|
name: "module-federation-esm-shims",
|
|
1913
2032
|
enforce: "pre",
|
|
1914
2033
|
apply: "build",
|
|
2034
|
+
config(config) {
|
|
2035
|
+
const runtimeInitId = virtualRuntimeInitStatus.getImportId();
|
|
2036
|
+
config.build = config.build || {};
|
|
2037
|
+
config.build.rollupOptions = config.build.rollupOptions || {};
|
|
2038
|
+
if (!Array.isArray(config.build.rollupOptions.output)) {
|
|
2039
|
+
const output = config.build.rollupOptions.output ||= {};
|
|
2040
|
+
const existingManualChunks = output.manualChunks;
|
|
2041
|
+
output.manualChunks = function(id) {
|
|
2042
|
+
if (id.includes(runtimeInitId)) return "runtimeInit";
|
|
2043
|
+
if (id.includes(LOAD_SHARE_TAG)) {
|
|
2044
|
+
const match = id.match(/([^/\\]+__loadShare__[^/\\]+)/);
|
|
2045
|
+
return match ? match[1] : "loadShare";
|
|
2046
|
+
}
|
|
2047
|
+
if (typeof existingManualChunks === "function") return existingManualChunks.apply(this, arguments);
|
|
2048
|
+
if (existingManualChunks && typeof existingManualChunks === "object") {
|
|
2049
|
+
for (const [key, ids] of Object.entries(existingManualChunks)) if (Array.isArray(ids) && ids.some((v) => id.includes(v))) return key;
|
|
2050
|
+
}
|
|
2051
|
+
};
|
|
2052
|
+
}
|
|
2053
|
+
},
|
|
1915
2054
|
load(id) {
|
|
1916
2055
|
if (id.startsWith("\0")) return;
|
|
1917
2056
|
if (id.includes(LOAD_SHARE_TAG) || id.includes(LOAD_REMOTE_TAG)) {
|
|
1918
2057
|
let code = (0, fs.readFileSync)(id, "utf-8");
|
|
2058
|
+
code = code.replace(/import\s+["'][^"']*__prebuild__[^"']*["']\s*;?/g, "");
|
|
2059
|
+
code = code.replace(/export\s+\*\s+from\s+["'][^"']*__prebuild__[^"']*["']\s*;?/g, "");
|
|
1919
2060
|
/**
|
|
1920
2061
|
* Shared/remote shims only have `export default exportModule`.
|
|
1921
2062
|
*
|
|
@@ -1938,6 +2079,134 @@ function federation(mfUserOptions) {
|
|
|
1938
2079
|
syntheticNamedExports: "__moduleExports"
|
|
1939
2080
|
};
|
|
1940
2081
|
}
|
|
2082
|
+
},
|
|
2083
|
+
generateBundle(_, bundle) {
|
|
2084
|
+
for (const [fileName, chunk] of Object.entries(bundle)) {
|
|
2085
|
+
if (chunk.type !== "chunk") continue;
|
|
2086
|
+
if (fileName.includes(LOAD_SHARE_TAG)) continue;
|
|
2087
|
+
let code = chunk.code;
|
|
2088
|
+
let m;
|
|
2089
|
+
const importedFromLoadShare = /* @__PURE__ */ new Set();
|
|
2090
|
+
const importRegex = /import\s*\{([^}]+)\}\s*from\s*["'][^"']*__loadShare__[^"']*["']/g;
|
|
2091
|
+
while ((m = importRegex.exec(code)) !== null) for (const spec of m[1].split(",")) {
|
|
2092
|
+
const parts = spec.trim().split(/\s+as\s+/);
|
|
2093
|
+
const local = (parts[1] || parts[0]).trim();
|
|
2094
|
+
if (local) importedFromLoadShare.add(local);
|
|
2095
|
+
}
|
|
2096
|
+
const allInits = [];
|
|
2097
|
+
for (const v of importedFromLoadShare) if (new RegExp("\\(" + v + "\\(\\)\\s*,\\s*\\w+\\(\\w+\\)\\)").test(code)) allInits.push(v);
|
|
2098
|
+
if (allInits.length === 0) continue;
|
|
2099
|
+
const awaits = allInits.map((v) => `await ${v}();`).join("");
|
|
2100
|
+
const lastFromRegex = /\bfrom\s*["'][^"']*["']\s*;?/g;
|
|
2101
|
+
let lastFromEnd = -1;
|
|
2102
|
+
while ((m = lastFromRegex.exec(code)) !== null) lastFromEnd = m.index + m[0].length;
|
|
2103
|
+
if (lastFromEnd !== -1) {
|
|
2104
|
+
chunk.code = code.slice(0, lastFromEnd) + awaits + code.slice(lastFromEnd);
|
|
2105
|
+
continue;
|
|
2106
|
+
}
|
|
2107
|
+
const exportIdx = code.search(/\bexport\s*[{d]/);
|
|
2108
|
+
if (exportIdx !== -1) {
|
|
2109
|
+
chunk.code = code.slice(0, exportIdx) + awaits + code.slice(exportIdx);
|
|
2110
|
+
continue;
|
|
2111
|
+
}
|
|
2112
|
+
}
|
|
2113
|
+
const proxyChunks = /* @__PURE__ */ new Map();
|
|
2114
|
+
for (const [fileName, chunk] of Object.entries(bundle)) {
|
|
2115
|
+
if (chunk.type !== "chunk") continue;
|
|
2116
|
+
if (fileName.includes(LOAD_SHARE_TAG) && fileName.includes("commonjs-proxy")) proxyChunks.set(fileName, {
|
|
2117
|
+
code: chunk.code,
|
|
2118
|
+
fileName
|
|
2119
|
+
});
|
|
2120
|
+
}
|
|
2121
|
+
if (proxyChunks.size === 0) return;
|
|
2122
|
+
for (const [fileName, chunk] of Object.entries(bundle)) {
|
|
2123
|
+
if (chunk.type !== "chunk") continue;
|
|
2124
|
+
if (fileName.includes(LOAD_SHARE_TAG)) continue;
|
|
2125
|
+
let code = chunk.code;
|
|
2126
|
+
let modified = false;
|
|
2127
|
+
for (const [proxyFileName, proxyInfo] of proxyChunks) {
|
|
2128
|
+
const proxyBaseName = proxyFileName.replace(/^.*\//, "").replace(/\.js$/, "").replace(/-[A-Za-z0-9_-]+$/, "");
|
|
2129
|
+
const importMatch = new RegExp(`import\\s*\\{([^}]+)\\}\\s*from\\s*["']([^"']*${proxyBaseName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}[^"']*)["']\\s*;?`).exec(code);
|
|
2130
|
+
if (!importMatch) continue;
|
|
2131
|
+
const fullImport = importMatch[0];
|
|
2132
|
+
const bindings = importMatch[1].split(",").map((s) => {
|
|
2133
|
+
const parts = s.trim().split(/\s+as\s+/);
|
|
2134
|
+
return {
|
|
2135
|
+
imported: parts[0].trim(),
|
|
2136
|
+
local: (parts[1] || parts[0]).trim()
|
|
2137
|
+
};
|
|
2138
|
+
});
|
|
2139
|
+
const proxyCode = proxyInfo.code;
|
|
2140
|
+
const exportMapMatch = proxyCode.match(/export\s*\{([^}]+)\}/);
|
|
2141
|
+
if (!exportMapMatch) continue;
|
|
2142
|
+
const exportMap = {};
|
|
2143
|
+
for (const entry of exportMapMatch[1].split(",")) {
|
|
2144
|
+
const parts = entry.trim().split(/\s+as\s+/);
|
|
2145
|
+
if (parts.length === 2) exportMap[parts[1].trim()] = parts[0].trim();
|
|
2146
|
+
}
|
|
2147
|
+
const inlineable = [];
|
|
2148
|
+
const nonInlineable = [];
|
|
2149
|
+
for (const b of bindings) {
|
|
2150
|
+
const proxyLocal = exportMap[b.imported];
|
|
2151
|
+
if (!proxyLocal) {
|
|
2152
|
+
nonInlineable.push(b);
|
|
2153
|
+
continue;
|
|
2154
|
+
}
|
|
2155
|
+
const funcRe = new RegExp(`function\\s+${proxyLocal}\\s*\\([^)]*\\)\\s*\\{`);
|
|
2156
|
+
if (funcRe.test(proxyCode)) {
|
|
2157
|
+
const funcStart = proxyCode.search(funcRe);
|
|
2158
|
+
let depth = 0;
|
|
2159
|
+
let funcEnd = funcStart;
|
|
2160
|
+
for (let i = proxyCode.indexOf("{", funcStart); i < proxyCode.length; i++) if (proxyCode[i] === "{") depth++;
|
|
2161
|
+
else if (proxyCode[i] === "}") {
|
|
2162
|
+
depth--;
|
|
2163
|
+
if (depth === 0) {
|
|
2164
|
+
funcEnd = i + 1;
|
|
2165
|
+
break;
|
|
2166
|
+
}
|
|
2167
|
+
}
|
|
2168
|
+
const renamedFunc = proxyCode.slice(funcStart, funcEnd).replace(new RegExp(`function\\s+${proxyLocal}\\s*\\(`), `function ${b.local}(`);
|
|
2169
|
+
inlineable.push({
|
|
2170
|
+
local: b.local,
|
|
2171
|
+
funcBody: renamedFunc
|
|
2172
|
+
});
|
|
2173
|
+
} else nonInlineable.push(b);
|
|
2174
|
+
}
|
|
2175
|
+
if (inlineable.length === 0) continue;
|
|
2176
|
+
let replacement = "";
|
|
2177
|
+
if (nonInlineable.length > 0) replacement = `import{${nonInlineable.map((b) => b.imported === b.local ? b.imported : `${b.imported} as ${b.local}`).join(",")}}from"${importMatch[2]}";`;
|
|
2178
|
+
replacement += inlineable.map((f) => f.funcBody).join("");
|
|
2179
|
+
code = code.replace(fullImport, replacement);
|
|
2180
|
+
modified = true;
|
|
2181
|
+
}
|
|
2182
|
+
if (modified) chunk.code = code;
|
|
2183
|
+
}
|
|
2184
|
+
}
|
|
2185
|
+
},
|
|
2186
|
+
{
|
|
2187
|
+
name: "module-federation-dev-await-shared-init",
|
|
2188
|
+
apply: "serve",
|
|
2189
|
+
enforce: "post",
|
|
2190
|
+
transform(code, id) {
|
|
2191
|
+
if (!id.includes(".vite/deps/")) return;
|
|
2192
|
+
const initPattern = /\b(init_\w+__loadShare__\w+)\b/g;
|
|
2193
|
+
const initFns = /* @__PURE__ */ new Set();
|
|
2194
|
+
let match;
|
|
2195
|
+
while ((match = initPattern.exec(code)) !== null) initFns.add(match[1]);
|
|
2196
|
+
if (initFns.size === 0) return;
|
|
2197
|
+
if (![...initFns].some((fn) => {
|
|
2198
|
+
return code.includes(`${fn}(),`) || code.includes(`${fn}()`);
|
|
2199
|
+
})) return;
|
|
2200
|
+
if (/await\s+init_\w+__loadShare__/.test(code)) return;
|
|
2201
|
+
if (code.includes("__esmMin")) return;
|
|
2202
|
+
const awaits = [...initFns].map((fn) => `await ${fn}();`).join("\n");
|
|
2203
|
+
const topLevelImportRe = /^import\s/gm;
|
|
2204
|
+
let lastImportIdx = -1;
|
|
2205
|
+
let importMatch;
|
|
2206
|
+
while ((importMatch = topLevelImportRe.exec(code)) !== null) lastImportIdx = importMatch.index;
|
|
2207
|
+
if (lastImportIdx === -1) return;
|
|
2208
|
+
const lineEnd = code.indexOf("\n", lastImportIdx);
|
|
2209
|
+
return code.slice(0, lineEnd + 1) + awaits + "\n" + code.slice(lineEnd + 1);
|
|
1941
2210
|
}
|
|
1942
2211
|
},
|
|
1943
2212
|
PluginDevProxyModuleTopLevelAwait(),
|
|
@@ -1946,16 +2215,22 @@ function federation(mfUserOptions) {
|
|
|
1946
2215
|
enforce: "post",
|
|
1947
2216
|
_options: options,
|
|
1948
2217
|
config(config, { command: _command }) {
|
|
2218
|
+
const isRolldown = !!this?.meta?.rolldownVersion;
|
|
2219
|
+
let implementation = options.implementation;
|
|
2220
|
+
if (isRolldown) implementation = implementation.replace(/\.cjs\.cjs$/, ".esm.js");
|
|
1949
2221
|
config.resolve.alias.push({
|
|
1950
2222
|
find: "@module-federation/runtime",
|
|
1951
|
-
replacement:
|
|
2223
|
+
replacement: implementation
|
|
1952
2224
|
});
|
|
1953
2225
|
config.build = (0, defu.default)(config.build || {}, { commonjsOptions: { strictRequires: "auto" } });
|
|
1954
2226
|
const virtualDir = options.virtualModuleDir || "__mf__virtual";
|
|
1955
2227
|
config.optimizeDeps?.include?.push("@module-federation/runtime");
|
|
1956
2228
|
config.optimizeDeps?.include?.push(virtualDir);
|
|
1957
|
-
config.
|
|
1958
|
-
|
|
2229
|
+
if (isRolldown) config.build = (0, defu.default)(config.build || {}, { target: "esnext" });
|
|
2230
|
+
else {
|
|
2231
|
+
config.optimizeDeps?.needsInterop?.push(virtualDir);
|
|
2232
|
+
config.optimizeDeps?.needsInterop?.push(getLocalSharedImportMapPath());
|
|
2233
|
+
}
|
|
1959
2234
|
const resolvedTarget = options.target ?? (config.build?.ssr ? "node" : "web");
|
|
1960
2235
|
if (!config.define) config.define = {};
|
|
1961
2236
|
if (!("ENV_TARGET" in config.define)) config.define["ENV_TARGET"] = JSON.stringify(resolvedTarget);
|
|
@@ -1963,7 +2238,25 @@ function federation(mfUserOptions) {
|
|
|
1963
2238
|
}
|
|
1964
2239
|
},
|
|
1965
2240
|
...Manifest(),
|
|
1966
|
-
...VarRemoteEntry()
|
|
2241
|
+
...VarRemoteEntry(),
|
|
2242
|
+
...Object.keys(options.exposes).length > 0 ? [{
|
|
2243
|
+
name: "module-federation-fix-preload",
|
|
2244
|
+
enforce: "post",
|
|
2245
|
+
apply: "build",
|
|
2246
|
+
generateBundle(_, bundle) {
|
|
2247
|
+
for (const chunk of Object.values(bundle)) {
|
|
2248
|
+
if (chunk.type !== "chunk") continue;
|
|
2249
|
+
if (!chunk.code.includes("modulepreload")) continue;
|
|
2250
|
+
const replacement = "=function($1){return new URL(\"../\"+$1,import.meta.url).href}";
|
|
2251
|
+
const replaced = chunk.code.replace(/=\(?(\w+)(?:,\w+)?\)?\s*=>\s*["'`][^"'`]*["'`]\s*\+\s*\1/, replacement);
|
|
2252
|
+
if (replaced !== chunk.code) {
|
|
2253
|
+
chunk.code = replaced;
|
|
2254
|
+
continue;
|
|
2255
|
+
}
|
|
2256
|
+
chunk.code = chunk.code.replace(/=function\((\w+)(?:,\w+)?\)\{return\s*["'`][^"'`]*["'`]\s*\+\s*\1\s*\}/, replacement);
|
|
2257
|
+
}
|
|
2258
|
+
}
|
|
2259
|
+
}] : []
|
|
1967
2260
|
];
|
|
1968
2261
|
}
|
|
1969
2262
|
|