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