@module-federation/vite 1.11.1 → 1.12.1-next.1
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 +7 -0
- package/lib/index.cjs +404 -127
- package/lib/index.d.cts +7 -0
- package/lib/index.d.mts +7 -0
- package/lib/index.mjs +398 -118
- package/package.json +29 -25
package/lib/index.mjs
CHANGED
|
@@ -6,15 +6,13 @@ import * as path$1 from "pathe";
|
|
|
6
6
|
import path, { basename, dirname, join, parse, resolve } from "pathe";
|
|
7
7
|
import MagicString from "magic-string";
|
|
8
8
|
import { createFilter } from "@rollup/pluginutils";
|
|
9
|
-
import { walk } from "estree-walker";
|
|
10
9
|
import { normalizeOptions } from "@module-federation/sdk";
|
|
11
10
|
import { consumeTypesAPI, generateTypesAPI, isTSProject, normalizeConsumeTypesOptions, normalizeDtsOptions, normalizeGenerateTypesOptions } from "@module-federation/dts-plugin";
|
|
12
11
|
import { rpc } from "@module-federation/dts-plugin/core";
|
|
12
|
+
import { createRequire as createRequire$1 } from "module";
|
|
13
13
|
import { fileURLToPath } from "url";
|
|
14
|
-
|
|
15
14
|
//#region \0rolldown/runtime.js
|
|
16
15
|
var __require = /* @__PURE__ */ createRequire(import.meta.url);
|
|
17
|
-
|
|
18
16
|
//#endregion
|
|
19
17
|
//#region src/utils/mapCodeToCodeWithSourcemap.ts
|
|
20
18
|
async function mapCodeToCodeWithSourcemap(code) {
|
|
@@ -26,14 +24,14 @@ async function mapCodeToCodeWithSourcemap(code) {
|
|
|
26
24
|
map: s.generateMap({ hires: true })
|
|
27
25
|
};
|
|
28
26
|
}
|
|
29
|
-
|
|
30
27
|
//#endregion
|
|
31
28
|
//#region src/plugins/pluginAddEntry.ts
|
|
32
29
|
function getFirstHtmlEntryFile(entryFiles) {
|
|
33
30
|
return entryFiles.find((file) => file.endsWith(".html"));
|
|
34
31
|
}
|
|
35
32
|
const addEntry = ({ entryName, entryPath, fileName, inject = "entry" }) => {
|
|
36
|
-
|
|
33
|
+
const getEntryPath = () => typeof entryPath === "function" ? entryPath() : entryPath;
|
|
34
|
+
let devEntryPath = "";
|
|
37
35
|
let entryFiles = [];
|
|
38
36
|
let htmlFilePath;
|
|
39
37
|
let _command;
|
|
@@ -53,6 +51,8 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry" }) => {
|
|
|
53
51
|
},
|
|
54
52
|
configResolved(config) {
|
|
55
53
|
viteConfig = config;
|
|
54
|
+
const resolvedEntryPath = getEntryPath();
|
|
55
|
+
devEntryPath = resolvedEntryPath.startsWith("virtual:mf") ? "@id/" + resolvedEntryPath : resolvedEntryPath;
|
|
56
56
|
devEntryPath = config.base + devEntryPath.replace(/\\\\?/g, "/").replace(/.+?\:([/\\])[/\\]?/, "$1").replace(/^\//, "");
|
|
57
57
|
},
|
|
58
58
|
configureServer(server) {
|
|
@@ -94,7 +94,7 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry" }) => {
|
|
|
94
94
|
const emitFileOptions = {
|
|
95
95
|
name: entryName,
|
|
96
96
|
type: "chunk",
|
|
97
|
-
id:
|
|
97
|
+
id: getEntryPath(),
|
|
98
98
|
preserveSignature: "strict"
|
|
99
99
|
};
|
|
100
100
|
if (!hasHash) emitFileOptions.fileName = fileName;
|
|
@@ -140,12 +140,11 @@ const addEntry = ({ entryName, entryPath, fileName, inject = "entry" }) => {
|
|
|
140
140
|
},
|
|
141
141
|
transform(code, id) {
|
|
142
142
|
if (injectEntry() && entryFiles.some((file) => id.endsWith(file))) return mapCodeToCodeWithSourcemap(`
|
|
143
|
-
import ${JSON.stringify(
|
|
143
|
+
import ${JSON.stringify(getEntryPath())};
|
|
144
144
|
` + code);
|
|
145
145
|
}
|
|
146
146
|
}];
|
|
147
147
|
};
|
|
148
|
-
|
|
149
148
|
//#endregion
|
|
150
149
|
//#region src/plugins/pluginCheckAliasConflicts.ts
|
|
151
150
|
/**
|
|
@@ -185,19 +184,23 @@ function checkAliasConflicts(options) {
|
|
|
185
184
|
}
|
|
186
185
|
};
|
|
187
186
|
}
|
|
188
|
-
|
|
189
187
|
//#endregion
|
|
190
188
|
//#region src/plugins/pluginDevProxyModuleTopLevelAwait.ts
|
|
191
189
|
/**
|
|
192
190
|
* Solve the problem that dev mode dependency prebunding does not support top-level await syntax
|
|
193
191
|
*/
|
|
192
|
+
let walkPromise = null;
|
|
193
|
+
function loadWalk() {
|
|
194
|
+
walkPromise ||= import("estree-walker").then(({ walk }) => walk);
|
|
195
|
+
return walkPromise;
|
|
196
|
+
}
|
|
194
197
|
function PluginDevProxyModuleTopLevelAwait() {
|
|
195
198
|
const filterFunction = createFilter();
|
|
196
199
|
const processedFlag = "/* already-processed-by-dev-proxy-module-top-level-await */";
|
|
197
200
|
return {
|
|
198
201
|
name: "dev-proxy-module-top-level-await",
|
|
199
202
|
apply: "serve",
|
|
200
|
-
transform(code, id) {
|
|
203
|
+
async transform(code, id) {
|
|
201
204
|
if (code.includes(processedFlag)) return null;
|
|
202
205
|
if (!code.includes("/*mf top-level-await placeholder replacement mf*/")) return null;
|
|
203
206
|
if (!filterFunction(id)) return null;
|
|
@@ -208,7 +211,7 @@ function PluginDevProxyModuleTopLevelAwait() {
|
|
|
208
211
|
throw new Error(`${id}: ${e}`);
|
|
209
212
|
}
|
|
210
213
|
const magicString = new MagicString(code);
|
|
211
|
-
|
|
214
|
+
(await loadWalk())(ast, { enter(node) {
|
|
212
215
|
if (node.type === "ExportNamedDeclaration" && node.specifiers) {
|
|
213
216
|
const exportSpecifiers = node.specifiers.map((specifier) => specifier.exported.name);
|
|
214
217
|
const proxyStatements = exportSpecifiers.map((name) => `
|
|
@@ -250,7 +253,6 @@ function PluginDevProxyModuleTopLevelAwait() {
|
|
|
250
253
|
}
|
|
251
254
|
};
|
|
252
255
|
}
|
|
253
|
-
|
|
254
256
|
//#endregion
|
|
255
257
|
//#region src/plugins/pluginDts.ts
|
|
256
258
|
const DEFAULT_DEV_OPTIONS = {
|
|
@@ -478,7 +480,6 @@ function pluginDts(options) {
|
|
|
478
480
|
}
|
|
479
481
|
}];
|
|
480
482
|
}
|
|
481
|
-
|
|
482
483
|
//#endregion
|
|
483
484
|
//#region src/utils/normalizeModuleFederationOptions.ts
|
|
484
485
|
function normalizeExposesItem(key, item) {
|
|
@@ -553,8 +554,7 @@ function normalizeShareItem(key, shareItem) {
|
|
|
553
554
|
version = __require(path$1.join(removePathFromNpmPackage(key), "package.json")).version;
|
|
554
555
|
} catch (e1) {
|
|
555
556
|
try {
|
|
556
|
-
|
|
557
|
-
version = __require(localPath).version;
|
|
557
|
+
version = __require(path$1.join(process.cwd(), "node_modules", removePathFromNpmPackage(key), "package.json")).version;
|
|
558
558
|
} catch (e2) {
|
|
559
559
|
version = searchPackageVersion(key);
|
|
560
560
|
if (!version) console.error(e1);
|
|
@@ -645,11 +645,11 @@ function normalizeModuleFederationOptions(options) {
|
|
|
645
645
|
hostInitInjectLocation: options.hostInitInjectLocation || "html",
|
|
646
646
|
bundleAllCSS: options.bundleAllCSS || false,
|
|
647
647
|
moduleParseTimeout: options.moduleParseTimeout || 10,
|
|
648
|
+
moduleParseIdleTimeout: options.moduleParseIdleTimeout,
|
|
648
649
|
varFilename: options.varFilename,
|
|
649
650
|
target: options.target
|
|
650
651
|
};
|
|
651
652
|
}
|
|
652
|
-
|
|
653
653
|
//#endregion
|
|
654
654
|
//#region src/utils/packageNameUtils.ts
|
|
655
655
|
/**
|
|
@@ -678,7 +678,6 @@ function packageNameDecode(encoded) {
|
|
|
678
678
|
if (typeof encoded !== "string") throw new Error("A string encoded file name is required");
|
|
679
679
|
return encoded.replace(/_mf_0_/g, "@").replace(/_mf_1_/g, "/").replace(/_mf_2_/g, "-").replace(/_mf_3_/g, ".");
|
|
680
680
|
}
|
|
681
|
-
|
|
682
681
|
//#endregion
|
|
683
682
|
//#region src/utils/localSharedImportMap_temp.ts
|
|
684
683
|
/**
|
|
@@ -695,7 +694,6 @@ function createFile(filePath, content) {
|
|
|
695
694
|
mkdirSync(path.dirname(filePath), { recursive: true });
|
|
696
695
|
writeFileSync(filePath, content);
|
|
697
696
|
}
|
|
698
|
-
|
|
699
697
|
//#endregion
|
|
700
698
|
//#region src/utils/serializeRuntimeOptions.ts
|
|
701
699
|
/**
|
|
@@ -743,9 +741,22 @@ function serializeRuntimeOptions(options) {
|
|
|
743
741
|
for (const key in options) if (Object.prototype.hasOwnProperty.call(options, key)) topLevelProps.push(`${JSON.stringify(key)}: ${valueToCode(options[key])}`);
|
|
744
742
|
return `{${topLevelProps.join(", ")}}`;
|
|
745
743
|
}
|
|
746
|
-
|
|
747
744
|
//#endregion
|
|
748
745
|
//#region src/utils/VirtualModule.ts
|
|
746
|
+
/**
|
|
747
|
+
* Initialize virtual module infrastructure BEFORE VirtualModule class is used.
|
|
748
|
+
* This must be called in the config hook to ensure the directory exists
|
|
749
|
+
* before Vite's optimization phase.
|
|
750
|
+
*/
|
|
751
|
+
function initVirtualModuleInfrastructure(root, virtualModuleDir = "__mf__virtual") {
|
|
752
|
+
const virtualPackagePath = join(join(root, "node_modules"), virtualModuleDir);
|
|
753
|
+
mkdirSync(virtualPackagePath, { recursive: true });
|
|
754
|
+
writeFileSync(join(virtualPackagePath, "empty.js"), "");
|
|
755
|
+
writeFileSync(join(virtualPackagePath, "package.json"), JSON.stringify({
|
|
756
|
+
name: virtualModuleDir,
|
|
757
|
+
main: "empty.js"
|
|
758
|
+
}));
|
|
759
|
+
}
|
|
749
760
|
let rootDir;
|
|
750
761
|
function findNodeModulesDir(root = process.cwd()) {
|
|
751
762
|
let currentDir = root;
|
|
@@ -793,14 +804,12 @@ var VirtualModule = class {
|
|
|
793
804
|
const nodeModulesDir = getNodeModulesDir();
|
|
794
805
|
const { virtualModuleDir } = getNormalizeModuleFederationOptions();
|
|
795
806
|
const virtualPackagePath = resolve(nodeModulesDir, virtualModuleDir);
|
|
796
|
-
|
|
797
|
-
|
|
798
|
-
|
|
799
|
-
|
|
800
|
-
|
|
801
|
-
|
|
802
|
-
}));
|
|
803
|
-
}
|
|
807
|
+
mkdirSync(virtualPackagePath, { recursive: true });
|
|
808
|
+
writeFileSync(resolve(virtualPackagePath, "empty.js"), "");
|
|
809
|
+
writeFileSync(resolve(virtualPackagePath, "package.json"), JSON.stringify({
|
|
810
|
+
name: virtualModuleDir,
|
|
811
|
+
main: "empty.js"
|
|
812
|
+
}));
|
|
804
813
|
}
|
|
805
814
|
static findModule(tag, str = "") {
|
|
806
815
|
if (!patternMap[tag]) patternMap[tag] = new RegExp(`(.*${packageNameEncode(tag)}(.+?)${packageNameEncode(tag)}.*)`);
|
|
@@ -831,12 +840,12 @@ var VirtualModule = class {
|
|
|
831
840
|
writeFile(this.getPath(), code, function() {});
|
|
832
841
|
}
|
|
833
842
|
};
|
|
834
|
-
|
|
835
843
|
//#endregion
|
|
836
844
|
//#region src/virtualModules/virtualExposes.ts
|
|
837
|
-
|
|
838
|
-
|
|
839
|
-
|
|
845
|
+
function getVirtualExposesId(options) {
|
|
846
|
+
return `virtual:mf-exposes:${`${options.name}__${options.filename}`.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
|
|
847
|
+
}
|
|
848
|
+
function generateExposes(options) {
|
|
840
849
|
return `
|
|
841
850
|
export default {
|
|
842
851
|
${Object.keys(options.exposes).map((key) => {
|
|
@@ -856,7 +865,6 @@ function generateExposes() {
|
|
|
856
865
|
}
|
|
857
866
|
`;
|
|
858
867
|
}
|
|
859
|
-
|
|
860
868
|
//#endregion
|
|
861
869
|
//#region src/virtualModules/virtualRuntimeInitStatus.ts
|
|
862
870
|
const virtualRuntimeInitStatus = new VirtualModule("runtimeInit");
|
|
@@ -881,15 +889,14 @@ if (!globalThis[globalKey]) {
|
|
|
881
889
|
${exportStatement}
|
|
882
890
|
`);
|
|
883
891
|
}
|
|
884
|
-
|
|
885
892
|
//#endregion
|
|
886
893
|
//#region src/virtualModules/virtualRemotes.ts
|
|
887
894
|
const cacheRemoteMap = {};
|
|
888
895
|
const LOAD_REMOTE_TAG = "__loadRemote__";
|
|
889
|
-
function getRemoteVirtualModule(remote, command) {
|
|
896
|
+
function getRemoteVirtualModule(remote, command, isRolldown) {
|
|
890
897
|
if (!cacheRemoteMap[remote]) {
|
|
891
|
-
cacheRemoteMap[remote] = new VirtualModule(remote, LOAD_REMOTE_TAG, ".js");
|
|
892
|
-
cacheRemoteMap[remote].writeSync(generateRemotes(remote, command));
|
|
898
|
+
cacheRemoteMap[remote] = new VirtualModule(remote, LOAD_REMOTE_TAG, isRolldown ? ".mjs" : ".js");
|
|
899
|
+
cacheRemoteMap[remote].writeSync(generateRemotes(remote, command, isRolldown));
|
|
893
900
|
}
|
|
894
901
|
return cacheRemoteMap[remote];
|
|
895
902
|
}
|
|
@@ -901,11 +908,11 @@ function addUsedRemote(remoteKey, remoteModule) {
|
|
|
901
908
|
function getUsedRemotesMap() {
|
|
902
909
|
return usedRemotesMap;
|
|
903
910
|
}
|
|
904
|
-
function generateRemotes(id, command) {
|
|
905
|
-
const
|
|
906
|
-
const importLine =
|
|
907
|
-
const awaitOrPlaceholder =
|
|
908
|
-
const exportLine =
|
|
911
|
+
function generateRemotes(id, command, isRolldown) {
|
|
912
|
+
const useESM = command === "build" || isRolldown;
|
|
913
|
+
const importLine = useESM ? `import { initPromise } from "${virtualRuntimeInitStatus.getImportId()}"` : `const {initPromise} = require("${virtualRuntimeInitStatus.getImportId()}")`;
|
|
914
|
+
const awaitOrPlaceholder = useESM ? "await " : "/*mf top-level-await placeholder replacement mf*/";
|
|
915
|
+
const exportLine = command === "serve" && useESM ? "export default exportModule.default ?? exportModule" : useESM ? "export default exportModule" : "module.exports = exportModule";
|
|
909
916
|
return `
|
|
910
917
|
${importLine}
|
|
911
918
|
const res = initPromise.then(runtime => runtime.loadRemote(${JSON.stringify(id)}))
|
|
@@ -913,9 +920,26 @@ function generateRemotes(id, command) {
|
|
|
913
920
|
${exportLine}
|
|
914
921
|
`;
|
|
915
922
|
}
|
|
916
|
-
|
|
917
923
|
//#endregion
|
|
918
924
|
//#region src/virtualModules/virtualShared_preBuild.ts
|
|
925
|
+
/**
|
|
926
|
+
* Even the resolveId hook cannot interfere with vite pre-build,
|
|
927
|
+
* and adding query parameter virtual modules will also fail.
|
|
928
|
+
* You can only proxy to the real file through alias
|
|
929
|
+
*/
|
|
930
|
+
/**
|
|
931
|
+
* shared will be proxied:
|
|
932
|
+
* 1. __prebuild__: export shareModule (pre-built source code of modules such as vue, react, etc.)
|
|
933
|
+
* 2. __loadShare__: load shareModule (mfRuntime.loadShare('vue'))
|
|
934
|
+
*/
|
|
935
|
+
function getPackageNamedExports(pkg) {
|
|
936
|
+
try {
|
|
937
|
+
const mod = createRequire$1(new URL("file://" + process.cwd() + "/package.json"))(pkg);
|
|
938
|
+
return Object.keys(mod).filter((k) => k !== "default" && k !== "__esModule");
|
|
939
|
+
} catch {
|
|
940
|
+
return [];
|
|
941
|
+
}
|
|
942
|
+
}
|
|
919
943
|
const preBuildCacheMap = {};
|
|
920
944
|
const PREBUILD_TAG = "__prebuild__";
|
|
921
945
|
function writePreBuildLibPath(pkg) {
|
|
@@ -928,17 +952,24 @@ function getPreBuildLibImportId(pkg) {
|
|
|
928
952
|
}
|
|
929
953
|
const LOAD_SHARE_TAG = "__loadShare__";
|
|
930
954
|
const loadShareCacheMap = {};
|
|
931
|
-
function getLoadShareModulePath(pkg) {
|
|
932
|
-
if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, ".js");
|
|
955
|
+
function getLoadShareModulePath(pkg, isRolldown, command) {
|
|
956
|
+
if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, isRolldown || command === "build" ? ".mjs" : ".js");
|
|
933
957
|
return loadShareCacheMap[pkg].getPath();
|
|
934
958
|
}
|
|
935
|
-
function writeLoadShareModule(pkg, shareItem, command) {
|
|
936
|
-
|
|
937
|
-
const
|
|
938
|
-
const
|
|
939
|
-
const
|
|
959
|
+
function writeLoadShareModule(pkg, shareItem, command, isRolldown) {
|
|
960
|
+
if (!loadShareCacheMap[pkg]) loadShareCacheMap[pkg] = new VirtualModule(pkg, LOAD_SHARE_TAG, isRolldown || command === "build" ? ".mjs" : ".js");
|
|
961
|
+
const useESM = command === "build" || isRolldown;
|
|
962
|
+
const importLine = useESM ? `import { initPromise } from "${virtualRuntimeInitStatus.getImportId()}"` : `const {initPromise} = require("${virtualRuntimeInitStatus.getImportId()}")`;
|
|
963
|
+
const awaitOrPlaceholder = useESM ? "await " : "/*mf top-level-await placeholder replacement mf*/";
|
|
964
|
+
const namedExports = getPackageNamedExports(pkg);
|
|
965
|
+
let exportLine;
|
|
966
|
+
if (namedExports.length > 0) {
|
|
967
|
+
const destructure = `const { ${namedExports.join(", ")} } = exportModule;`;
|
|
968
|
+
const namedExportLine = `export { ${namedExports.join(", ")} };`;
|
|
969
|
+
exportLine = useESM ? `export default exportModule;\n ${destructure}\n ${namedExportLine}` : `module.exports = exportModule;\n ${destructure}\n Object.assign(module.exports, { ${namedExports.join(", ")} });`;
|
|
970
|
+
} else exportLine = useESM ? `export default exportModule\n export * from ${JSON.stringify(getPreBuildLibImportId(pkg))}` : "module.exports = exportModule";
|
|
940
971
|
loadShareCacheMap[pkg].writeSync(`
|
|
941
|
-
|
|
972
|
+
import ${JSON.stringify(getPreBuildLibImportId(pkg))};
|
|
942
973
|
${command !== "build" ? `;() => import(${JSON.stringify(pkg)}).catch(() => {});` : ""}
|
|
943
974
|
${importLine}
|
|
944
975
|
const res = initPromise.then(runtime => runtime.loadShare(${JSON.stringify(pkg)}, {
|
|
@@ -948,11 +979,10 @@ function writeLoadShareModule(pkg, shareItem, command) {
|
|
|
948
979
|
requiredVersion: ${JSON.stringify(shareItem.shareConfig.requiredVersion)}
|
|
949
980
|
}}
|
|
950
981
|
}))
|
|
951
|
-
const exportModule = ${awaitOrPlaceholder}res.then(factory => factory())
|
|
982
|
+
const exportModule = ${awaitOrPlaceholder}res.then((factory) => (typeof factory === "function" ? factory() : factory))
|
|
952
983
|
${exportLine}
|
|
953
984
|
`);
|
|
954
985
|
}
|
|
955
|
-
|
|
956
986
|
//#endregion
|
|
957
987
|
//#region src/virtualModules/virtualRemoteEntry.ts
|
|
958
988
|
let usedShares = /* @__PURE__ */ new Set();
|
|
@@ -1047,7 +1077,10 @@ function generateLocalSharedImportMap() {
|
|
|
1047
1077
|
`;
|
|
1048
1078
|
}
|
|
1049
1079
|
const REMOTE_ENTRY_ID = "virtual:mf-REMOTE_ENTRY_ID";
|
|
1050
|
-
function
|
|
1080
|
+
function getRemoteEntryId(options) {
|
|
1081
|
+
return `${REMOTE_ENTRY_ID}:${`${options.name}__${options.filename}`.replace(/[^a-zA-Z0-9_-]/g, "_")}`;
|
|
1082
|
+
}
|
|
1083
|
+
function generateRemoteEntry(options, virtualExposesId = getVirtualExposesId(options)) {
|
|
1051
1084
|
const pluginImportNames = options.runtimePlugins.map((p, i) => {
|
|
1052
1085
|
if (typeof p === "string") return [
|
|
1053
1086
|
`$runtimePlugin_${i}`,
|
|
@@ -1063,7 +1096,7 @@ function generateRemoteEntry(options) {
|
|
|
1063
1096
|
return `
|
|
1064
1097
|
import {init as runtimeInit, loadRemote} from "@module-federation/runtime";
|
|
1065
1098
|
${pluginImportNames.map((item) => item[1]).join("\n")}
|
|
1066
|
-
import exposesMap from "${
|
|
1099
|
+
import exposesMap from "${virtualExposesId}"
|
|
1067
1100
|
import {usedShared, usedRemotes} from "${getLocalSharedImportMapPath()}"
|
|
1068
1101
|
import {
|
|
1069
1102
|
initResolve
|
|
@@ -1109,15 +1142,10 @@ function generateRemoteEntry(options) {
|
|
|
1109
1142
|
}
|
|
1110
1143
|
`;
|
|
1111
1144
|
}
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
* and will not inject remoteEntry
|
|
1115
|
-
*/
|
|
1116
|
-
const HOST_AUTO_INIT_TAG = "__H_A_I__";
|
|
1117
|
-
const hostAutoInitModule = new VirtualModule("hostAutoInit", HOST_AUTO_INIT_TAG);
|
|
1118
|
-
function writeHostAutoInit() {
|
|
1145
|
+
const hostAutoInitModule = new VirtualModule("hostAutoInit", "__H_A_I__");
|
|
1146
|
+
function writeHostAutoInit(remoteEntryId = REMOTE_ENTRY_ID) {
|
|
1119
1147
|
hostAutoInitModule.writeSync(`
|
|
1120
|
-
const remoteEntryPromise = import("${
|
|
1148
|
+
const remoteEntryPromise = import("${remoteEntryId}")
|
|
1121
1149
|
// __tla only serves as a hack for vite-plugin-top-level-await.
|
|
1122
1150
|
Promise.resolve(remoteEntryPromise)
|
|
1123
1151
|
.then(remoteEntry => {
|
|
@@ -1132,21 +1160,18 @@ function getHostAutoInitImportId() {
|
|
|
1132
1160
|
function getHostAutoInitPath() {
|
|
1133
1161
|
return hostAutoInitModule.getPath();
|
|
1134
1162
|
}
|
|
1135
|
-
|
|
1136
1163
|
//#endregion
|
|
1137
1164
|
//#region src/virtualModules/index.ts
|
|
1138
|
-
function initVirtualModules(command) {
|
|
1165
|
+
function initVirtualModules(command, remoteEntryId) {
|
|
1139
1166
|
writeLocalSharedImportMap();
|
|
1140
|
-
writeHostAutoInit();
|
|
1167
|
+
writeHostAutoInit(remoteEntryId);
|
|
1141
1168
|
writeRuntimeInitStatus(command);
|
|
1142
1169
|
}
|
|
1143
|
-
|
|
1144
1170
|
//#endregion
|
|
1145
1171
|
//#region src/utils/bundleHelpers.ts
|
|
1146
1172
|
function findRemoteEntryFile(filename, bundle) {
|
|
1147
1173
|
for (const [_, fileData] of Object.entries(bundle)) if (filename.replace(/[\[\]]/g, "_").replace(/\.[^/.]+$/, "") === fileData.name || fileData.name === "remoteEntry") return fileData.fileName;
|
|
1148
1174
|
}
|
|
1149
|
-
|
|
1150
1175
|
//#endregion
|
|
1151
1176
|
//#region src/utils/cssModuleHelpers.ts
|
|
1152
1177
|
const ASSET_TYPES = ["js", "css"];
|
|
@@ -1267,7 +1292,6 @@ const buildFileToShareKeyMap = async (shareKeys, resolveFn) => {
|
|
|
1267
1292
|
for (const resolution of resolutions) if (resolution?.file) fileToShareKey.set(resolution.file, resolution.shareKey);
|
|
1268
1293
|
return fileToShareKey;
|
|
1269
1294
|
};
|
|
1270
|
-
|
|
1271
1295
|
//#endregion
|
|
1272
1296
|
//#region src/utils/publicPath.ts
|
|
1273
1297
|
/**
|
|
@@ -1283,7 +1307,6 @@ function resolvePublicPath(options, viteBase, originalBase) {
|
|
|
1283
1307
|
if (viteBase) return viteBase.replace(/\/?$/, "/");
|
|
1284
1308
|
return "auto";
|
|
1285
1309
|
}
|
|
1286
|
-
|
|
1287
1310
|
//#endregion
|
|
1288
1311
|
//#region src/plugins/pluginMFManifest.ts
|
|
1289
1312
|
const Manifest = () => {
|
|
@@ -1498,7 +1521,6 @@ const Manifest = () => {
|
|
|
1498
1521
|
};
|
|
1499
1522
|
}
|
|
1500
1523
|
};
|
|
1501
|
-
|
|
1502
1524
|
//#endregion
|
|
1503
1525
|
//#region src/plugins/pluginModuleParseEnd.ts
|
|
1504
1526
|
let _resolve, _parseTimeout;
|
|
@@ -1515,12 +1537,19 @@ function setParseTimeout(timeout) {
|
|
|
1515
1537
|
_resolve(1);
|
|
1516
1538
|
}, timeout * 1e3);
|
|
1517
1539
|
}
|
|
1540
|
+
function resetIdleTimeout(timeout) {
|
|
1541
|
+
clearTimeout(_parseTimeout);
|
|
1542
|
+
_parseTimeout = setTimeout(() => {
|
|
1543
|
+
console.warn(`moduleParseIdleTimeout: no module activity for ${timeout}s, forcing resolve. Some shared/remote dependencies may be missing. Consider increasing moduleParseIdleTimeout.`);
|
|
1544
|
+
_resolve(1);
|
|
1545
|
+
}, timeout * 1e3);
|
|
1546
|
+
}
|
|
1518
1547
|
let parsePromise = promise;
|
|
1519
1548
|
let exposesParseEnd = false;
|
|
1520
1549
|
const parseStartSet = /* @__PURE__ */ new Set();
|
|
1521
1550
|
const parseEndSet = /* @__PURE__ */ new Set();
|
|
1522
1551
|
function pluginModuleParseEnd_default(excludeFn, options) {
|
|
1523
|
-
|
|
1552
|
+
const idleTimeout = options.moduleParseIdleTimeout;
|
|
1524
1553
|
return [
|
|
1525
1554
|
{
|
|
1526
1555
|
name: "_",
|
|
@@ -1533,6 +1562,10 @@ function pluginModuleParseEnd_default(excludeFn, options) {
|
|
|
1533
1562
|
enforce: "pre",
|
|
1534
1563
|
name: "parseStart",
|
|
1535
1564
|
apply: "build",
|
|
1565
|
+
buildStart() {
|
|
1566
|
+
if (idleTimeout) resetIdleTimeout(idleTimeout);
|
|
1567
|
+
else setParseTimeout(options.moduleParseTimeout);
|
|
1568
|
+
},
|
|
1536
1569
|
load(id) {
|
|
1537
1570
|
if (excludeFn(id)) return;
|
|
1538
1571
|
parseStartSet.add(id);
|
|
@@ -1544,7 +1577,8 @@ function pluginModuleParseEnd_default(excludeFn, options) {
|
|
|
1544
1577
|
apply: "build",
|
|
1545
1578
|
moduleParsed(module) {
|
|
1546
1579
|
const id = module.id;
|
|
1547
|
-
if (id ===
|
|
1580
|
+
if (id === options.virtualExposesId) exposesParseEnd = true;
|
|
1581
|
+
if (idleTimeout) resetIdleTimeout(idleTimeout);
|
|
1548
1582
|
if (excludeFn(id)) return;
|
|
1549
1583
|
parseEndSet.add(id);
|
|
1550
1584
|
if (exposesParseEnd && parseStartSet.size === parseEndSet.size) _resolve(1);
|
|
@@ -1552,11 +1586,10 @@ function pluginModuleParseEnd_default(excludeFn, options) {
|
|
|
1552
1586
|
}
|
|
1553
1587
|
];
|
|
1554
1588
|
}
|
|
1555
|
-
|
|
1556
1589
|
//#endregion
|
|
1557
1590
|
//#region src/plugins/pluginProxyRemoteEntry.ts
|
|
1558
1591
|
const filter = createFilter();
|
|
1559
|
-
function pluginProxyRemoteEntry_default() {
|
|
1592
|
+
function pluginProxyRemoteEntry_default({ options, remoteEntryId, virtualExposesId }) {
|
|
1560
1593
|
let viteConfig, _command;
|
|
1561
1594
|
return {
|
|
1562
1595
|
name: "proxyRemoteEntry",
|
|
@@ -1567,28 +1600,37 @@ function pluginProxyRemoteEntry_default() {
|
|
|
1567
1600
|
config(config, { command }) {
|
|
1568
1601
|
_command = command;
|
|
1569
1602
|
},
|
|
1603
|
+
async buildStart() {
|
|
1604
|
+
if (_command !== "build") return;
|
|
1605
|
+
for (const expose of Object.values(options.exposes)) {
|
|
1606
|
+
const resolved = await this.resolve(expose.import);
|
|
1607
|
+
if (resolved) this.emitFile({
|
|
1608
|
+
type: "chunk",
|
|
1609
|
+
id: resolved.id
|
|
1610
|
+
});
|
|
1611
|
+
}
|
|
1612
|
+
},
|
|
1570
1613
|
async resolveId(id, importer) {
|
|
1571
|
-
if (id ===
|
|
1572
|
-
if (id ===
|
|
1614
|
+
if (id === remoteEntryId) return remoteEntryId;
|
|
1615
|
+
if (id === virtualExposesId) return virtualExposesId;
|
|
1573
1616
|
if (_command === "serve" && id.includes(getHostAutoInitPath())) return id;
|
|
1574
|
-
if (importer ===
|
|
1575
|
-
typeof __filename === "string" ? __filename : fileURLToPath(import.meta.url);
|
|
1576
|
-
const resolved = await this.resolve(id,
|
|
1617
|
+
if (importer === remoteEntryId && !id.startsWith(".") && !id.startsWith("/") && !id.startsWith("\0") && !id.startsWith("virtual:")) {
|
|
1618
|
+
const importPath = typeof __filename === "string" ? __filename : fileURLToPath(import.meta.url);
|
|
1619
|
+
const resolved = await this.resolve(id, importPath, { skipSelf: true });
|
|
1577
1620
|
if (resolved) return resolved;
|
|
1578
1621
|
}
|
|
1579
1622
|
},
|
|
1580
1623
|
load(id) {
|
|
1581
|
-
if (id ===
|
|
1582
|
-
if (id ===
|
|
1624
|
+
if (id === remoteEntryId) return parsePromise.then((_) => generateRemoteEntry(options, virtualExposesId));
|
|
1625
|
+
if (id === virtualExposesId) return generateExposes(options);
|
|
1583
1626
|
if (_command === "serve" && id.includes(getHostAutoInitPath())) return id;
|
|
1584
1627
|
},
|
|
1585
1628
|
transform(code, id) {
|
|
1586
1629
|
return mapCodeToCodeWithSourcemap((() => {
|
|
1587
1630
|
if (!filter(id)) return;
|
|
1588
|
-
if (id.includes(
|
|
1589
|
-
if (id ===
|
|
1631
|
+
if (id.includes(remoteEntryId)) return parsePromise.then((_) => generateRemoteEntry(options, virtualExposesId));
|
|
1632
|
+
if (id === virtualExposesId) return generateExposes(options);
|
|
1590
1633
|
if (id.includes(getHostAutoInitPath())) {
|
|
1591
|
-
const options = getNormalizeModuleFederationOptions();
|
|
1592
1634
|
if (_command === "serve") {
|
|
1593
1635
|
const host = typeof viteConfig.server?.host === "string" && viteConfig.server.host !== "0.0.0.0" ? viteConfig.server.host : "localhost";
|
|
1594
1636
|
const publicPath = JSON.stringify(resolvePublicPath(options, viteConfig.base) + options.filename);
|
|
@@ -1609,7 +1651,6 @@ function pluginProxyRemoteEntry_default() {
|
|
|
1609
1651
|
}
|
|
1610
1652
|
};
|
|
1611
1653
|
}
|
|
1612
|
-
|
|
1613
1654
|
//#endregion
|
|
1614
1655
|
//#region src/plugins/pluginProxyRemotes.ts
|
|
1615
1656
|
createFilter();
|
|
@@ -1618,13 +1659,14 @@ function pluginProxyRemotes_default(options) {
|
|
|
1618
1659
|
return {
|
|
1619
1660
|
name: "proxyRemotes",
|
|
1620
1661
|
config(config, { command: _command }) {
|
|
1662
|
+
const isRolldown = !!this?.meta?.rolldownVersion;
|
|
1621
1663
|
Object.keys(remotes).forEach((key) => {
|
|
1622
1664
|
const remote = remotes[key];
|
|
1623
1665
|
config.resolve.alias.push({
|
|
1624
1666
|
find: new RegExp(`^(${remote.name}(\/.*|$))`),
|
|
1625
1667
|
replacement: "$1",
|
|
1626
1668
|
customResolver(source) {
|
|
1627
|
-
const remoteModule = getRemoteVirtualModule(source, _command);
|
|
1669
|
+
const remoteModule = getRemoteVirtualModule(source, _command, isRolldown);
|
|
1628
1670
|
addUsedRemote(remote.name, source);
|
|
1629
1671
|
return remoteModule.getPath();
|
|
1630
1672
|
}
|
|
@@ -1633,7 +1675,6 @@ function pluginProxyRemotes_default(options) {
|
|
|
1633
1675
|
}
|
|
1634
1676
|
};
|
|
1635
1677
|
}
|
|
1636
|
-
|
|
1637
1678
|
//#endregion
|
|
1638
1679
|
//#region src/utils/PromiseStore.ts
|
|
1639
1680
|
/**
|
|
@@ -1667,12 +1708,13 @@ var PromiseStore = class {
|
|
|
1667
1708
|
return pendingPromise;
|
|
1668
1709
|
}
|
|
1669
1710
|
};
|
|
1670
|
-
|
|
1671
1711
|
//#endregion
|
|
1672
1712
|
//#region src/plugins/pluginProxySharedModule_preBuild.ts
|
|
1673
1713
|
function proxySharedModule(options) {
|
|
1674
|
-
|
|
1714
|
+
const { shared = {} } = options;
|
|
1675
1715
|
let _config;
|
|
1716
|
+
let _command = "serve";
|
|
1717
|
+
const savePrebuild = new PromiseStore();
|
|
1676
1718
|
return [{
|
|
1677
1719
|
name: "generateLocalSharedImportMap",
|
|
1678
1720
|
enforce: "post",
|
|
@@ -1685,19 +1727,23 @@ function proxySharedModule(options) {
|
|
|
1685
1727
|
}, {
|
|
1686
1728
|
name: "proxyPreBuildShared",
|
|
1687
1729
|
enforce: "post",
|
|
1688
|
-
configResolved(config) {
|
|
1689
|
-
_config = config;
|
|
1690
|
-
},
|
|
1691
1730
|
config(config, { command }) {
|
|
1731
|
+
const isRolldown = !!this?.meta?.rolldownVersion;
|
|
1732
|
+
_command = command;
|
|
1692
1733
|
config.resolve.alias.push(...Object.keys(shared).map((key) => {
|
|
1693
|
-
const
|
|
1734
|
+
const keyBase = key.endsWith("/") ? key.slice(0, -1) : key;
|
|
1735
|
+
const escapeRegex = (value) => value.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
|
|
1736
|
+
const escapedKeyBase = escapeRegex(keyBase);
|
|
1737
|
+
const pattern = key.endsWith("/") ? `^(${escapedKeyBase}(?:\\/.*)?)$` : `^(${escapedKeyBase})$`;
|
|
1694
1738
|
return {
|
|
1695
1739
|
find: new RegExp(pattern),
|
|
1696
1740
|
replacement: "$1",
|
|
1697
1741
|
customResolver(source, importer) {
|
|
1698
1742
|
if (/\.css$/.test(source)) return;
|
|
1699
|
-
|
|
1700
|
-
|
|
1743
|
+
if (importer && importer.includes("localSharedImportMap")) return;
|
|
1744
|
+
if (key.endsWith("/") && source !== key.slice(0, -1)) return;
|
|
1745
|
+
const loadSharePath = getLoadShareModulePath(source, isRolldown, command);
|
|
1746
|
+
writeLoadShareModule(source, shared[key], command, isRolldown);
|
|
1701
1747
|
writePreBuildLibPath(source);
|
|
1702
1748
|
addUsedShares(source);
|
|
1703
1749
|
writeLocalSharedImportMap();
|
|
@@ -1705,7 +1751,6 @@ function proxySharedModule(options) {
|
|
|
1705
1751
|
}
|
|
1706
1752
|
};
|
|
1707
1753
|
}));
|
|
1708
|
-
const savePrebuild = new PromiseStore();
|
|
1709
1754
|
config.resolve.alias.push(...Object.keys(shared).map((key) => {
|
|
1710
1755
|
return command === "build" ? {
|
|
1711
1756
|
find: new RegExp(`(.*${PREBUILD_TAG}.*)`),
|
|
@@ -1718,15 +1763,25 @@ function proxySharedModule(options) {
|
|
|
1718
1763
|
async customResolver(source, importer) {
|
|
1719
1764
|
const pkgName = assertModuleFound(PREBUILD_TAG, source).name;
|
|
1720
1765
|
const result = await this.resolve(pkgName, importer).then((item) => item.id);
|
|
1721
|
-
if (!result.includes(_config.cacheDir)) savePrebuild.set(pkgName, Promise.resolve(result));
|
|
1766
|
+
if (_config && !result.includes(_config.cacheDir)) savePrebuild.set(pkgName, Promise.resolve(result));
|
|
1722
1767
|
return await this.resolve(await savePrebuild.get(pkgName), importer);
|
|
1723
1768
|
}
|
|
1724
1769
|
};
|
|
1725
1770
|
}));
|
|
1771
|
+
},
|
|
1772
|
+
configResolved(config) {
|
|
1773
|
+
_config = config;
|
|
1774
|
+
const isRolldown = !!config.experimental?.rolldownDev;
|
|
1775
|
+
Object.keys(shared).forEach((key) => {
|
|
1776
|
+
if (key.endsWith("/")) return;
|
|
1777
|
+
writeLoadShareModule(key, shared[key], _command, isRolldown);
|
|
1778
|
+
writePreBuildLibPath(key);
|
|
1779
|
+
addUsedShares(key);
|
|
1780
|
+
});
|
|
1781
|
+
writeLocalSharedImportMap();
|
|
1726
1782
|
}
|
|
1727
1783
|
}];
|
|
1728
1784
|
}
|
|
1729
|
-
|
|
1730
1785
|
//#endregion
|
|
1731
1786
|
//#region src/plugins/pluginVarRemoteEntry.ts
|
|
1732
1787
|
const VarRemoteEntry = () => {
|
|
@@ -1807,7 +1862,6 @@ const VarRemoteEntry = () => {
|
|
|
1807
1862
|
`;
|
|
1808
1863
|
}
|
|
1809
1864
|
};
|
|
1810
|
-
|
|
1811
1865
|
//#endregion
|
|
1812
1866
|
//#region src/utils/aliasToArrayPlugin.ts
|
|
1813
1867
|
var aliasToArrayPlugin_default = {
|
|
@@ -1822,7 +1876,6 @@ var aliasToArrayPlugin_default = {
|
|
|
1822
1876
|
}));
|
|
1823
1877
|
}
|
|
1824
1878
|
};
|
|
1825
|
-
|
|
1826
1879
|
//#endregion
|
|
1827
1880
|
//#region src/utils/normalizeOptimizeDeps.ts
|
|
1828
1881
|
var normalizeOptimizeDeps_default = {
|
|
@@ -1833,20 +1886,59 @@ var normalizeOptimizeDeps_default = {
|
|
|
1833
1886
|
config.optimizeDeps = {};
|
|
1834
1887
|
optimizeDeps = config.optimizeDeps;
|
|
1835
1888
|
}
|
|
1836
|
-
optimizeDeps.force = true;
|
|
1837
1889
|
if (!optimizeDeps.include) optimizeDeps.include = [];
|
|
1890
|
+
if (!optimizeDeps.exclude) optimizeDeps.exclude = [];
|
|
1838
1891
|
if (!optimizeDeps.needsInterop) optimizeDeps.needsInterop = [];
|
|
1839
1892
|
}
|
|
1840
1893
|
};
|
|
1841
|
-
|
|
1842
1894
|
//#endregion
|
|
1843
1895
|
//#region src/index.ts
|
|
1896
|
+
/**
|
|
1897
|
+
* Plugin that runs FIRST to create virtual module files in the config hook.
|
|
1898
|
+
* This prevents 504 "Outdated Optimize Dep" errors by ensuring files exist
|
|
1899
|
+
* before Vite's optimization phase.
|
|
1900
|
+
*/
|
|
1901
|
+
function createEarlyVirtualModulesPlugin(options) {
|
|
1902
|
+
const { shared, remotes, virtualModuleDir } = options;
|
|
1903
|
+
return {
|
|
1904
|
+
name: "vite:module-federation-early-init",
|
|
1905
|
+
enforce: "pre",
|
|
1906
|
+
config(config, { command: _command }) {
|
|
1907
|
+
if (_command !== "serve") return;
|
|
1908
|
+
const isRolldown = !!this?.meta?.rolldownVersion;
|
|
1909
|
+
const root = config.root || process.cwd();
|
|
1910
|
+
initVirtualModuleInfrastructure(root, virtualModuleDir);
|
|
1911
|
+
VirtualModule.setRoot(root);
|
|
1912
|
+
VirtualModule.ensureVirtualPackageExists();
|
|
1913
|
+
initVirtualModules(_command, getRemoteEntryId(options));
|
|
1914
|
+
if (remotes && Object.keys(remotes).length > 0) for (const key of Object.keys(remotes)) addUsedRemote(key, key);
|
|
1915
|
+
if (shared && Object.keys(shared).length > 0) {
|
|
1916
|
+
config.optimizeDeps = config.optimizeDeps || {};
|
|
1917
|
+
config.optimizeDeps.include = config.optimizeDeps.include || [];
|
|
1918
|
+
config.optimizeDeps.include.push(virtualRuntimeInitStatus.getImportId());
|
|
1919
|
+
for (const key of Object.keys(shared)) {
|
|
1920
|
+
if (key.endsWith("/")) continue;
|
|
1921
|
+
const shareItem = shared[key];
|
|
1922
|
+
getLoadShareModulePath(key, isRolldown);
|
|
1923
|
+
writeLoadShareModule(key, shareItem, _command, isRolldown);
|
|
1924
|
+
writePreBuildLibPath(key);
|
|
1925
|
+
addUsedShares(key);
|
|
1926
|
+
config.optimizeDeps.include.push(getPreBuildLibImportId(key));
|
|
1927
|
+
}
|
|
1928
|
+
writeLocalSharedImportMap();
|
|
1929
|
+
}
|
|
1930
|
+
}
|
|
1931
|
+
};
|
|
1932
|
+
}
|
|
1844
1933
|
function federation(mfUserOptions) {
|
|
1845
1934
|
const options = normalizeModuleFederationOptions(mfUserOptions);
|
|
1846
1935
|
const { name, remotes, shared, filename, hostInitInjectLocation } = options;
|
|
1847
1936
|
if (!name) throw new Error("name is required");
|
|
1937
|
+
const remoteEntryId = getRemoteEntryId(options);
|
|
1938
|
+
const virtualExposesId = getVirtualExposesId(options);
|
|
1848
1939
|
let command;
|
|
1849
1940
|
return [
|
|
1941
|
+
createEarlyVirtualModulesPlugin(options),
|
|
1850
1942
|
{
|
|
1851
1943
|
name: "vite:module-federation-config",
|
|
1852
1944
|
enforce: "pre",
|
|
@@ -1856,7 +1948,7 @@ function federation(mfUserOptions) {
|
|
|
1856
1948
|
configResolved(config) {
|
|
1857
1949
|
VirtualModule.setRoot(config.root);
|
|
1858
1950
|
VirtualModule.ensureVirtualPackageExists();
|
|
1859
|
-
initVirtualModules(command);
|
|
1951
|
+
initVirtualModules(command, remoteEntryId);
|
|
1860
1952
|
}
|
|
1861
1953
|
},
|
|
1862
1954
|
aliasToArrayPlugin_default,
|
|
@@ -1865,32 +1957,62 @@ function federation(mfUserOptions) {
|
|
|
1865
1957
|
...pluginDts(options),
|
|
1866
1958
|
...addEntry({
|
|
1867
1959
|
entryName: "remoteEntry",
|
|
1868
|
-
entryPath:
|
|
1960
|
+
entryPath: remoteEntryId,
|
|
1869
1961
|
fileName: filename
|
|
1870
1962
|
}),
|
|
1871
1963
|
...addEntry({
|
|
1872
1964
|
entryName: "hostInit",
|
|
1873
|
-
entryPath: getHostAutoInitPath(),
|
|
1965
|
+
entryPath: () => getHostAutoInitPath(),
|
|
1874
1966
|
inject: hostInitInjectLocation
|
|
1875
1967
|
}),
|
|
1876
1968
|
...addEntry({
|
|
1877
1969
|
entryName: "virtualExposes",
|
|
1878
|
-
entryPath:
|
|
1970
|
+
entryPath: virtualExposesId
|
|
1971
|
+
}),
|
|
1972
|
+
pluginProxyRemoteEntry_default({
|
|
1973
|
+
options,
|
|
1974
|
+
remoteEntryId,
|
|
1975
|
+
virtualExposesId
|
|
1879
1976
|
}),
|
|
1880
|
-
pluginProxyRemoteEntry_default(),
|
|
1881
1977
|
pluginProxyRemotes_default(options),
|
|
1882
1978
|
...pluginModuleParseEnd_default((id) => {
|
|
1883
|
-
return id.includes(getHostAutoInitImportId()) || id.includes(
|
|
1884
|
-
}, {
|
|
1979
|
+
return id.includes(getHostAutoInitImportId()) || id.includes(remoteEntryId) || id.includes(virtualExposesId) || id.includes(getLocalSharedImportMapPath());
|
|
1980
|
+
}, {
|
|
1981
|
+
moduleParseTimeout: options.moduleParseTimeout,
|
|
1982
|
+
moduleParseIdleTimeout: options.moduleParseIdleTimeout,
|
|
1983
|
+
virtualExposesId
|
|
1984
|
+
}),
|
|
1885
1985
|
...proxySharedModule({ shared }),
|
|
1886
1986
|
{
|
|
1887
1987
|
name: "module-federation-esm-shims",
|
|
1888
1988
|
enforce: "pre",
|
|
1889
1989
|
apply: "build",
|
|
1990
|
+
config(config) {
|
|
1991
|
+
const runtimeInitId = virtualRuntimeInitStatus.getImportId();
|
|
1992
|
+
config.build = config.build || {};
|
|
1993
|
+
config.build.rollupOptions = config.build.rollupOptions || {};
|
|
1994
|
+
if (!Array.isArray(config.build.rollupOptions.output)) {
|
|
1995
|
+
const output = config.build.rollupOptions.output ||= {};
|
|
1996
|
+
const existingManualChunks = output.manualChunks;
|
|
1997
|
+
output.manualChunks = function(id) {
|
|
1998
|
+
if (id.includes(runtimeInitId)) return "runtimeInit";
|
|
1999
|
+
if (id.includes("__loadShare__")) {
|
|
2000
|
+
const match = id.match(/([^/\\]+__loadShare__[^/\\]+)/);
|
|
2001
|
+
return match ? match[1] : "loadShare";
|
|
2002
|
+
}
|
|
2003
|
+
if (typeof existingManualChunks === "function") return existingManualChunks.apply(this, arguments);
|
|
2004
|
+
if (existingManualChunks && typeof existingManualChunks === "object") {
|
|
2005
|
+
for (const [key, ids] of Object.entries(existingManualChunks)) if (Array.isArray(ids) && ids.some((v) => id.includes(v))) return key;
|
|
2006
|
+
}
|
|
2007
|
+
};
|
|
2008
|
+
}
|
|
2009
|
+
},
|
|
1890
2010
|
load(id) {
|
|
1891
2011
|
if (id.startsWith("\0")) return;
|
|
1892
|
-
if (id.includes(
|
|
2012
|
+
if (id.includes("__loadShare__") || id.includes("__loadRemote__")) {
|
|
1893
2013
|
let code = readFileSync(id, "utf-8");
|
|
2014
|
+
code = code.replace(/import\s+["'][^"']*__prebuild__[^"']*["']\s*;?/g, "");
|
|
2015
|
+
code = code.replace(/export\s+\*\s+from\s+["'][^"']*__prebuild__[^"']*["']\s*;?/g, "");
|
|
1894
2016
|
/**
|
|
1895
2017
|
* Shared/remote shims only have `export default exportModule`.
|
|
1896
2018
|
*
|
|
@@ -1913,6 +2035,134 @@ function federation(mfUserOptions) {
|
|
|
1913
2035
|
syntheticNamedExports: "__moduleExports"
|
|
1914
2036
|
};
|
|
1915
2037
|
}
|
|
2038
|
+
},
|
|
2039
|
+
generateBundle(_, bundle) {
|
|
2040
|
+
for (const [fileName, chunk] of Object.entries(bundle)) {
|
|
2041
|
+
if (chunk.type !== "chunk") continue;
|
|
2042
|
+
if (fileName.includes("__loadShare__")) continue;
|
|
2043
|
+
let code = chunk.code;
|
|
2044
|
+
let m;
|
|
2045
|
+
const importedFromLoadShare = /* @__PURE__ */ new Set();
|
|
2046
|
+
const importRegex = /import\s*\{([^}]+)\}\s*from\s*["'][^"']*__loadShare__[^"']*["']/g;
|
|
2047
|
+
while ((m = importRegex.exec(code)) !== null) for (const spec of m[1].split(",")) {
|
|
2048
|
+
const parts = spec.trim().split(/\s+as\s+/);
|
|
2049
|
+
const local = (parts[1] || parts[0]).trim();
|
|
2050
|
+
if (local) importedFromLoadShare.add(local);
|
|
2051
|
+
}
|
|
2052
|
+
const allInits = [];
|
|
2053
|
+
for (const v of importedFromLoadShare) if (new RegExp("\\(" + v + "\\(\\)\\s*,\\s*\\w+\\(\\w+\\)\\)").test(code)) allInits.push(v);
|
|
2054
|
+
if (allInits.length === 0) continue;
|
|
2055
|
+
const awaits = allInits.map((v) => `await ${v}();`).join("");
|
|
2056
|
+
const lastFromRegex = /\bfrom\s*["'][^"']*["']\s*;?/g;
|
|
2057
|
+
let lastFromEnd = -1;
|
|
2058
|
+
while ((m = lastFromRegex.exec(code)) !== null) lastFromEnd = m.index + m[0].length;
|
|
2059
|
+
if (lastFromEnd !== -1) {
|
|
2060
|
+
chunk.code = code.slice(0, lastFromEnd) + awaits + code.slice(lastFromEnd);
|
|
2061
|
+
continue;
|
|
2062
|
+
}
|
|
2063
|
+
const exportIdx = code.search(/\bexport\s*[{d]/);
|
|
2064
|
+
if (exportIdx !== -1) {
|
|
2065
|
+
chunk.code = code.slice(0, exportIdx) + awaits + code.slice(exportIdx);
|
|
2066
|
+
continue;
|
|
2067
|
+
}
|
|
2068
|
+
}
|
|
2069
|
+
const proxyChunks = /* @__PURE__ */ new Map();
|
|
2070
|
+
for (const [fileName, chunk] of Object.entries(bundle)) {
|
|
2071
|
+
if (chunk.type !== "chunk") continue;
|
|
2072
|
+
if (fileName.includes("__loadShare__") && fileName.includes("commonjs-proxy")) proxyChunks.set(fileName, {
|
|
2073
|
+
code: chunk.code,
|
|
2074
|
+
fileName
|
|
2075
|
+
});
|
|
2076
|
+
}
|
|
2077
|
+
if (proxyChunks.size === 0) return;
|
|
2078
|
+
for (const [fileName, chunk] of Object.entries(bundle)) {
|
|
2079
|
+
if (chunk.type !== "chunk") continue;
|
|
2080
|
+
if (fileName.includes("__loadShare__")) continue;
|
|
2081
|
+
let code = chunk.code;
|
|
2082
|
+
let modified = false;
|
|
2083
|
+
for (const [proxyFileName, proxyInfo] of proxyChunks) {
|
|
2084
|
+
const proxyBaseName = proxyFileName.replace(/^.*\//, "").replace(/\.js$/, "").replace(/-[A-Za-z0-9_-]+$/, "");
|
|
2085
|
+
const importMatch = new RegExp(`import\\s*\\{([^}]+)\\}\\s*from\\s*["']([^"']*${proxyBaseName.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}[^"']*)["']\\s*;?`).exec(code);
|
|
2086
|
+
if (!importMatch) continue;
|
|
2087
|
+
const fullImport = importMatch[0];
|
|
2088
|
+
const bindings = importMatch[1].split(",").map((s) => {
|
|
2089
|
+
const parts = s.trim().split(/\s+as\s+/);
|
|
2090
|
+
return {
|
|
2091
|
+
imported: parts[0].trim(),
|
|
2092
|
+
local: (parts[1] || parts[0]).trim()
|
|
2093
|
+
};
|
|
2094
|
+
});
|
|
2095
|
+
const proxyCode = proxyInfo.code;
|
|
2096
|
+
const exportMapMatch = proxyCode.match(/export\s*\{([^}]+)\}/);
|
|
2097
|
+
if (!exportMapMatch) continue;
|
|
2098
|
+
const exportMap = {};
|
|
2099
|
+
for (const entry of exportMapMatch[1].split(",")) {
|
|
2100
|
+
const parts = entry.trim().split(/\s+as\s+/);
|
|
2101
|
+
if (parts.length === 2) exportMap[parts[1].trim()] = parts[0].trim();
|
|
2102
|
+
}
|
|
2103
|
+
const inlineable = [];
|
|
2104
|
+
const nonInlineable = [];
|
|
2105
|
+
for (const b of bindings) {
|
|
2106
|
+
const proxyLocal = exportMap[b.imported];
|
|
2107
|
+
if (!proxyLocal) {
|
|
2108
|
+
nonInlineable.push(b);
|
|
2109
|
+
continue;
|
|
2110
|
+
}
|
|
2111
|
+
const funcRe = new RegExp(`function\\s+${proxyLocal}\\s*\\([^)]*\\)\\s*\\{`);
|
|
2112
|
+
if (funcRe.test(proxyCode)) {
|
|
2113
|
+
const funcStart = proxyCode.search(funcRe);
|
|
2114
|
+
let depth = 0;
|
|
2115
|
+
let funcEnd = funcStart;
|
|
2116
|
+
for (let i = proxyCode.indexOf("{", funcStart); i < proxyCode.length; i++) if (proxyCode[i] === "{") depth++;
|
|
2117
|
+
else if (proxyCode[i] === "}") {
|
|
2118
|
+
depth--;
|
|
2119
|
+
if (depth === 0) {
|
|
2120
|
+
funcEnd = i + 1;
|
|
2121
|
+
break;
|
|
2122
|
+
}
|
|
2123
|
+
}
|
|
2124
|
+
const renamedFunc = proxyCode.slice(funcStart, funcEnd).replace(new RegExp(`function\\s+${proxyLocal}\\s*\\(`), `function ${b.local}(`);
|
|
2125
|
+
inlineable.push({
|
|
2126
|
+
local: b.local,
|
|
2127
|
+
funcBody: renamedFunc
|
|
2128
|
+
});
|
|
2129
|
+
} else nonInlineable.push(b);
|
|
2130
|
+
}
|
|
2131
|
+
if (inlineable.length === 0) continue;
|
|
2132
|
+
let replacement = "";
|
|
2133
|
+
if (nonInlineable.length > 0) replacement = `import{${nonInlineable.map((b) => b.imported === b.local ? b.imported : `${b.imported} as ${b.local}`).join(",")}}from"${importMatch[2]}";`;
|
|
2134
|
+
replacement += inlineable.map((f) => f.funcBody).join("");
|
|
2135
|
+
code = code.replace(fullImport, replacement);
|
|
2136
|
+
modified = true;
|
|
2137
|
+
}
|
|
2138
|
+
if (modified) chunk.code = code;
|
|
2139
|
+
}
|
|
2140
|
+
}
|
|
2141
|
+
},
|
|
2142
|
+
{
|
|
2143
|
+
name: "module-federation-dev-await-shared-init",
|
|
2144
|
+
apply: "serve",
|
|
2145
|
+
enforce: "post",
|
|
2146
|
+
transform(code, id) {
|
|
2147
|
+
if (!id.includes(".vite/deps/")) return;
|
|
2148
|
+
const initPattern = /\b(init_\w+__loadShare__\w+)\b/g;
|
|
2149
|
+
const initFns = /* @__PURE__ */ new Set();
|
|
2150
|
+
let match;
|
|
2151
|
+
while ((match = initPattern.exec(code)) !== null) initFns.add(match[1]);
|
|
2152
|
+
if (initFns.size === 0) return;
|
|
2153
|
+
if (![...initFns].some((fn) => {
|
|
2154
|
+
return code.includes(`${fn}(),`) || code.includes(`${fn}()`);
|
|
2155
|
+
})) return;
|
|
2156
|
+
if (/await\s+init_\w+__loadShare__/.test(code)) return;
|
|
2157
|
+
if (code.includes("__esmMin")) return;
|
|
2158
|
+
const awaits = [...initFns].map((fn) => `await ${fn}();`).join("\n");
|
|
2159
|
+
const topLevelImportRe = /^import\s/gm;
|
|
2160
|
+
let lastImportIdx = -1;
|
|
2161
|
+
let importMatch;
|
|
2162
|
+
while ((importMatch = topLevelImportRe.exec(code)) !== null) lastImportIdx = importMatch.index;
|
|
2163
|
+
if (lastImportIdx === -1) return;
|
|
2164
|
+
const lineEnd = code.indexOf("\n", lastImportIdx);
|
|
2165
|
+
return code.slice(0, lineEnd + 1) + awaits + "\n" + code.slice(lineEnd + 1);
|
|
1916
2166
|
}
|
|
1917
2167
|
},
|
|
1918
2168
|
PluginDevProxyModuleTopLevelAwait(),
|
|
@@ -1921,16 +2171,29 @@ function federation(mfUserOptions) {
|
|
|
1921
2171
|
enforce: "post",
|
|
1922
2172
|
_options: options,
|
|
1923
2173
|
config(config, { command: _command }) {
|
|
2174
|
+
const isRolldown = !!this?.meta?.rolldownVersion;
|
|
2175
|
+
let implementation = options.implementation;
|
|
2176
|
+
if (isRolldown) implementation = implementation.replace(/\.cjs\.cjs$/, ".esm.js");
|
|
1924
2177
|
config.resolve.alias.push({
|
|
1925
2178
|
find: "@module-federation/runtime",
|
|
1926
|
-
replacement:
|
|
2179
|
+
replacement: implementation
|
|
1927
2180
|
});
|
|
1928
2181
|
config.build = defu(config.build || {}, { commonjsOptions: { strictRequires: "auto" } });
|
|
1929
2182
|
const virtualDir = options.virtualModuleDir || "__mf__virtual";
|
|
1930
|
-
config.optimizeDeps
|
|
1931
|
-
config.optimizeDeps
|
|
1932
|
-
config.optimizeDeps
|
|
1933
|
-
config.optimizeDeps
|
|
2183
|
+
config.optimizeDeps ||= {};
|
|
2184
|
+
config.optimizeDeps.include ||= [];
|
|
2185
|
+
config.optimizeDeps.include.push("@module-federation/runtime");
|
|
2186
|
+
config.optimizeDeps.include.push(virtualDir);
|
|
2187
|
+
options.runtimePlugins.forEach((p) => {
|
|
2188
|
+
const pluginPath = typeof p === "string" ? p : p[0];
|
|
2189
|
+
if (pluginPath && !pluginPath.startsWith(".") && !pluginPath.startsWith("/") && !pluginPath.startsWith("\0") && !pluginPath.startsWith("virtual:")) config.optimizeDeps.include.push(pluginPath);
|
|
2190
|
+
});
|
|
2191
|
+
if (isRolldown) config.build = defu(config.build || {}, { target: "esnext" });
|
|
2192
|
+
else {
|
|
2193
|
+
config.optimizeDeps.needsInterop ||= [];
|
|
2194
|
+
config.optimizeDeps.needsInterop.push(virtualDir);
|
|
2195
|
+
config.optimizeDeps.needsInterop.push(getLocalSharedImportMapPath());
|
|
2196
|
+
}
|
|
1934
2197
|
const resolvedTarget = options.target ?? (config.build?.ssr ? "node" : "web");
|
|
1935
2198
|
if (!config.define) config.define = {};
|
|
1936
2199
|
if (!("ENV_TARGET" in config.define)) config.define["ENV_TARGET"] = JSON.stringify(resolvedTarget);
|
|
@@ -1938,9 +2201,26 @@ function federation(mfUserOptions) {
|
|
|
1938
2201
|
}
|
|
1939
2202
|
},
|
|
1940
2203
|
...Manifest(),
|
|
1941
|
-
...VarRemoteEntry()
|
|
2204
|
+
...VarRemoteEntry(),
|
|
2205
|
+
...Object.keys(options.exposes).length > 0 ? [{
|
|
2206
|
+
name: "module-federation-fix-preload",
|
|
2207
|
+
enforce: "post",
|
|
2208
|
+
apply: "build",
|
|
2209
|
+
generateBundle(_, bundle) {
|
|
2210
|
+
for (const chunk of Object.values(bundle)) {
|
|
2211
|
+
if (chunk.type !== "chunk") continue;
|
|
2212
|
+
if (!chunk.code.includes("modulepreload")) continue;
|
|
2213
|
+
const replacement = "=function($1){return new URL(\"../\"+$1,import.meta.url).href}";
|
|
2214
|
+
const replaced = chunk.code.replace(/=\(?(\w+)(?:,\w+)?\)?\s*=>\s*["'`][^"'`]*["'`]\s*\+\s*\1/, replacement);
|
|
2215
|
+
if (replaced !== chunk.code) {
|
|
2216
|
+
chunk.code = replaced;
|
|
2217
|
+
continue;
|
|
2218
|
+
}
|
|
2219
|
+
chunk.code = chunk.code.replace(/=function\((\w+)(?:,\w+)?\)\{return\s*["'`][^"'`]*["'`]\s*\+\s*\1\s*\}/, replacement);
|
|
2220
|
+
}
|
|
2221
|
+
}
|
|
2222
|
+
}] : []
|
|
1942
2223
|
];
|
|
1943
2224
|
}
|
|
1944
|
-
|
|
1945
2225
|
//#endregion
|
|
1946
|
-
export { federation };
|
|
2226
|
+
export { federation };
|