@module-federation/vite 1.7.1 → 1.8.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 +290 -141
- package/lib/index.esm.js +291 -142
- package/lib/index.modern.js +263 -130
- package/lib/index.umd.js +290 -141
- package/lib/plugins/pluginMFManifest.d.ts +1 -1
- package/lib/utils/__tests__/cssModuleHelpers.test.d.ts +1 -0
- package/lib/utils/__tests__/helpers.d.ts +2 -0
- package/lib/utils/__tests__/publicPath.test.d.ts +1 -0
- package/lib/utils/cssModuleHelpers.d.ts +75 -0
- package/lib/utils/normalizeModuleFederationOptions.d.ts +6 -0
- package/lib/utils/publicPath.d.ts +9 -0
- package/package.json +2 -1
package/lib/index.modern.js
CHANGED
|
@@ -2,7 +2,7 @@ import defu from 'defu';
|
|
|
2
2
|
import * as fs from 'fs';
|
|
3
3
|
import { mkdirSync, writeFileSync, existsSync, writeFile } from 'fs';
|
|
4
4
|
import * as path from 'pathe';
|
|
5
|
-
import path__default, { resolve, basename, parse, join, dirname
|
|
5
|
+
import path__default, { resolve, basename, parse, join, dirname } from 'pathe';
|
|
6
6
|
import { createFilter } from '@rollup/pluginutils';
|
|
7
7
|
import { walk } from 'estree-walker';
|
|
8
8
|
import MagicString from 'magic-string';
|
|
@@ -97,7 +97,7 @@ const addEntry = ({
|
|
|
97
97
|
emitFileOptions.fileName = fileName;
|
|
98
98
|
}
|
|
99
99
|
emitFileId = this.emitFile(emitFileOptions);
|
|
100
|
-
if (htmlFilePath) {
|
|
100
|
+
if (htmlFilePath && fs.existsSync(htmlFilePath)) {
|
|
101
101
|
const htmlContent = fs.readFileSync(htmlFilePath, 'utf-8');
|
|
102
102
|
const scriptRegex = /<script\s+[^>]*src=["']([^"']+)["'][^>]*>/gi;
|
|
103
103
|
let match;
|
|
@@ -138,10 +138,14 @@ const addEntry = ({
|
|
|
138
138
|
*/
|
|
139
139
|
function PluginDevProxyModuleTopLevelAwait() {
|
|
140
140
|
const filterFunction = createFilter();
|
|
141
|
+
const processedFlag = '/* already-processed-by-dev-proxy-module-top-level-await */';
|
|
141
142
|
return {
|
|
142
143
|
name: 'dev-proxy-module-top-level-await',
|
|
143
144
|
apply: 'serve',
|
|
144
145
|
transform(code, id) {
|
|
146
|
+
if (code.includes(processedFlag)) {
|
|
147
|
+
return null;
|
|
148
|
+
}
|
|
145
149
|
if (!code.includes('/*mf top-level-await placeholder replacement mf*/')) {
|
|
146
150
|
return null;
|
|
147
151
|
}
|
|
@@ -200,8 +204,9 @@ function PluginDevProxyModuleTopLevelAwait() {
|
|
|
200
204
|
}
|
|
201
205
|
}
|
|
202
206
|
});
|
|
207
|
+
const transformedCode = magicString.toString();
|
|
203
208
|
return {
|
|
204
|
-
code:
|
|
209
|
+
code: `${processedFlag}\n${transformedCode}`,
|
|
205
210
|
map: magicString.generateMap({
|
|
206
211
|
hires: true
|
|
207
212
|
})
|
|
@@ -406,6 +411,7 @@ function normalizeModuleFederationOptions(options) {
|
|
|
406
411
|
dev: options.dev,
|
|
407
412
|
dts: options.dts,
|
|
408
413
|
getPublicPath: options.getPublicPath,
|
|
414
|
+
publicPath: options.publicPath,
|
|
409
415
|
shareStrategy: options.shareStrategy || 'version-first',
|
|
410
416
|
ignoreOrigin: options.ignoreOrigin || false,
|
|
411
417
|
virtualModuleDir: options.virtualModuleDir || '__mf__virtual'
|
|
@@ -700,7 +706,7 @@ function generateLocalSharedImportMap() {
|
|
|
700
706
|
const options = getNormalizeModuleFederationOptions();
|
|
701
707
|
return `
|
|
702
708
|
const importMap = {
|
|
703
|
-
${Array.from(getUsedShares()).map(pkg => `
|
|
709
|
+
${Array.from(getUsedShares()).sort().map(pkg => `
|
|
704
710
|
${JSON.stringify(pkg)}: async () => {
|
|
705
711
|
let pkg = await import("${getPreBuildLibImportId(pkg)}")
|
|
706
712
|
return pkg
|
|
@@ -708,7 +714,7 @@ function generateLocalSharedImportMap() {
|
|
|
708
714
|
`).join(',')}
|
|
709
715
|
}
|
|
710
716
|
const usedShared = {
|
|
711
|
-
${Array.from(getUsedShares()).map(key => {
|
|
717
|
+
${Array.from(getUsedShares()).sort().map(key => {
|
|
712
718
|
const shareItem = getNormalizeShareItem(key);
|
|
713
719
|
if (!shareItem) return null;
|
|
714
720
|
return `
|
|
@@ -843,6 +849,153 @@ function initVirtualModules() {
|
|
|
843
849
|
writeRuntimeInitStatus();
|
|
844
850
|
}
|
|
845
851
|
|
|
852
|
+
const ASSET_TYPES = ['js', 'css'];
|
|
853
|
+
const LOAD_TIMINGS = ['sync', 'async'];
|
|
854
|
+
const JS_EXTENSIONS = ['.ts', '.tsx', '.jsx', '.mjs', '.cjs'];
|
|
855
|
+
/**
|
|
856
|
+
* Creates an empty asset map structure for tracking JS and CSS assets
|
|
857
|
+
* @returns Initialized asset map with sync/async arrays for JS and CSS
|
|
858
|
+
*/
|
|
859
|
+
const createEmptyAssetMap = () => ({
|
|
860
|
+
js: {
|
|
861
|
+
sync: [],
|
|
862
|
+
async: []
|
|
863
|
+
},
|
|
864
|
+
css: {
|
|
865
|
+
sync: [],
|
|
866
|
+
async: []
|
|
867
|
+
}
|
|
868
|
+
});
|
|
869
|
+
/**
|
|
870
|
+
* Tracks an asset in the preload map with deduplication
|
|
871
|
+
* @param map - The preload map to update
|
|
872
|
+
* @param key - The module key to track under
|
|
873
|
+
* @param fileName - The asset filename to track
|
|
874
|
+
* @param isAsync - Whether the asset is loaded async
|
|
875
|
+
* @param type - The asset type ('js' or 'css')
|
|
876
|
+
*/
|
|
877
|
+
const trackAsset = (map, key, fileName, isAsync, type) => {
|
|
878
|
+
if (!map[key]) {
|
|
879
|
+
map[key] = createEmptyAssetMap();
|
|
880
|
+
}
|
|
881
|
+
const target = isAsync ? map[key][type].async : map[key][type].sync;
|
|
882
|
+
if (!target.includes(fileName)) {
|
|
883
|
+
target.push(fileName);
|
|
884
|
+
}
|
|
885
|
+
};
|
|
886
|
+
/**
|
|
887
|
+
* Checks if a file is a CSS file by extension
|
|
888
|
+
* @param fileName - The filename to check
|
|
889
|
+
* @returns True if file has a CSS extension (.css, .scss, .less)
|
|
890
|
+
*/
|
|
891
|
+
const isCSSFile = fileName => {
|
|
892
|
+
return fileName.endsWith('.css') || fileName.endsWith('.scss') || fileName.endsWith('.less');
|
|
893
|
+
};
|
|
894
|
+
/**
|
|
895
|
+
* Collects all CSS assets from the bundle
|
|
896
|
+
* @param bundle - The Rollup output bundle
|
|
897
|
+
* @returns Set of CSS asset filenames
|
|
898
|
+
*/
|
|
899
|
+
const collectCssAssets = bundle => {
|
|
900
|
+
const cssAssets = new Set();
|
|
901
|
+
for (const [fileName, fileData] of Object.entries(bundle)) {
|
|
902
|
+
if (fileData.type === 'asset' && isCSSFile(fileName)) {
|
|
903
|
+
cssAssets.add(fileName);
|
|
904
|
+
}
|
|
905
|
+
}
|
|
906
|
+
return cssAssets;
|
|
907
|
+
};
|
|
908
|
+
/**
|
|
909
|
+
* Processes module assets and tracks them in the files map
|
|
910
|
+
* @param bundle - The Rollup output bundle
|
|
911
|
+
* @param filesMap - The preload map to populate
|
|
912
|
+
* @param moduleMatcher - Function that matches module paths to keys
|
|
913
|
+
*/
|
|
914
|
+
const processModuleAssets = (bundle, filesMap, moduleMatcher) => {
|
|
915
|
+
for (const [fileName, fileData] of Object.entries(bundle)) {
|
|
916
|
+
if (fileData.type !== 'chunk') continue;
|
|
917
|
+
if (!fileData.modules) continue;
|
|
918
|
+
for (const modulePath of Object.keys(fileData.modules)) {
|
|
919
|
+
const matchKey = moduleMatcher(modulePath);
|
|
920
|
+
if (!matchKey) continue;
|
|
921
|
+
// Track main JS chunk
|
|
922
|
+
trackAsset(filesMap, matchKey, fileName, false, 'js');
|
|
923
|
+
// Handle dynamic imports
|
|
924
|
+
if (fileData.dynamicImports) {
|
|
925
|
+
for (const dynamicImport of fileData.dynamicImports) {
|
|
926
|
+
const importData = bundle[dynamicImport];
|
|
927
|
+
if (!importData) continue;
|
|
928
|
+
const isCss = isCSSFile(dynamicImport);
|
|
929
|
+
trackAsset(filesMap, matchKey, dynamicImport, true, isCss ? 'css' : 'js');
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
}
|
|
933
|
+
}
|
|
934
|
+
};
|
|
935
|
+
/**
|
|
936
|
+
* Deduplicates assets in the files map
|
|
937
|
+
* @param filesMap - The preload map to deduplicate
|
|
938
|
+
* @returns New deduplicated preload map
|
|
939
|
+
*/
|
|
940
|
+
const deduplicateAssets = filesMap => {
|
|
941
|
+
const result = {};
|
|
942
|
+
for (const [key, assetMaps] of Object.entries(filesMap)) {
|
|
943
|
+
result[key] = createEmptyAssetMap();
|
|
944
|
+
for (const type of ASSET_TYPES) {
|
|
945
|
+
for (const timing of LOAD_TIMINGS) {
|
|
946
|
+
result[key][type][timing] = Array.from(new Set(assetMaps[type][timing]));
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
}
|
|
950
|
+
return result;
|
|
951
|
+
};
|
|
952
|
+
/**
|
|
953
|
+
* Builds a mapping between module files and their share keys
|
|
954
|
+
* @param shareKeys - Set of share keys to map
|
|
955
|
+
* @param resolveFn - Function to resolve module paths
|
|
956
|
+
* @returns Map of file paths to their corresponding share keys
|
|
957
|
+
*/
|
|
958
|
+
const buildFileToShareKeyMap = async (shareKeys, resolveFn) => {
|
|
959
|
+
const fileToShareKey = new Map();
|
|
960
|
+
const resolutions = await Promise.all(Array.from(shareKeys).map(shareKey => resolveFn(getPreBuildLibImportId(shareKey)).then(resolution => {
|
|
961
|
+
var _resolution$id;
|
|
962
|
+
return {
|
|
963
|
+
shareKey,
|
|
964
|
+
file: resolution == null || (_resolution$id = resolution.id) == null ? void 0 : _resolution$id.split('?')[0]
|
|
965
|
+
};
|
|
966
|
+
}).catch(() => null)));
|
|
967
|
+
for (const resolution of resolutions) {
|
|
968
|
+
if (resolution != null && resolution.file) {
|
|
969
|
+
fileToShareKey.set(resolution.file, resolution.shareKey);
|
|
970
|
+
}
|
|
971
|
+
}
|
|
972
|
+
return fileToShareKey;
|
|
973
|
+
};
|
|
974
|
+
|
|
975
|
+
/**
|
|
976
|
+
* Resolves the public path for remote entries
|
|
977
|
+
* @param options - Module Federation options
|
|
978
|
+
* @param viteBase - Vite's base config value
|
|
979
|
+
* @param originalBase - Original base config before any transformations
|
|
980
|
+
* @returns The resolved public path
|
|
981
|
+
*/
|
|
982
|
+
function resolvePublicPath(options, viteBase, originalBase) {
|
|
983
|
+
// Use explicitly set publicPath if provided
|
|
984
|
+
if (options.publicPath) {
|
|
985
|
+
return options.publicPath;
|
|
986
|
+
}
|
|
987
|
+
// Handle empty original base case
|
|
988
|
+
if (originalBase === '') {
|
|
989
|
+
return 'auto';
|
|
990
|
+
}
|
|
991
|
+
// Use viteBase if available, ensuring it ends with a slash
|
|
992
|
+
if (viteBase) {
|
|
993
|
+
return viteBase.replace(/\/?$/, '/');
|
|
994
|
+
}
|
|
995
|
+
// Fallback to auto if no base is specified
|
|
996
|
+
return 'auto';
|
|
997
|
+
}
|
|
998
|
+
|
|
846
999
|
const Manifest = () => {
|
|
847
1000
|
const mfOptions = getNormalizeModuleFederationOptions();
|
|
848
1001
|
const {
|
|
@@ -856,21 +1009,43 @@ const Manifest = () => {
|
|
|
856
1009
|
mfManifestName = 'mf-manifest.json';
|
|
857
1010
|
}
|
|
858
1011
|
if (typeof manifestOptions !== 'boolean') {
|
|
859
|
-
mfManifestName = join((manifestOptions == null ? void 0 : manifestOptions.filePath) || '', (manifestOptions == null ? void 0 : manifestOptions.fileName) || '');
|
|
1012
|
+
mfManifestName = path.join((manifestOptions == null ? void 0 : manifestOptions.filePath) || '', (manifestOptions == null ? void 0 : manifestOptions.fileName) || '');
|
|
860
1013
|
}
|
|
861
|
-
let extensions;
|
|
862
1014
|
let root;
|
|
863
1015
|
let remoteEntryFile;
|
|
864
1016
|
let publicPath;
|
|
865
1017
|
let _command;
|
|
866
1018
|
let _originalConfigBase;
|
|
867
1019
|
let viteConfig;
|
|
1020
|
+
/**
|
|
1021
|
+
* Adds global CSS assets to all module exports
|
|
1022
|
+
* @param filesMap - The preload map to update
|
|
1023
|
+
* @param cssAssets - Set of CSS asset filenames to add
|
|
1024
|
+
*/
|
|
1025
|
+
const addCssAssetsToAllExports = (filesMap, cssAssets) => {
|
|
1026
|
+
Object.keys(filesMap).forEach(key => {
|
|
1027
|
+
cssAssets.forEach(cssAsset => {
|
|
1028
|
+
trackAsset(filesMap, key, cssAsset, false, 'css');
|
|
1029
|
+
});
|
|
1030
|
+
});
|
|
1031
|
+
};
|
|
868
1032
|
return [{
|
|
869
1033
|
name: 'module-federation-manifest',
|
|
870
1034
|
apply: 'serve',
|
|
1035
|
+
/**
|
|
1036
|
+
* Stores resolved Vite config for later use
|
|
1037
|
+
*/
|
|
1038
|
+
/**
|
|
1039
|
+
* Finalizes configuration after all plugins are resolved
|
|
1040
|
+
* @param config - Fully resolved Vite config
|
|
1041
|
+
*/
|
|
871
1042
|
configResolved(config) {
|
|
872
1043
|
viteConfig = config;
|
|
873
1044
|
},
|
|
1045
|
+
/**
|
|
1046
|
+
* Configures dev server middleware to handle manifest requests
|
|
1047
|
+
* @param server - Vite dev server instance
|
|
1048
|
+
*/
|
|
874
1049
|
configureServer(server) {
|
|
875
1050
|
server.middlewares.use((req, res, next) => {
|
|
876
1051
|
var _req$url;
|
|
@@ -918,119 +1093,85 @@ const Manifest = () => {
|
|
|
918
1093
|
}, {
|
|
919
1094
|
name: 'module-federation-manifest',
|
|
920
1095
|
enforce: 'post',
|
|
1096
|
+
/**
|
|
1097
|
+
* Initial plugin configuration
|
|
1098
|
+
* @param config - Vite config object
|
|
1099
|
+
* @param command - Current Vite command (serve/build)
|
|
1100
|
+
*/
|
|
921
1101
|
config(config, {
|
|
922
1102
|
command
|
|
923
1103
|
}) {
|
|
924
1104
|
if (!config.build) config.build = {};
|
|
925
|
-
if (!config.build.manifest)
|
|
1105
|
+
if (!config.build.manifest) {
|
|
1106
|
+
config.build.manifest = config.build.manifest || !!manifestOptions;
|
|
1107
|
+
}
|
|
926
1108
|
_command = command;
|
|
927
1109
|
_originalConfigBase = config.base;
|
|
928
1110
|
},
|
|
929
1111
|
configResolved(config) {
|
|
930
1112
|
root = config.root;
|
|
931
|
-
extensions = config.resolve.extensions || ['.mjs', '.js', '.mts', '.ts', '.jsx', '.tsx', '.json'];
|
|
932
1113
|
let base = config.base;
|
|
933
1114
|
if (_command === 'serve') {
|
|
934
1115
|
base = (config.server.origin || '') + config.base;
|
|
935
1116
|
}
|
|
936
|
-
publicPath =
|
|
1117
|
+
publicPath = resolvePublicPath(mfOptions, base, _originalConfigBase);
|
|
937
1118
|
},
|
|
1119
|
+
/**
|
|
1120
|
+
* Generates the module federation manifest file
|
|
1121
|
+
* @param options - Rollup output options
|
|
1122
|
+
* @param bundle - Generated bundle assets
|
|
1123
|
+
*/
|
|
938
1124
|
async generateBundle(options, bundle) {
|
|
939
1125
|
if (!mfManifestName) return;
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
const isModuleMatched = (relativeModulePath, preloadModule) => {
|
|
944
|
-
// 先尝试直接匹配
|
|
945
|
-
if (relativeModulePath === preloadModule) return true;
|
|
946
|
-
// 如果 preloadModule 没有后缀,尝试添加可能的后缀进行匹配
|
|
947
|
-
for (const ext of extensions) {
|
|
948
|
-
if (relativeModulePath === `${preloadModule}${ext}`) {
|
|
949
|
-
return true;
|
|
950
|
-
}
|
|
951
|
-
}
|
|
952
|
-
return false;
|
|
953
|
-
};
|
|
954
|
-
// 遍历打包生成的每个文件
|
|
955
|
-
for (const [fileName, fileData] of Object.entries(bundle)) {
|
|
1126
|
+
let filesMap = {};
|
|
1127
|
+
// First pass: Find remoteEntry file
|
|
1128
|
+
for (const [_, fileData] of Object.entries(bundle)) {
|
|
956
1129
|
if (mfOptions.filename.replace(/[\[\]]/g, '_').replace(/\.[^/.]+$/, '') === fileData.name || fileData.name === 'remoteEntry') {
|
|
957
1130
|
remoteEntryFile = fileData.fileName;
|
|
958
|
-
|
|
959
|
-
if (fileData.type === 'chunk') {
|
|
960
|
-
// 遍历该文件的所有模块
|
|
961
|
-
for (const modulePath of Object.keys(fileData.modules)) {
|
|
962
|
-
// 将绝对路径转换为相对于 Vite root 的相对路径
|
|
963
|
-
const relativeModulePath = relative(root, modulePath);
|
|
964
|
-
// 检查模块是否在 preloadModules 列表中
|
|
965
|
-
for (const preloadModule of exposesModules) {
|
|
966
|
-
const formatPreloadModule = preloadModule.replace('./', '');
|
|
967
|
-
if (isModuleMatched(relativeModulePath, formatPreloadModule)) {
|
|
968
|
-
if (!filesContainingModules[preloadModule]) {
|
|
969
|
-
filesContainingModules[preloadModule] = {
|
|
970
|
-
sync: [],
|
|
971
|
-
async: []
|
|
972
|
-
};
|
|
973
|
-
}
|
|
974
|
-
console.log(Object.keys(fileData.modules));
|
|
975
|
-
filesContainingModules[preloadModule].sync.push(fileName);
|
|
976
|
-
filesContainingModules[preloadModule].async.push(...(fileData.dynamicImports || []));
|
|
977
|
-
findSynchronousImports(fileName, filesContainingModules[preloadModule].sync);
|
|
978
|
-
break; // 如果找到匹配,跳出循环
|
|
979
|
-
}
|
|
980
|
-
}
|
|
981
|
-
}
|
|
982
|
-
}
|
|
983
|
-
}
|
|
984
|
-
// 递归查找模块的同步导入文件
|
|
985
|
-
function findSynchronousImports(fileName, array) {
|
|
986
|
-
const fileData = bundle[fileName];
|
|
987
|
-
if (fileData && fileData.type === 'chunk') {
|
|
988
|
-
array.push(fileName); // 将当前文件加入预加载列表
|
|
989
|
-
// 遍历该文件的同步导入文件
|
|
990
|
-
fileData.imports.forEach(importedFile => {
|
|
991
|
-
if (array.indexOf(importedFile) === -1) {
|
|
992
|
-
findSynchronousImports(importedFile, array); // 递归查找同步导入的文件
|
|
993
|
-
}
|
|
994
|
-
});
|
|
1131
|
+
break; // We can break early since we only need to find remoteEntry once
|
|
995
1132
|
}
|
|
996
1133
|
}
|
|
997
|
-
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
|
|
1002
|
-
|
|
1003
|
-
|
|
1004
|
-
|
|
1005
|
-
//
|
|
1006
|
-
|
|
1007
|
-
|
|
1008
|
-
if (sharedKey) {
|
|
1009
|
-
if (!filesContainingModules[sharedKey]) {
|
|
1010
|
-
filesContainingModules[sharedKey] = {
|
|
1011
|
-
sync: [],
|
|
1012
|
-
async: []
|
|
1013
|
-
};
|
|
1014
|
-
}
|
|
1015
|
-
filesContainingModules[sharedKey].sync.push(fileName);
|
|
1016
|
-
filesContainingModules[sharedKey].async.push(...(fileData.dynamicImports || []));
|
|
1017
|
-
findSynchronousImports(fileName, filesContainingModules[sharedKey].sync);
|
|
1018
|
-
break; // 如果找到匹配,跳出循环
|
|
1019
|
-
}
|
|
1134
|
+
// Second pass: Collect all CSS assets
|
|
1135
|
+
const allCssAssets = collectCssAssets(bundle);
|
|
1136
|
+
const exposesModules = Object.keys(mfOptions.exposes).map(item => mfOptions.exposes[item].import);
|
|
1137
|
+
// Process exposed modules
|
|
1138
|
+
processModuleAssets(bundle, filesMap, modulePath => {
|
|
1139
|
+
const absoluteModulePath = path.resolve(root, modulePath);
|
|
1140
|
+
return exposesModules.find(exposeModule => {
|
|
1141
|
+
const exposePath = path.resolve(root, exposeModule);
|
|
1142
|
+
// First try exact path match
|
|
1143
|
+
if (absoluteModulePath === exposePath) {
|
|
1144
|
+
return true;
|
|
1020
1145
|
}
|
|
1021
|
-
|
|
1022
|
-
|
|
1023
|
-
|
|
1024
|
-
|
|
1025
|
-
|
|
1146
|
+
// Then try path match without known extensions
|
|
1147
|
+
const getPathWithoutKnownExt = filePath => {
|
|
1148
|
+
const ext = path.extname(filePath);
|
|
1149
|
+
return JS_EXTENSIONS.includes(ext) ? path.join(path.dirname(filePath), path.basename(filePath, ext)) : filePath;
|
|
1150
|
+
};
|
|
1151
|
+
const modulePathNoExt = getPathWithoutKnownExt(absoluteModulePath);
|
|
1152
|
+
const exposePathNoExt = getPathWithoutKnownExt(exposePath);
|
|
1153
|
+
return modulePathNoExt === exposePathNoExt;
|
|
1154
|
+
});
|
|
1026
1155
|
});
|
|
1156
|
+
// Process shared modules
|
|
1157
|
+
const fileToShareKey = await buildFileToShareKeyMap(getUsedShares(), this.resolve.bind(this));
|
|
1158
|
+
processModuleAssets(bundle, filesMap, modulePath => fileToShareKey.get(modulePath));
|
|
1159
|
+
// Add all CSS assets to every export
|
|
1160
|
+
addCssAssetsToAllExports(filesMap, allCssAssets);
|
|
1161
|
+
// Final deduplication of all assets
|
|
1162
|
+
filesMap = deduplicateAssets(filesMap);
|
|
1027
1163
|
this.emitFile({
|
|
1028
1164
|
type: 'asset',
|
|
1029
1165
|
fileName: mfManifestName,
|
|
1030
|
-
source: JSON.stringify(generateMFManifest(
|
|
1166
|
+
source: JSON.stringify(generateMFManifest(filesMap))
|
|
1031
1167
|
});
|
|
1032
1168
|
}
|
|
1033
1169
|
}];
|
|
1170
|
+
/**
|
|
1171
|
+
* Generates the final manifest JSON structure
|
|
1172
|
+
* @param preloadMap - Map of module assets to include
|
|
1173
|
+
* @returns Complete manifest object
|
|
1174
|
+
*/
|
|
1034
1175
|
function generateMFManifest(preloadMap) {
|
|
1035
1176
|
const options = getNormalizeModuleFederationOptions();
|
|
1036
1177
|
const {
|
|
@@ -1041,23 +1182,17 @@ const Manifest = () => {
|
|
|
1041
1182
|
path: '',
|
|
1042
1183
|
type: 'module'
|
|
1043
1184
|
};
|
|
1044
|
-
|
|
1045
|
-
const
|
|
1046
|
-
|
|
1047
|
-
|
|
1048
|
-
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
alias: remoteKey,
|
|
1053
|
-
entry: '*'
|
|
1054
|
-
});
|
|
1055
|
-
});
|
|
1056
|
-
});
|
|
1057
|
-
// @ts-ignore
|
|
1185
|
+
// Process remotes
|
|
1186
|
+
const remotes = Array.from(Object.entries(getUsedRemotesMap())).flatMap(([remoteKey, modules]) => Array.from(modules).map(moduleKey => ({
|
|
1187
|
+
federationContainerName: options.remotes[remoteKey].entry,
|
|
1188
|
+
moduleName: moduleKey.replace(remoteKey, '').replace('/', ''),
|
|
1189
|
+
alias: remoteKey,
|
|
1190
|
+
entry: '*'
|
|
1191
|
+
})));
|
|
1192
|
+
// Process shared dependencies
|
|
1058
1193
|
const shared = Array.from(getUsedShares()).map(shareKey => {
|
|
1059
|
-
var _preloadMap$shareKey, _preloadMap$shareKey2;
|
|
1060
1194
|
const shareItem = getNormalizeShareItem(shareKey);
|
|
1195
|
+
const assets = preloadMap[shareKey] || createEmptyAssetMap();
|
|
1061
1196
|
return {
|
|
1062
1197
|
id: `${name}:${shareKey}`,
|
|
1063
1198
|
name: shareKey,
|
|
@@ -1065,42 +1200,42 @@ const Manifest = () => {
|
|
|
1065
1200
|
requiredVersion: shareItem.shareConfig.requiredVersion,
|
|
1066
1201
|
assets: {
|
|
1067
1202
|
js: {
|
|
1068
|
-
async:
|
|
1069
|
-
sync:
|
|
1203
|
+
async: assets.js.async,
|
|
1204
|
+
sync: assets.js.sync
|
|
1070
1205
|
},
|
|
1071
1206
|
css: {
|
|
1072
|
-
async:
|
|
1073
|
-
sync:
|
|
1207
|
+
async: assets.css.async,
|
|
1208
|
+
sync: assets.css.sync
|
|
1074
1209
|
}
|
|
1075
1210
|
}
|
|
1076
1211
|
};
|
|
1077
|
-
}).filter(
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
// assets(.css, .jpg, .svg等)其他资源, 不重要, 暂未处理
|
|
1212
|
+
}).filter(Boolean);
|
|
1213
|
+
// Process exposed modules
|
|
1214
|
+
const exposes = Object.entries(options.exposes).map(([key, value]) => {
|
|
1081
1215
|
const formatKey = key.replace('./', '');
|
|
1082
|
-
const sourceFile =
|
|
1216
|
+
const sourceFile = value.import;
|
|
1217
|
+
const assets = preloadMap[sourceFile] || createEmptyAssetMap();
|
|
1083
1218
|
return {
|
|
1084
|
-
id: name
|
|
1219
|
+
id: `${name}:${formatKey}`,
|
|
1085
1220
|
name: formatKey,
|
|
1086
1221
|
assets: {
|
|
1087
1222
|
js: {
|
|
1088
|
-
async:
|
|
1089
|
-
sync:
|
|
1223
|
+
async: assets.js.async,
|
|
1224
|
+
sync: assets.js.sync
|
|
1090
1225
|
},
|
|
1091
1226
|
css: {
|
|
1092
|
-
|
|
1093
|
-
|
|
1227
|
+
async: assets.css.async,
|
|
1228
|
+
sync: assets.css.sync
|
|
1094
1229
|
}
|
|
1095
1230
|
},
|
|
1096
1231
|
path: key
|
|
1097
1232
|
};
|
|
1098
|
-
}).filter(
|
|
1099
|
-
|
|
1233
|
+
}).filter(Boolean);
|
|
1234
|
+
return {
|
|
1100
1235
|
id: name,
|
|
1101
|
-
name
|
|
1236
|
+
name,
|
|
1102
1237
|
metaData: _extends({
|
|
1103
|
-
name
|
|
1238
|
+
name,
|
|
1104
1239
|
type: 'app',
|
|
1105
1240
|
buildInfo: {
|
|
1106
1241
|
buildVersion: '1.0.0',
|
|
@@ -1111,8 +1246,6 @@ const Manifest = () => {
|
|
|
1111
1246
|
types: {
|
|
1112
1247
|
path: '',
|
|
1113
1248
|
name: ''
|
|
1114
|
-
// "zip": "@mf-types.zip",
|
|
1115
|
-
// "api": "@mf-types.d.ts"
|
|
1116
1249
|
},
|
|
1117
1250
|
globalName: name,
|
|
1118
1251
|
pluginVersion: '0.2.5'
|
|
@@ -1125,7 +1258,6 @@ const Manifest = () => {
|
|
|
1125
1258
|
remotes,
|
|
1126
1259
|
exposes
|
|
1127
1260
|
};
|
|
1128
|
-
return result;
|
|
1129
1261
|
}
|
|
1130
1262
|
};
|
|
1131
1263
|
|
|
@@ -1225,10 +1357,11 @@ function pluginProxyRemoteEntry () {
|
|
|
1225
1357
|
if (_command === 'serve') {
|
|
1226
1358
|
var _viteConfig$server, _viteConfig$server2;
|
|
1227
1359
|
const host = typeof ((_viteConfig$server = viteConfig.server) == null ? void 0 : _viteConfig$server.host) === 'string' && viteConfig.server.host !== '0.0.0.0' ? viteConfig.server.host : 'localhost';
|
|
1360
|
+
const publicPath = JSON.stringify(resolvePublicPath(options, viteConfig.base) + options.filename);
|
|
1228
1361
|
return `
|
|
1229
1362
|
const origin = (window && ${!options.ignoreOrigin}) ? window.origin : "//${host}:${(_viteConfig$server2 = viteConfig.server) == null ? void 0 : _viteConfig$server2.port}"
|
|
1230
|
-
const remoteEntryPromise = await import(origin +
|
|
1231
|
-
// __tla only serves as a hack for vite-plugin-top-level-await.
|
|
1363
|
+
const remoteEntryPromise = await import(origin + ${publicPath})
|
|
1364
|
+
// __tla only serves as a hack for vite-plugin-top-level-await.
|
|
1232
1365
|
Promise.resolve(remoteEntryPromise)
|
|
1233
1366
|
.then(remoteEntry => {
|
|
1234
1367
|
return Promise.resolve(remoteEntry.__tla)
|