@module-federation/runtime 1.0.0-canary.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/helpers.cjs.d.ts +2 -0
- package/helpers.cjs.js +33 -0
- package/helpers.esm.js +31 -0
- package/index.cjs.d.ts +1 -0
- package/index.cjs.js +1927 -0
- package/index.esm.js +1917 -0
- package/package.json +40 -0
- package/share.cjs.js +782 -0
- package/share.esm.js +741 -0
- package/src/constant.d.ts +2 -0
- package/src/core.d.ts +113 -0
- package/src/global.d.ts +57 -0
- package/src/helpers.d.ts +32 -0
- package/src/index.d.ts +10 -0
- package/src/module/index.d.ts +25 -0
- package/src/plugins/generate-preload-assets.d.ts +8 -0
- package/src/plugins/snapshot/SnapshotHandler.d.ts +43 -0
- package/src/plugins/snapshot/index.d.ts +5 -0
- package/src/type/config.d.ts +94 -0
- package/src/type/index.d.ts +3 -0
- package/src/type/plugin.d.ts +20 -0
- package/src/type/preload.d.ts +25 -0
- package/src/types.d.ts +1 -0
- package/src/utils/dom.d.ts +8 -0
- package/src/utils/env.d.ts +4 -0
- package/src/utils/hooks/asyncHook.d.ts +6 -0
- package/src/utils/hooks/asyncWaterfallHooks.d.ts +10 -0
- package/src/utils/hooks/index.d.ts +6 -0
- package/src/utils/hooks/pluginSystem.d.ts +15 -0
- package/src/utils/hooks/syncHook.d.ts +12 -0
- package/src/utils/hooks/syncWaterfallHook.d.ts +9 -0
- package/src/utils/index.d.ts +6 -0
- package/src/utils/load.d.ts +17 -0
- package/src/utils/logger.d.ts +3 -0
- package/src/utils/manifest.d.ts +9 -0
- package/src/utils/plugin.d.ts +4 -0
- package/src/utils/preload.d.ts +6 -0
- package/src/utils/semver/compare.d.ts +9 -0
- package/src/utils/semver/constants.d.ts +10 -0
- package/src/utils/semver/index.d.ts +2 -0
- package/src/utils/semver/parser.d.ts +9 -0
- package/src/utils/semver/utils.d.ts +11 -0
- package/src/utils/share.d.ts +7 -0
- package/src/utils/tool.d.ts +12 -0
- package/type.cjs.d.ts +1 -0
- package/type.cjs.js +2 -0
- package/type.esm.js +1 -0
package/index.esm.js
ADDED
|
@@ -0,0 +1,1917 @@
|
|
|
1
|
+
import { i as isStaticResourcesEqual, s as safeWrapper, g as getGlobalHostPlugins, _ as _extends, D as DEFAULT_REMOTE_TYPE, a as DEFAULT_SCOPE, b as globalLoading, c as getRemoteEntryExports, d as assert, e as safeToString$1, G as Global, f as getFMId, h as isObject, j as error, w as warn, k as isPlainObject, l as isRemoteInfoWithEntry, m as isPureRemoteEntry, n as getGlobalShare, o as getInfoWithoutType, p as getPreloaded, q as setPreloaded, r as getGlobalSnapshotInfoByModuleInfo, t as setGlobalSnapshotInfoByModuleInfo, u as getGlobalSnapshot, v as addUniqueItem, x as formatShareConfigs, y as isBrowserEnv$1, z as getGlobalShareScope, A as _object_without_properties_loose, B as getBuilderId, C as setGlobalFederationConstructor, E as getGlobalFederationInstance, F as getGlobalFederationConstructor, H as setGlobalFederationInstance } from './share.esm.js';
|
|
2
|
+
export { I as registerGlobalPlugins } from './share.esm.js';
|
|
3
|
+
|
|
4
|
+
function getResourceUrl(module, sourceUrl) {
|
|
5
|
+
if ('getPublicPath' in module) {
|
|
6
|
+
const publicPath = new Function(module.getPublicPath)();
|
|
7
|
+
return `${publicPath}${sourceUrl}`;
|
|
8
|
+
} else if ('publicPath' in module) {
|
|
9
|
+
return `${module.publicPath}${sourceUrl}`;
|
|
10
|
+
} else {
|
|
11
|
+
console.warn('Cannot get resource URL. If in debug mode, please ignore.', module, sourceUrl);
|
|
12
|
+
return '';
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
// id: pkgName(@federation/app1) + expose(button) = @federation/app1/button
|
|
16
|
+
// id: alias(app1) + expose(button) = app1/button
|
|
17
|
+
// id: alias(app1/utils) + expose(loadash/sort) = app1/utils/loadash/sort
|
|
18
|
+
function matchRemoteWithNameAndExpose(remotes, id) {
|
|
19
|
+
for (const remote of remotes){
|
|
20
|
+
// match pkgName
|
|
21
|
+
const matchNameSuccess = id.startsWith(remote.name);
|
|
22
|
+
let expose = id.replace(remote.name, '');
|
|
23
|
+
if (matchNameSuccess) {
|
|
24
|
+
if (expose.startsWith('/')) {
|
|
25
|
+
const pkgNameOrAlias = remote.name;
|
|
26
|
+
expose = `.${expose}`;
|
|
27
|
+
return {
|
|
28
|
+
pkgNameOrAlias,
|
|
29
|
+
expose,
|
|
30
|
+
remote
|
|
31
|
+
};
|
|
32
|
+
} else if (expose === '') {
|
|
33
|
+
return {
|
|
34
|
+
pkgNameOrAlias: remote.name,
|
|
35
|
+
expose: '.',
|
|
36
|
+
remote
|
|
37
|
+
};
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
// match alias
|
|
41
|
+
const matchAliasSuccess = remote.alias && id.startsWith(remote.alias);
|
|
42
|
+
let exposeWithAlias = remote.alias && id.replace(remote.alias, '');
|
|
43
|
+
if (remote.alias && matchAliasSuccess) {
|
|
44
|
+
if (exposeWithAlias && exposeWithAlias.startsWith('/')) {
|
|
45
|
+
const pkgNameOrAlias = remote.alias;
|
|
46
|
+
exposeWithAlias = `.${exposeWithAlias}`;
|
|
47
|
+
return {
|
|
48
|
+
pkgNameOrAlias,
|
|
49
|
+
expose: exposeWithAlias,
|
|
50
|
+
remote
|
|
51
|
+
};
|
|
52
|
+
} else if (exposeWithAlias === '') {
|
|
53
|
+
return {
|
|
54
|
+
pkgNameOrAlias: remote.alias,
|
|
55
|
+
expose: '.',
|
|
56
|
+
remote
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
function matchRemote(remotes, nameOrAlias) {
|
|
64
|
+
for (const remote of remotes){
|
|
65
|
+
const matchNameSuccess = nameOrAlias === remote.name;
|
|
66
|
+
if (matchNameSuccess) {
|
|
67
|
+
return remote;
|
|
68
|
+
}
|
|
69
|
+
const matchAliasSuccess = remote.alias && nameOrAlias === remote.alias;
|
|
70
|
+
if (matchAliasSuccess) {
|
|
71
|
+
return remote;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
function createScript(url, cb, attrs, createScriptHook) {
|
|
78
|
+
// get the existing script element by src
|
|
79
|
+
let script = null;
|
|
80
|
+
let needAttach = true;
|
|
81
|
+
const scripts = document.getElementsByTagName('script');
|
|
82
|
+
for(let i = 0; i < scripts.length; i++){
|
|
83
|
+
const s = scripts[i];
|
|
84
|
+
const scriptSrc = s.getAttribute('src');
|
|
85
|
+
if (scriptSrc && isStaticResourcesEqual(scriptSrc, url)) {
|
|
86
|
+
script = s;
|
|
87
|
+
needAttach = false;
|
|
88
|
+
break;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
if (!script) {
|
|
92
|
+
script = document.createElement('script');
|
|
93
|
+
script.type = 'text/javascript';
|
|
94
|
+
script.src = url;
|
|
95
|
+
if (createScriptHook) {
|
|
96
|
+
const createScriptRes = createScriptHook(url);
|
|
97
|
+
if (createScriptRes instanceof HTMLScriptElement) {
|
|
98
|
+
script = createScriptRes;
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
if (attrs) {
|
|
103
|
+
Object.keys(attrs).forEach((name)=>{
|
|
104
|
+
if (script) {
|
|
105
|
+
if (name === 'async' || name === 'defer') {
|
|
106
|
+
script[name] = attrs[name];
|
|
107
|
+
} else {
|
|
108
|
+
script.setAttribute(name, attrs[name]);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
});
|
|
112
|
+
}
|
|
113
|
+
const onScriptComplete = (prev, // eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
114
|
+
event)=>{
|
|
115
|
+
// avoid memory leaks in IE.
|
|
116
|
+
if (script) {
|
|
117
|
+
script.onerror = null;
|
|
118
|
+
script.onload = null;
|
|
119
|
+
safeWrapper(()=>{
|
|
120
|
+
(script == null ? void 0 : script.parentNode) && script.parentNode.removeChild(script);
|
|
121
|
+
});
|
|
122
|
+
if (prev) {
|
|
123
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
124
|
+
const res = prev(event);
|
|
125
|
+
cb();
|
|
126
|
+
return res;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
cb();
|
|
130
|
+
};
|
|
131
|
+
script.onerror = onScriptComplete.bind(null, script.onerror);
|
|
132
|
+
script.onload = onScriptComplete.bind(null, script.onload);
|
|
133
|
+
return {
|
|
134
|
+
script,
|
|
135
|
+
needAttach
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
function loadScript(url, info) {
|
|
139
|
+
const { attrs, createScriptHook } = info;
|
|
140
|
+
return new Promise((resolve, _reject)=>{
|
|
141
|
+
const { script, needAttach } = createScript(url, resolve, attrs, createScriptHook);
|
|
142
|
+
needAttach && document.getElementsByTagName('head')[0].appendChild(script);
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function registerPlugins(plugins, hookInstances) {
|
|
147
|
+
const globalPlugins = getGlobalHostPlugins();
|
|
148
|
+
// Register global plugins
|
|
149
|
+
if (globalPlugins.length > 0) {
|
|
150
|
+
globalPlugins.forEach((plugin)=>{
|
|
151
|
+
if (plugins == null ? void 0 : plugins.find((item)=>item.name !== plugin.name)) {
|
|
152
|
+
plugins.push(plugin);
|
|
153
|
+
}
|
|
154
|
+
});
|
|
155
|
+
}
|
|
156
|
+
if (plugins && plugins.length > 0) {
|
|
157
|
+
plugins.forEach((plugin)=>{
|
|
158
|
+
hookInstances.forEach((hookInstance)=>{
|
|
159
|
+
hookInstance.usePlugin(plugin);
|
|
160
|
+
});
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function _instanceof(left, right) {
|
|
166
|
+
if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
|
|
167
|
+
return !!right[Symbol.hasInstance](left);
|
|
168
|
+
} else {
|
|
169
|
+
return left instanceof right;
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
function _define_property$2(obj, key, value) {
|
|
173
|
+
if (key in obj) {
|
|
174
|
+
Object.defineProperty(obj, key, {
|
|
175
|
+
value: value,
|
|
176
|
+
enumerable: true,
|
|
177
|
+
configurable: true,
|
|
178
|
+
writable: true
|
|
179
|
+
});
|
|
180
|
+
} else {
|
|
181
|
+
obj[key] = value;
|
|
182
|
+
}
|
|
183
|
+
return obj;
|
|
184
|
+
}
|
|
185
|
+
var MANIFEST_EXT = ".json";
|
|
186
|
+
var BROWSER_LOG_KEY = "''";
|
|
187
|
+
var BROWSER_LOG_VALUE = "1";
|
|
188
|
+
var NameTransformSymbol = {
|
|
189
|
+
AT: "@",
|
|
190
|
+
HYPHEN: "-",
|
|
191
|
+
SLASH: "/"
|
|
192
|
+
};
|
|
193
|
+
var _obj;
|
|
194
|
+
var NameTransformMap = (_obj = {}, _define_property$2(_obj, NameTransformSymbol.AT, "scope_"), _define_property$2(_obj, NameTransformSymbol.HYPHEN, "_"), _define_property$2(_obj, NameTransformSymbol.SLASH, "__"), _obj);
|
|
195
|
+
var _obj1;
|
|
196
|
+
(_obj1 = {}, _define_property$2(_obj1, NameTransformMap[NameTransformSymbol.AT], NameTransformSymbol.AT), _define_property$2(_obj1, NameTransformMap[NameTransformSymbol.HYPHEN], NameTransformSymbol.HYPHEN), _define_property$2(_obj1, NameTransformMap[NameTransformSymbol.SLASH], NameTransformSymbol.SLASH), _obj1);
|
|
197
|
+
var SEPARATOR = ":";
|
|
198
|
+
function isBrowserEnv() {
|
|
199
|
+
return typeof window !== "undefined";
|
|
200
|
+
}
|
|
201
|
+
function isDebugMode() {
|
|
202
|
+
if (typeof process !== "undefined" && process.env && process.env["''"]) {
|
|
203
|
+
return Boolean(process.env["''"]);
|
|
204
|
+
}
|
|
205
|
+
return Boolean('');
|
|
206
|
+
}
|
|
207
|
+
function _array_like_to_array$1(arr, len) {
|
|
208
|
+
if (len == null || len > arr.length) len = arr.length;
|
|
209
|
+
for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
|
|
210
|
+
return arr2;
|
|
211
|
+
}
|
|
212
|
+
function _array_without_holes(arr) {
|
|
213
|
+
if (Array.isArray(arr)) return _array_like_to_array$1(arr);
|
|
214
|
+
}
|
|
215
|
+
function _class_call_check(instance, Constructor) {
|
|
216
|
+
if (!_instanceof(instance, Constructor)) {
|
|
217
|
+
throw new TypeError("Cannot call a class as a function");
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
function _defineProperties(target, props) {
|
|
221
|
+
for(var i = 0; i < props.length; i++){
|
|
222
|
+
var descriptor = props[i];
|
|
223
|
+
descriptor.enumerable = descriptor.enumerable || false;
|
|
224
|
+
descriptor.configurable = true;
|
|
225
|
+
if ("value" in descriptor) descriptor.writable = true;
|
|
226
|
+
Object.defineProperty(target, descriptor.key, descriptor);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
function _create_class(Constructor, protoProps, staticProps) {
|
|
230
|
+
if (protoProps) _defineProperties(Constructor.prototype, protoProps);
|
|
231
|
+
if (staticProps) _defineProperties(Constructor, staticProps);
|
|
232
|
+
return Constructor;
|
|
233
|
+
}
|
|
234
|
+
function _define_property$1(obj, key, value) {
|
|
235
|
+
if (key in obj) {
|
|
236
|
+
Object.defineProperty(obj, key, {
|
|
237
|
+
value: value,
|
|
238
|
+
enumerable: true,
|
|
239
|
+
configurable: true,
|
|
240
|
+
writable: true
|
|
241
|
+
});
|
|
242
|
+
} else {
|
|
243
|
+
obj[key] = value;
|
|
244
|
+
}
|
|
245
|
+
return obj;
|
|
246
|
+
}
|
|
247
|
+
function _iterable_to_array$1(iter) {
|
|
248
|
+
if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
|
|
249
|
+
}
|
|
250
|
+
function _non_iterable_spread() {
|
|
251
|
+
throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
|
|
252
|
+
}
|
|
253
|
+
function _to_consumable_array(arr) {
|
|
254
|
+
return _array_without_holes(arr) || _iterable_to_array$1(arr) || _unsupported_iterable_to_array$1(arr) || _non_iterable_spread();
|
|
255
|
+
}
|
|
256
|
+
function _unsupported_iterable_to_array$1(o, minLen) {
|
|
257
|
+
if (!o) return;
|
|
258
|
+
if (typeof o === "string") return _array_like_to_array$1(o, minLen);
|
|
259
|
+
var n = Object.prototype.toString.call(o).slice(8, -1);
|
|
260
|
+
if (n === "Object" && o.constructor) n = o.constructor.name;
|
|
261
|
+
if (n === "Map" || n === "Set") return Array.from(n);
|
|
262
|
+
if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array$1(o, minLen);
|
|
263
|
+
}
|
|
264
|
+
function safeToString(info) {
|
|
265
|
+
try {
|
|
266
|
+
return JSON.stringify(info, null, 2);
|
|
267
|
+
} catch (e) {
|
|
268
|
+
return "";
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
var DEBUG_LOG = "[ FEDERATION DEBUG ]";
|
|
272
|
+
var Logger = /*#__PURE__*/ function() {
|
|
273
|
+
function Logger(identifier) {
|
|
274
|
+
_class_call_check(this, Logger);
|
|
275
|
+
_define_property$1(this, "enable", false);
|
|
276
|
+
_define_property$1(this, "identifier", void 0);
|
|
277
|
+
this.identifier = identifier || DEBUG_LOG;
|
|
278
|
+
if (isBrowserEnv() && localStorage.getItem(BROWSER_LOG_KEY) === BROWSER_LOG_VALUE) {
|
|
279
|
+
this.enable = true;
|
|
280
|
+
} else if (isDebugMode()) {
|
|
281
|
+
this.enable = true;
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
_create_class(Logger, [
|
|
285
|
+
{
|
|
286
|
+
key: "info",
|
|
287
|
+
value: function info(msg, info) {
|
|
288
|
+
if (this.enable) {
|
|
289
|
+
var argsToString = safeToString(info) || "";
|
|
290
|
+
if (isBrowserEnv()) {
|
|
291
|
+
console.info("%c ".concat(this.identifier, ": ").concat(msg, " ").concat(argsToString), "color:#3300CC");
|
|
292
|
+
} else {
|
|
293
|
+
console.info("\x1b[34m%s", "".concat(this.identifier, ": ").concat(msg, " ").concat(argsToString ? "\n".concat(argsToString) : ""));
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
},
|
|
298
|
+
{
|
|
299
|
+
key: "logOriginalInfo",
|
|
300
|
+
value: function logOriginalInfo() {
|
|
301
|
+
for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
|
|
302
|
+
args[_key] = arguments[_key];
|
|
303
|
+
}
|
|
304
|
+
if (this.enable) {
|
|
305
|
+
if (isBrowserEnv()) {
|
|
306
|
+
var _console;
|
|
307
|
+
console.info("%c ".concat(this.identifier, ": OriginalInfo"), "color:#3300CC");
|
|
308
|
+
(_console = console).log.apply(_console, _to_consumable_array(args));
|
|
309
|
+
} else {
|
|
310
|
+
var _console1;
|
|
311
|
+
console.info("%c ".concat(this.identifier, ": OriginalInfo"), "color:#3300CC");
|
|
312
|
+
(_console1 = console).log.apply(_console1, _to_consumable_array(args));
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
]);
|
|
318
|
+
return Logger;
|
|
319
|
+
}();
|
|
320
|
+
new Logger();
|
|
321
|
+
var composeKeyWithSeparator = function composeKeyWithSeparator() {
|
|
322
|
+
for(var _len = arguments.length, args = new Array(_len), _key = 0; _key < _len; _key++){
|
|
323
|
+
args[_key] = arguments[_key];
|
|
324
|
+
}
|
|
325
|
+
if (!args.length) {
|
|
326
|
+
return "";
|
|
327
|
+
}
|
|
328
|
+
return args.reduce(function(sum, cur) {
|
|
329
|
+
if (!cur) {
|
|
330
|
+
return sum;
|
|
331
|
+
}
|
|
332
|
+
if (!sum) {
|
|
333
|
+
return cur;
|
|
334
|
+
}
|
|
335
|
+
return "".concat(sum).concat(SEPARATOR).concat(cur);
|
|
336
|
+
}, "");
|
|
337
|
+
};
|
|
338
|
+
function _define_property(obj, key, value) {
|
|
339
|
+
if (key in obj) {
|
|
340
|
+
Object.defineProperty(obj, key, {
|
|
341
|
+
value: value,
|
|
342
|
+
enumerable: true,
|
|
343
|
+
configurable: true,
|
|
344
|
+
writable: true
|
|
345
|
+
});
|
|
346
|
+
} else {
|
|
347
|
+
obj[key] = value;
|
|
348
|
+
}
|
|
349
|
+
return obj;
|
|
350
|
+
}
|
|
351
|
+
function _object_spread(target) {
|
|
352
|
+
for(var i = 1; i < arguments.length; i++){
|
|
353
|
+
var source = arguments[i] != null ? arguments[i] : {};
|
|
354
|
+
var ownKeys = Object.keys(source);
|
|
355
|
+
if (typeof Object.getOwnPropertySymbols === "function") {
|
|
356
|
+
ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
|
|
357
|
+
return Object.getOwnPropertyDescriptor(source, sym).enumerable;
|
|
358
|
+
}));
|
|
359
|
+
}
|
|
360
|
+
ownKeys.forEach(function(key) {
|
|
361
|
+
_define_property(target, key, source[key]);
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
return target;
|
|
365
|
+
}
|
|
366
|
+
function ownKeys(object, enumerableOnly) {
|
|
367
|
+
var keys = Object.keys(object);
|
|
368
|
+
if (Object.getOwnPropertySymbols) {
|
|
369
|
+
var symbols = Object.getOwnPropertySymbols(object);
|
|
370
|
+
if (enumerableOnly) {
|
|
371
|
+
symbols = symbols.filter(function(sym) {
|
|
372
|
+
return Object.getOwnPropertyDescriptor(object, sym).enumerable;
|
|
373
|
+
});
|
|
374
|
+
}
|
|
375
|
+
keys.push.apply(keys, symbols);
|
|
376
|
+
}
|
|
377
|
+
return keys;
|
|
378
|
+
}
|
|
379
|
+
function _object_spread_props(target, source) {
|
|
380
|
+
source = source != null ? source : {};
|
|
381
|
+
if (Object.getOwnPropertyDescriptors) {
|
|
382
|
+
Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
|
|
383
|
+
} else {
|
|
384
|
+
ownKeys(Object(source)).forEach(function(key) {
|
|
385
|
+
Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
|
|
386
|
+
});
|
|
387
|
+
}
|
|
388
|
+
return target;
|
|
389
|
+
}
|
|
390
|
+
var simpleJoinRemoteEntry = function simpleJoinRemoteEntry(rPath, rName) {
|
|
391
|
+
if (!rPath) {
|
|
392
|
+
return rName;
|
|
393
|
+
}
|
|
394
|
+
var transformPath = function transformPath(str) {
|
|
395
|
+
if (str === ".") {
|
|
396
|
+
return "";
|
|
397
|
+
}
|
|
398
|
+
if (str.startsWith("./")) {
|
|
399
|
+
return str.replace("./", "");
|
|
400
|
+
}
|
|
401
|
+
if (str.startsWith("/")) {
|
|
402
|
+
var strWithoutSlash = str.slice(1);
|
|
403
|
+
if (strWithoutSlash.endsWith("/")) {
|
|
404
|
+
return strWithoutSlash.slice(0, -1);
|
|
405
|
+
}
|
|
406
|
+
return strWithoutSlash;
|
|
407
|
+
}
|
|
408
|
+
return str;
|
|
409
|
+
};
|
|
410
|
+
var transformedPath = transformPath(rPath);
|
|
411
|
+
if (!transformedPath) {
|
|
412
|
+
return rName;
|
|
413
|
+
}
|
|
414
|
+
if (transformedPath.endsWith("/")) {
|
|
415
|
+
return "".concat(transformedPath).concat(rName);
|
|
416
|
+
}
|
|
417
|
+
return "".concat(transformedPath, "/").concat(rName);
|
|
418
|
+
};
|
|
419
|
+
// 优先级:overrides > remotes
|
|
420
|
+
// eslint-disable-next-line max-lines-per-function
|
|
421
|
+
function generateSnapshotFromManifest(manifest) {
|
|
422
|
+
var options = arguments.length > 1 && arguments[1] !== void 0 ? arguments[1] : {};
|
|
423
|
+
var _options_remotes = options.remotes, remotes = _options_remotes === void 0 ? {} : _options_remotes, _options_overrides = options.overrides, overrides = _options_overrides === void 0 ? {} : _options_overrides, version = options.version;
|
|
424
|
+
var remoteSnapshot;
|
|
425
|
+
var getPublicPath = function getPublicPath() {
|
|
426
|
+
if ("publicPath" in manifest.metaData) {
|
|
427
|
+
return manifest.metaData.publicPath;
|
|
428
|
+
} else {
|
|
429
|
+
return manifest.metaData.getPublicPath;
|
|
430
|
+
}
|
|
431
|
+
};
|
|
432
|
+
var overridesKeys = Object.keys(overrides);
|
|
433
|
+
var remotesInfo = {};
|
|
434
|
+
// If remotes are not passed, only the remotes in the manifest will be read
|
|
435
|
+
if (!Object.keys(remotes).length) {
|
|
436
|
+
var _manifest_remotes;
|
|
437
|
+
remotesInfo = ((_manifest_remotes = manifest.remotes) === null || _manifest_remotes === void 0 ? void 0 : _manifest_remotes.reduce(function(res, next) {
|
|
438
|
+
var matchedVersion;
|
|
439
|
+
var name = next.federationContainerName;
|
|
440
|
+
// overrides has hight priority
|
|
441
|
+
if (overridesKeys.includes(name)) {
|
|
442
|
+
matchedVersion = overrides[name];
|
|
443
|
+
} else {
|
|
444
|
+
if ("version" in next) {
|
|
445
|
+
matchedVersion = next.version;
|
|
446
|
+
} else {
|
|
447
|
+
matchedVersion = next.entry;
|
|
448
|
+
}
|
|
449
|
+
}
|
|
450
|
+
res[name] = {
|
|
451
|
+
matchedVersion: matchedVersion
|
|
452
|
+
};
|
|
453
|
+
return res;
|
|
454
|
+
}, {})) || {};
|
|
455
|
+
}
|
|
456
|
+
// If remotes (deploy scenario) are specified, you need to traverse it again
|
|
457
|
+
Object.keys(remotes).forEach(function(key) {
|
|
458
|
+
return remotesInfo[key] = {
|
|
459
|
+
// overrides will override dependencies
|
|
460
|
+
matchedVersion: overridesKeys.includes(key) ? overrides[key] : remotes[key]
|
|
461
|
+
};
|
|
462
|
+
});
|
|
463
|
+
var _manifest_metaData = manifest.metaData, _manifest_metaData_remoteEntry = _manifest_metaData.remoteEntry, remoteEntryPath = _manifest_metaData_remoteEntry.path, remoteEntryName = _manifest_metaData_remoteEntry.name, remoteEntryType = _manifest_metaData_remoteEntry.type, remoteTypes = _manifest_metaData.types, buildVersion = _manifest_metaData.buildInfo.buildVersion, globalName = _manifest_metaData.globalName;
|
|
464
|
+
var exposes = manifest.exposes;
|
|
465
|
+
var basicRemoteSnapshot = {
|
|
466
|
+
version: version ? version : "",
|
|
467
|
+
buildVersion: buildVersion,
|
|
468
|
+
globalName: globalName,
|
|
469
|
+
remoteEntry: simpleJoinRemoteEntry(remoteEntryPath, remoteEntryName),
|
|
470
|
+
remoteEntryType: remoteEntryType,
|
|
471
|
+
remoteTypes: simpleJoinRemoteEntry(remoteTypes.path, remoteTypes.name),
|
|
472
|
+
remotesInfo: remotesInfo,
|
|
473
|
+
shared: manifest === null || manifest === void 0 ? void 0 : manifest.shared.map(function(item) {
|
|
474
|
+
return {
|
|
475
|
+
assets: item.assets,
|
|
476
|
+
sharedName: item.name
|
|
477
|
+
};
|
|
478
|
+
}),
|
|
479
|
+
modules: exposes === null || exposes === void 0 ? void 0 : exposes.map(function(expose) {
|
|
480
|
+
return {
|
|
481
|
+
moduleName: expose.name,
|
|
482
|
+
modulePath: expose.path,
|
|
483
|
+
assets: expose.assets
|
|
484
|
+
};
|
|
485
|
+
})
|
|
486
|
+
};
|
|
487
|
+
if ("publicPath" in manifest.metaData) {
|
|
488
|
+
remoteSnapshot = _object_spread_props(_object_spread({}, basicRemoteSnapshot), {
|
|
489
|
+
publicPath: getPublicPath()
|
|
490
|
+
});
|
|
491
|
+
} else {
|
|
492
|
+
remoteSnapshot = _object_spread_props(_object_spread({}, basicRemoteSnapshot), {
|
|
493
|
+
getPublicPath: getPublicPath()
|
|
494
|
+
});
|
|
495
|
+
}
|
|
496
|
+
return remoteSnapshot;
|
|
497
|
+
}
|
|
498
|
+
function isManifestProvider(moduleInfo) {
|
|
499
|
+
if ("remoteEntry" in moduleInfo && moduleInfo.remoteEntry.endsWith(MANIFEST_EXT)) {
|
|
500
|
+
return true;
|
|
501
|
+
} else {
|
|
502
|
+
return false;
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
async function loadEsmEntry({ entry, remoteEntryExports }) {
|
|
507
|
+
return new Promise((resolve, reject)=>{
|
|
508
|
+
try {
|
|
509
|
+
if (!remoteEntryExports) {
|
|
510
|
+
// eslint-disable-next-line no-eval
|
|
511
|
+
new Function('resolve', `import("${entry}").then((res)=>{resolve(res);}, (error)=> reject(error))`)(resolve);
|
|
512
|
+
} else {
|
|
513
|
+
resolve(remoteEntryExports);
|
|
514
|
+
}
|
|
515
|
+
} catch (e) {
|
|
516
|
+
reject(e);
|
|
517
|
+
}
|
|
518
|
+
});
|
|
519
|
+
}
|
|
520
|
+
async function loadEntryScript({ name, globalName, entry, createScriptHook }) {
|
|
521
|
+
const { entryExports: remoteEntryExports } = getRemoteEntryExports(name, globalName);
|
|
522
|
+
if (remoteEntryExports) {
|
|
523
|
+
return remoteEntryExports;
|
|
524
|
+
}
|
|
525
|
+
return loadScript(entry, {
|
|
526
|
+
attrs: {},
|
|
527
|
+
createScriptHook
|
|
528
|
+
}).then(()=>{
|
|
529
|
+
const { remoteEntryKey, entryExports } = getRemoteEntryExports(name, globalName);
|
|
530
|
+
assert(entryExports, `
|
|
531
|
+
Cannot use the ${name}'s '${entry}' URL with ${remoteEntryKey}'s globalName to get remoteEntry exports.
|
|
532
|
+
The following reasons may be causing the problem:\n
|
|
533
|
+
1. '${entry}' is not the correct URL, or the remoteEntry resource or name is incorrect.\n
|
|
534
|
+
2. Unable to use ${remoteEntryKey} to get remoteEntry exports in the window object.
|
|
535
|
+
`);
|
|
536
|
+
return entryExports;
|
|
537
|
+
});
|
|
538
|
+
}
|
|
539
|
+
async function getRemoteEntry({ remoteEntryExports, remoteInfo, createScriptHook }) {
|
|
540
|
+
const { entry, name, type, entryGlobalName } = remoteInfo;
|
|
541
|
+
const uniqueKey = composeKeyWithSeparator(name, entry);
|
|
542
|
+
if (remoteEntryExports) {
|
|
543
|
+
return remoteEntryExports;
|
|
544
|
+
}
|
|
545
|
+
if (!globalLoading[uniqueKey]) {
|
|
546
|
+
if (type === 'esm') {
|
|
547
|
+
globalLoading[uniqueKey] = loadEsmEntry({
|
|
548
|
+
entry,
|
|
549
|
+
remoteEntryExports
|
|
550
|
+
});
|
|
551
|
+
} else {
|
|
552
|
+
globalLoading[uniqueKey] = loadEntryScript({
|
|
553
|
+
name,
|
|
554
|
+
globalName: entryGlobalName,
|
|
555
|
+
entry,
|
|
556
|
+
createScriptHook
|
|
557
|
+
});
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
return globalLoading[uniqueKey];
|
|
561
|
+
}
|
|
562
|
+
function getRemoteInfo(remote) {
|
|
563
|
+
return _extends({}, remote, {
|
|
564
|
+
entry: 'entry' in remote ? remote.entry : '',
|
|
565
|
+
type: remote.type || DEFAULT_REMOTE_TYPE,
|
|
566
|
+
entryGlobalName: remote.entryGlobalName || remote.name,
|
|
567
|
+
shareScope: remote.shareScope || DEFAULT_SCOPE
|
|
568
|
+
});
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
let Module = class Module {
|
|
572
|
+
async getEntry() {
|
|
573
|
+
if (this.remoteEntryExports) {
|
|
574
|
+
return this.remoteEntryExports;
|
|
575
|
+
}
|
|
576
|
+
// Get remoteEntry.js
|
|
577
|
+
const remoteEntryExports = await getRemoteEntry({
|
|
578
|
+
remoteInfo: this.remoteInfo,
|
|
579
|
+
remoteEntryExports: this.remoteEntryExports,
|
|
580
|
+
createScriptHook: (url)=>{
|
|
581
|
+
const res = this.loaderHook.lifecycle.createScript.emit({
|
|
582
|
+
url
|
|
583
|
+
});
|
|
584
|
+
if (res instanceof HTMLScriptElement) {
|
|
585
|
+
return res;
|
|
586
|
+
}
|
|
587
|
+
return;
|
|
588
|
+
}
|
|
589
|
+
});
|
|
590
|
+
assert(remoteEntryExports, `remoteEntryExports is undefined \n ${safeToString$1(this.remoteInfo)}`);
|
|
591
|
+
this.remoteEntryExports = remoteEntryExports;
|
|
592
|
+
return this.remoteEntryExports;
|
|
593
|
+
}
|
|
594
|
+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
595
|
+
async get(expose, options) {
|
|
596
|
+
const { loadFactory = true } = options || {
|
|
597
|
+
loadFactory: true
|
|
598
|
+
};
|
|
599
|
+
// Get remoteEntry.js
|
|
600
|
+
const remoteEntryExports = await this.getEntry();
|
|
601
|
+
if (!this.inited) {
|
|
602
|
+
const globalShareScope = Global.__FEDERATION__.__SHARE__;
|
|
603
|
+
const remoteShareScope = this.remoteInfo.shareScope || 'default';
|
|
604
|
+
if (!globalShareScope[remoteShareScope]) {
|
|
605
|
+
globalShareScope[remoteShareScope] = {};
|
|
606
|
+
}
|
|
607
|
+
const shareScope = globalShareScope[remoteShareScope];
|
|
608
|
+
// TODO: compat logic , it could be moved after providing startup hooks
|
|
609
|
+
const remoteEntryInitOptions = {
|
|
610
|
+
version: this.remoteInfo.version || '',
|
|
611
|
+
// @ts-ignore it will be passed by startup hooks
|
|
612
|
+
region: this.hostInfo.region
|
|
613
|
+
};
|
|
614
|
+
remoteEntryExports.init(shareScope, [], remoteEntryInitOptions);
|
|
615
|
+
const federationInstance = Global.__FEDERATION__.__INSTANCES__.find((i)=>i.options.id === composeKeyWithSeparator(this.remoteInfo.name, this.remoteInfo.buildVersion));
|
|
616
|
+
if (federationInstance) {
|
|
617
|
+
federationInstance.initOptions(_extends({}, remoteEntryInitOptions, {
|
|
618
|
+
remotes: [],
|
|
619
|
+
name: this.remoteInfo.name
|
|
620
|
+
}));
|
|
621
|
+
}
|
|
622
|
+
}
|
|
623
|
+
this.lib = remoteEntryExports;
|
|
624
|
+
this.inited = true;
|
|
625
|
+
// get exposeGetter
|
|
626
|
+
const moduleFactory = await remoteEntryExports.get(expose);
|
|
627
|
+
assert(moduleFactory, `${getFMId(this.remoteInfo)} remote don't export ${expose}.`);
|
|
628
|
+
if (!loadFactory) {
|
|
629
|
+
return moduleFactory;
|
|
630
|
+
}
|
|
631
|
+
const exposeContent = await moduleFactory();
|
|
632
|
+
return exposeContent;
|
|
633
|
+
}
|
|
634
|
+
// loading: Record<string, undefined | Promise<RemoteEntryExports | void>> = {};
|
|
635
|
+
constructor({ hostInfo, remoteInfo, shared, loaderHook }){
|
|
636
|
+
this.inited = false;
|
|
637
|
+
this.shared = {};
|
|
638
|
+
this.lib = undefined;
|
|
639
|
+
this.hostInfo = hostInfo;
|
|
640
|
+
this.remoteInfo = remoteInfo;
|
|
641
|
+
this.shared = shared;
|
|
642
|
+
this.loaderHook = loaderHook;
|
|
643
|
+
}
|
|
644
|
+
};
|
|
645
|
+
|
|
646
|
+
class SyncHook {
|
|
647
|
+
on(fn) {
|
|
648
|
+
if (typeof fn === 'function') {
|
|
649
|
+
this.listeners.add(fn);
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
once(fn) {
|
|
653
|
+
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
654
|
+
const self = this;
|
|
655
|
+
this.on(function wrapper(...args) {
|
|
656
|
+
self.remove(wrapper);
|
|
657
|
+
// eslint-disable-next-line prefer-spread
|
|
658
|
+
return fn.apply(null, args);
|
|
659
|
+
});
|
|
660
|
+
}
|
|
661
|
+
emit(...data) {
|
|
662
|
+
let result;
|
|
663
|
+
if (this.listeners.size > 0) {
|
|
664
|
+
// eslint-disable-next-line prefer-spread
|
|
665
|
+
this.listeners.forEach((fn)=>{
|
|
666
|
+
result = fn(...data);
|
|
667
|
+
});
|
|
668
|
+
}
|
|
669
|
+
return result;
|
|
670
|
+
}
|
|
671
|
+
remove(fn) {
|
|
672
|
+
this.listeners.delete(fn);
|
|
673
|
+
}
|
|
674
|
+
removeAll() {
|
|
675
|
+
this.listeners.clear();
|
|
676
|
+
}
|
|
677
|
+
constructor(type){
|
|
678
|
+
this.type = '';
|
|
679
|
+
this.listeners = new Set();
|
|
680
|
+
if (type) {
|
|
681
|
+
this.type = type;
|
|
682
|
+
}
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
|
|
686
|
+
class AsyncHook extends SyncHook {
|
|
687
|
+
emit(...data) {
|
|
688
|
+
let result;
|
|
689
|
+
const ls = Array.from(this.listeners);
|
|
690
|
+
if (ls.length > 0) {
|
|
691
|
+
let i = 0;
|
|
692
|
+
const call = (prev)=>{
|
|
693
|
+
if (prev === false) {
|
|
694
|
+
return false; // Abort process
|
|
695
|
+
} else if (i < ls.length) {
|
|
696
|
+
return Promise.resolve(ls[i++].apply(null, data)).then(call);
|
|
697
|
+
} else {
|
|
698
|
+
return prev;
|
|
699
|
+
}
|
|
700
|
+
};
|
|
701
|
+
result = call();
|
|
702
|
+
}
|
|
703
|
+
return Promise.resolve(result);
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
|
|
707
|
+
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
708
|
+
function checkReturnData(originData, returnData) {
|
|
709
|
+
if (!isObject(returnData)) {
|
|
710
|
+
return false;
|
|
711
|
+
}
|
|
712
|
+
if (originData !== returnData) {
|
|
713
|
+
// eslint-disable-next-line no-restricted-syntax
|
|
714
|
+
for(const key in originData){
|
|
715
|
+
if (!(key in returnData)) {
|
|
716
|
+
return false;
|
|
717
|
+
}
|
|
718
|
+
}
|
|
719
|
+
}
|
|
720
|
+
return true;
|
|
721
|
+
}
|
|
722
|
+
class SyncWaterfallHook extends SyncHook {
|
|
723
|
+
emit(data) {
|
|
724
|
+
if (!isObject(data)) {
|
|
725
|
+
error(`"${this.type}" hook response data must be an object.`);
|
|
726
|
+
}
|
|
727
|
+
for (const fn of this.listeners){
|
|
728
|
+
try {
|
|
729
|
+
const tempData = fn(data);
|
|
730
|
+
if (checkReturnData(data, tempData)) {
|
|
731
|
+
data = tempData;
|
|
732
|
+
} else {
|
|
733
|
+
this.onerror(`The "${this.type}" type has a plugin return value error.`);
|
|
734
|
+
break;
|
|
735
|
+
}
|
|
736
|
+
} catch (e) {
|
|
737
|
+
warn(e);
|
|
738
|
+
this.onerror(e);
|
|
739
|
+
}
|
|
740
|
+
}
|
|
741
|
+
return data;
|
|
742
|
+
}
|
|
743
|
+
constructor(type){
|
|
744
|
+
super();
|
|
745
|
+
this.onerror = error;
|
|
746
|
+
this.type = type;
|
|
747
|
+
}
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
class AsyncWaterfallHook extends SyncHook {
|
|
751
|
+
emit(data) {
|
|
752
|
+
if (!isObject(data)) {
|
|
753
|
+
error(`"${this.type}" hook response data must be an object.`);
|
|
754
|
+
}
|
|
755
|
+
const ls = Array.from(this.listeners);
|
|
756
|
+
if (ls.length > 0) {
|
|
757
|
+
let i = 0;
|
|
758
|
+
const processError = (e)=>{
|
|
759
|
+
warn(e);
|
|
760
|
+
this.onerror(e);
|
|
761
|
+
return data;
|
|
762
|
+
};
|
|
763
|
+
const call = (prevData)=>{
|
|
764
|
+
if (checkReturnData(data, prevData)) {
|
|
765
|
+
data = prevData;
|
|
766
|
+
if (i < ls.length) {
|
|
767
|
+
try {
|
|
768
|
+
return Promise.resolve(ls[i++](data)).then(call, processError);
|
|
769
|
+
} catch (e) {
|
|
770
|
+
return processError(e);
|
|
771
|
+
}
|
|
772
|
+
}
|
|
773
|
+
} else {
|
|
774
|
+
this.onerror(`The "${this.type}" type has a plugin return value error.`);
|
|
775
|
+
}
|
|
776
|
+
return data;
|
|
777
|
+
};
|
|
778
|
+
return Promise.resolve(call(data));
|
|
779
|
+
}
|
|
780
|
+
return Promise.resolve(data);
|
|
781
|
+
}
|
|
782
|
+
constructor(type){
|
|
783
|
+
super();
|
|
784
|
+
this.onerror = error;
|
|
785
|
+
this.type = type;
|
|
786
|
+
}
|
|
787
|
+
}
|
|
788
|
+
|
|
789
|
+
class PluginSystem {
|
|
790
|
+
usePlugin(plugin) {
|
|
791
|
+
assert(isPlainObject(plugin), 'Invalid plugin configuration.');
|
|
792
|
+
// The plugin name is required and must be unique
|
|
793
|
+
const pluginName = plugin.name;
|
|
794
|
+
assert(pluginName, 'Plugin must provide a name.');
|
|
795
|
+
if (!this.registerPlugins[pluginName]) {
|
|
796
|
+
this.registerPlugins[pluginName] = plugin;
|
|
797
|
+
Object.keys(this.lifecycle).forEach((key)=>{
|
|
798
|
+
const pluginLife = plugin[key];
|
|
799
|
+
if (pluginLife) {
|
|
800
|
+
this.lifecycle[key].on(pluginLife);
|
|
801
|
+
}
|
|
802
|
+
});
|
|
803
|
+
}
|
|
804
|
+
}
|
|
805
|
+
removePlugin(pluginName) {
|
|
806
|
+
assert(pluginName, 'Must provide a name.');
|
|
807
|
+
const plugin = this.registerPlugins[pluginName];
|
|
808
|
+
assert(plugin, `plugin "${pluginName}" is not registered.`);
|
|
809
|
+
Object.keys(plugin).forEach((key)=>{
|
|
810
|
+
if (key !== 'name') {
|
|
811
|
+
this.lifecycle[key].remove(plugin[key]);
|
|
812
|
+
}
|
|
813
|
+
});
|
|
814
|
+
}
|
|
815
|
+
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
816
|
+
inherit({ lifecycle, registerPlugins }) {
|
|
817
|
+
Object.keys(lifecycle).forEach((hookName)=>{
|
|
818
|
+
assert(!this.lifecycle[hookName], `"${hookName}" hook has conflict and cannot be inherited.`);
|
|
819
|
+
this.lifecycle[hookName] = lifecycle[hookName];
|
|
820
|
+
});
|
|
821
|
+
Object.keys(registerPlugins).forEach((pluginName)=>{
|
|
822
|
+
assert(!this.registerPlugins[pluginName], `"${pluginName}" plugin has conflict and cannot be inherited.`);
|
|
823
|
+
this.usePlugin(registerPlugins[pluginName]);
|
|
824
|
+
});
|
|
825
|
+
}
|
|
826
|
+
constructor(lifecycle){
|
|
827
|
+
this.registerPlugins = {};
|
|
828
|
+
this.lifecycle = lifecycle;
|
|
829
|
+
this.lifecycleKeys = Object.keys(lifecycle);
|
|
830
|
+
}
|
|
831
|
+
}
|
|
832
|
+
|
|
833
|
+
function defaultPreloadArgs(preloadConfig) {
|
|
834
|
+
return _extends({
|
|
835
|
+
resourceCategory: 'sync',
|
|
836
|
+
share: true,
|
|
837
|
+
depsRemote: true
|
|
838
|
+
}, preloadConfig);
|
|
839
|
+
}
|
|
840
|
+
function formatPreloadArgs(remotes, preloadArgs) {
|
|
841
|
+
// let preloadOps: PreloadOptions;
|
|
842
|
+
return preloadArgs.map((args)=>{
|
|
843
|
+
const remoteInfo = matchRemote(remotes, args.nameOrAlias);
|
|
844
|
+
assert(remoteInfo, `can't preload ${args.nameOrAlias},it is no't include in ${!remoteInfo && safeToString$1({
|
|
845
|
+
remoteInfo,
|
|
846
|
+
remotes
|
|
847
|
+
})} `);
|
|
848
|
+
return {
|
|
849
|
+
remote: remoteInfo,
|
|
850
|
+
preloadConfig: defaultPreloadArgs(args)
|
|
851
|
+
};
|
|
852
|
+
});
|
|
853
|
+
}
|
|
854
|
+
function normalizePreloadExposes(exposes) {
|
|
855
|
+
if (!exposes) {
|
|
856
|
+
return [];
|
|
857
|
+
}
|
|
858
|
+
return exposes.map((expose)=>{
|
|
859
|
+
if (expose === '.') {
|
|
860
|
+
return expose;
|
|
861
|
+
}
|
|
862
|
+
if (expose.startsWith('./')) {
|
|
863
|
+
return expose.replace('./', '');
|
|
864
|
+
}
|
|
865
|
+
return expose;
|
|
866
|
+
});
|
|
867
|
+
}
|
|
868
|
+
function preloadAssets(remoteInfo, host, assets) {
|
|
869
|
+
const { cssAssets, jsAssetsWithoutEntry, entryAssets } = assets;
|
|
870
|
+
if (host.options.inBrowser) {
|
|
871
|
+
entryAssets.forEach((asset)=>{
|
|
872
|
+
const { moduleInfo } = asset;
|
|
873
|
+
const module = host.moduleCache.get(remoteInfo.name);
|
|
874
|
+
if (module) {
|
|
875
|
+
getRemoteEntry({
|
|
876
|
+
remoteInfo: moduleInfo,
|
|
877
|
+
remoteEntryExports: module.remoteEntryExports,
|
|
878
|
+
createScriptHook: (url)=>{
|
|
879
|
+
const res = host.loaderHook.lifecycle.createScript.emit({
|
|
880
|
+
url
|
|
881
|
+
});
|
|
882
|
+
if (res instanceof HTMLScriptElement) {
|
|
883
|
+
return res;
|
|
884
|
+
}
|
|
885
|
+
return;
|
|
886
|
+
}
|
|
887
|
+
});
|
|
888
|
+
} else {
|
|
889
|
+
getRemoteEntry({
|
|
890
|
+
remoteInfo: moduleInfo,
|
|
891
|
+
remoteEntryExports: undefined,
|
|
892
|
+
createScriptHook: (url)=>{
|
|
893
|
+
const res = host.loaderHook.lifecycle.createScript.emit({
|
|
894
|
+
url
|
|
895
|
+
});
|
|
896
|
+
if (res instanceof HTMLScriptElement) {
|
|
897
|
+
return res;
|
|
898
|
+
}
|
|
899
|
+
return;
|
|
900
|
+
}
|
|
901
|
+
});
|
|
902
|
+
}
|
|
903
|
+
});
|
|
904
|
+
const fragment = document.createDocumentFragment();
|
|
905
|
+
cssAssets.forEach((cssUrl)=>{
|
|
906
|
+
const cssEl = document.createElement('link');
|
|
907
|
+
cssEl.setAttribute('rel', 'preload');
|
|
908
|
+
cssEl.setAttribute('href', cssUrl);
|
|
909
|
+
cssEl.setAttribute('as', 'style');
|
|
910
|
+
cssEl.setAttribute('crossorigin', 'anonymous');
|
|
911
|
+
fragment.appendChild(cssEl);
|
|
912
|
+
});
|
|
913
|
+
document.head.appendChild(fragment);
|
|
914
|
+
jsAssetsWithoutEntry.forEach((jsUrl)=>{
|
|
915
|
+
const { script: scriptEl } = createScript(jsUrl, ()=>{
|
|
916
|
+
// noop
|
|
917
|
+
}, {}, (url)=>{
|
|
918
|
+
const res = host.loaderHook.lifecycle.createScript.emit({
|
|
919
|
+
url
|
|
920
|
+
});
|
|
921
|
+
if (res instanceof HTMLScriptElement) {
|
|
922
|
+
return res;
|
|
923
|
+
}
|
|
924
|
+
return;
|
|
925
|
+
});
|
|
926
|
+
document.head.appendChild(scriptEl);
|
|
927
|
+
});
|
|
928
|
+
}
|
|
929
|
+
}
|
|
930
|
+
|
|
931
|
+
function assignRemoteInfo(remoteInfo, remoteSnapshot) {
|
|
932
|
+
if (!('remoteEntry' in remoteSnapshot) || !remoteSnapshot.remoteEntry) {
|
|
933
|
+
error(`The remoteEntry attribute of ${name} cannot be undefined.`);
|
|
934
|
+
}
|
|
935
|
+
const { remoteEntry } = remoteSnapshot;
|
|
936
|
+
const entryUrl = getResourceUrl(remoteSnapshot, remoteEntry);
|
|
937
|
+
remoteInfo.type = remoteSnapshot.remoteEntryType;
|
|
938
|
+
remoteInfo.entryGlobalName = remoteSnapshot.globalName;
|
|
939
|
+
remoteInfo.entry = entryUrl;
|
|
940
|
+
remoteInfo.version = remoteSnapshot.version;
|
|
941
|
+
remoteInfo.buildVersion = remoteSnapshot.buildVersion;
|
|
942
|
+
}
|
|
943
|
+
function snapshotPlugin() {
|
|
944
|
+
return {
|
|
945
|
+
name: 'snapshot-plugin',
|
|
946
|
+
async loadRemoteMatch (args) {
|
|
947
|
+
const { remote, pkgNameOrAlias, expose, origin, remoteInfo } = args;
|
|
948
|
+
if (!isRemoteInfoWithEntry(remote) || !isPureRemoteEntry(remote)) {
|
|
949
|
+
const { remoteSnapshot, globalSnapshot } = await origin.snapshotHandler.loadRemoteSnapshotInfo(remote);
|
|
950
|
+
assignRemoteInfo(remoteInfo, remoteSnapshot);
|
|
951
|
+
// preload assets
|
|
952
|
+
const preloadOptions = {
|
|
953
|
+
remote,
|
|
954
|
+
preloadConfig: {
|
|
955
|
+
nameOrAlias: pkgNameOrAlias,
|
|
956
|
+
exposes: [
|
|
957
|
+
expose
|
|
958
|
+
],
|
|
959
|
+
resourceCategory: 'sync',
|
|
960
|
+
share: false,
|
|
961
|
+
depsRemote: false
|
|
962
|
+
}
|
|
963
|
+
};
|
|
964
|
+
const assets = await origin.hooks.lifecycle.generatePreloadAssets.emit({
|
|
965
|
+
origin,
|
|
966
|
+
preloadOptions,
|
|
967
|
+
remoteInfo,
|
|
968
|
+
remote,
|
|
969
|
+
remoteSnapshot,
|
|
970
|
+
globalSnapshot
|
|
971
|
+
});
|
|
972
|
+
if (assets) {
|
|
973
|
+
preloadAssets(remoteInfo, origin, assets);
|
|
974
|
+
}
|
|
975
|
+
}
|
|
976
|
+
return args;
|
|
977
|
+
}
|
|
978
|
+
};
|
|
979
|
+
}
|
|
980
|
+
|
|
981
|
+
// name
|
|
982
|
+
// name:version
|
|
983
|
+
function splitId(id) {
|
|
984
|
+
const splitInfo = id.split(':');
|
|
985
|
+
if (splitInfo.length === 1) {
|
|
986
|
+
return {
|
|
987
|
+
name: splitInfo[0],
|
|
988
|
+
version: undefined
|
|
989
|
+
};
|
|
990
|
+
} else if (splitInfo.length === 2) {
|
|
991
|
+
return {
|
|
992
|
+
name: splitInfo[0],
|
|
993
|
+
version: splitInfo[1]
|
|
994
|
+
};
|
|
995
|
+
} else {
|
|
996
|
+
return {
|
|
997
|
+
name: splitInfo[1],
|
|
998
|
+
version: splitInfo[2]
|
|
999
|
+
};
|
|
1000
|
+
}
|
|
1001
|
+
}
|
|
1002
|
+
// Traverse all nodes through moduleInfo and traverse the entire snapshot
|
|
1003
|
+
function traverseModuleInfo(globalSnapshot, remoteInfo, traverse, isRoot, memo = {}, remoteSnapshot, getModuleInfoHook) {
|
|
1004
|
+
const id = getFMId(remoteInfo);
|
|
1005
|
+
const { value: snapshotValue } = getInfoWithoutType(globalSnapshot, id, getModuleInfoHook);
|
|
1006
|
+
const effectRemoteSnapshot = remoteSnapshot || snapshotValue;
|
|
1007
|
+
if (effectRemoteSnapshot && !isManifestProvider(effectRemoteSnapshot)) {
|
|
1008
|
+
traverse(effectRemoteSnapshot, remoteInfo, isRoot);
|
|
1009
|
+
if (effectRemoteSnapshot.remotesInfo) {
|
|
1010
|
+
const remoteKeys = Object.keys(effectRemoteSnapshot.remotesInfo);
|
|
1011
|
+
for (const key of remoteKeys){
|
|
1012
|
+
if (memo[key]) {
|
|
1013
|
+
continue;
|
|
1014
|
+
}
|
|
1015
|
+
memo[key] = true;
|
|
1016
|
+
const subRemoteInfo = splitId(key);
|
|
1017
|
+
const remoteValue = effectRemoteSnapshot.remotesInfo[key];
|
|
1018
|
+
traverseModuleInfo(globalSnapshot, {
|
|
1019
|
+
name: subRemoteInfo.name,
|
|
1020
|
+
version: remoteValue.matchedVersion
|
|
1021
|
+
}, traverse, false, memo, undefined, getModuleInfoHook);
|
|
1022
|
+
}
|
|
1023
|
+
}
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
// eslint-disable-next-line max-lines-per-function
|
|
1027
|
+
function generatePreloadAssets(origin, preloadOptions, remote, globalSnapshot, remoteSnapshot) {
|
|
1028
|
+
const cssAssets = [];
|
|
1029
|
+
const jsAssets = [];
|
|
1030
|
+
const entryAssets = [];
|
|
1031
|
+
const loadedSharedJsAssets = new Set();
|
|
1032
|
+
const loadedSharedCssAssets = new Set();
|
|
1033
|
+
const { options } = origin;
|
|
1034
|
+
const { preloadConfig: rootPreloadConfig } = preloadOptions;
|
|
1035
|
+
const { depsRemote } = rootPreloadConfig;
|
|
1036
|
+
const memo = {};
|
|
1037
|
+
traverseModuleInfo(globalSnapshot, remote, (moduleInfoSnapshot, remoteInfo, isRoot)=>{
|
|
1038
|
+
let preloadConfig;
|
|
1039
|
+
if (isRoot) {
|
|
1040
|
+
preloadConfig = rootPreloadConfig;
|
|
1041
|
+
} else {
|
|
1042
|
+
if (Array.isArray(depsRemote)) {
|
|
1043
|
+
// eslint-disable-next-line array-callback-return
|
|
1044
|
+
const findPreloadConfig = depsRemote.find((remoteConfig)=>{
|
|
1045
|
+
if (remoteConfig.nameOrAlias === remoteInfo.name || remoteConfig.nameOrAlias === remoteInfo.alias) {
|
|
1046
|
+
return true;
|
|
1047
|
+
}
|
|
1048
|
+
return false;
|
|
1049
|
+
});
|
|
1050
|
+
if (!findPreloadConfig) {
|
|
1051
|
+
return;
|
|
1052
|
+
}
|
|
1053
|
+
preloadConfig = defaultPreloadArgs(findPreloadConfig);
|
|
1054
|
+
} else if (depsRemote === true) {
|
|
1055
|
+
preloadConfig = rootPreloadConfig;
|
|
1056
|
+
} else {
|
|
1057
|
+
return;
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
const remoteEntryUrl = getResourceUrl(moduleInfoSnapshot, 'remoteEntry' in moduleInfoSnapshot ? moduleInfoSnapshot.remoteEntry : '');
|
|
1061
|
+
if (remoteEntryUrl) {
|
|
1062
|
+
entryAssets.push({
|
|
1063
|
+
name: remoteInfo.name,
|
|
1064
|
+
moduleInfo: {
|
|
1065
|
+
name: remoteInfo.name,
|
|
1066
|
+
entry: remoteEntryUrl,
|
|
1067
|
+
type: 'remoteEntryType' in moduleInfoSnapshot ? moduleInfoSnapshot.remoteEntryType : 'global',
|
|
1068
|
+
entryGlobalName: 'globalName' in moduleInfoSnapshot ? moduleInfoSnapshot.globalName : remoteInfo.name,
|
|
1069
|
+
shareScope: '',
|
|
1070
|
+
version: 'version' in moduleInfoSnapshot ? moduleInfoSnapshot.version : undefined
|
|
1071
|
+
},
|
|
1072
|
+
url: remoteEntryUrl
|
|
1073
|
+
});
|
|
1074
|
+
}
|
|
1075
|
+
let moduleAssetsInfo = 'modules' in moduleInfoSnapshot ? moduleInfoSnapshot.modules : [];
|
|
1076
|
+
const normalizedPreloadExposes = normalizePreloadExposes(preloadConfig.exposes);
|
|
1077
|
+
if (normalizedPreloadExposes.length && 'modules' in moduleInfoSnapshot) {
|
|
1078
|
+
var _moduleInfoSnapshot_modules;
|
|
1079
|
+
moduleAssetsInfo = moduleInfoSnapshot == null ? void 0 : (_moduleInfoSnapshot_modules = moduleInfoSnapshot.modules) == null ? void 0 : _moduleInfoSnapshot_modules.reduce((assets, moduleAssetInfo)=>{
|
|
1080
|
+
if ((normalizedPreloadExposes == null ? void 0 : normalizedPreloadExposes.indexOf(moduleAssetInfo.moduleName)) !== -1) {
|
|
1081
|
+
assets.push(moduleAssetInfo);
|
|
1082
|
+
}
|
|
1083
|
+
return assets;
|
|
1084
|
+
}, []);
|
|
1085
|
+
}
|
|
1086
|
+
function handlerAssets(assets) {
|
|
1087
|
+
const assetsRes = assets.map((asset)=>getResourceUrl(moduleInfoSnapshot, asset));
|
|
1088
|
+
if (preloadConfig.filter) {
|
|
1089
|
+
return assetsRes.filter(preloadConfig.filter);
|
|
1090
|
+
}
|
|
1091
|
+
return assetsRes;
|
|
1092
|
+
}
|
|
1093
|
+
if (moduleAssetsInfo) {
|
|
1094
|
+
const assetsLength = moduleAssetsInfo.length;
|
|
1095
|
+
for(let index = 0; index < assetsLength; index++){
|
|
1096
|
+
const assetsInfo = moduleAssetsInfo[index];
|
|
1097
|
+
// for (const assetsInfo of moduleAssetsInfo) {
|
|
1098
|
+
const exposeFullPath = `${remoteInfo.name}/${assetsInfo.moduleName}`;
|
|
1099
|
+
const preloaded = getPreloaded(exposeFullPath);
|
|
1100
|
+
if (preloaded) {
|
|
1101
|
+
continue;
|
|
1102
|
+
}
|
|
1103
|
+
if (preloadConfig.resourceCategory === 'all') {
|
|
1104
|
+
cssAssets.push(...handlerAssets(assetsInfo.assets.css.async));
|
|
1105
|
+
cssAssets.push(...handlerAssets(assetsInfo.assets.css.sync));
|
|
1106
|
+
jsAssets.push(...handlerAssets(assetsInfo.assets.js.async));
|
|
1107
|
+
jsAssets.push(...handlerAssets(assetsInfo.assets.js.sync));
|
|
1108
|
+
// eslint-disable-next-line no-constant-condition
|
|
1109
|
+
} else if (preloadConfig.resourceCategory = 'sync') {
|
|
1110
|
+
cssAssets.push(...handlerAssets(assetsInfo.assets.css.sync));
|
|
1111
|
+
jsAssets.push(...handlerAssets(assetsInfo.assets.js.sync));
|
|
1112
|
+
}
|
|
1113
|
+
setPreloaded(exposeFullPath);
|
|
1114
|
+
}
|
|
1115
|
+
}
|
|
1116
|
+
}, true, memo, remoteSnapshot, (target, key)=>{
|
|
1117
|
+
const res = origin.loaderHook.lifecycle.getModuleInfo.emit({
|
|
1118
|
+
target,
|
|
1119
|
+
key
|
|
1120
|
+
});
|
|
1121
|
+
if (res && !(res instanceof Promise)) {
|
|
1122
|
+
return res;
|
|
1123
|
+
}
|
|
1124
|
+
return;
|
|
1125
|
+
});
|
|
1126
|
+
if (remoteSnapshot.shared) {
|
|
1127
|
+
remoteSnapshot.shared.forEach((shared)=>{
|
|
1128
|
+
var _options_shared;
|
|
1129
|
+
const shareInfo = (_options_shared = options.shared) == null ? void 0 : _options_shared[shared.sharedName];
|
|
1130
|
+
// When data is downgraded, the shared configuration may be different.
|
|
1131
|
+
if (!shareInfo) {
|
|
1132
|
+
return;
|
|
1133
|
+
}
|
|
1134
|
+
const globalShare = getGlobalShare(shared.sharedName, shareInfo);
|
|
1135
|
+
// If the global share does not exist, or the lib function does not exist, it means that the shared has not been loaded yet and can be preloaded.
|
|
1136
|
+
if (globalShare && typeof globalShare.lib === 'function') {
|
|
1137
|
+
shared.assets.js.sync.forEach((asset)=>{
|
|
1138
|
+
loadedSharedJsAssets.add(asset);
|
|
1139
|
+
});
|
|
1140
|
+
shared.assets.css.sync.forEach((asset)=>{
|
|
1141
|
+
loadedSharedCssAssets.add(asset);
|
|
1142
|
+
});
|
|
1143
|
+
}
|
|
1144
|
+
});
|
|
1145
|
+
}
|
|
1146
|
+
const needPreloadJsAssets = jsAssets.filter((asset)=>!loadedSharedJsAssets.has(asset));
|
|
1147
|
+
const needPreloadCssAssets = cssAssets.filter((asset)=>!loadedSharedCssAssets.has(asset));
|
|
1148
|
+
return {
|
|
1149
|
+
cssAssets: needPreloadCssAssets,
|
|
1150
|
+
jsAssetsWithoutEntry: needPreloadJsAssets,
|
|
1151
|
+
entryAssets
|
|
1152
|
+
};
|
|
1153
|
+
}
|
|
1154
|
+
const generatePreloadAssetsPlugin = function() {
|
|
1155
|
+
return {
|
|
1156
|
+
name: 'generate-preload-assets-plugin',
|
|
1157
|
+
async generatePreloadAssets (args) {
|
|
1158
|
+
const { origin, preloadOptions, remoteInfo, remote, globalSnapshot, remoteSnapshot } = args;
|
|
1159
|
+
if (isRemoteInfoWithEntry(remote) && isPureRemoteEntry(remote)) {
|
|
1160
|
+
return {
|
|
1161
|
+
cssAssets: [],
|
|
1162
|
+
jsAssetsWithoutEntry: [],
|
|
1163
|
+
entryAssets: [
|
|
1164
|
+
{
|
|
1165
|
+
name: remote.name,
|
|
1166
|
+
url: remote.entry,
|
|
1167
|
+
moduleInfo: {
|
|
1168
|
+
name: remoteInfo.name,
|
|
1169
|
+
entry: remote.entry,
|
|
1170
|
+
type: 'global',
|
|
1171
|
+
entryGlobalName: '',
|
|
1172
|
+
shareScope: ''
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
]
|
|
1176
|
+
};
|
|
1177
|
+
}
|
|
1178
|
+
assignRemoteInfo(remoteInfo, remoteSnapshot);
|
|
1179
|
+
const assets = generatePreloadAssets(origin, preloadOptions, remoteInfo, globalSnapshot, remoteSnapshot);
|
|
1180
|
+
return assets;
|
|
1181
|
+
}
|
|
1182
|
+
};
|
|
1183
|
+
};
|
|
1184
|
+
|
|
1185
|
+
class SnapshotHandler {
|
|
1186
|
+
async loadSnapshot(moduleInfo) {
|
|
1187
|
+
const { options } = this.HostInstance;
|
|
1188
|
+
const { hostGlobalSnapshot, remoteSnapshot, globalSnapshot } = this.getGlobalRemoteInfo(moduleInfo);
|
|
1189
|
+
const { remoteSnapshot: globalRemoteSnapshot, globalSnapshot: globalSnapshotRes } = await this.hooks.lifecycle.loadSnapshot.emit({
|
|
1190
|
+
options,
|
|
1191
|
+
moduleInfo,
|
|
1192
|
+
hostGlobalSnapshot,
|
|
1193
|
+
remoteSnapshot,
|
|
1194
|
+
globalSnapshot
|
|
1195
|
+
});
|
|
1196
|
+
return {
|
|
1197
|
+
remoteSnapshot: globalRemoteSnapshot,
|
|
1198
|
+
globalSnapshot: globalSnapshotRes
|
|
1199
|
+
};
|
|
1200
|
+
}
|
|
1201
|
+
// eslint-disable-next-line max-lines-per-function
|
|
1202
|
+
async loadRemoteSnapshotInfo(moduleInfo) {
|
|
1203
|
+
const { options } = this.HostInstance;
|
|
1204
|
+
const hostSnapshot = getGlobalSnapshotInfoByModuleInfo({
|
|
1205
|
+
name: this.HostInstance.options.name,
|
|
1206
|
+
version: this.HostInstance.options.version
|
|
1207
|
+
}, {
|
|
1208
|
+
getModuleInfoHook: (target, key)=>{
|
|
1209
|
+
const res = this.HostInstance.loaderHook.lifecycle.getModuleInfo.emit({
|
|
1210
|
+
target,
|
|
1211
|
+
key
|
|
1212
|
+
});
|
|
1213
|
+
if (res && !(res instanceof Promise)) {
|
|
1214
|
+
return res;
|
|
1215
|
+
}
|
|
1216
|
+
return;
|
|
1217
|
+
}
|
|
1218
|
+
});
|
|
1219
|
+
await this.hooks.lifecycle.beforeLoadRemoteSnapshot.emit({
|
|
1220
|
+
options,
|
|
1221
|
+
moduleInfo
|
|
1222
|
+
});
|
|
1223
|
+
// In the dynamic loadRemote scenario, incomplete remotesInfo delivery may occur. In this case, the remotesInfo in the host needs to be completed in the snapshot at runtime.
|
|
1224
|
+
// Ensure the integrity of the snapshot, and at the same time help the chrome plug-in correctly identify all producer modules, ensuring that proxyable producer modules will not be missing
|
|
1225
|
+
// In the dynamic loadRemote scenario, incomplete remotesInfo delivery may occur. In this case, the remotesInfo in the host needs to be completed in the snapshot at runtime.
|
|
1226
|
+
// Ensure the integrity of the snapshot, and at the same time help the chrome plug-in correctly identify all producer modules, ensuring that proxyable producer modules will not be missing
|
|
1227
|
+
if (hostSnapshot && 'remotesInfo' in hostSnapshot && !getInfoWithoutType(hostSnapshot.remotesInfo, moduleInfo.name, (target, key)=>{
|
|
1228
|
+
const res = this.HostInstance.loaderHook.lifecycle.getModuleInfo.emit({
|
|
1229
|
+
target,
|
|
1230
|
+
key
|
|
1231
|
+
});
|
|
1232
|
+
if (res && !(res instanceof Promise)) {
|
|
1233
|
+
return res;
|
|
1234
|
+
}
|
|
1235
|
+
return;
|
|
1236
|
+
}).value) {
|
|
1237
|
+
if ('version' in moduleInfo || 'entry' in moduleInfo) {
|
|
1238
|
+
hostSnapshot.remotesInfo = _extends({}, hostSnapshot == null ? void 0 : hostSnapshot.remotesInfo, {
|
|
1239
|
+
[moduleInfo.name]: {
|
|
1240
|
+
matchedVersion: 'version' in moduleInfo ? moduleInfo.version : moduleInfo.entry
|
|
1241
|
+
}
|
|
1242
|
+
});
|
|
1243
|
+
}
|
|
1244
|
+
}
|
|
1245
|
+
const { hostGlobalSnapshot, remoteSnapshot, globalSnapshot } = this.getGlobalRemoteInfo(moduleInfo);
|
|
1246
|
+
const { remoteSnapshot: globalRemoteSnapshot, globalSnapshot: globalSnapshotRes } = await this.hooks.lifecycle.loadSnapshot.emit({
|
|
1247
|
+
options,
|
|
1248
|
+
moduleInfo,
|
|
1249
|
+
hostGlobalSnapshot,
|
|
1250
|
+
remoteSnapshot,
|
|
1251
|
+
globalSnapshot
|
|
1252
|
+
});
|
|
1253
|
+
// global snapshot include manifest or module info include manifest
|
|
1254
|
+
if (globalRemoteSnapshot) {
|
|
1255
|
+
if (isManifestProvider(globalRemoteSnapshot)) {
|
|
1256
|
+
const moduleSnapshot = await this.getManifestJson(globalRemoteSnapshot.remoteEntry, moduleInfo, {});
|
|
1257
|
+
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
1258
|
+
const globalSnapshotRes = setGlobalSnapshotInfoByModuleInfo(_extends({}, moduleInfo), moduleSnapshot);
|
|
1259
|
+
return {
|
|
1260
|
+
remoteSnapshot: moduleSnapshot,
|
|
1261
|
+
globalSnapshot: globalSnapshotRes
|
|
1262
|
+
};
|
|
1263
|
+
} else {
|
|
1264
|
+
const { remoteSnapshot: remoteSnapshotRes } = await this.hooks.lifecycle.loadRemoteSnapshot.emit({
|
|
1265
|
+
options: this.HostInstance.options,
|
|
1266
|
+
moduleInfo,
|
|
1267
|
+
remoteSnapshot: globalRemoteSnapshot,
|
|
1268
|
+
from: 'global'
|
|
1269
|
+
});
|
|
1270
|
+
return {
|
|
1271
|
+
remoteSnapshot: remoteSnapshotRes,
|
|
1272
|
+
globalSnapshot: globalSnapshotRes
|
|
1273
|
+
};
|
|
1274
|
+
}
|
|
1275
|
+
} else {
|
|
1276
|
+
if (isRemoteInfoWithEntry(moduleInfo)) {
|
|
1277
|
+
// get from manifest.json and merge remote info from remote server
|
|
1278
|
+
const moduleSnapshot = await this.getManifestJson(moduleInfo.entry, moduleInfo, {});
|
|
1279
|
+
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
1280
|
+
const globalSnapshotRes = setGlobalSnapshotInfoByModuleInfo(moduleInfo, moduleSnapshot);
|
|
1281
|
+
const { remoteSnapshot: remoteSnapshotRes } = await this.hooks.lifecycle.loadRemoteSnapshot.emit({
|
|
1282
|
+
options: this.HostInstance.options,
|
|
1283
|
+
moduleInfo,
|
|
1284
|
+
remoteSnapshot: moduleSnapshot,
|
|
1285
|
+
from: 'global'
|
|
1286
|
+
});
|
|
1287
|
+
return {
|
|
1288
|
+
remoteSnapshot: remoteSnapshotRes,
|
|
1289
|
+
globalSnapshot: globalSnapshotRes
|
|
1290
|
+
};
|
|
1291
|
+
} else {
|
|
1292
|
+
error(`
|
|
1293
|
+
Cannot get remoteSnapshot with the name: '${moduleInfo.name}', version: '${moduleInfo.version}' from __FEDERATION__.moduleInfo. The following reasons may be causing the problem:\n
|
|
1294
|
+
1. The Deploy platform did not deliver the correct data. You can use __FEDERATION__.moduleInfo to check the remoteInfo.\n
|
|
1295
|
+
2. The remote '${moduleInfo.name}' version '${moduleInfo.version}' is not released.\n
|
|
1296
|
+
The transformed module info: ${JSON.stringify(globalSnapshotRes)}
|
|
1297
|
+
`);
|
|
1298
|
+
}
|
|
1299
|
+
}
|
|
1300
|
+
}
|
|
1301
|
+
getGlobalRemoteInfo(moduleInfo) {
|
|
1302
|
+
const hostGlobalSnapshot = getGlobalSnapshotInfoByModuleInfo({
|
|
1303
|
+
name: this.HostInstance.options.name,
|
|
1304
|
+
version: this.HostInstance.options.version
|
|
1305
|
+
}, {
|
|
1306
|
+
getModuleInfoHook: (target, key)=>{
|
|
1307
|
+
const res = this.HostInstance.loaderHook.lifecycle.getModuleInfo.emit({
|
|
1308
|
+
target,
|
|
1309
|
+
key
|
|
1310
|
+
});
|
|
1311
|
+
if (res && !(res instanceof Promise)) {
|
|
1312
|
+
return res;
|
|
1313
|
+
}
|
|
1314
|
+
return;
|
|
1315
|
+
}
|
|
1316
|
+
});
|
|
1317
|
+
// get remote detail info from global
|
|
1318
|
+
const globalRemoteInfo = hostGlobalSnapshot && 'remotesInfo' in hostGlobalSnapshot && hostGlobalSnapshot.remotesInfo && getInfoWithoutType(hostGlobalSnapshot.remotesInfo, moduleInfo.name, (target, key)=>{
|
|
1319
|
+
const res = this.HostInstance.loaderHook.lifecycle.getModuleInfo.emit({
|
|
1320
|
+
target,
|
|
1321
|
+
key
|
|
1322
|
+
});
|
|
1323
|
+
if (res && !(res instanceof Promise)) {
|
|
1324
|
+
return res;
|
|
1325
|
+
}
|
|
1326
|
+
return;
|
|
1327
|
+
}).value;
|
|
1328
|
+
if (globalRemoteInfo && globalRemoteInfo.matchedVersion) {
|
|
1329
|
+
return {
|
|
1330
|
+
hostGlobalSnapshot,
|
|
1331
|
+
globalSnapshot: getGlobalSnapshot(),
|
|
1332
|
+
remoteSnapshot: getGlobalSnapshotInfoByModuleInfo({
|
|
1333
|
+
name: moduleInfo.name,
|
|
1334
|
+
version: globalRemoteInfo.matchedVersion
|
|
1335
|
+
}, {
|
|
1336
|
+
getModuleInfoHook: (target, key)=>{
|
|
1337
|
+
const res = this.HostInstance.loaderHook.lifecycle.getModuleInfo.emit({
|
|
1338
|
+
target,
|
|
1339
|
+
key
|
|
1340
|
+
});
|
|
1341
|
+
if (res && !(res instanceof Promise)) {
|
|
1342
|
+
return res;
|
|
1343
|
+
}
|
|
1344
|
+
return;
|
|
1345
|
+
}
|
|
1346
|
+
})
|
|
1347
|
+
};
|
|
1348
|
+
}
|
|
1349
|
+
return {
|
|
1350
|
+
hostGlobalSnapshot: undefined,
|
|
1351
|
+
globalSnapshot: getGlobalSnapshot(),
|
|
1352
|
+
remoteSnapshot: getGlobalSnapshotInfoByModuleInfo({
|
|
1353
|
+
name: moduleInfo.name,
|
|
1354
|
+
version: 'version' in moduleInfo ? moduleInfo.version : undefined
|
|
1355
|
+
}, {
|
|
1356
|
+
getModuleInfoHook: (target, key)=>{
|
|
1357
|
+
const res = this.HostInstance.loaderHook.lifecycle.getModuleInfo.emit({
|
|
1358
|
+
target,
|
|
1359
|
+
key
|
|
1360
|
+
});
|
|
1361
|
+
if (res && !(res instanceof Promise)) {
|
|
1362
|
+
return res;
|
|
1363
|
+
}
|
|
1364
|
+
return;
|
|
1365
|
+
}
|
|
1366
|
+
})
|
|
1367
|
+
};
|
|
1368
|
+
}
|
|
1369
|
+
async getManifestJson(manifestUrl, moduleInfo, extraOptions) {
|
|
1370
|
+
const getManifest = async ()=>{
|
|
1371
|
+
let manifestJson = this.manifestCache.get(manifestUrl);
|
|
1372
|
+
if (manifestJson) {
|
|
1373
|
+
return manifestJson;
|
|
1374
|
+
}
|
|
1375
|
+
try {
|
|
1376
|
+
const res = await fetch(manifestUrl);
|
|
1377
|
+
manifestJson = await res.json();
|
|
1378
|
+
assert(manifestJson.metaData && manifestJson.exposes && manifestJson.shared, `${manifestUrl} is not federation manifest`);
|
|
1379
|
+
this.manifestCache.set(manifestUrl, manifestJson);
|
|
1380
|
+
return manifestJson;
|
|
1381
|
+
} catch (err) {
|
|
1382
|
+
error(`Failed to get manifestJson for ${moduleInfo.name}. The manifest URL is ${manifestUrl}. Please ensure that the manifestUrl is accessible.
|
|
1383
|
+
\n Error message:
|
|
1384
|
+
\n ${err}`);
|
|
1385
|
+
}
|
|
1386
|
+
};
|
|
1387
|
+
const asyncLoadProcess = async ()=>{
|
|
1388
|
+
const manifestJson = await getManifest();
|
|
1389
|
+
const remoteSnapshot = generateSnapshotFromManifest(manifestJson, {
|
|
1390
|
+
version: manifestUrl
|
|
1391
|
+
});
|
|
1392
|
+
const { remoteSnapshot: remoteSnapshotRes } = await this.hooks.lifecycle.loadRemoteSnapshot.emit({
|
|
1393
|
+
options: this.HostInstance.options,
|
|
1394
|
+
moduleInfo,
|
|
1395
|
+
manifestJson,
|
|
1396
|
+
remoteSnapshot,
|
|
1397
|
+
manifestUrl,
|
|
1398
|
+
from: 'manifest'
|
|
1399
|
+
});
|
|
1400
|
+
return remoteSnapshotRes;
|
|
1401
|
+
};
|
|
1402
|
+
if (!this.manifestLoading[manifestUrl]) {
|
|
1403
|
+
this.manifestLoading[manifestUrl] = asyncLoadProcess().then((res)=>res);
|
|
1404
|
+
}
|
|
1405
|
+
return this.manifestLoading[manifestUrl];
|
|
1406
|
+
}
|
|
1407
|
+
constructor(HostInstance){
|
|
1408
|
+
this.loadingHostSnapshot = null;
|
|
1409
|
+
this.manifestCache = new Map();
|
|
1410
|
+
this.hooks = new PluginSystem({
|
|
1411
|
+
beforeLoadRemoteSnapshot: new AsyncHook('beforeLoadRemoteSnapshot'),
|
|
1412
|
+
loadSnapshot: new AsyncWaterfallHook('loadGlobalSnapshot'),
|
|
1413
|
+
loadRemoteSnapshot: new AsyncWaterfallHook('loadRemoteSnapshot')
|
|
1414
|
+
});
|
|
1415
|
+
this.manifestLoading = Global.__FEDERATION__.__MANIFEST_LOADING__;
|
|
1416
|
+
this.HostInstance = HostInstance;
|
|
1417
|
+
}
|
|
1418
|
+
}
|
|
1419
|
+
|
|
1420
|
+
class FederationHost {
|
|
1421
|
+
initOptions(userOptions) {
|
|
1422
|
+
this.registerPlugins(userOptions.plugins);
|
|
1423
|
+
const options = this.formatOptions(this.options, userOptions);
|
|
1424
|
+
this.options = options;
|
|
1425
|
+
return options;
|
|
1426
|
+
}
|
|
1427
|
+
// overrideSharedOptions(shareScope: GlobalShareScope[string]): void {}
|
|
1428
|
+
async loadShare(pkgName, customShareInfo) {
|
|
1429
|
+
var _this_options_shared;
|
|
1430
|
+
// 1. Verify whether the currently loaded share already exists, and report an error if it does not exist
|
|
1431
|
+
// 2. Search globally to see if there is a matching share, and if so, use it directly
|
|
1432
|
+
// 3. If not, get it from the current share and store the obtained share globally.
|
|
1433
|
+
const shareInfo = Object.assign({}, (_this_options_shared = this.options.shared) == null ? void 0 : _this_options_shared[pkgName], customShareInfo);
|
|
1434
|
+
const loadShareRes = await this.hooks.lifecycle.beforeLoadShare.emit({
|
|
1435
|
+
pkgName,
|
|
1436
|
+
shareInfo,
|
|
1437
|
+
shared: this.options.shared,
|
|
1438
|
+
origin: this
|
|
1439
|
+
});
|
|
1440
|
+
const { shareInfo: shareInfoRes } = loadShareRes;
|
|
1441
|
+
assert(shareInfoRes, `cannot find ${pkgName} Share in the ${this.options.name}. Perhaps you have not injected the ${pkgName} Share parameters`);
|
|
1442
|
+
// get from cache
|
|
1443
|
+
const globalShare = getGlobalShare(pkgName, shareInfoRes);
|
|
1444
|
+
if (globalShare && globalShare.lib) {
|
|
1445
|
+
addUniqueItem(globalShare.useIn, this.options.name);
|
|
1446
|
+
return globalShare.lib;
|
|
1447
|
+
} else if (globalShare && globalShare.loading) {
|
|
1448
|
+
const factory = await globalShare.loading;
|
|
1449
|
+
addUniqueItem(globalShare.useIn, this.options.name);
|
|
1450
|
+
return factory;
|
|
1451
|
+
} else if (globalShare) {
|
|
1452
|
+
const asyncLoadProcess = async ()=>{
|
|
1453
|
+
const factory = await globalShare.get();
|
|
1454
|
+
shareInfoRes.lib = factory;
|
|
1455
|
+
addUniqueItem(shareInfoRes.useIn, this.options.name);
|
|
1456
|
+
const gShared = getGlobalShare(pkgName, shareInfoRes);
|
|
1457
|
+
if (gShared) {
|
|
1458
|
+
gShared.lib = factory;
|
|
1459
|
+
}
|
|
1460
|
+
return factory;
|
|
1461
|
+
};
|
|
1462
|
+
const loading = asyncLoadProcess();
|
|
1463
|
+
this.setShared({
|
|
1464
|
+
pkgName,
|
|
1465
|
+
loaded: true,
|
|
1466
|
+
shared: shareInfoRes,
|
|
1467
|
+
from: this.options.name,
|
|
1468
|
+
lib: null,
|
|
1469
|
+
loading
|
|
1470
|
+
});
|
|
1471
|
+
return loading;
|
|
1472
|
+
} else {
|
|
1473
|
+
if (customShareInfo) {
|
|
1474
|
+
return false;
|
|
1475
|
+
}
|
|
1476
|
+
const asyncLoadProcess = async ()=>{
|
|
1477
|
+
const factory = await shareInfoRes.get();
|
|
1478
|
+
shareInfoRes.lib = factory;
|
|
1479
|
+
addUniqueItem(shareInfoRes.useIn, this.options.name);
|
|
1480
|
+
const gShared = getGlobalShare(pkgName, shareInfoRes);
|
|
1481
|
+
if (gShared) {
|
|
1482
|
+
gShared.lib = factory;
|
|
1483
|
+
}
|
|
1484
|
+
return factory;
|
|
1485
|
+
};
|
|
1486
|
+
const loading = asyncLoadProcess();
|
|
1487
|
+
this.setShared({
|
|
1488
|
+
pkgName,
|
|
1489
|
+
loaded: true,
|
|
1490
|
+
shared: shareInfoRes,
|
|
1491
|
+
from: this.options.name,
|
|
1492
|
+
lib: null,
|
|
1493
|
+
loading
|
|
1494
|
+
});
|
|
1495
|
+
return loading;
|
|
1496
|
+
}
|
|
1497
|
+
}
|
|
1498
|
+
// There will be a lib function only if the shared set by eager or runtime init is set or the shared is successfully loaded.
|
|
1499
|
+
// 1. If the loaded shared already exists globally, then reuse
|
|
1500
|
+
// 2. If lib exists in local shared, use it directly
|
|
1501
|
+
// 3. If the local get returns something other than Promise, then use it directly
|
|
1502
|
+
loadShareSync(pkgName) {
|
|
1503
|
+
var _this_options_shared;
|
|
1504
|
+
const shareInfo = (_this_options_shared = this.options.shared) == null ? void 0 : _this_options_shared[pkgName];
|
|
1505
|
+
const globalShare = getGlobalShare(pkgName, shareInfo);
|
|
1506
|
+
if (globalShare && typeof globalShare.lib === 'function') {
|
|
1507
|
+
addUniqueItem(globalShare.useIn, this.options.name);
|
|
1508
|
+
if (!globalShare.loaded) {
|
|
1509
|
+
globalShare.loaded = true;
|
|
1510
|
+
if (globalShare.from === this.options.name) {
|
|
1511
|
+
shareInfo.loaded = true;
|
|
1512
|
+
}
|
|
1513
|
+
}
|
|
1514
|
+
return globalShare.lib;
|
|
1515
|
+
}
|
|
1516
|
+
if (shareInfo.lib) {
|
|
1517
|
+
if (!shareInfo.loaded) {
|
|
1518
|
+
shareInfo.loaded = true;
|
|
1519
|
+
}
|
|
1520
|
+
return shareInfo.lib;
|
|
1521
|
+
}
|
|
1522
|
+
if (shareInfo.get) {
|
|
1523
|
+
const module = shareInfo.get();
|
|
1524
|
+
if (module instanceof Promise) {
|
|
1525
|
+
throw new Error(`
|
|
1526
|
+
The loadShareSync function failed to load ${pkgName}. Cannot find ${pkgName} in ${this.options.name}.
|
|
1527
|
+
Failure reason: \n
|
|
1528
|
+
1. Registered ${pkgName} share with the 'get' attribute, but did not use loadShare before.\n
|
|
1529
|
+
2. Did not register ${pkgName} share with the 'lib' attribute.\n
|
|
1530
|
+
`);
|
|
1531
|
+
}
|
|
1532
|
+
shareInfo.lib = module;
|
|
1533
|
+
this.setShared({
|
|
1534
|
+
pkgName,
|
|
1535
|
+
loaded: true,
|
|
1536
|
+
from: this.options.name,
|
|
1537
|
+
lib: shareInfo.lib,
|
|
1538
|
+
shared: shareInfo
|
|
1539
|
+
});
|
|
1540
|
+
return shareInfo.lib;
|
|
1541
|
+
}
|
|
1542
|
+
throw new Error(`
|
|
1543
|
+
The loadShareSync function failed to load ${pkgName}. Cannot find ${pkgName} in ${this.options.name}.
|
|
1544
|
+
Failure reason: \n
|
|
1545
|
+
1. Registered ${pkgName} share with the 'get' attribute, but did not use loadShare before.\n
|
|
1546
|
+
2. Did not register ${pkgName} share with the 'lib' attribute.\n
|
|
1547
|
+
`);
|
|
1548
|
+
}
|
|
1549
|
+
async _getRemoteModuleAndOptions(id) {
|
|
1550
|
+
const loadRemoteArgs = await this.hooks.lifecycle.beforeLoadRemote.emit({
|
|
1551
|
+
id,
|
|
1552
|
+
options: this.options,
|
|
1553
|
+
origin: this
|
|
1554
|
+
});
|
|
1555
|
+
const { id: idRes } = loadRemoteArgs;
|
|
1556
|
+
const remoteSplitInfo = matchRemoteWithNameAndExpose(this.options.remotes, idRes);
|
|
1557
|
+
assert(remoteSplitInfo, `
|
|
1558
|
+
Cannot find ${idRes} in ${this.options.name}. Possible cause of failure:\n
|
|
1559
|
+
1. ${idRes} was not injected into ${this.options.name}'s 'remotes' parameter.\n
|
|
1560
|
+
2. Cannot find ${idRes} in ${this.options.name}'s 'remotes' with attribute 'name' or 'alias'.
|
|
1561
|
+
3. The 'beforeLoadRemote' hook was provided but did not return the correct 'remoteInfo' when loading ${idRes}.
|
|
1562
|
+
`);
|
|
1563
|
+
const { remote: rawRemote } = remoteSplitInfo;
|
|
1564
|
+
const remoteInfo = getRemoteInfo(rawRemote);
|
|
1565
|
+
const matchInfo = await this.hooks.lifecycle.loadRemoteMatch.emit(_extends({
|
|
1566
|
+
id: idRes
|
|
1567
|
+
}, remoteSplitInfo, {
|
|
1568
|
+
options: this.options,
|
|
1569
|
+
origin: this,
|
|
1570
|
+
remoteInfo
|
|
1571
|
+
}));
|
|
1572
|
+
const { remote, expose } = matchInfo;
|
|
1573
|
+
assert(remote && expose, `The 'beforeLoadRemote' hook was provided but did not return the correct 'remote' and 'expose' when loading ${idRes}.`);
|
|
1574
|
+
let module = this.moduleCache.get(remote.name);
|
|
1575
|
+
const moduleOptions = {
|
|
1576
|
+
hostInfo: {
|
|
1577
|
+
name: this.options.name,
|
|
1578
|
+
version: this.options.version || 'custom'
|
|
1579
|
+
},
|
|
1580
|
+
remoteInfo,
|
|
1581
|
+
shared: this.options.shared || {},
|
|
1582
|
+
plugins: this.options.plugins,
|
|
1583
|
+
loaderHook: this.loaderHook
|
|
1584
|
+
};
|
|
1585
|
+
if (!module) {
|
|
1586
|
+
module = new Module(moduleOptions);
|
|
1587
|
+
this.moduleCache.set(remote.name, module);
|
|
1588
|
+
}
|
|
1589
|
+
return {
|
|
1590
|
+
module,
|
|
1591
|
+
moduleOptions,
|
|
1592
|
+
remoteMatchInfo: matchInfo
|
|
1593
|
+
};
|
|
1594
|
+
}
|
|
1595
|
+
// eslint-disable-next-line max-lines-per-function
|
|
1596
|
+
// eslint-disable-next-line @typescript-eslint/member-ordering
|
|
1597
|
+
async loadRemote(id, options) {
|
|
1598
|
+
try {
|
|
1599
|
+
const { loadFactory = true } = options || {
|
|
1600
|
+
loadFactory: true
|
|
1601
|
+
};
|
|
1602
|
+
// 1. Verify whether the parameters of the obtained module are legal. There are two module request methods: pkgName + expose and alias + expose.
|
|
1603
|
+
// 2. Request the snapshot information of the current host and store the obtained snapshot information globally. The obtained module information is partly offline and partly online. The online module information will obtain the modules used online.
|
|
1604
|
+
// 3. Get the detailed information of the current module from global (remoteEntry address, expose resource address)
|
|
1605
|
+
// 4. After obtaining remoteEntry, call the init of the module, and then obtain the exported content of the module through get
|
|
1606
|
+
// id: pkgName(@federation/app1) + expose(button) = @federation/app1/button
|
|
1607
|
+
// id: alias(app1) + expose(button) = app1/button
|
|
1608
|
+
// id: alias(app1/utils) + expose(loadash/sort) = app1/utils/loadash/sort
|
|
1609
|
+
const { module, moduleOptions, remoteMatchInfo } = await this._getRemoteModuleAndOptions(id);
|
|
1610
|
+
const { pkgNameOrAlias, remote, expose, id: idRes } = remoteMatchInfo;
|
|
1611
|
+
const moduleOrFactory = await module.get(expose, options);
|
|
1612
|
+
await this.hooks.lifecycle.loadRemote.emit({
|
|
1613
|
+
id: idRes,
|
|
1614
|
+
pkgNameOrAlias,
|
|
1615
|
+
expose,
|
|
1616
|
+
exposeModule: loadFactory ? moduleOrFactory : undefined,
|
|
1617
|
+
exposeModuleFactory: loadFactory ? undefined : moduleOrFactory,
|
|
1618
|
+
remote,
|
|
1619
|
+
options: moduleOptions,
|
|
1620
|
+
moduleInstance: module,
|
|
1621
|
+
origin: this
|
|
1622
|
+
});
|
|
1623
|
+
return moduleOrFactory;
|
|
1624
|
+
} catch (error) {
|
|
1625
|
+
this.hooks.lifecycle.errorLoadRemote.emit({
|
|
1626
|
+
id,
|
|
1627
|
+
error
|
|
1628
|
+
});
|
|
1629
|
+
throw error;
|
|
1630
|
+
}
|
|
1631
|
+
}
|
|
1632
|
+
// eslint-disable-next-line @typescript-eslint/member-ordering
|
|
1633
|
+
async preloadRemote(preloadOptions) {
|
|
1634
|
+
await this.hooks.lifecycle.beforePreloadRemote.emit({
|
|
1635
|
+
preloadOptions,
|
|
1636
|
+
options: this.options,
|
|
1637
|
+
origin: this
|
|
1638
|
+
});
|
|
1639
|
+
const preloadOps = formatPreloadArgs(this.options.remotes, preloadOptions);
|
|
1640
|
+
await Promise.all(preloadOps.map(async (ops)=>{
|
|
1641
|
+
const { remote } = ops;
|
|
1642
|
+
const remoteInfo = getRemoteInfo(remote);
|
|
1643
|
+
const { globalSnapshot, remoteSnapshot } = await this.snapshotHandler.loadRemoteSnapshotInfo(remote);
|
|
1644
|
+
const assets = await this.hooks.lifecycle.generatePreloadAssets.emit({
|
|
1645
|
+
origin: this,
|
|
1646
|
+
preloadOptions: ops,
|
|
1647
|
+
remote,
|
|
1648
|
+
remoteInfo,
|
|
1649
|
+
globalSnapshot,
|
|
1650
|
+
remoteSnapshot
|
|
1651
|
+
});
|
|
1652
|
+
if (!assets) {
|
|
1653
|
+
return;
|
|
1654
|
+
}
|
|
1655
|
+
preloadAssets(remoteInfo, this, assets);
|
|
1656
|
+
}));
|
|
1657
|
+
}
|
|
1658
|
+
/**
|
|
1659
|
+
* The sharing init sequence function (only runs once per share scope).
|
|
1660
|
+
* Has one argument, the name of the share scope.
|
|
1661
|
+
* Creates a share scope if not existing
|
|
1662
|
+
*/ // eslint-disable-next-line @typescript-eslint/member-ordering
|
|
1663
|
+
initializeSharing(shareScopeName = DEFAULT_SCOPE) {
|
|
1664
|
+
const shareScopeLoading = Global.__FEDERATION__.__SHARE_SCOPE_LOADING__;
|
|
1665
|
+
const shareScope = Global.__FEDERATION__.__SHARE__;
|
|
1666
|
+
const hostName = this.options.name;
|
|
1667
|
+
// only runs once
|
|
1668
|
+
if (shareScopeLoading[shareScopeName]) {
|
|
1669
|
+
return shareScopeLoading[shareScopeName];
|
|
1670
|
+
}
|
|
1671
|
+
// creates a new share scope if needed
|
|
1672
|
+
if (!shareScope[shareScopeName]) {
|
|
1673
|
+
shareScope[shareScopeName] = {};
|
|
1674
|
+
}
|
|
1675
|
+
// runs all init snippets from all modules reachable
|
|
1676
|
+
const scope = shareScope[shareScopeName];
|
|
1677
|
+
const register = (name, shared)=>{
|
|
1678
|
+
const { version, eager } = shared;
|
|
1679
|
+
scope[name] = scope[name] || {};
|
|
1680
|
+
const versions = scope[name];
|
|
1681
|
+
const activeVersion = versions[version];
|
|
1682
|
+
const activeVersionEager = Boolean(activeVersion && (activeVersion.eager || activeVersion.shareConfig.eager));
|
|
1683
|
+
if (!activeVersion || !activeVersion.loaded && (Boolean(!eager) !== !activeVersionEager ? eager : hostName > activeVersion.from)) {
|
|
1684
|
+
versions[version] = shared;
|
|
1685
|
+
}
|
|
1686
|
+
};
|
|
1687
|
+
const promises = [];
|
|
1688
|
+
const initRemoteModule = async (key)=>{
|
|
1689
|
+
const { module } = await this._getRemoteModuleAndOptions(key);
|
|
1690
|
+
const initFn = (mod)=>mod && mod.init && mod.init(shareScope[shareScopeName]);
|
|
1691
|
+
const entry = await module.getEntry();
|
|
1692
|
+
initFn(entry);
|
|
1693
|
+
};
|
|
1694
|
+
Object.keys(this.options.shared).forEach((shareName)=>{
|
|
1695
|
+
const shared = this.options.shared[shareName];
|
|
1696
|
+
if (shared.scope.includes(shareScopeName)) {
|
|
1697
|
+
register(shareName, shared);
|
|
1698
|
+
}
|
|
1699
|
+
});
|
|
1700
|
+
this.options.remotes.forEach((remote)=>{
|
|
1701
|
+
if (remote.shareScope === shareScopeName) {
|
|
1702
|
+
promises.push(initRemoteModule(remote.name));
|
|
1703
|
+
}
|
|
1704
|
+
});
|
|
1705
|
+
if (!promises.length) {
|
|
1706
|
+
return shareScopeLoading[shareScopeName] = true;
|
|
1707
|
+
}
|
|
1708
|
+
return shareScopeLoading[shareScopeName] = Promise.all(promises).then(()=>shareScopeLoading[shareScopeName] = true);
|
|
1709
|
+
}
|
|
1710
|
+
formatOptions(globalOptions, userOptions) {
|
|
1711
|
+
const formatShareOptions = formatShareConfigs(userOptions.shared || {}, userOptions.name);
|
|
1712
|
+
const shared = _extends({}, globalOptions.shared, formatShareOptions);
|
|
1713
|
+
const { userOptions: userOptionsRes, options: globalOptionsRes } = this.hooks.lifecycle.beforeInit.emit({
|
|
1714
|
+
origin: this,
|
|
1715
|
+
userOptions,
|
|
1716
|
+
options: globalOptions,
|
|
1717
|
+
shareInfo: shared
|
|
1718
|
+
});
|
|
1719
|
+
const userRemotes = userOptionsRes.remotes || [];
|
|
1720
|
+
const remotes = userRemotes.reduce((res, remote)=>{
|
|
1721
|
+
if (!res.find((item)=>item.name === remote.name)) {
|
|
1722
|
+
if (remote.alias) {
|
|
1723
|
+
// 校验 alias 是否等于 remote.name 和 remote.alias 的前缀,如果是则报错
|
|
1724
|
+
// 因为引用支持多级路径的引用时无法保证名称是否唯一,所以不支持 alias 为 remote.name 的前缀
|
|
1725
|
+
const findEqual = res.find((item)=>{
|
|
1726
|
+
var _item_alias;
|
|
1727
|
+
return remote.alias && (item.name.startsWith(remote.alias) || ((_item_alias = item.alias) == null ? void 0 : _item_alias.startsWith(remote.alias)));
|
|
1728
|
+
});
|
|
1729
|
+
assert(!findEqual, `The alias ${remote.alias} of remote ${remote.name} is not allowed to be the prefix of ${findEqual && findEqual.name} name or alias`);
|
|
1730
|
+
}
|
|
1731
|
+
// Set the remote entry to a complete path
|
|
1732
|
+
if ('entry' in remote) {
|
|
1733
|
+
if (isBrowserEnv$1()) {
|
|
1734
|
+
remote.entry = new URL(remote.entry, window.location.origin).href;
|
|
1735
|
+
}
|
|
1736
|
+
}
|
|
1737
|
+
if (!remote.shareScope) {
|
|
1738
|
+
remote.shareScope = DEFAULT_SCOPE;
|
|
1739
|
+
}
|
|
1740
|
+
if (!remote.type) {
|
|
1741
|
+
// FIXME: The build plugin need to support this field
|
|
1742
|
+
remote.type = DEFAULT_REMOTE_TYPE;
|
|
1743
|
+
}
|
|
1744
|
+
res.push(remote);
|
|
1745
|
+
}
|
|
1746
|
+
return res;
|
|
1747
|
+
}, globalOptionsRes.remotes);
|
|
1748
|
+
// register shared include lib
|
|
1749
|
+
const sharedKeys = Object.keys(formatShareOptions);
|
|
1750
|
+
sharedKeys.forEach((sharedKey)=>{
|
|
1751
|
+
const sharedVal = formatShareOptions[sharedKey];
|
|
1752
|
+
const globalShare = getGlobalShare(sharedKey, sharedVal);
|
|
1753
|
+
if (!globalShare && sharedVal && sharedVal.lib) {
|
|
1754
|
+
this.setShared({
|
|
1755
|
+
pkgName: sharedKey,
|
|
1756
|
+
lib: sharedVal.lib,
|
|
1757
|
+
get: sharedVal.get,
|
|
1758
|
+
shared: sharedVal,
|
|
1759
|
+
from: userOptions.name
|
|
1760
|
+
});
|
|
1761
|
+
}
|
|
1762
|
+
});
|
|
1763
|
+
const plugins = [
|
|
1764
|
+
...globalOptionsRes.plugins
|
|
1765
|
+
];
|
|
1766
|
+
if (userOptionsRes.plugins) {
|
|
1767
|
+
userOptionsRes.plugins.forEach((plugin)=>{
|
|
1768
|
+
if (!plugins.includes(plugin)) {
|
|
1769
|
+
plugins.push(plugin);
|
|
1770
|
+
}
|
|
1771
|
+
});
|
|
1772
|
+
}
|
|
1773
|
+
const optionsRes = _extends({}, globalOptions, userOptions, {
|
|
1774
|
+
plugins,
|
|
1775
|
+
remotes,
|
|
1776
|
+
shared
|
|
1777
|
+
});
|
|
1778
|
+
this.hooks.lifecycle.init.emit({
|
|
1779
|
+
origin: this,
|
|
1780
|
+
options: optionsRes
|
|
1781
|
+
});
|
|
1782
|
+
return optionsRes;
|
|
1783
|
+
}
|
|
1784
|
+
registerPlugins(plugins) {
|
|
1785
|
+
registerPlugins(plugins, [
|
|
1786
|
+
this.hooks,
|
|
1787
|
+
this.snapshotHandler.hooks,
|
|
1788
|
+
this.loaderHook
|
|
1789
|
+
]);
|
|
1790
|
+
}
|
|
1791
|
+
setShared({ pkgName, shared, from, lib, loading, loaded, get }) {
|
|
1792
|
+
const target = getGlobalShareScope();
|
|
1793
|
+
const { version, scope = 'default' } = shared, shareInfo = _object_without_properties_loose(shared, [
|
|
1794
|
+
"version",
|
|
1795
|
+
"scope"
|
|
1796
|
+
]);
|
|
1797
|
+
const scopes = Array.isArray(scope) ? scope : [
|
|
1798
|
+
scope
|
|
1799
|
+
];
|
|
1800
|
+
scopes.forEach((sc)=>{
|
|
1801
|
+
if (!target[sc]) {
|
|
1802
|
+
target[sc] = {};
|
|
1803
|
+
}
|
|
1804
|
+
if (!target[sc][pkgName]) {
|
|
1805
|
+
target[sc][pkgName] = {};
|
|
1806
|
+
}
|
|
1807
|
+
if (target[sc][pkgName][version]) {
|
|
1808
|
+
warn(// eslint-disable-next-line max-len
|
|
1809
|
+
`The share \n ${safeToString$1({
|
|
1810
|
+
scope: sc,
|
|
1811
|
+
pkgName,
|
|
1812
|
+
version,
|
|
1813
|
+
from: target[sc][pkgName][version].from
|
|
1814
|
+
})} has been registered`);
|
|
1815
|
+
return;
|
|
1816
|
+
}
|
|
1817
|
+
target[sc][pkgName][version] = _extends({
|
|
1818
|
+
version,
|
|
1819
|
+
scope: [
|
|
1820
|
+
'default'
|
|
1821
|
+
]
|
|
1822
|
+
}, shareInfo, {
|
|
1823
|
+
lib,
|
|
1824
|
+
loaded,
|
|
1825
|
+
loading
|
|
1826
|
+
});
|
|
1827
|
+
if (get) {
|
|
1828
|
+
target[sc][pkgName][version].get = get;
|
|
1829
|
+
}
|
|
1830
|
+
});
|
|
1831
|
+
}
|
|
1832
|
+
constructor(userOptions){
|
|
1833
|
+
this.hooks = new PluginSystem({
|
|
1834
|
+
beforeInit: new SyncWaterfallHook('beforeInit'),
|
|
1835
|
+
init: new SyncHook(),
|
|
1836
|
+
beforeLoadRemote: new AsyncWaterfallHook('beforeLoadRemote'),
|
|
1837
|
+
loadRemoteMatch: new AsyncWaterfallHook('loadRemoteMatch'),
|
|
1838
|
+
loadRemote: new AsyncHook('loadRemote'),
|
|
1839
|
+
errorLoadRemote: new AsyncHook('errorLoadRemote'),
|
|
1840
|
+
beforeLoadShare: new AsyncWaterfallHook('beforeLoadShare'),
|
|
1841
|
+
loadShare: new AsyncHook(),
|
|
1842
|
+
beforePreloadRemote: new AsyncHook(),
|
|
1843
|
+
generatePreloadAssets: new AsyncHook('generatePreloadAssets'),
|
|
1844
|
+
afterPreloadRemote: new AsyncHook()
|
|
1845
|
+
});
|
|
1846
|
+
this.version = '0.0.1';
|
|
1847
|
+
this.moduleCache = new Map();
|
|
1848
|
+
this.loaderHook = new PluginSystem({
|
|
1849
|
+
// FIXME: may not be suitable
|
|
1850
|
+
getModuleInfo: new SyncHook(),
|
|
1851
|
+
createScript: new SyncHook()
|
|
1852
|
+
});
|
|
1853
|
+
this.loadingShare = {};
|
|
1854
|
+
// TODO: check options detail type
|
|
1855
|
+
// set options default value
|
|
1856
|
+
const defaultOptions = {
|
|
1857
|
+
id: getBuilderId(),
|
|
1858
|
+
name: userOptions.name,
|
|
1859
|
+
plugins: [
|
|
1860
|
+
snapshotPlugin(),
|
|
1861
|
+
generatePreloadAssetsPlugin()
|
|
1862
|
+
],
|
|
1863
|
+
remotes: [],
|
|
1864
|
+
shared: {},
|
|
1865
|
+
inBrowser: isBrowserEnv$1()
|
|
1866
|
+
};
|
|
1867
|
+
this.name = userOptions.name;
|
|
1868
|
+
this.options = defaultOptions;
|
|
1869
|
+
this.snapshotHandler = new SnapshotHandler(this);
|
|
1870
|
+
this.registerPlugins([
|
|
1871
|
+
...defaultOptions.plugins,
|
|
1872
|
+
...userOptions.plugins || []
|
|
1873
|
+
]);
|
|
1874
|
+
this.options = this.formatOptions(defaultOptions, userOptions);
|
|
1875
|
+
}
|
|
1876
|
+
}
|
|
1877
|
+
|
|
1878
|
+
let FederationInstance = null;
|
|
1879
|
+
function init(options) {
|
|
1880
|
+
// Retrieve the same instance with the same name
|
|
1881
|
+
const instance = getGlobalFederationInstance(options.name, options.version);
|
|
1882
|
+
if (!instance) {
|
|
1883
|
+
// Retrieve debug constructor
|
|
1884
|
+
const FederationConstructor = getGlobalFederationConstructor() || FederationHost;
|
|
1885
|
+
FederationInstance = new FederationConstructor(options);
|
|
1886
|
+
setGlobalFederationInstance(FederationInstance);
|
|
1887
|
+
return FederationInstance;
|
|
1888
|
+
} else {
|
|
1889
|
+
// Merge options
|
|
1890
|
+
instance.initOptions(options);
|
|
1891
|
+
return instance;
|
|
1892
|
+
}
|
|
1893
|
+
}
|
|
1894
|
+
function loadRemote(...args) {
|
|
1895
|
+
assert(FederationInstance, 'Please call init first');
|
|
1896
|
+
// eslint-disable-next-line prefer-spread
|
|
1897
|
+
return FederationInstance.loadRemote.apply(FederationInstance, args);
|
|
1898
|
+
}
|
|
1899
|
+
function loadShare(...args) {
|
|
1900
|
+
assert(FederationInstance, 'Please call init first');
|
|
1901
|
+
// eslint-disable-next-line prefer-spread
|
|
1902
|
+
return FederationInstance.loadShare.apply(FederationInstance, args);
|
|
1903
|
+
}
|
|
1904
|
+
function loadShareSync(...args) {
|
|
1905
|
+
assert(FederationInstance, 'Please call init first');
|
|
1906
|
+
// eslint-disable-next-line prefer-spread
|
|
1907
|
+
return FederationInstance.loadShareSync.apply(FederationInstance, args);
|
|
1908
|
+
}
|
|
1909
|
+
function preloadRemote(...args) {
|
|
1910
|
+
assert(FederationInstance, 'Please call init first');
|
|
1911
|
+
// eslint-disable-next-line prefer-spread
|
|
1912
|
+
return FederationInstance.preloadRemote.apply(FederationInstance, args);
|
|
1913
|
+
}
|
|
1914
|
+
// Inject for debug
|
|
1915
|
+
setGlobalFederationConstructor(FederationHost);
|
|
1916
|
+
|
|
1917
|
+
export { FederationHost, init, loadRemote, loadScript, loadShare, loadShareSync, preloadRemote };
|