remote-reload-utils 0.0.14 → 0.0.17
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/CHANGELOG.md +27 -0
- package/dist/index.d.ts +2 -5
- package/dist/loader/index.d.ts +4 -2
- package/dist/loader/remote-source/index.d.ts +28 -0
- package/dist/loader/utils.d.ts +6 -2
- package/dist/main.cjs +850 -1007
- package/dist/main.js +199 -321
- package/dist/plugins/register-shared-react.d.ts +6 -0
- package/dist/types/index.d.ts +1 -1
- package/loadRemote.md +67 -2
- package/package.json +28 -2
- package/dist/components/ErrorBoundary.d.ts +0 -34
- package/dist/components/RemoteModuleProvider.d.ts +0 -95
- package/dist/components/SuspenseLoader.d.ts +0 -131
- package/dist/components/index.d.ts +0 -6
package/dist/main.cjs
CHANGED
|
@@ -1,25 +1,5 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
};
|
|
4
|
-
var __webpack_module_cache__ = {};
|
|
5
|
-
function __webpack_require__(moduleId) {
|
|
6
|
-
var cachedModule = __webpack_module_cache__[moduleId];
|
|
7
|
-
if (void 0 !== cachedModule) return cachedModule.exports;
|
|
8
|
-
var module = __webpack_module_cache__[moduleId] = {
|
|
9
|
-
exports: {}
|
|
10
|
-
};
|
|
11
|
-
__webpack_modules__[moduleId](module, module.exports, __webpack_require__);
|
|
12
|
-
return module.exports;
|
|
13
|
-
}
|
|
14
|
-
(()=>{
|
|
15
|
-
__webpack_require__.n = (module)=>{
|
|
16
|
-
var getter = module && module.__esModule ? ()=>module['default'] : ()=>module;
|
|
17
|
-
__webpack_require__.d(getter, {
|
|
18
|
-
a: getter
|
|
19
|
-
});
|
|
20
|
-
return getter;
|
|
21
|
-
};
|
|
22
|
-
})();
|
|
1
|
+
"use strict";
|
|
2
|
+
var __webpack_require__ = {};
|
|
23
3
|
(()=>{
|
|
24
4
|
__webpack_require__.d = (exports1, definition)=>{
|
|
25
5
|
for(var key in definition)if (__webpack_require__.o(definition, key) && !__webpack_require__.o(exports1, key)) Object.defineProperty(exports1, key, {
|
|
@@ -42,1042 +22,916 @@ function __webpack_require__(moduleId) {
|
|
|
42
22
|
};
|
|
43
23
|
})();
|
|
44
24
|
var __webpack_exports__ = {};
|
|
45
|
-
(
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
25
|
+
__webpack_require__.r(__webpack_exports__);
|
|
26
|
+
__webpack_require__.d(__webpack_exports__, {
|
|
27
|
+
compareVersions: ()=>compareVersions,
|
|
28
|
+
fetchAvailableVersions: ()=>fetchAvailableVersions,
|
|
29
|
+
sortVersions: ()=>sortVersions,
|
|
30
|
+
registerRemoteInstance: ()=>registerRemoteInstance,
|
|
31
|
+
fallbackPlugin: ()=>fallbackPlugin,
|
|
32
|
+
createEventBus: ()=>createEventBus,
|
|
33
|
+
getPreloadStatus: ()=>getPreloadStatus,
|
|
34
|
+
parseVersion: ()=>parseVersion,
|
|
35
|
+
resolveFinalVersion: ()=>resolveFinalVersion,
|
|
36
|
+
buildFinalUrls: ()=>buildFinalUrls,
|
|
37
|
+
fetchLatestVersion: ()=>fetchLatestVersion,
|
|
38
|
+
isRemoteLoaded: ()=>isRemoteLoaded,
|
|
39
|
+
getFinalSharedConfig: ()=>getFinalSharedConfig,
|
|
40
|
+
tryLoadRemote: ()=>tryLoadRemote,
|
|
41
|
+
getVersionCache: ()=>getVersionCache,
|
|
42
|
+
eventBus: ()=>eventBus,
|
|
43
|
+
loadRemoteMultiVersion: ()=>loadRemoteMultiVersion,
|
|
44
|
+
clearPreloadCache: ()=>clearPreloadCache,
|
|
45
|
+
loadReactVersion: ()=>loadReactVersion,
|
|
46
|
+
getRemoteHealthReport: ()=>getRemoteHealthReport,
|
|
47
|
+
getStableVersions: ()=>getStableVersions,
|
|
48
|
+
checkModuleLoadable: ()=>checkModuleLoadable,
|
|
49
|
+
buildCdnUrls: ()=>buildCdnUrls,
|
|
50
|
+
extractMajorVersion: ()=>extractMajorVersion,
|
|
51
|
+
preloadRemoteList: ()=>preloadRemoteList,
|
|
52
|
+
registerLoadedModule: ()=>registerLoadedModule,
|
|
53
|
+
unloadRemote: ()=>unloadRemote,
|
|
54
|
+
getCompatibleReactVersions: ()=>getCompatibleReactVersions,
|
|
55
|
+
cancelPreload: ()=>cancelPreload,
|
|
56
|
+
findCompatibleVersion: ()=>findCompatibleVersion,
|
|
57
|
+
getLoadedRemotes: ()=>getLoadedRemotes,
|
|
58
|
+
getLatestVersion: ()=>getLatestVersion,
|
|
59
|
+
preloadRemote: ()=>preloadRemote,
|
|
60
|
+
satisfiesVersion: ()=>satisfiesVersion,
|
|
61
|
+
formatHealthStatus: ()=>formatHealthStatus,
|
|
62
|
+
unloadAll: ()=>unloadAll,
|
|
63
|
+
createRemoteSourcePlugin: ()=>createRemoteSourcePlugin,
|
|
64
|
+
setVersionCache: ()=>setVersionCache,
|
|
65
|
+
isPrerelease: ()=>isPrerelease,
|
|
66
|
+
checkRemoteHealth: ()=>checkRemoteHealth,
|
|
67
|
+
checkVersionCompatibility: ()=>checkVersionCompatibility
|
|
68
|
+
});
|
|
69
|
+
const runtime_namespaceObject = require("@module-federation/enhanced/runtime");
|
|
70
|
+
async function loadReactVersion(version) {
|
|
71
|
+
const runtime = await (0, runtime_namespaceObject.createInstance)({
|
|
72
|
+
name: `react_${version}_runtime`,
|
|
73
|
+
remotes: [
|
|
74
|
+
{
|
|
75
|
+
name: `react@${version}`,
|
|
76
|
+
entry: `https://cdn.jsdelivr.net/npm/react@${version}/umd/react.production.min.js`,
|
|
77
|
+
type: 'var',
|
|
78
|
+
entryGlobalName: 'React'
|
|
79
|
+
},
|
|
80
|
+
{
|
|
81
|
+
name: `react-dom@${version}`,
|
|
82
|
+
entry: `https://cdn.jsdelivr.net/npm/react-dom@${version}/umd/react-dom.production.min.js`,
|
|
83
|
+
type: 'var',
|
|
84
|
+
entryGlobalName: 'ReactDOM'
|
|
85
|
+
}
|
|
86
|
+
]
|
|
98
87
|
});
|
|
99
|
-
|
|
100
|
-
const
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
const version = required.replace(/^(>=|<=|>|<|=|~|\^)/, '');
|
|
154
|
-
const cmp = compareVersions(current, version);
|
|
155
|
-
switch(operator){
|
|
156
|
-
case '>':
|
|
157
|
-
return cmp > 0;
|
|
158
|
-
case '>=':
|
|
159
|
-
return cmp >= 0;
|
|
160
|
-
case '<':
|
|
161
|
-
return cmp < 0;
|
|
162
|
-
case '<=':
|
|
163
|
-
return cmp <= 0;
|
|
164
|
-
case '=':
|
|
165
|
-
case '':
|
|
166
|
-
return 0 === cmp;
|
|
167
|
-
case '^':
|
|
168
|
-
return parseVersion(current).major === parseVersion(version).major && (parseVersion(current).major > 0 || parseVersion(current).minor === parseVersion(version).minor);
|
|
169
|
-
case '~':
|
|
170
|
-
return parseVersion(current).major === parseVersion(version).major && parseVersion(current).minor === parseVersion(version).minor;
|
|
171
|
-
default:
|
|
172
|
-
return 0 === cmp;
|
|
173
|
-
}
|
|
88
|
+
const React = await runtime.loadRemote(`react@${version}`);
|
|
89
|
+
const ReactDOM = await runtime.loadRemote(`react-dom@${version}`);
|
|
90
|
+
return {
|
|
91
|
+
React,
|
|
92
|
+
ReactDOM
|
|
93
|
+
};
|
|
94
|
+
}
|
|
95
|
+
function parseVersion(version) {
|
|
96
|
+
const cleaned = version.replace(/^v/i, '');
|
|
97
|
+
const parts = cleaned.split(/[-+]/);
|
|
98
|
+
const [major, minor, patch] = parts[0].split('.').map(Number);
|
|
99
|
+
return {
|
|
100
|
+
major: isNaN(major) ? 0 : major,
|
|
101
|
+
minor: isNaN(minor) ? 0 : minor,
|
|
102
|
+
patch: isNaN(patch) ? 0 : patch,
|
|
103
|
+
prerelease: parts[1],
|
|
104
|
+
build: parts[2],
|
|
105
|
+
raw: cleaned
|
|
106
|
+
};
|
|
107
|
+
}
|
|
108
|
+
function compareVersions(v1, v2) {
|
|
109
|
+
const p1 = parseVersion(v1);
|
|
110
|
+
const p2 = parseVersion(v2);
|
|
111
|
+
if (p1.major !== p2.major) return p1.major - p2.major;
|
|
112
|
+
if (p1.minor !== p2.minor) return p1.minor - p2.minor;
|
|
113
|
+
if (p1.patch !== p2.patch) return p1.patch - p2.patch;
|
|
114
|
+
if (p1.prerelease && !p2.prerelease) return -1;
|
|
115
|
+
if (!p1.prerelease && p2.prerelease) return 1;
|
|
116
|
+
if (p1.prerelease && p2.prerelease) return p1.prerelease.localeCompare(p2.prerelease);
|
|
117
|
+
return 0;
|
|
118
|
+
}
|
|
119
|
+
function satisfiesVersion(current, required) {
|
|
120
|
+
const opMatch = required.match(/^(>=|<=|>|<|=|~|\^)?/);
|
|
121
|
+
const operator = opMatch?.[1] || '=';
|
|
122
|
+
const version = required.replace(/^(>=|<=|>|<|=|~|\^)/, '');
|
|
123
|
+
const cmp = compareVersions(current, version);
|
|
124
|
+
switch(operator){
|
|
125
|
+
case '>':
|
|
126
|
+
return cmp > 0;
|
|
127
|
+
case '>=':
|
|
128
|
+
return cmp >= 0;
|
|
129
|
+
case '<':
|
|
130
|
+
return cmp < 0;
|
|
131
|
+
case '<=':
|
|
132
|
+
return cmp <= 0;
|
|
133
|
+
case '=':
|
|
134
|
+
case '':
|
|
135
|
+
return 0 === cmp;
|
|
136
|
+
case '^':
|
|
137
|
+
return parseVersion(current).major === parseVersion(version).major && (parseVersion(current).major > 0 || parseVersion(current).minor === parseVersion(version).minor);
|
|
138
|
+
case '~':
|
|
139
|
+
return parseVersion(current).major === parseVersion(version).major && parseVersion(current).minor === parseVersion(version).minor;
|
|
140
|
+
default:
|
|
141
|
+
return 0 === cmp;
|
|
174
142
|
}
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
143
|
+
}
|
|
144
|
+
function checkVersionCompatibility(currentVersion, requiredVersion, packageName) {
|
|
145
|
+
const isCompatible = satisfiesVersion(currentVersion, requiredVersion);
|
|
146
|
+
const current = parseVersion(currentVersion);
|
|
147
|
+
const required = parseVersion(requiredVersion);
|
|
148
|
+
let message;
|
|
149
|
+
let suggestion;
|
|
150
|
+
let severity;
|
|
151
|
+
if (isCompatible) {
|
|
152
|
+
message = `${packageName}@${currentVersion} 满足要求 ${requiredVersion}`;
|
|
153
|
+
severity = 'info';
|
|
154
|
+
} else {
|
|
155
|
+
const cmp = compareVersions(currentVersion, requiredVersion);
|
|
156
|
+
if (cmp < 0) {
|
|
157
|
+
message = `${packageName}@${currentVersion} 版本过低,需要 ${requiredVersion}`;
|
|
158
|
+
severity = 'error';
|
|
159
|
+
current.patch;
|
|
160
|
+
current.major, current.minor;
|
|
161
|
+
suggestion = `建议升级到 ${current.major}.${current.minor}.x 或更高版本`;
|
|
185
162
|
} else {
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
163
|
+
message = `${packageName}@${currentVersion} 版本过高,需要 ${requiredVersion}`;
|
|
164
|
+
severity = 'warning';
|
|
165
|
+
suggestion = `建议降级到 ${required.major}.${required.minor}.x 或匹配主版本的兼容版本`;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
return {
|
|
169
|
+
compatible: isCompatible,
|
|
170
|
+
currentVersion,
|
|
171
|
+
requiredVersion,
|
|
172
|
+
suggestion,
|
|
173
|
+
severity,
|
|
174
|
+
message
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
function findCompatibleVersion(availableVersions, range) {
|
|
178
|
+
let candidates = availableVersions;
|
|
179
|
+
if (range.exact) candidates = candidates.filter((v)=>v === range.exact);
|
|
180
|
+
else {
|
|
181
|
+
if (range.min) candidates = candidates.filter((v)=>compareVersions(v, range.min) >= 0);
|
|
182
|
+
if (range.max) candidates = candidates.filter((v)=>compareVersions(v, range.max) <= 0);
|
|
183
|
+
}
|
|
184
|
+
if (0 === candidates.length) return null;
|
|
185
|
+
return candidates.sort((a, b)=>compareVersions(b, a))[0];
|
|
186
|
+
}
|
|
187
|
+
function getCompatibleReactVersions(hostVersion) {
|
|
188
|
+
const host = parseVersion(hostVersion);
|
|
189
|
+
const versions = [];
|
|
190
|
+
for(let i = host.major; i >= 15; i--)for(let j = 0; j <= 5; j++){
|
|
191
|
+
const version = `${i}.${j}.0`;
|
|
192
|
+
if (checkVersionCompatibility(version, `^${host.major}.0.0`, 'react').compatible) versions.push(version);
|
|
193
|
+
}
|
|
194
|
+
const uniqueVersions = [];
|
|
195
|
+
const seen = new Set();
|
|
196
|
+
for (const v of versions)if (!seen.has(v)) {
|
|
197
|
+
seen.add(v);
|
|
198
|
+
uniqueVersions.push(v);
|
|
199
|
+
}
|
|
200
|
+
return uniqueVersions;
|
|
201
|
+
}
|
|
202
|
+
async function fetchAvailableVersions(pkg) {
|
|
203
|
+
try {
|
|
204
|
+
const res = await fetch(`https://registry.npmjs.org/${pkg}`);
|
|
205
|
+
if (!res.ok) return [];
|
|
206
|
+
const data = await res.json();
|
|
207
|
+
return Object.keys(data.versions || {});
|
|
208
|
+
} catch {
|
|
209
|
+
return [];
|
|
207
210
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
211
|
+
}
|
|
212
|
+
function sortVersions(versions, order = 'desc') {
|
|
213
|
+
return [
|
|
214
|
+
...versions
|
|
215
|
+
].sort((a, b)=>{
|
|
216
|
+
const cmp = compareVersions(a, b);
|
|
217
|
+
return 'desc' === order ? -cmp : cmp;
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
function getLatestVersion(versions) {
|
|
221
|
+
if (0 === versions.length) return null;
|
|
222
|
+
return sortVersions(versions, 'desc')[0];
|
|
223
|
+
}
|
|
224
|
+
function getStableVersions(versions) {
|
|
225
|
+
return versions.filter((v)=>!v.includes('alpha') && !v.includes('beta') && !v.includes('rc'));
|
|
226
|
+
}
|
|
227
|
+
function extractMajorVersion(version) {
|
|
228
|
+
return parseVersion(version).major;
|
|
229
|
+
}
|
|
230
|
+
function isPrerelease(version) {
|
|
231
|
+
const v = parseVersion(version);
|
|
232
|
+
return !!v.prerelease;
|
|
233
|
+
}
|
|
234
|
+
const fallbackPlugin = ()=>({
|
|
235
|
+
name: 'fallback-plugin',
|
|
236
|
+
errorLoadRemote (args) {
|
|
237
|
+
const fallback = 'fallback';
|
|
238
|
+
console.log(args, 'args');
|
|
239
|
+
return fallback;
|
|
214
240
|
}
|
|
215
|
-
|
|
216
|
-
|
|
241
|
+
});
|
|
242
|
+
const DEFAULT_CDN_TEMPLATES = [
|
|
243
|
+
'https://cdn.jsdelivr.net/npm/{pkg}@{version}/dist/remoteEntry.js',
|
|
244
|
+
'https://unpkg.com/{pkg}@{version}/dist/remoteEntry.js'
|
|
245
|
+
];
|
|
246
|
+
const DEFAULT_SHARED_CONFIG = {
|
|
247
|
+
react: {
|
|
248
|
+
shareConfig: {
|
|
249
|
+
singleton: true,
|
|
250
|
+
eager: true,
|
|
251
|
+
requiredVersion: false,
|
|
252
|
+
strictVersion: false
|
|
253
|
+
},
|
|
254
|
+
strategy: 'loaded-first'
|
|
255
|
+
},
|
|
256
|
+
'react-dom': {
|
|
257
|
+
shareConfig: {
|
|
258
|
+
singleton: true,
|
|
259
|
+
eager: true,
|
|
260
|
+
requiredVersion: false,
|
|
261
|
+
strictVersion: false
|
|
262
|
+
},
|
|
263
|
+
strategy: 'loaded-first'
|
|
264
|
+
},
|
|
265
|
+
'react-dom/client': {
|
|
266
|
+
shareConfig: {
|
|
267
|
+
singleton: true,
|
|
268
|
+
eager: true,
|
|
269
|
+
requiredVersion: false,
|
|
270
|
+
strictVersion: false
|
|
271
|
+
},
|
|
272
|
+
strategy: 'loaded-first'
|
|
273
|
+
},
|
|
274
|
+
'react/jsx-runtime': {
|
|
275
|
+
shareConfig: {
|
|
276
|
+
singleton: true,
|
|
277
|
+
eager: true,
|
|
278
|
+
requiredVersion: false,
|
|
279
|
+
strictVersion: false
|
|
280
|
+
},
|
|
281
|
+
strategy: 'loaded-first'
|
|
282
|
+
},
|
|
283
|
+
'react/jsx-dev-runtime': {
|
|
284
|
+
shareConfig: {
|
|
285
|
+
singleton: true,
|
|
286
|
+
eager: true,
|
|
287
|
+
requiredVersion: false,
|
|
288
|
+
strictVersion: false
|
|
289
|
+
},
|
|
290
|
+
strategy: 'loaded-first'
|
|
217
291
|
}
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
}
|
|
231
|
-
|
|
292
|
+
};
|
|
293
|
+
async function fetchLatestVersion(pkg) {
|
|
294
|
+
const res = await fetch(`https://registry.npmjs.org/${pkg}`);
|
|
295
|
+
if (!res.ok) throw new Error(`[MF] 无法获取 ${pkg} 的版本信息,状态码:${res.status}`);
|
|
296
|
+
const data = await res.json();
|
|
297
|
+
const latest = data['dist-tags']?.latest;
|
|
298
|
+
if (!latest) throw new Error(`[MF] 无法从 NPM 获取 ${pkg} 的 latest tag`);
|
|
299
|
+
return latest;
|
|
300
|
+
}
|
|
301
|
+
function getVersionCache() {
|
|
302
|
+
try {
|
|
303
|
+
const cacheStr = localStorage.getItem('mf-multi-version');
|
|
304
|
+
return cacheStr ? JSON.parse(cacheStr) : {};
|
|
305
|
+
} catch (e) {
|
|
306
|
+
console.error('[MF Cache] 读取缓存失败:', e);
|
|
307
|
+
return {};
|
|
232
308
|
}
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
309
|
+
}
|
|
310
|
+
function setVersionCache(pkg, version) {
|
|
311
|
+
try {
|
|
312
|
+
const cache = getVersionCache();
|
|
313
|
+
cache[pkg] = cache[pkg] || {};
|
|
314
|
+
cache[pkg][version] = {
|
|
315
|
+
timestamp: Date.now()
|
|
316
|
+
};
|
|
317
|
+
localStorage.setItem('mf-multi-version', JSON.stringify(cache));
|
|
318
|
+
} catch (e) {
|
|
319
|
+
console.error('[MF Cache] 写入缓存失败:', e);
|
|
242
320
|
}
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
321
|
+
}
|
|
322
|
+
function buildCdnUrls(pkg, version) {
|
|
323
|
+
return DEFAULT_CDN_TEMPLATES.map((template)=>template.replace('{pkg}', pkg).replace('{version}', version));
|
|
324
|
+
}
|
|
325
|
+
const mfInstanceCache = new Map();
|
|
326
|
+
const mfInstanceLoadingCache = new Map();
|
|
327
|
+
function buildRemotesIdentity(remotes) {
|
|
328
|
+
if (0 === remotes.length) return '';
|
|
329
|
+
return remotes.map((remote)=>JSON.stringify({
|
|
330
|
+
name: remote.name,
|
|
331
|
+
entry: 'entry' in remote ? remote.entry : '',
|
|
332
|
+
version: 'version' in remote ? remote.version : '',
|
|
333
|
+
alias: remote.alias || '',
|
|
334
|
+
type: remote.type || '',
|
|
335
|
+
entryGlobalName: remote.entryGlobalName || ''
|
|
336
|
+
})).sort().join('|');
|
|
337
|
+
}
|
|
338
|
+
async function tryLoadRemote(scopeName, url, _retries, _delay, sharedConfig, plugins, extraRemotes = [], registerOptions = {}) {
|
|
339
|
+
const remotesIdentity = buildRemotesIdentity(extraRemotes);
|
|
340
|
+
const cacheKey = `${scopeName}::${url}::${remotesIdentity}::${registerOptions.force ? 'force' : 'normal'}`;
|
|
341
|
+
const cachedMfs = mfInstanceCache.get(cacheKey);
|
|
342
|
+
if (cachedMfs) return {
|
|
343
|
+
scopeName,
|
|
344
|
+
mf: cachedMfs
|
|
345
|
+
};
|
|
346
|
+
const loadingMfs = mfInstanceLoadingCache.get(cacheKey);
|
|
347
|
+
if (loadingMfs) return loadingMfs;
|
|
348
|
+
const loadPromise = Promise.resolve().then(()=>{
|
|
349
|
+
const mf = (0, runtime_namespaceObject.createInstance)({
|
|
350
|
+
name: 'host',
|
|
351
|
+
remotes: [
|
|
352
|
+
{
|
|
353
|
+
name: scopeName,
|
|
354
|
+
entry: url
|
|
355
|
+
}
|
|
356
|
+
],
|
|
357
|
+
shared: sharedConfig,
|
|
358
|
+
plugins: [
|
|
359
|
+
...plugins,
|
|
360
|
+
fallbackPlugin()
|
|
361
|
+
]
|
|
249
362
|
});
|
|
363
|
+
if (extraRemotes.length > 0) mf.registerRemotes(extraRemotes, registerOptions);
|
|
364
|
+
const result = {
|
|
365
|
+
scopeName,
|
|
366
|
+
mf
|
|
367
|
+
};
|
|
368
|
+
mfInstanceCache.set(cacheKey, mf);
|
|
369
|
+
return result;
|
|
370
|
+
});
|
|
371
|
+
mfInstanceLoadingCache.set(cacheKey, loadPromise);
|
|
372
|
+
try {
|
|
373
|
+
return await loadPromise;
|
|
374
|
+
} finally{
|
|
375
|
+
mfInstanceLoadingCache.delete(cacheKey);
|
|
250
376
|
}
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
377
|
+
}
|
|
378
|
+
function getFinalSharedConfig(customShared) {
|
|
379
|
+
const globalReact = window.React;
|
|
380
|
+
const globalReactDOM = window.ReactDOM;
|
|
381
|
+
const globalShared = {};
|
|
382
|
+
if (globalReact && globalReactDOM) {
|
|
383
|
+
const isValidReact = 'object' == typeof globalReact && 'function' == typeof globalReact.useCallback;
|
|
384
|
+
if (isValidReact) {
|
|
385
|
+
globalShared.react = {
|
|
386
|
+
version: globalReact.version || '18.0.0',
|
|
387
|
+
lib: ()=>globalReact,
|
|
388
|
+
shareConfig: {
|
|
389
|
+
singleton: true,
|
|
390
|
+
eager: true,
|
|
391
|
+
requiredVersion: false,
|
|
392
|
+
strictVersion: false
|
|
393
|
+
},
|
|
394
|
+
strategy: 'loaded-first'
|
|
395
|
+
};
|
|
396
|
+
globalShared['react-dom'] = {
|
|
397
|
+
version: globalReactDOM.version || '18.0.0',
|
|
398
|
+
lib: ()=>globalReactDOM,
|
|
399
|
+
shareConfig: {
|
|
400
|
+
singleton: true,
|
|
401
|
+
eager: true,
|
|
402
|
+
requiredVersion: false,
|
|
403
|
+
strictVersion: false
|
|
404
|
+
},
|
|
405
|
+
strategy: 'loaded-first'
|
|
406
|
+
};
|
|
407
|
+
globalShared['react-dom/client'] = {
|
|
408
|
+
version: globalReactDOM.version || '18.0.0',
|
|
409
|
+
lib: ()=>globalReactDOM,
|
|
410
|
+
shareConfig: {
|
|
411
|
+
singleton: true,
|
|
412
|
+
eager: true,
|
|
413
|
+
requiredVersion: false,
|
|
414
|
+
strictVersion: false
|
|
415
|
+
},
|
|
416
|
+
strategy: 'loaded-first'
|
|
417
|
+
};
|
|
418
|
+
console.log('[getFinalSharedConfig] Using global React instance', {
|
|
419
|
+
version: globalReact.version
|
|
420
|
+
});
|
|
421
|
+
} else console.warn('[getFinalSharedConfig] Global React found but is invalid', {
|
|
422
|
+
type: typeof globalReact,
|
|
423
|
+
useCallback: typeof globalReact?.useCallback
|
|
272
424
|
});
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
425
|
+
} else console.log('[getFinalSharedConfig] No global React found, using default shared config');
|
|
426
|
+
const mergedShared = {
|
|
427
|
+
...DEFAULT_SHARED_CONFIG,
|
|
428
|
+
...globalShared,
|
|
429
|
+
...customShared || {}
|
|
430
|
+
};
|
|
431
|
+
const keepSingletonPackages = [
|
|
432
|
+
'react',
|
|
433
|
+
'react-dom',
|
|
434
|
+
'react-dom/client',
|
|
435
|
+
'react/jsx-runtime',
|
|
436
|
+
'react/jsx-dev-runtime'
|
|
276
437
|
];
|
|
277
|
-
const
|
|
278
|
-
|
|
438
|
+
for (const pkgName of keepSingletonPackages){
|
|
439
|
+
const base = mergedShared[pkgName] || {};
|
|
440
|
+
mergedShared[pkgName] = {
|
|
441
|
+
...base,
|
|
442
|
+
strategy: 'loaded-first',
|
|
279
443
|
shareConfig: {
|
|
280
444
|
singleton: true,
|
|
281
445
|
eager: true,
|
|
282
|
-
requiredVersion: false
|
|
446
|
+
requiredVersion: false,
|
|
447
|
+
strictVersion: false,
|
|
448
|
+
...base.shareConfig || {}
|
|
283
449
|
}
|
|
284
|
-
}
|
|
285
|
-
'react-dom': {
|
|
286
|
-
shareConfig: {
|
|
287
|
-
singleton: true,
|
|
288
|
-
eager: true,
|
|
289
|
-
requiredVersion: false
|
|
290
|
-
}
|
|
291
|
-
}
|
|
292
|
-
};
|
|
293
|
-
async function fetchLatestVersion(pkg) {
|
|
294
|
-
const res = await fetch(`https://registry.npmjs.org/${pkg}`);
|
|
295
|
-
if (!res.ok) throw new Error(`[MF] 无法获取 ${pkg} 的版本信息,状态码:${res.status}`);
|
|
296
|
-
const data = await res.json();
|
|
297
|
-
const latest = data['dist-tags']?.latest;
|
|
298
|
-
if (!latest) throw new Error(`[MF] 无法从 NPM 获取 ${pkg} 的 latest tag`);
|
|
299
|
-
return latest;
|
|
450
|
+
};
|
|
300
451
|
}
|
|
301
|
-
function
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
452
|
+
if ('function' == typeof globalShared.react?.lib) mergedShared.react = {
|
|
453
|
+
...mergedShared.react || {},
|
|
454
|
+
lib: globalShared.react.lib,
|
|
455
|
+
version: globalShared.react.version
|
|
456
|
+
};
|
|
457
|
+
if ('function' == typeof globalShared['react-dom']?.lib) mergedShared['react-dom'] = {
|
|
458
|
+
...mergedShared['react-dom'] || {},
|
|
459
|
+
lib: globalShared['react-dom'].lib,
|
|
460
|
+
version: globalShared['react-dom'].version
|
|
461
|
+
};
|
|
462
|
+
if ('function' == typeof globalShared['react-dom/client']?.lib) mergedShared['react-dom/client'] = {
|
|
463
|
+
...mergedShared['react-dom/client'] || {},
|
|
464
|
+
lib: globalShared['react-dom/client'].lib,
|
|
465
|
+
version: globalShared['react-dom/client'].version
|
|
466
|
+
};
|
|
467
|
+
return mergedShared;
|
|
468
|
+
}
|
|
469
|
+
async function resolveFinalVersion(pkg, version, cacheTTL, revalidate) {
|
|
470
|
+
let finalVersion = version;
|
|
471
|
+
if ('latest' === version) {
|
|
472
|
+
const cache = getVersionCache();
|
|
473
|
+
const versions = cache[pkg] || {};
|
|
474
|
+
const latestCached = Object.keys(versions).sort((a, b)=>versions[b].timestamp - versions[a].timestamp)[0];
|
|
475
|
+
if (latestCached && Date.now() - versions[latestCached].timestamp < cacheTTL) {
|
|
476
|
+
finalVersion = latestCached;
|
|
477
|
+
if (revalidate) fetchLatestVersion(pkg).then((latest)=>{
|
|
478
|
+
if (latest !== latestCached) {
|
|
479
|
+
console.log(`[MF] 发现 ${pkg} 新版本 ${latest},已更新缓存。`);
|
|
480
|
+
setVersionCache(pkg, latest);
|
|
481
|
+
}
|
|
482
|
+
}).catch((e)=>console.error(`[MF] 异步检查最新版本失败:`, e));
|
|
483
|
+
} else {
|
|
484
|
+
finalVersion = await fetchLatestVersion(pkg);
|
|
485
|
+
setVersionCache(pkg, finalVersion);
|
|
308
486
|
}
|
|
309
487
|
}
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
488
|
+
return finalVersion;
|
|
489
|
+
}
|
|
490
|
+
function buildFinalUrls(pkg, version, localFallback) {
|
|
491
|
+
const urls = buildCdnUrls(pkg, version);
|
|
492
|
+
if (localFallback) urls.push(localFallback);
|
|
493
|
+
return urls;
|
|
494
|
+
}
|
|
495
|
+
function dedupeRemotes(remotes) {
|
|
496
|
+
const map = new Map();
|
|
497
|
+
for (const remote of remotes){
|
|
498
|
+
if (!remote?.name) continue;
|
|
499
|
+
const key = [
|
|
500
|
+
remote.name,
|
|
501
|
+
'entry' in remote ? remote.entry || '' : '',
|
|
502
|
+
'version' in remote ? remote.version || '' : '',
|
|
503
|
+
remote.alias || ''
|
|
504
|
+
].join('::');
|
|
505
|
+
if (!map.has(key)) map.set(key, remote);
|
|
506
|
+
}
|
|
507
|
+
return Array.from(map.values());
|
|
508
|
+
}
|
|
509
|
+
async function resolveRegisteredRemotes(context, baseRemotes, remoteSourcePlugins) {
|
|
510
|
+
const remoteList = [
|
|
511
|
+
...baseRemotes
|
|
512
|
+
];
|
|
513
|
+
for (const plugin of remoteSourcePlugins)if (plugin.registerRemotes) try {
|
|
514
|
+
const pluginRemotes = await plugin.registerRemotes(context);
|
|
515
|
+
if (pluginRemotes?.length) remoteList.push(...pluginRemotes);
|
|
516
|
+
} catch (error) {
|
|
517
|
+
throw new Error(`[MF] remote 来源插件 ${plugin.name} 执行失败: ${error.message}`);
|
|
321
518
|
}
|
|
322
|
-
|
|
323
|
-
|
|
519
|
+
return dedupeRemotes(remoteList).filter((remote)=>!(remote.name === context.scopeName && 'entry' in remote && remote.entry === context.currentEntry));
|
|
520
|
+
}
|
|
521
|
+
function createRemoteSourcePlugin(name, remotes) {
|
|
522
|
+
return {
|
|
523
|
+
name,
|
|
524
|
+
registerRemotes: ()=>remotes
|
|
525
|
+
};
|
|
526
|
+
}
|
|
527
|
+
async function loadRemoteMultiVersion(options, plugins = [], extraOptions = {}) {
|
|
528
|
+
const { name, pkg, version = 'latest', retries = 3, delay = 1000, localFallback, cacheTTL = 86400000, revalidate = true, shared: customShared } = options;
|
|
529
|
+
const { remoteSourcePlugins = [], baseRemotes = [], registerOptions = {} } = extraOptions;
|
|
530
|
+
const finalVersion = await resolveFinalVersion(pkg, version, cacheTTL, revalidate);
|
|
531
|
+
const scopeName = `${name}`;
|
|
532
|
+
const urls = buildFinalUrls(pkg, finalVersion, localFallback);
|
|
533
|
+
const finalSharedConfig = getFinalSharedConfig(customShared);
|
|
534
|
+
for (const url of urls)try {
|
|
535
|
+
const registeredRemotes = await resolveRegisteredRemotes({
|
|
536
|
+
options,
|
|
537
|
+
scopeName,
|
|
538
|
+
pkg,
|
|
539
|
+
finalVersion,
|
|
540
|
+
currentEntry: url,
|
|
541
|
+
allEntries: urls
|
|
542
|
+
}, baseRemotes, remoteSourcePlugins);
|
|
543
|
+
return await tryLoadRemote(scopeName, url, retries, delay, finalSharedConfig, plugins, registeredRemotes, registerOptions);
|
|
544
|
+
} catch (e) {
|
|
545
|
+
console.warn(`[MF] 切换 CDN 路径:${url} 失败,尝试下一个...`, e);
|
|
546
|
+
}
|
|
547
|
+
throw new Error(`[MF] 所有加载源 (${urls.length} 个) 均加载失败。`);
|
|
548
|
+
}
|
|
549
|
+
const preloadCache = {};
|
|
550
|
+
const PRELOAD_CACHE_TTL = 300000;
|
|
551
|
+
function getCachedPreload(pkg, version) {
|
|
552
|
+
const cached = preloadCache[pkg];
|
|
553
|
+
if (!cached) return null;
|
|
554
|
+
if (cached.version !== version) return null;
|
|
555
|
+
if (Date.now() - cached.timestamp > PRELOAD_CACHE_TTL) {
|
|
556
|
+
delete preloadCache[pkg];
|
|
557
|
+
return null;
|
|
558
|
+
}
|
|
559
|
+
return {
|
|
560
|
+
scopeName: cached.scopeName,
|
|
561
|
+
mf: cached.mf
|
|
562
|
+
};
|
|
563
|
+
}
|
|
564
|
+
function setCachedPreload(pkg, version, scopeName, mf) {
|
|
565
|
+
preloadCache[pkg] = {
|
|
566
|
+
version,
|
|
567
|
+
scopeName,
|
|
568
|
+
mf,
|
|
569
|
+
timestamp: Date.now()
|
|
570
|
+
};
|
|
571
|
+
}
|
|
572
|
+
function executeWhenIdle(callback) {
|
|
573
|
+
if ('undefined' != typeof requestIdleCallback) requestIdleCallback(()=>callback());
|
|
574
|
+
else setTimeout(callback, 1);
|
|
575
|
+
}
|
|
576
|
+
async function preloadRemote(options) {
|
|
577
|
+
const { pkg, version = 'latest', priority = 'idle', force = false } = options;
|
|
578
|
+
if (!force) {
|
|
579
|
+
const cached = getCachedPreload(pkg, version);
|
|
580
|
+
if (cached) return cached;
|
|
324
581
|
}
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
name: 'host',
|
|
330
|
-
remotes: [
|
|
331
|
-
{
|
|
332
|
-
name: scopeName,
|
|
333
|
-
entry: url
|
|
334
|
-
}
|
|
335
|
-
],
|
|
336
|
-
shared: sharedConfig,
|
|
337
|
-
plugins: [
|
|
338
|
-
...plugins,
|
|
339
|
-
fallbackPlugin()
|
|
340
|
-
]
|
|
341
|
-
});
|
|
582
|
+
const preloadTask = async ()=>{
|
|
583
|
+
try {
|
|
584
|
+
const { scopeName, mf } = await loadRemoteMultiVersion(options, []);
|
|
585
|
+
setCachedPreload(pkg, version, scopeName, mf);
|
|
342
586
|
return {
|
|
343
587
|
scopeName,
|
|
344
588
|
mf
|
|
345
589
|
};
|
|
346
590
|
} catch (e) {
|
|
347
|
-
|
|
348
|
-
console.warn(`[MF] URL ${url} 加载失败,第 ${i + 1} 次重试...`);
|
|
349
|
-
if (i < retries - 1) await new Promise((res)=>setTimeout(res, delay));
|
|
350
|
-
}
|
|
351
|
-
throw new Error(`[MF] URL ${url} 经过 ${retries} 次重试仍加载失败。`, {
|
|
352
|
-
cause: lastError
|
|
353
|
-
});
|
|
354
|
-
}
|
|
355
|
-
function getFinalSharedConfig(customShared) {
|
|
356
|
-
return {
|
|
357
|
-
...DEFAULT_SHARED_CONFIG,
|
|
358
|
-
...customShared || {}
|
|
359
|
-
};
|
|
360
|
-
}
|
|
361
|
-
async function resolveFinalVersion(pkg, version, cacheTTL, revalidate) {
|
|
362
|
-
let finalVersion = version;
|
|
363
|
-
if ('latest' === version) {
|
|
364
|
-
const cache = getVersionCache();
|
|
365
|
-
const versions = cache[pkg] || {};
|
|
366
|
-
const latestCached = Object.keys(versions).sort((a, b)=>versions[b].timestamp - versions[a].timestamp)[0];
|
|
367
|
-
if (latestCached && Date.now() - versions[latestCached].timestamp < cacheTTL) {
|
|
368
|
-
finalVersion = latestCached;
|
|
369
|
-
if (revalidate) fetchLatestVersion(pkg).then((latest)=>{
|
|
370
|
-
if (latest !== latestCached) {
|
|
371
|
-
console.log(`[MF] 发现 ${pkg} 新版本 ${latest},已更新缓存。`);
|
|
372
|
-
setVersionCache(pkg, latest);
|
|
373
|
-
}
|
|
374
|
-
}).catch((e)=>console.error(`[MF] 异步检查最新版本失败:`, e));
|
|
375
|
-
} else {
|
|
376
|
-
finalVersion = await fetchLatestVersion(pkg);
|
|
377
|
-
setVersionCache(pkg, finalVersion);
|
|
378
|
-
}
|
|
379
|
-
}
|
|
380
|
-
return finalVersion;
|
|
381
|
-
}
|
|
382
|
-
function buildFinalUrls(pkg, version, localFallback) {
|
|
383
|
-
const urls = buildCdnUrls(pkg, version);
|
|
384
|
-
if (localFallback) urls.push(localFallback);
|
|
385
|
-
return urls;
|
|
386
|
-
}
|
|
387
|
-
async function loadRemoteMultiVersion(options, plugins) {
|
|
388
|
-
const { name, pkg, version = 'latest', retries = 3, delay = 1000, localFallback, cacheTTL = 86400000, revalidate = true, shared: customShared } = options;
|
|
389
|
-
const finalVersion = await resolveFinalVersion(pkg, version, cacheTTL, revalidate);
|
|
390
|
-
const scopeName = `${name}`;
|
|
391
|
-
const urls = buildFinalUrls(pkg, finalVersion, localFallback);
|
|
392
|
-
const finalSharedConfig = getFinalSharedConfig(customShared);
|
|
393
|
-
for (const url of urls)try {
|
|
394
|
-
return await tryLoadRemote(scopeName, url, retries, delay, finalSharedConfig, plugins);
|
|
395
|
-
} catch (e) {
|
|
396
|
-
console.warn(`[MF] 切换 CDN 路径:${url} 失败,尝试下一个...`, e);
|
|
397
|
-
}
|
|
398
|
-
throw new Error(`[MF] 所有加载源 (${urls.length} 个) 均加载失败。`);
|
|
399
|
-
}
|
|
400
|
-
const preloadCache = {};
|
|
401
|
-
const PRELOAD_CACHE_TTL = 300000;
|
|
402
|
-
function getCachedPreload(pkg, version) {
|
|
403
|
-
const cached = preloadCache[pkg];
|
|
404
|
-
if (!cached) return null;
|
|
405
|
-
if (cached.version !== version) return null;
|
|
406
|
-
if (Date.now() - cached.timestamp > PRELOAD_CACHE_TTL) {
|
|
407
|
-
delete preloadCache[pkg];
|
|
591
|
+
console.warn(`[MF Preload] 预加载失败 ${pkg}@${version}:`, e);
|
|
408
592
|
return null;
|
|
409
593
|
}
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
preloadCache[pkg] = {
|
|
417
|
-
version,
|
|
418
|
-
scopeName,
|
|
419
|
-
mf,
|
|
420
|
-
timestamp: Date.now()
|
|
421
|
-
};
|
|
422
|
-
}
|
|
423
|
-
function executeWhenIdle(callback) {
|
|
424
|
-
if ('undefined' != typeof requestIdleCallback) requestIdleCallback(()=>callback());
|
|
425
|
-
else setTimeout(callback, 1);
|
|
426
|
-
}
|
|
427
|
-
async function preloadRemote(options) {
|
|
428
|
-
const { pkg, version = 'latest', priority = 'idle', force = false } = options;
|
|
429
|
-
if (!force) {
|
|
430
|
-
const cached = getCachedPreload(pkg, version);
|
|
431
|
-
if (cached) return cached;
|
|
432
|
-
}
|
|
433
|
-
const preloadTask = async ()=>{
|
|
434
|
-
try {
|
|
435
|
-
const { scopeName, mf } = await loadRemoteMultiVersion(options, []);
|
|
436
|
-
setCachedPreload(pkg, version, scopeName, mf);
|
|
437
|
-
return {
|
|
438
|
-
scopeName,
|
|
439
|
-
mf
|
|
440
|
-
};
|
|
441
|
-
} catch (e) {
|
|
442
|
-
console.warn(`[MF Preload] 预加载失败 ${pkg}@${version}:`, e);
|
|
443
|
-
return null;
|
|
444
|
-
}
|
|
445
|
-
};
|
|
446
|
-
if ('high' === priority) return preloadTask();
|
|
447
|
-
return new Promise((resolve)=>{
|
|
448
|
-
executeWhenIdle(async ()=>{
|
|
449
|
-
const result = await preloadTask();
|
|
450
|
-
resolve(result);
|
|
451
|
-
});
|
|
594
|
+
};
|
|
595
|
+
if ('high' === priority) return preloadTask();
|
|
596
|
+
return new Promise((resolve)=>{
|
|
597
|
+
executeWhenIdle(async ()=>{
|
|
598
|
+
const result = await preloadTask();
|
|
599
|
+
resolve(result);
|
|
452
600
|
});
|
|
601
|
+
});
|
|
602
|
+
}
|
|
603
|
+
function preloadRemoteList(optionsList, onProgress) {
|
|
604
|
+
let loaded = 0;
|
|
605
|
+
const total = optionsList.length;
|
|
606
|
+
const promises = optionsList.map((options)=>preloadRemote(options).then((result)=>{
|
|
607
|
+
loaded++;
|
|
608
|
+
onProgress?.(loaded, total);
|
|
609
|
+
return result;
|
|
610
|
+
}));
|
|
611
|
+
return Promise.all(promises);
|
|
612
|
+
}
|
|
613
|
+
function cancelPreload(pkg) {
|
|
614
|
+
const cached = preloadCache[pkg];
|
|
615
|
+
if (cached) delete preloadCache[pkg];
|
|
616
|
+
}
|
|
617
|
+
function clearPreloadCache() {
|
|
618
|
+
Object.keys(preloadCache).forEach((pkg)=>delete preloadCache[pkg]);
|
|
619
|
+
}
|
|
620
|
+
function getPreloadStatus(pkg) {
|
|
621
|
+
const cached = preloadCache[pkg];
|
|
622
|
+
if (!cached) return null;
|
|
623
|
+
return {
|
|
624
|
+
loaded: true,
|
|
625
|
+
timestamp: cached.timestamp
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
const remoteInstances = new Map();
|
|
629
|
+
function generateInstanceKey(name, pkg, version) {
|
|
630
|
+
return `${name}::${pkg}@${version}`;
|
|
631
|
+
}
|
|
632
|
+
async function unloadRemote(options) {
|
|
633
|
+
const { name, pkg, version = '*', clearCache = false } = options;
|
|
634
|
+
const keysToDelete = [];
|
|
635
|
+
remoteInstances.forEach((instance, key)=>{
|
|
636
|
+
const versionMatch = '*' === version || instance.version === version;
|
|
637
|
+
const pkgMatch = instance.pkg === pkg;
|
|
638
|
+
const nameMatch = instance.name === name;
|
|
639
|
+
if (nameMatch && pkgMatch && versionMatch) keysToDelete.push(key);
|
|
640
|
+
});
|
|
641
|
+
for (const key of keysToDelete){
|
|
642
|
+
const instance = remoteInstances.get(key);
|
|
643
|
+
if (instance) {
|
|
644
|
+
await cleanupInstance(instance);
|
|
645
|
+
remoteInstances.delete(key);
|
|
646
|
+
}
|
|
453
647
|
}
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
function cancelPreload(pkg) {
|
|
465
|
-
const cached = preloadCache[pkg];
|
|
466
|
-
if (cached) delete preloadCache[pkg];
|
|
467
|
-
}
|
|
468
|
-
function clearPreloadCache() {
|
|
469
|
-
Object.keys(preloadCache).forEach((pkg)=>delete preloadCache[pkg]);
|
|
470
|
-
}
|
|
471
|
-
function getPreloadStatus(pkg) {
|
|
472
|
-
const cached = preloadCache[pkg];
|
|
473
|
-
if (!cached) return null;
|
|
474
|
-
return {
|
|
475
|
-
loaded: true,
|
|
476
|
-
timestamp: cached.timestamp
|
|
477
|
-
};
|
|
648
|
+
if (clearCache) clearVersionCache(pkg, version);
|
|
649
|
+
return keysToDelete.length > 0;
|
|
650
|
+
}
|
|
651
|
+
async function cleanupInstance(instance) {
|
|
652
|
+
try {
|
|
653
|
+
instance.loadedModules.clear();
|
|
654
|
+
if (instance.mf && 'function' == typeof instance.mf.cleanup) await instance.mf.cleanup();
|
|
655
|
+
console.log(`[MF Unload] 已卸载 ${instance.pkg}@${instance.version}`);
|
|
656
|
+
} catch (e) {
|
|
657
|
+
console.warn(`[MF Unload] 卸载时出错 ${instance.pkg}:`, e);
|
|
478
658
|
}
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
659
|
+
}
|
|
660
|
+
function clearVersionCache(pkg, version) {
|
|
661
|
+
try {
|
|
662
|
+
const cacheKey = 'mf-multi-version';
|
|
663
|
+
const cacheStr = localStorage.getItem(cacheKey);
|
|
664
|
+
if (!cacheStr) return;
|
|
665
|
+
const cache = JSON.parse(cacheStr);
|
|
666
|
+
if (!cache[pkg]) return;
|
|
667
|
+
if ('*' === version) delete cache[pkg];
|
|
668
|
+
else delete cache[pkg][version];
|
|
669
|
+
localStorage.setItem(cacheKey, JSON.stringify(cache));
|
|
670
|
+
console.log(`[MF Unload] 已清除版本缓存 ${pkg}@${version}`);
|
|
671
|
+
} catch (e) {
|
|
672
|
+
console.warn('[MF Unload] 清除缓存失败:', e);
|
|
482
673
|
}
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
674
|
+
}
|
|
675
|
+
function registerRemoteInstance(name, scopeName, pkg, version, mf) {
|
|
676
|
+
const key = generateInstanceKey(name, pkg, version);
|
|
677
|
+
const instance = {
|
|
678
|
+
name,
|
|
679
|
+
scopeName,
|
|
680
|
+
pkg,
|
|
681
|
+
version,
|
|
682
|
+
mf,
|
|
683
|
+
loadedModules: new Set(),
|
|
684
|
+
timestamp: Date.now()
|
|
685
|
+
};
|
|
686
|
+
remoteInstances.set(key, instance);
|
|
687
|
+
return key;
|
|
688
|
+
}
|
|
689
|
+
function registerLoadedModule(key, moduleId) {
|
|
690
|
+
const instance = remoteInstances.get(key);
|
|
691
|
+
if (instance) instance.loadedModules.add(moduleId);
|
|
692
|
+
}
|
|
693
|
+
function unloadAll(clearAllCache = false) {
|
|
694
|
+
return new Promise((resolve)=>{
|
|
695
|
+
const keys = Array.from(remoteInstances.keys());
|
|
696
|
+
if (0 === keys.length) return void resolve();
|
|
697
|
+
let completed = 0;
|
|
698
|
+
keys.forEach(async (key)=>{
|
|
493
699
|
const instance = remoteInstances.get(key);
|
|
494
700
|
if (instance) {
|
|
495
701
|
await cleanupInstance(instance);
|
|
496
702
|
remoteInstances.delete(key);
|
|
497
703
|
}
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
instance.loadedModules.clear();
|
|
505
|
-
if (instance.mf && 'function' == typeof instance.mf.cleanup) await instance.mf.cleanup();
|
|
506
|
-
console.log(`[MF Unload] 已卸载 ${instance.pkg}@${instance.version}`);
|
|
507
|
-
} catch (e) {
|
|
508
|
-
console.warn(`[MF Unload] 卸载时出错 ${instance.pkg}:`, e);
|
|
509
|
-
}
|
|
510
|
-
}
|
|
511
|
-
function clearVersionCache(pkg, version) {
|
|
512
|
-
try {
|
|
513
|
-
const cacheKey = 'mf-multi-version';
|
|
514
|
-
const cacheStr = localStorage.getItem(cacheKey);
|
|
515
|
-
if (!cacheStr) return;
|
|
516
|
-
const cache = JSON.parse(cacheStr);
|
|
517
|
-
if (!cache[pkg]) return;
|
|
518
|
-
if ('*' === version) delete cache[pkg];
|
|
519
|
-
else delete cache[pkg][version];
|
|
520
|
-
localStorage.setItem(cacheKey, JSON.stringify(cache));
|
|
521
|
-
console.log(`[MF Unload] 已清除版本缓存 ${pkg}@${version}`);
|
|
522
|
-
} catch (e) {
|
|
523
|
-
console.warn('[MF Unload] 清除缓存失败:', e);
|
|
524
|
-
}
|
|
525
|
-
}
|
|
526
|
-
function registerRemoteInstance(name, scopeName, pkg, version, mf) {
|
|
527
|
-
const key = generateInstanceKey(name, pkg, version);
|
|
528
|
-
const instance = {
|
|
529
|
-
name,
|
|
530
|
-
scopeName,
|
|
531
|
-
pkg,
|
|
532
|
-
version,
|
|
533
|
-
mf,
|
|
534
|
-
loadedModules: new Set(),
|
|
535
|
-
timestamp: Date.now()
|
|
536
|
-
};
|
|
537
|
-
remoteInstances.set(key, instance);
|
|
538
|
-
return key;
|
|
539
|
-
}
|
|
540
|
-
function registerLoadedModule(key, moduleId) {
|
|
541
|
-
const instance = remoteInstances.get(key);
|
|
542
|
-
if (instance) instance.loadedModules.add(moduleId);
|
|
543
|
-
}
|
|
544
|
-
function unloadAll(clearAllCache = false) {
|
|
545
|
-
return new Promise((resolve)=>{
|
|
546
|
-
const keys = Array.from(remoteInstances.keys());
|
|
547
|
-
if (0 === keys.length) return void resolve();
|
|
548
|
-
let completed = 0;
|
|
549
|
-
keys.forEach(async (key)=>{
|
|
550
|
-
const instance = remoteInstances.get(key);
|
|
551
|
-
if (instance) {
|
|
552
|
-
await cleanupInstance(instance);
|
|
553
|
-
remoteInstances.delete(key);
|
|
554
|
-
}
|
|
555
|
-
completed++;
|
|
556
|
-
if (completed >= keys.length) {
|
|
557
|
-
if (clearAllCache) try {
|
|
558
|
-
localStorage.removeItem('mf-multi-version');
|
|
559
|
-
} catch (e) {
|
|
560
|
-
console.warn('[MF Unload] 清除所有缓存失败:', e);
|
|
561
|
-
}
|
|
562
|
-
resolve();
|
|
704
|
+
completed++;
|
|
705
|
+
if (completed >= keys.length) {
|
|
706
|
+
if (clearAllCache) try {
|
|
707
|
+
localStorage.removeItem('mf-multi-version');
|
|
708
|
+
} catch (e) {
|
|
709
|
+
console.warn('[MF Unload] 清除所有缓存失败:', e);
|
|
563
710
|
}
|
|
564
|
-
|
|
711
|
+
resolve();
|
|
712
|
+
}
|
|
565
713
|
});
|
|
566
|
-
}
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
576
|
-
|
|
714
|
+
});
|
|
715
|
+
}
|
|
716
|
+
function getLoadedRemotes() {
|
|
717
|
+
const result = [];
|
|
718
|
+
remoteInstances.forEach((instance)=>{
|
|
719
|
+
result.push({
|
|
720
|
+
name: instance.name,
|
|
721
|
+
pkg: instance.pkg,
|
|
722
|
+
version: instance.version,
|
|
723
|
+
loadedModules: instance.loadedModules.size,
|
|
724
|
+
timestamp: instance.timestamp
|
|
577
725
|
});
|
|
578
|
-
|
|
726
|
+
});
|
|
727
|
+
return result;
|
|
728
|
+
}
|
|
729
|
+
function isRemoteLoaded(name, pkg, version) {
|
|
730
|
+
const key = generateInstanceKey(name, pkg, version || '*');
|
|
731
|
+
return remoteInstances.has(key);
|
|
732
|
+
}
|
|
733
|
+
const CDN_URLS = [
|
|
734
|
+
'https://cdn.jsdelivr.net/npm/{pkg}@{version}/dist/remoteEntry.js',
|
|
735
|
+
'https://unpkg.com/{pkg}@{version}/dist/remoteEntry.js'
|
|
736
|
+
];
|
|
737
|
+
async function checkCdnAccess(cdnUrl) {
|
|
738
|
+
const start = performance.now();
|
|
739
|
+
try {
|
|
740
|
+
const controller = new AbortController();
|
|
741
|
+
const timeout = setTimeout(()=>controller.abort(), 5000);
|
|
742
|
+
const res = await fetch(cdnUrl, {
|
|
743
|
+
method: 'HEAD',
|
|
744
|
+
signal: controller.signal
|
|
745
|
+
});
|
|
746
|
+
clearTimeout(timeout);
|
|
747
|
+
const latency = Math.round(performance.now() - start);
|
|
748
|
+
return {
|
|
749
|
+
reachable: res.ok,
|
|
750
|
+
latency
|
|
751
|
+
};
|
|
752
|
+
} catch (e) {
|
|
753
|
+
const latency = Math.round(performance.now() - start);
|
|
754
|
+
return {
|
|
755
|
+
reachable: false,
|
|
756
|
+
latency
|
|
757
|
+
};
|
|
579
758
|
}
|
|
580
|
-
|
|
581
|
-
|
|
582
|
-
|
|
759
|
+
}
|
|
760
|
+
async function health_fetchLatestVersion(pkg) {
|
|
761
|
+
try {
|
|
762
|
+
const res = await fetch(`https://registry.npmjs.org/${pkg}`);
|
|
763
|
+
if (!res.ok) return null;
|
|
764
|
+
const data = await res.json();
|
|
765
|
+
return data['dist-tags']?.latest || null;
|
|
766
|
+
} catch {
|
|
767
|
+
return null;
|
|
583
768
|
}
|
|
584
|
-
|
|
585
|
-
|
|
586
|
-
|
|
587
|
-
|
|
588
|
-
|
|
589
|
-
|
|
590
|
-
|
|
591
|
-
|
|
592
|
-
|
|
593
|
-
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
});
|
|
597
|
-
clearTimeout(timeout);
|
|
598
|
-
const latency = Math.round(performance.now() - start);
|
|
599
|
-
return {
|
|
600
|
-
reachable: res.ok,
|
|
601
|
-
latency
|
|
602
|
-
};
|
|
603
|
-
} catch (e) {
|
|
604
|
-
const latency = Math.round(performance.now() - start);
|
|
605
|
-
return {
|
|
606
|
-
reachable: false,
|
|
607
|
-
latency
|
|
608
|
-
};
|
|
609
|
-
}
|
|
769
|
+
}
|
|
770
|
+
async function checkRemoteHealth(options) {
|
|
771
|
+
const { pkg, version = 'latest' } = options;
|
|
772
|
+
const actualVersion = 'latest' === version ? await health_fetchLatestVersion(pkg) || version : version;
|
|
773
|
+
const results = [];
|
|
774
|
+
for (const template of CDN_URLS){
|
|
775
|
+
const url = template.replace('{pkg}', pkg).replace('{version}', actualVersion);
|
|
776
|
+
const result = await checkCdnAccess(url);
|
|
777
|
+
results.push({
|
|
778
|
+
cdn: url,
|
|
779
|
+
...result
|
|
780
|
+
});
|
|
610
781
|
}
|
|
611
|
-
|
|
612
|
-
|
|
613
|
-
|
|
614
|
-
|
|
615
|
-
|
|
616
|
-
|
|
617
|
-
|
|
618
|
-
|
|
782
|
+
const workingCdn = results.find((r)=>r.reachable);
|
|
783
|
+
const bestCdn = results.sort((a, b)=>a.latency - b.latency)[0];
|
|
784
|
+
let status = 'unhealthy';
|
|
785
|
+
if (workingCdn) status = bestCdn.latency < 1000 ? 'healthy' : 'degraded';
|
|
786
|
+
return {
|
|
787
|
+
pkg,
|
|
788
|
+
version: actualVersion,
|
|
789
|
+
status,
|
|
790
|
+
latency: bestCdn?.latency || 0,
|
|
791
|
+
cdn: bestCdn?.cdn || '',
|
|
792
|
+
details: {
|
|
793
|
+
cdnReachable: !!workingCdn,
|
|
794
|
+
remoteEntryValid: false,
|
|
795
|
+
modulesLoadable: false
|
|
619
796
|
}
|
|
797
|
+
};
|
|
798
|
+
}
|
|
799
|
+
async function checkModuleLoadable(scopeName, modulePath, mf) {
|
|
800
|
+
try {
|
|
801
|
+
if (!mf || 'function' != typeof mf.loadRemote) return false;
|
|
802
|
+
const mod = await mf.loadRemote(`${scopeName}/${modulePath}`);
|
|
803
|
+
return null != mod;
|
|
804
|
+
} catch {
|
|
805
|
+
return false;
|
|
620
806
|
}
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
625
|
-
|
|
626
|
-
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
637
|
-
|
|
638
|
-
|
|
639
|
-
|
|
640
|
-
|
|
641
|
-
|
|
642
|
-
|
|
643
|
-
|
|
644
|
-
|
|
645
|
-
|
|
646
|
-
|
|
647
|
-
|
|
807
|
+
}
|
|
808
|
+
async function getRemoteHealthReport(remotes) {
|
|
809
|
+
const results = await Promise.all(remotes.map((r)=>checkRemoteHealth(r)));
|
|
810
|
+
let overall = 'healthy';
|
|
811
|
+
if (results.some((r)=>'unhealthy' === r.status)) overall = 'unhealthy';
|
|
812
|
+
else if (results.some((r)=>'degraded' === r.status)) overall = 'degraded';
|
|
813
|
+
return {
|
|
814
|
+
timestamp: Date.now(),
|
|
815
|
+
overall,
|
|
816
|
+
remotes: results
|
|
817
|
+
};
|
|
818
|
+
}
|
|
819
|
+
function formatHealthStatus(status) {
|
|
820
|
+
const icons = {
|
|
821
|
+
healthy: '🟢',
|
|
822
|
+
degraded: '🟡',
|
|
823
|
+
unhealthy: '🔴'
|
|
824
|
+
};
|
|
825
|
+
return `${icons[status]} ${status}`;
|
|
826
|
+
}
|
|
827
|
+
class EventBusClass {
|
|
828
|
+
listeners = new Map();
|
|
829
|
+
eventHistory = new Map();
|
|
830
|
+
maxHistorySize = 100;
|
|
831
|
+
generateId() {
|
|
832
|
+
return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
833
|
+
}
|
|
834
|
+
on(event, callback, options) {
|
|
835
|
+
const onceValue = options?.once ?? false;
|
|
836
|
+
if (!this.listeners.has(event)) this.listeners.set(event, new Set());
|
|
837
|
+
const subscription = {
|
|
838
|
+
callback,
|
|
839
|
+
once: onceValue,
|
|
840
|
+
filter: options?.filter
|
|
648
841
|
};
|
|
649
|
-
|
|
650
|
-
|
|
651
|
-
|
|
652
|
-
if (!mf || 'function' != typeof mf.loadRemote) return false;
|
|
653
|
-
const mod = await mf.loadRemote(`${scopeName}/${modulePath}`);
|
|
654
|
-
return null != mod;
|
|
655
|
-
} catch {
|
|
656
|
-
return false;
|
|
657
|
-
}
|
|
658
|
-
}
|
|
659
|
-
async function getRemoteHealthReport(remotes) {
|
|
660
|
-
const results = await Promise.all(remotes.map((r)=>checkRemoteHealth(r)));
|
|
661
|
-
let overall = 'healthy';
|
|
662
|
-
if (results.some((r)=>'unhealthy' === r.status)) overall = 'unhealthy';
|
|
663
|
-
else if (results.some((r)=>'degraded' === r.status)) overall = 'degraded';
|
|
664
|
-
return {
|
|
665
|
-
timestamp: Date.now(),
|
|
666
|
-
overall,
|
|
667
|
-
remotes: results
|
|
842
|
+
this.listeners.get(event).add(subscription);
|
|
843
|
+
return ()=>{
|
|
844
|
+
this.off(event, callback);
|
|
668
845
|
};
|
|
669
846
|
}
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
|
|
673
|
-
|
|
674
|
-
unhealthy: '🔴'
|
|
675
|
-
};
|
|
676
|
-
return `${icons[status]} ${status}`;
|
|
847
|
+
once(event, callback) {
|
|
848
|
+
return this.on(event, callback, {
|
|
849
|
+
once: true
|
|
850
|
+
});
|
|
677
851
|
}
|
|
678
|
-
|
|
679
|
-
|
|
680
|
-
|
|
681
|
-
maxHistorySize = 100;
|
|
682
|
-
generateId() {
|
|
683
|
-
return `${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
|
|
684
|
-
}
|
|
685
|
-
on(event, callback, options) {
|
|
686
|
-
const onceValue = options?.once ?? false;
|
|
687
|
-
if (!this.listeners.has(event)) this.listeners.set(event, new Set());
|
|
688
|
-
const subscription = {
|
|
689
|
-
callback,
|
|
690
|
-
once: onceValue,
|
|
691
|
-
filter: options?.filter
|
|
692
|
-
};
|
|
693
|
-
this.listeners.get(event).add(subscription);
|
|
694
|
-
return ()=>{
|
|
695
|
-
this.off(event, callback);
|
|
696
|
-
};
|
|
697
|
-
}
|
|
698
|
-
once(event, callback) {
|
|
699
|
-
return this.on(event, callback, {
|
|
700
|
-
once: true
|
|
701
|
-
});
|
|
702
|
-
}
|
|
703
|
-
off(event, callback) {
|
|
704
|
-
if (!this.listeners.has(event)) return;
|
|
705
|
-
if (callback) {
|
|
706
|
-
const subscriptions = this.listeners.get(event);
|
|
707
|
-
subscriptions.forEach((sub)=>{
|
|
708
|
-
if (sub.callback === callback) subscriptions.delete(sub);
|
|
709
|
-
});
|
|
710
|
-
} else this.listeners.delete(event);
|
|
711
|
-
}
|
|
712
|
-
emit(event, data, meta) {
|
|
713
|
-
const eventMeta = {
|
|
714
|
-
timestamp: Date.now(),
|
|
715
|
-
source: meta?.source,
|
|
716
|
-
id: meta?.id || this.generateId()
|
|
717
|
-
};
|
|
718
|
-
this.addToHistory(event, data, eventMeta);
|
|
852
|
+
off(event, callback) {
|
|
853
|
+
if (!this.listeners.has(event)) return;
|
|
854
|
+
if (callback) {
|
|
719
855
|
const subscriptions = this.listeners.get(event);
|
|
720
|
-
if (!subscriptions) return;
|
|
721
|
-
const toRemove = [];
|
|
722
856
|
subscriptions.forEach((sub)=>{
|
|
723
|
-
if (sub.
|
|
724
|
-
try {
|
|
725
|
-
sub.callback(data, eventMeta);
|
|
726
|
-
} catch (e) {
|
|
727
|
-
console.error(`[MF EventBus] 事件 ${event} 处理出错:`, e);
|
|
728
|
-
}
|
|
729
|
-
if (sub.once) toRemove.push(sub);
|
|
857
|
+
if (sub.callback === callback) subscriptions.delete(sub);
|
|
730
858
|
});
|
|
731
|
-
|
|
732
|
-
}
|
|
733
|
-
addToHistory(event, data, meta) {
|
|
734
|
-
if (!this.eventHistory.has(event)) this.eventHistory.set(event, []);
|
|
735
|
-
const history = this.eventHistory.get(event);
|
|
736
|
-
history.push({
|
|
737
|
-
data,
|
|
738
|
-
meta
|
|
739
|
-
});
|
|
740
|
-
if (history.length > this.maxHistorySize) history.shift();
|
|
741
|
-
}
|
|
742
|
-
getHistory(event) {
|
|
743
|
-
return this.eventHistory.get(event) || [];
|
|
744
|
-
}
|
|
745
|
-
getEvents() {
|
|
746
|
-
return Array.from(this.listeners.keys());
|
|
747
|
-
}
|
|
748
|
-
getListenerCount(event) {
|
|
749
|
-
return this.listeners.get(event)?.size || 0;
|
|
750
|
-
}
|
|
751
|
-
hasListeners(event) {
|
|
752
|
-
return this.listeners.has(event) && this.listeners.get(event).size > 0;
|
|
753
|
-
}
|
|
754
|
-
clear(event) {
|
|
755
|
-
if (event) {
|
|
756
|
-
this.listeners.delete(event);
|
|
757
|
-
this.eventHistory.delete(event);
|
|
758
|
-
} else {
|
|
759
|
-
this.listeners.clear();
|
|
760
|
-
this.eventHistory.clear();
|
|
761
|
-
}
|
|
762
|
-
}
|
|
763
|
-
listenerExists(event, callback) {
|
|
764
|
-
const subscriptions = this.listeners.get(event);
|
|
765
|
-
if (!subscriptions) return false;
|
|
766
|
-
let exists = false;
|
|
767
|
-
subscriptions.forEach((sub)=>{
|
|
768
|
-
if (sub.callback === callback) exists = true;
|
|
769
|
-
});
|
|
770
|
-
return exists;
|
|
771
|
-
}
|
|
772
|
-
emitAsync(event, data, meta) {
|
|
773
|
-
return new Promise((resolve)=>{
|
|
774
|
-
this.emit(event, data, meta);
|
|
775
|
-
resolve();
|
|
776
|
-
});
|
|
777
|
-
}
|
|
778
|
-
static create() {
|
|
779
|
-
return new EventBusClass();
|
|
780
|
-
}
|
|
781
|
-
}
|
|
782
|
-
const eventBus = EventBusClass.create();
|
|
783
|
-
function createEventBus() {
|
|
784
|
-
return EventBusClass.create();
|
|
859
|
+
} else this.listeners.delete(event);
|
|
785
860
|
}
|
|
786
|
-
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
this.state = {
|
|
792
|
-
hasError: false,
|
|
793
|
-
error: null,
|
|
794
|
-
errorInfo: null
|
|
795
|
-
};
|
|
796
|
-
}
|
|
797
|
-
static getDerivedStateFromError(error) {
|
|
798
|
-
return {
|
|
799
|
-
hasError: true,
|
|
800
|
-
error,
|
|
801
|
-
errorInfo: null
|
|
802
|
-
};
|
|
803
|
-
}
|
|
804
|
-
componentDidCatch(error, errorInfo) {
|
|
805
|
-
this.setState({
|
|
806
|
-
errorInfo
|
|
807
|
-
});
|
|
808
|
-
this.props.onError?.(error, errorInfo);
|
|
809
|
-
console.error('[RemoteReloadUtils] ErrorBoundary caught error:', error, errorInfo);
|
|
810
|
-
}
|
|
811
|
-
handleReset = ()=>{
|
|
812
|
-
this.setState({
|
|
813
|
-
hasError: false,
|
|
814
|
-
error: null,
|
|
815
|
-
errorInfo: null
|
|
816
|
-
});
|
|
817
|
-
this.props.onReset?.();
|
|
861
|
+
emit(event, data, meta) {
|
|
862
|
+
const eventMeta = {
|
|
863
|
+
timestamp: Date.now(),
|
|
864
|
+
source: meta?.source,
|
|
865
|
+
id: meta?.id || this.generateId()
|
|
818
866
|
};
|
|
819
|
-
|
|
820
|
-
|
|
821
|
-
|
|
822
|
-
|
|
823
|
-
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
className: "text-red-700"
|
|
830
|
-
}, this.state.error.message), /*#__PURE__*/ external_react_default().createElement("button", {
|
|
831
|
-
onClick: this.handleReset,
|
|
832
|
-
className: "mt-3 px-4 py-2 text-sm font-medium text-white bg-red-600 rounded hover:bg-red-700 cursor-pointer transition-colors"
|
|
833
|
-
}, "Try again"));
|
|
867
|
+
this.addToHistory(event, data, eventMeta);
|
|
868
|
+
const subscriptions = this.listeners.get(event);
|
|
869
|
+
if (!subscriptions) return;
|
|
870
|
+
const toRemove = [];
|
|
871
|
+
subscriptions.forEach((sub)=>{
|
|
872
|
+
if (sub.filter && !sub.filter(data, eventMeta)) return;
|
|
873
|
+
try {
|
|
874
|
+
sub.callback(data, eventMeta);
|
|
875
|
+
} catch (e) {
|
|
876
|
+
console.error(`[MF EventBus] 事件 ${event} 处理出错:`, e);
|
|
834
877
|
}
|
|
835
|
-
|
|
836
|
-
}
|
|
837
|
-
}
|
|
838
|
-
function useRemoteModule({ pkg, version, moduleName, scopeName, onError, onLoad, retryKey = 0 }) {
|
|
839
|
-
const [moduleState, setModuleState] = (0, external_react_namespaceObject.useState)({
|
|
840
|
-
loading: true,
|
|
841
|
-
error: null,
|
|
842
|
-
component: null
|
|
878
|
+
if (sub.once) toRemove.push(sub);
|
|
843
879
|
});
|
|
844
|
-
|
|
845
|
-
|
|
846
|
-
|
|
847
|
-
|
|
848
|
-
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
}));
|
|
853
|
-
const { mf } = await loadRemoteMultiVersion({
|
|
854
|
-
name: scopeName,
|
|
855
|
-
pkg,
|
|
856
|
-
version
|
|
857
|
-
}, []);
|
|
858
|
-
if (!mf || !mounted) return;
|
|
859
|
-
const mod = await mf.loadRemote(`${scopeName}/${moduleName}`);
|
|
860
|
-
if (!mounted) return;
|
|
861
|
-
if (mod && 'object' == typeof mod && 'default' in mod) {
|
|
862
|
-
const Component = mod.default;
|
|
863
|
-
setModuleState({
|
|
864
|
-
loading: false,
|
|
865
|
-
error: null,
|
|
866
|
-
component: Component
|
|
867
|
-
});
|
|
868
|
-
onLoad?.(Component);
|
|
869
|
-
} else throw new Error(`Module "${scopeName}/${moduleName}" does not export a default component`);
|
|
870
|
-
} catch (err) {
|
|
871
|
-
if (mounted) {
|
|
872
|
-
const error = err instanceof Error ? err : new Error(String(err));
|
|
873
|
-
setModuleState({
|
|
874
|
-
loading: false,
|
|
875
|
-
error,
|
|
876
|
-
component: null
|
|
877
|
-
});
|
|
878
|
-
onError?.(error);
|
|
879
|
-
}
|
|
880
|
-
}
|
|
881
|
-
}
|
|
882
|
-
loadModule();
|
|
883
|
-
return ()=>{
|
|
884
|
-
mounted = false;
|
|
885
|
-
};
|
|
886
|
-
}, [
|
|
887
|
-
pkg,
|
|
888
|
-
version,
|
|
889
|
-
moduleName,
|
|
890
|
-
scopeName,
|
|
891
|
-
onError,
|
|
892
|
-
onLoad,
|
|
893
|
-
retryKey
|
|
894
|
-
]);
|
|
895
|
-
return moduleState;
|
|
896
|
-
}
|
|
897
|
-
function RemoteModuleRenderer({ pkg, version, moduleName, scopeName, loadingFallback, errorFallback, componentProps, className, style, onError, onLoad }) {
|
|
898
|
-
const moduleState = useRemoteModule({
|
|
899
|
-
pkg,
|
|
900
|
-
version,
|
|
901
|
-
moduleName,
|
|
902
|
-
scopeName,
|
|
903
|
-
onError,
|
|
904
|
-
onLoad
|
|
880
|
+
toRemove.forEach((sub)=>subscriptions.delete(sub));
|
|
881
|
+
}
|
|
882
|
+
addToHistory(event, data, meta) {
|
|
883
|
+
if (!this.eventHistory.has(event)) this.eventHistory.set(event, []);
|
|
884
|
+
const history = this.eventHistory.get(event);
|
|
885
|
+
history.push({
|
|
886
|
+
data,
|
|
887
|
+
meta
|
|
905
888
|
});
|
|
906
|
-
|
|
907
|
-
const handleRetry = (0, external_react_namespaceObject.useCallback)(()=>{
|
|
908
|
-
setRetryKey((prev)=>prev + 1);
|
|
909
|
-
}, []);
|
|
910
|
-
(0, external_react_namespaceObject.useEffect)(()=>{}, [
|
|
911
|
-
retryKey
|
|
912
|
-
]);
|
|
913
|
-
if (moduleState.loading) return /*#__PURE__*/ external_react_default().createElement("div", {
|
|
914
|
-
className: className,
|
|
915
|
-
style: style,
|
|
916
|
-
role: "status",
|
|
917
|
-
"aria-live": "polite"
|
|
918
|
-
}, loadingFallback || /*#__PURE__*/ external_react_default().createElement("div", {
|
|
919
|
-
className: "module-card module-card--loading"
|
|
920
|
-
}, /*#__PURE__*/ external_react_default().createElement("div", {
|
|
921
|
-
className: "loading-spinner",
|
|
922
|
-
"aria-hidden": "true"
|
|
923
|
-
}), /*#__PURE__*/ external_react_default().createElement("span", {
|
|
924
|
-
className: "text-gray-600"
|
|
925
|
-
}, "Loading ", moduleName, "...")));
|
|
926
|
-
if (moduleState.error) {
|
|
927
|
-
if ('function' == typeof errorFallback) return /*#__PURE__*/ external_react_default().createElement(external_react_default().Fragment, null, errorFallback(moduleState.error, handleRetry));
|
|
928
|
-
if (void 0 !== errorFallback) return /*#__PURE__*/ external_react_default().createElement(external_react_default().Fragment, null, errorFallback);
|
|
929
|
-
return /*#__PURE__*/ external_react_default().createElement("div", {
|
|
930
|
-
className: className,
|
|
931
|
-
style: style,
|
|
932
|
-
role: "alert"
|
|
933
|
-
}, /*#__PURE__*/ external_react_default().createElement("div", {
|
|
934
|
-
className: "module-card module-card--error"
|
|
935
|
-
}, /*#__PURE__*/ external_react_default().createElement("span", {
|
|
936
|
-
className: "error-icon",
|
|
937
|
-
"aria-hidden": "true"
|
|
938
|
-
}, "!"), /*#__PURE__*/ external_react_default().createElement("span", null, "Failed to load ", moduleName), /*#__PURE__*/ external_react_default().createElement("p", {
|
|
939
|
-
className: "error-message"
|
|
940
|
-
}, moduleState.error.message), /*#__PURE__*/ external_react_default().createElement("button", {
|
|
941
|
-
onClick: handleRetry,
|
|
942
|
-
className: "retry-button",
|
|
943
|
-
type: "button"
|
|
944
|
-
}, "Retry")));
|
|
945
|
-
}
|
|
946
|
-
if (!moduleState.component) return null;
|
|
947
|
-
const Component = moduleState.component;
|
|
948
|
-
return /*#__PURE__*/ external_react_default().createElement("div", {
|
|
949
|
-
className: className,
|
|
950
|
-
style: style
|
|
951
|
-
}, /*#__PURE__*/ external_react_default().createElement(Component, componentProps));
|
|
889
|
+
if (history.length > this.maxHistorySize) history.shift();
|
|
952
890
|
}
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
if (disableErrorBoundary) return /*#__PURE__*/ external_react_default().createElement(external_react_namespaceObject.Suspense, {
|
|
956
|
-
fallback: loadingFallback || /*#__PURE__*/ external_react_default().createElement("div", null, "Loading...")
|
|
957
|
-
}, /*#__PURE__*/ external_react_default().createElement(RemoteModuleRenderer, props));
|
|
958
|
-
return /*#__PURE__*/ external_react_default().createElement(ErrorBoundary, {
|
|
959
|
-
fallback: errorFallback,
|
|
960
|
-
onError: errorBoundaryOptions?.onError,
|
|
961
|
-
onReset: errorBoundaryOptions?.onReset
|
|
962
|
-
}, /*#__PURE__*/ external_react_default().createElement(external_react_namespaceObject.Suspense, {
|
|
963
|
-
fallback: loadingFallback || /*#__PURE__*/ external_react_default().createElement("div", null, "Loading...")
|
|
964
|
-
}, /*#__PURE__*/ external_react_default().createElement(RemoteModuleRenderer, props)));
|
|
891
|
+
getHistory(event) {
|
|
892
|
+
return this.eventHistory.get(event) || [];
|
|
965
893
|
}
|
|
966
|
-
|
|
967
|
-
|
|
968
|
-
let retryCount = 0;
|
|
969
|
-
const loadComponent = async ()=>{
|
|
970
|
-
try {
|
|
971
|
-
const { mf } = await loadRemoteMultiVersion({
|
|
972
|
-
name: scopeName,
|
|
973
|
-
pkg,
|
|
974
|
-
version
|
|
975
|
-
}, []);
|
|
976
|
-
if (!mf) throw new Error(`[RemoteReloadUtils] Failed to get Module Federation instance for ${scopeName}`);
|
|
977
|
-
const mod = await mf.loadRemote(`${scopeName}/${moduleName}`);
|
|
978
|
-
if (!mod || 'object' != typeof mod || !('default' in mod)) throw new Error(`[RemoteReloadUtils] Module "${scopeName}/${moduleName}" does not export a default component`);
|
|
979
|
-
return {
|
|
980
|
-
default: mod.default
|
|
981
|
-
};
|
|
982
|
-
} catch (error) {
|
|
983
|
-
if (retryCount < maxRetries) {
|
|
984
|
-
retryCount++;
|
|
985
|
-
await new Promise((resolve)=>setTimeout(resolve, retryDelay * retryCount));
|
|
986
|
-
return loadComponent();
|
|
987
|
-
}
|
|
988
|
-
throw error;
|
|
989
|
-
}
|
|
990
|
-
};
|
|
991
|
-
return /*#__PURE__*/ (0, external_react_namespaceObject.lazy)(loadComponent);
|
|
894
|
+
getEvents() {
|
|
895
|
+
return Array.from(this.listeners.keys());
|
|
992
896
|
}
|
|
993
|
-
|
|
994
|
-
return
|
|
995
|
-
fallback: fallback || /*#__PURE__*/ external_react_default().createElement("div", null, "Loading...")
|
|
996
|
-
}, children);
|
|
897
|
+
getListenerCount(event) {
|
|
898
|
+
return this.listeners.get(event)?.size || 0;
|
|
997
899
|
}
|
|
998
|
-
|
|
999
|
-
|
|
1000
|
-
pkg,
|
|
1001
|
-
version,
|
|
1002
|
-
moduleName,
|
|
1003
|
-
scopeName
|
|
1004
|
-
});
|
|
1005
|
-
if (errorFallback) return /*#__PURE__*/ external_react_default().createElement(ErrorBoundary, {
|
|
1006
|
-
fallback: errorFallback
|
|
1007
|
-
}, /*#__PURE__*/ external_react_default().createElement(external_react_namespaceObject.Suspense, {
|
|
1008
|
-
fallback: fallback || /*#__PURE__*/ external_react_default().createElement("div", null, "Loading...")
|
|
1009
|
-
}, /*#__PURE__*/ external_react_default().createElement(RemoteComponent, componentProps)));
|
|
1010
|
-
return /*#__PURE__*/ external_react_default().createElement(external_react_namespaceObject.Suspense, {
|
|
1011
|
-
fallback: fallback || /*#__PURE__*/ external_react_default().createElement("div", null, "Loading...")
|
|
1012
|
-
}, /*#__PURE__*/ external_react_default().createElement(RemoteComponent, componentProps));
|
|
900
|
+
hasListeners(event) {
|
|
901
|
+
return this.listeners.has(event) && this.listeners.get(event).size > 0;
|
|
1013
902
|
}
|
|
1014
|
-
|
|
1015
|
-
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1019
|
-
|
|
1020
|
-
|
|
903
|
+
clear(event) {
|
|
904
|
+
if (event) {
|
|
905
|
+
this.listeners.delete(event);
|
|
906
|
+
this.eventHistory.delete(event);
|
|
907
|
+
} else {
|
|
908
|
+
this.listeners.clear();
|
|
909
|
+
this.eventHistory.clear();
|
|
910
|
+
}
|
|
1021
911
|
}
|
|
1022
|
-
|
|
1023
|
-
const
|
|
1024
|
-
|
|
1025
|
-
|
|
1026
|
-
|
|
1027
|
-
|
|
912
|
+
listenerExists(event, callback) {
|
|
913
|
+
const subscriptions = this.listeners.get(event);
|
|
914
|
+
if (!subscriptions) return false;
|
|
915
|
+
let exists = false;
|
|
916
|
+
subscriptions.forEach((sub)=>{
|
|
917
|
+
if (sub.callback === callback) exists = true;
|
|
1028
918
|
});
|
|
1029
|
-
|
|
1030
|
-
let mounted = true;
|
|
1031
|
-
async function load() {
|
|
1032
|
-
try {
|
|
1033
|
-
setState((prev)=>({
|
|
1034
|
-
...prev,
|
|
1035
|
-
loading: true,
|
|
1036
|
-
error: null
|
|
1037
|
-
}));
|
|
1038
|
-
const { mf } = await loadRemoteMultiVersion({
|
|
1039
|
-
name: scopeName,
|
|
1040
|
-
pkg,
|
|
1041
|
-
version
|
|
1042
|
-
}, []);
|
|
1043
|
-
if (!mf) throw new Error(`[RemoteReloadUtils] Failed to get Module Federation instance for ${scopeName}`);
|
|
1044
|
-
const mod = await mf.loadRemote(`${scopeName}/${moduleName}`);
|
|
1045
|
-
if (mounted) if (mod && 'object' == typeof mod && 'default' in mod) setState({
|
|
1046
|
-
component: mod.default,
|
|
1047
|
-
loading: false,
|
|
1048
|
-
error: null
|
|
1049
|
-
});
|
|
1050
|
-
else throw new Error(`[RemoteReloadUtils] Module "${scopeName}/${moduleName}" does not export a default component`);
|
|
1051
|
-
} catch (err) {
|
|
1052
|
-
if (mounted) setState({
|
|
1053
|
-
component: null,
|
|
1054
|
-
loading: false,
|
|
1055
|
-
error: err instanceof Error ? err : new Error(String(err))
|
|
1056
|
-
});
|
|
1057
|
-
}
|
|
1058
|
-
}
|
|
1059
|
-
load();
|
|
1060
|
-
return ()=>{
|
|
1061
|
-
mounted = false;
|
|
1062
|
-
};
|
|
1063
|
-
}, [
|
|
1064
|
-
pkg,
|
|
1065
|
-
version,
|
|
1066
|
-
moduleName,
|
|
1067
|
-
scopeName
|
|
1068
|
-
]);
|
|
1069
|
-
return {
|
|
1070
|
-
component: state.component,
|
|
1071
|
-
loading: state.loading,
|
|
1072
|
-
error: state.error
|
|
1073
|
-
};
|
|
919
|
+
return exists;
|
|
1074
920
|
}
|
|
1075
|
-
|
|
1076
|
-
|
|
1077
|
-
|
|
1078
|
-
|
|
1079
|
-
|
|
1080
|
-
|
|
921
|
+
emitAsync(event, data, meta) {
|
|
922
|
+
return new Promise((resolve)=>{
|
|
923
|
+
this.emit(event, data, meta);
|
|
924
|
+
resolve();
|
|
925
|
+
});
|
|
926
|
+
}
|
|
927
|
+
static create() {
|
|
928
|
+
return new EventBusClass();
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
const eventBus = EventBusClass.create();
|
|
932
|
+
function createEventBus() {
|
|
933
|
+
return EventBusClass.create();
|
|
934
|
+
}
|
|
1081
935
|
exports.buildCdnUrls = __webpack_exports__.buildCdnUrls;
|
|
1082
936
|
exports.buildFinalUrls = __webpack_exports__.buildFinalUrls;
|
|
1083
937
|
exports.cancelPreload = __webpack_exports__.cancelPreload;
|
|
@@ -1087,6 +941,7 @@ exports.checkVersionCompatibility = __webpack_exports__.checkVersionCompatibilit
|
|
|
1087
941
|
exports.clearPreloadCache = __webpack_exports__.clearPreloadCache;
|
|
1088
942
|
exports.compareVersions = __webpack_exports__.compareVersions;
|
|
1089
943
|
exports.createEventBus = __webpack_exports__.createEventBus;
|
|
944
|
+
exports.createRemoteSourcePlugin = __webpack_exports__.createRemoteSourcePlugin;
|
|
1090
945
|
exports.eventBus = __webpack_exports__.eventBus;
|
|
1091
946
|
exports.extractMajorVersion = __webpack_exports__.extractMajorVersion;
|
|
1092
947
|
exports.fallbackPlugin = __webpack_exports__.fallbackPlugin;
|
|
@@ -1104,7 +959,6 @@ exports.getStableVersions = __webpack_exports__.getStableVersions;
|
|
|
1104
959
|
exports.getVersionCache = __webpack_exports__.getVersionCache;
|
|
1105
960
|
exports.isPrerelease = __webpack_exports__.isPrerelease;
|
|
1106
961
|
exports.isRemoteLoaded = __webpack_exports__.isRemoteLoaded;
|
|
1107
|
-
exports.lazyRemote = __webpack_exports__.lazyRemote;
|
|
1108
962
|
exports.loadReactVersion = __webpack_exports__.loadReactVersion;
|
|
1109
963
|
exports.loadRemoteMultiVersion = __webpack_exports__.loadRemoteMultiVersion;
|
|
1110
964
|
exports.parseVersion = __webpack_exports__.parseVersion;
|
|
@@ -1119,15 +973,7 @@ exports.sortVersions = __webpack_exports__.sortVersions;
|
|
|
1119
973
|
exports.tryLoadRemote = __webpack_exports__.tryLoadRemote;
|
|
1120
974
|
exports.unloadAll = __webpack_exports__.unloadAll;
|
|
1121
975
|
exports.unloadRemote = __webpack_exports__.unloadRemote;
|
|
1122
|
-
exports.useRemoteModule = __webpack_exports__.useRemoteModule;
|
|
1123
|
-
exports.useRemoteModuleHook = __webpack_exports__.useRemoteModuleHook;
|
|
1124
|
-
exports.withRemote = __webpack_exports__.withRemote;
|
|
1125
976
|
for(var __webpack_i__ in __webpack_exports__)if (-1 === [
|
|
1126
|
-
"ErrorBoundary",
|
|
1127
|
-
"RemoteModuleProvider",
|
|
1128
|
-
"RemoteModuleRenderer",
|
|
1129
|
-
"SuspenseRemote",
|
|
1130
|
-
"SuspenseRemoteLoader",
|
|
1131
977
|
"buildCdnUrls",
|
|
1132
978
|
"buildFinalUrls",
|
|
1133
979
|
"cancelPreload",
|
|
@@ -1137,6 +983,7 @@ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
|
|
|
1137
983
|
"clearPreloadCache",
|
|
1138
984
|
"compareVersions",
|
|
1139
985
|
"createEventBus",
|
|
986
|
+
"createRemoteSourcePlugin",
|
|
1140
987
|
"eventBus",
|
|
1141
988
|
"extractMajorVersion",
|
|
1142
989
|
"fallbackPlugin",
|
|
@@ -1154,7 +1001,6 @@ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
|
|
|
1154
1001
|
"getVersionCache",
|
|
1155
1002
|
"isPrerelease",
|
|
1156
1003
|
"isRemoteLoaded",
|
|
1157
|
-
"lazyRemote",
|
|
1158
1004
|
"loadReactVersion",
|
|
1159
1005
|
"loadRemoteMultiVersion",
|
|
1160
1006
|
"parseVersion",
|
|
@@ -1168,10 +1014,7 @@ for(var __webpack_i__ in __webpack_exports__)if (-1 === [
|
|
|
1168
1014
|
"sortVersions",
|
|
1169
1015
|
"tryLoadRemote",
|
|
1170
1016
|
"unloadAll",
|
|
1171
|
-
"unloadRemote"
|
|
1172
|
-
"useRemoteModule",
|
|
1173
|
-
"useRemoteModuleHook",
|
|
1174
|
-
"withRemote"
|
|
1017
|
+
"unloadRemote"
|
|
1175
1018
|
].indexOf(__webpack_i__)) exports[__webpack_i__] = __webpack_exports__[__webpack_i__];
|
|
1176
1019
|
Object.defineProperty(exports, '__esModule', {
|
|
1177
1020
|
value: true
|