@module-federation/runtime 1.0.1-canary.1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -0
- package/dist/LICENSE +21 -0
- package/dist/core.cjs.cjs +33 -0
- package/dist/core.cjs.cjs.map +1 -0
- package/dist/core.cjs.d.ts +2 -0
- package/dist/core.d.ts +2 -0
- package/dist/core.esm.js +4 -0
- package/dist/core.esm.js.map +1 -0
- package/dist/helpers.cjs.cjs +15 -0
- package/dist/helpers.cjs.cjs.map +1 -0
- package/dist/helpers.d.ts +2 -0
- package/dist/helpers.esm.js +13 -0
- package/dist/helpers.esm.js.map +1 -0
- package/dist/index.cjs.cjs +95 -0
- package/dist/index.cjs.cjs.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.esm.js +78 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/src/core.d.ts +3 -0
- package/dist/src/helpers.d.ts +11 -0
- package/dist/src/index.d.ts +16 -0
- package/dist/src/types.d.ts +1 -0
- package/dist/src/utils.d.ts +3 -0
- package/dist/types.cjs.cjs +17 -0
- package/dist/types.cjs.cjs.map +1 -0
- package/dist/types.cjs.d.ts +1 -0
- package/dist/types.d.ts +1 -0
- package/dist/types.esm.js +2 -0
- package/dist/types.esm.js.map +1 -0
- package/dist/utils.cjs.cjs +34 -0
- package/dist/utils.cjs.cjs.map +1 -0
- package/dist/utils.esm.js +32 -0
- package/dist/utils.esm.js.map +1 -0
- package/package.json +62 -16
- package/helpers.cjs.js +0 -33
- package/helpers.esm.js +0 -31
- package/index.cjs.js +0 -1614
- package/index.esm.js +0 -1605
- package/share.cjs.js +0 -771
- package/share.esm.js +0 -734
- package/src/constant.d.ts +0 -2
- package/src/core.d.ts +0 -120
- package/src/global.d.ts +0 -57
- package/src/helpers.d.ts +0 -32
- package/src/index.d.ts +0 -10
- package/src/module/index.d.ts +0 -25
- package/src/plugins/generate-preload-assets.d.ts +0 -8
- package/src/plugins/snapshot/SnapshotHandler.d.ts +0 -43
- package/src/plugins/snapshot/index.d.ts +0 -5
- package/src/type/config.d.ts +0 -94
- package/src/type/index.d.ts +0 -3
- package/src/type/plugin.d.ts +0 -20
- package/src/type/preload.d.ts +0 -26
- package/src/types.d.ts +0 -1
- package/src/utils/env.d.ts +0 -4
- package/src/utils/hooks/asyncHook.d.ts +0 -6
- package/src/utils/hooks/asyncWaterfallHooks.d.ts +0 -10
- package/src/utils/hooks/index.d.ts +0 -6
- package/src/utils/hooks/pluginSystem.d.ts +0 -15
- package/src/utils/hooks/syncHook.d.ts +0 -12
- package/src/utils/hooks/syncWaterfallHook.d.ts +0 -9
- package/src/utils/index.d.ts +0 -5
- package/src/utils/load.d.ts +0 -17
- package/src/utils/logger.d.ts +0 -3
- package/src/utils/manifest.d.ts +0 -7
- package/src/utils/plugin.d.ts +0 -4
- package/src/utils/preload.d.ts +0 -6
- package/src/utils/semver/compare.d.ts +0 -9
- package/src/utils/semver/constants.d.ts +0 -10
- package/src/utils/semver/index.d.ts +0 -2
- package/src/utils/semver/parser.d.ts +0 -9
- package/src/utils/semver/utils.d.ts +0 -11
- package/src/utils/share.d.ts +0 -7
- package/src/utils/tool.d.ts +0 -12
- package/type.cjs.d.ts +0 -1
- package/type.cjs.js +0 -2
- package/type.esm.js +0 -1
- /package/{helpers.cjs.d.ts → dist/helpers.cjs.d.ts} +0 -0
- /package/{index.cjs.d.ts → dist/index.cjs.d.ts} +0 -0
package/index.cjs.js
DELETED
|
@@ -1,1614 +0,0 @@
|
|
|
1
|
-
'use strict';
|
|
2
|
-
|
|
3
|
-
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
-
|
|
5
|
-
var share = require('./share.cjs.js');
|
|
6
|
-
var sdk = require('@module-federation/sdk');
|
|
7
|
-
|
|
8
|
-
// Function to match a remote with its name and expose
|
|
9
|
-
// id: pkgName(@federation/app1) + expose(button) = @federation/app1/button
|
|
10
|
-
// id: alias(app1) + expose(button) = app1/button
|
|
11
|
-
// id: alias(app1/utils) + expose(loadash/sort) = app1/utils/loadash/sort
|
|
12
|
-
function matchRemoteWithNameAndExpose(remotes, id) {
|
|
13
|
-
for (const remote of remotes){
|
|
14
|
-
// match pkgName
|
|
15
|
-
const isNameMatched = id.startsWith(remote.name);
|
|
16
|
-
let expose = id.replace(remote.name, '');
|
|
17
|
-
if (isNameMatched) {
|
|
18
|
-
if (expose.startsWith('/')) {
|
|
19
|
-
const pkgNameOrAlias = remote.name;
|
|
20
|
-
expose = `.${expose}`;
|
|
21
|
-
return {
|
|
22
|
-
pkgNameOrAlias,
|
|
23
|
-
expose,
|
|
24
|
-
remote
|
|
25
|
-
};
|
|
26
|
-
} else if (expose === '') {
|
|
27
|
-
return {
|
|
28
|
-
pkgNameOrAlias: remote.name,
|
|
29
|
-
expose: '.',
|
|
30
|
-
remote
|
|
31
|
-
};
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
// match alias
|
|
35
|
-
const isAliasMatched = remote.alias && id.startsWith(remote.alias);
|
|
36
|
-
let exposeWithAlias = remote.alias && id.replace(remote.alias, '');
|
|
37
|
-
if (remote.alias && isAliasMatched) {
|
|
38
|
-
if (exposeWithAlias && exposeWithAlias.startsWith('/')) {
|
|
39
|
-
const pkgNameOrAlias = remote.alias;
|
|
40
|
-
exposeWithAlias = `.${exposeWithAlias}`;
|
|
41
|
-
return {
|
|
42
|
-
pkgNameOrAlias,
|
|
43
|
-
expose: exposeWithAlias,
|
|
44
|
-
remote
|
|
45
|
-
};
|
|
46
|
-
} else if (exposeWithAlias === '') {
|
|
47
|
-
return {
|
|
48
|
-
pkgNameOrAlias: remote.alias,
|
|
49
|
-
expose: '.',
|
|
50
|
-
remote
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
}
|
|
55
|
-
return;
|
|
56
|
-
}
|
|
57
|
-
// Function to match a remote with its name or alias
|
|
58
|
-
function matchRemote(remotes, nameOrAlias) {
|
|
59
|
-
for (const remote of remotes){
|
|
60
|
-
const isNameMatched = nameOrAlias === remote.name;
|
|
61
|
-
if (isNameMatched) {
|
|
62
|
-
return remote;
|
|
63
|
-
}
|
|
64
|
-
const isAliasMatched = remote.alias && nameOrAlias === remote.alias;
|
|
65
|
-
if (isAliasMatched) {
|
|
66
|
-
return remote;
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
function registerPlugins(plugins, hookInstances) {
|
|
73
|
-
const globalPlugins = share.getGlobalHostPlugins();
|
|
74
|
-
// Incorporate global plugins
|
|
75
|
-
if (globalPlugins.length > 0) {
|
|
76
|
-
globalPlugins.forEach((plugin)=>{
|
|
77
|
-
if (plugins == null ? void 0 : plugins.find((item)=>item.name !== plugin.name)) {
|
|
78
|
-
plugins.push(plugin);
|
|
79
|
-
}
|
|
80
|
-
});
|
|
81
|
-
}
|
|
82
|
-
if (plugins && plugins.length > 0) {
|
|
83
|
-
plugins.forEach((plugin)=>{
|
|
84
|
-
hookInstances.forEach((hookInstance)=>{
|
|
85
|
-
hookInstance.usePlugin(plugin);
|
|
86
|
-
});
|
|
87
|
-
});
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
function _extends$5() {
|
|
92
|
-
_extends$5 = Object.assign || function(target) {
|
|
93
|
-
for(var i = 1; i < arguments.length; i++){
|
|
94
|
-
var source = arguments[i];
|
|
95
|
-
for(var key in source){
|
|
96
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
97
|
-
target[key] = source[key];
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
return target;
|
|
102
|
-
};
|
|
103
|
-
return _extends$5.apply(this, arguments);
|
|
104
|
-
}
|
|
105
|
-
async function loadEsmEntry({ entry, remoteEntryExports }) {
|
|
106
|
-
return new Promise((resolve, reject)=>{
|
|
107
|
-
try {
|
|
108
|
-
if (!remoteEntryExports) {
|
|
109
|
-
// eslint-disable-next-line no-eval
|
|
110
|
-
new Function('resolve', `import("${entry}").then((res)=>{resolve(res);}, (error)=> reject(error))`)(resolve);
|
|
111
|
-
} else {
|
|
112
|
-
resolve(remoteEntryExports);
|
|
113
|
-
}
|
|
114
|
-
} catch (e) {
|
|
115
|
-
reject(e);
|
|
116
|
-
}
|
|
117
|
-
});
|
|
118
|
-
}
|
|
119
|
-
async function loadEntryScript({ name, globalName, entry, createScriptHook }) {
|
|
120
|
-
const { entryExports: remoteEntryExports } = share.getRemoteEntryExports(name, globalName);
|
|
121
|
-
if (remoteEntryExports) {
|
|
122
|
-
return remoteEntryExports;
|
|
123
|
-
}
|
|
124
|
-
return sdk.loadScript(entry, {
|
|
125
|
-
attrs: {},
|
|
126
|
-
createScriptHook
|
|
127
|
-
}).then(()=>{
|
|
128
|
-
const { remoteEntryKey, entryExports } = share.getRemoteEntryExports(name, globalName);
|
|
129
|
-
share.assert(entryExports, `
|
|
130
|
-
Unable to use the ${name}'s '${entry}' URL with ${remoteEntryKey}'s globalName to get remoteEntry exports.
|
|
131
|
-
Possible reasons could be:\n
|
|
132
|
-
1. '${entry}' is not the correct URL, or the remoteEntry resource or name is incorrect.\n
|
|
133
|
-
2. ${remoteEntryKey} cannot be used to get remoteEntry exports in the window object.
|
|
134
|
-
`);
|
|
135
|
-
return entryExports;
|
|
136
|
-
});
|
|
137
|
-
}
|
|
138
|
-
async function getRemoteEntry({ remoteEntryExports, remoteInfo, createScriptHook }) {
|
|
139
|
-
const { entry, name, type, entryGlobalName } = remoteInfo;
|
|
140
|
-
const uniqueKey = sdk.composeKeyWithSeparator(name, entry);
|
|
141
|
-
if (remoteEntryExports) {
|
|
142
|
-
return remoteEntryExports;
|
|
143
|
-
}
|
|
144
|
-
if (!share.globalLoading[uniqueKey]) {
|
|
145
|
-
if (type === 'esm') {
|
|
146
|
-
share.globalLoading[uniqueKey] = loadEsmEntry({
|
|
147
|
-
entry,
|
|
148
|
-
remoteEntryExports
|
|
149
|
-
});
|
|
150
|
-
} else {
|
|
151
|
-
share.globalLoading[uniqueKey] = loadEntryScript({
|
|
152
|
-
name,
|
|
153
|
-
globalName: entryGlobalName,
|
|
154
|
-
entry,
|
|
155
|
-
createScriptHook
|
|
156
|
-
});
|
|
157
|
-
}
|
|
158
|
-
}
|
|
159
|
-
return share.globalLoading[uniqueKey];
|
|
160
|
-
}
|
|
161
|
-
function getRemoteInfo(remote) {
|
|
162
|
-
return _extends$5({}, remote, {
|
|
163
|
-
entry: 'entry' in remote ? remote.entry : '',
|
|
164
|
-
type: remote.type || share.DEFAULT_REMOTE_TYPE,
|
|
165
|
-
entryGlobalName: remote.entryGlobalName || remote.name,
|
|
166
|
-
shareScope: remote.shareScope || share.DEFAULT_SCOPE
|
|
167
|
-
});
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
function _extends$4() {
|
|
171
|
-
_extends$4 = Object.assign || function(target) {
|
|
172
|
-
for(var i = 1; i < arguments.length; i++){
|
|
173
|
-
var source = arguments[i];
|
|
174
|
-
for(var key in source){
|
|
175
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
176
|
-
target[key] = source[key];
|
|
177
|
-
}
|
|
178
|
-
}
|
|
179
|
-
}
|
|
180
|
-
return target;
|
|
181
|
-
};
|
|
182
|
-
return _extends$4.apply(this, arguments);
|
|
183
|
-
}
|
|
184
|
-
let Module = class Module {
|
|
185
|
-
async getEntry() {
|
|
186
|
-
if (this.remoteEntryExports) {
|
|
187
|
-
return this.remoteEntryExports;
|
|
188
|
-
}
|
|
189
|
-
// Get remoteEntry.js
|
|
190
|
-
const remoteEntryExports = await getRemoteEntry({
|
|
191
|
-
remoteInfo: this.remoteInfo,
|
|
192
|
-
remoteEntryExports: this.remoteEntryExports,
|
|
193
|
-
createScriptHook: (url)=>{
|
|
194
|
-
const res = this.loaderHook.lifecycle.createScript.emit({
|
|
195
|
-
url
|
|
196
|
-
});
|
|
197
|
-
if (res instanceof HTMLScriptElement) {
|
|
198
|
-
return res;
|
|
199
|
-
}
|
|
200
|
-
return;
|
|
201
|
-
}
|
|
202
|
-
});
|
|
203
|
-
share.assert(remoteEntryExports, `remoteEntryExports is undefined \n ${share.safeToString(this.remoteInfo)}`);
|
|
204
|
-
this.remoteEntryExports = remoteEntryExports;
|
|
205
|
-
return this.remoteEntryExports;
|
|
206
|
-
}
|
|
207
|
-
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
208
|
-
async get(expose, options) {
|
|
209
|
-
const { loadFactory = true } = options || {
|
|
210
|
-
loadFactory: true
|
|
211
|
-
};
|
|
212
|
-
// Get remoteEntry.js
|
|
213
|
-
const remoteEntryExports = await this.getEntry();
|
|
214
|
-
if (!this.inited) {
|
|
215
|
-
const globalShareScope = share.Global.__FEDERATION__.__SHARE__;
|
|
216
|
-
const remoteShareScope = this.remoteInfo.shareScope || 'default';
|
|
217
|
-
if (!globalShareScope[remoteShareScope]) {
|
|
218
|
-
globalShareScope[remoteShareScope] = {};
|
|
219
|
-
}
|
|
220
|
-
const shareScope = globalShareScope[remoteShareScope];
|
|
221
|
-
// TODO: compat logic , it could be moved after providing startup hooks
|
|
222
|
-
const remoteEntryInitOptions = {
|
|
223
|
-
version: this.remoteInfo.version || '',
|
|
224
|
-
// @ts-ignore it will be passed by startup hooks
|
|
225
|
-
region: this.hostInfo.region
|
|
226
|
-
};
|
|
227
|
-
remoteEntryExports.init(shareScope, [], remoteEntryInitOptions);
|
|
228
|
-
const federationInstance = share.Global.__FEDERATION__.__INSTANCES__.find((i)=>i.options.id === sdk.composeKeyWithSeparator(this.remoteInfo.name, this.remoteInfo.buildVersion));
|
|
229
|
-
if (federationInstance) {
|
|
230
|
-
federationInstance.initOptions(_extends$4({}, remoteEntryInitOptions, {
|
|
231
|
-
remotes: [],
|
|
232
|
-
name: this.remoteInfo.name
|
|
233
|
-
}));
|
|
234
|
-
}
|
|
235
|
-
}
|
|
236
|
-
this.lib = remoteEntryExports;
|
|
237
|
-
this.inited = true;
|
|
238
|
-
// get exposeGetter
|
|
239
|
-
const moduleFactory = await remoteEntryExports.get(expose);
|
|
240
|
-
share.assert(moduleFactory, `${share.getFMId(this.remoteInfo)} remote don't export ${expose}.`);
|
|
241
|
-
if (!loadFactory) {
|
|
242
|
-
return moduleFactory;
|
|
243
|
-
}
|
|
244
|
-
const exposeContent = await moduleFactory();
|
|
245
|
-
return exposeContent;
|
|
246
|
-
}
|
|
247
|
-
// loading: Record<string, undefined | Promise<RemoteEntryExports | void>> = {};
|
|
248
|
-
constructor({ hostInfo, remoteInfo, shared, loaderHook }){
|
|
249
|
-
this.inited = false;
|
|
250
|
-
this.shared = {};
|
|
251
|
-
this.lib = undefined;
|
|
252
|
-
this.hostInfo = hostInfo;
|
|
253
|
-
this.remoteInfo = remoteInfo;
|
|
254
|
-
this.shared = shared;
|
|
255
|
-
this.loaderHook = loaderHook;
|
|
256
|
-
}
|
|
257
|
-
};
|
|
258
|
-
|
|
259
|
-
class SyncHook {
|
|
260
|
-
on(fn) {
|
|
261
|
-
if (typeof fn === 'function') {
|
|
262
|
-
this.listeners.add(fn);
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
once(fn) {
|
|
266
|
-
// eslint-disable-next-line @typescript-eslint/no-this-alias
|
|
267
|
-
const self = this;
|
|
268
|
-
this.on(function wrapper(...args) {
|
|
269
|
-
self.remove(wrapper);
|
|
270
|
-
// eslint-disable-next-line prefer-spread
|
|
271
|
-
return fn.apply(null, args);
|
|
272
|
-
});
|
|
273
|
-
}
|
|
274
|
-
emit(...data) {
|
|
275
|
-
let result;
|
|
276
|
-
if (this.listeners.size > 0) {
|
|
277
|
-
// eslint-disable-next-line prefer-spread
|
|
278
|
-
this.listeners.forEach((fn)=>{
|
|
279
|
-
result = fn(...data);
|
|
280
|
-
});
|
|
281
|
-
}
|
|
282
|
-
return result;
|
|
283
|
-
}
|
|
284
|
-
remove(fn) {
|
|
285
|
-
this.listeners.delete(fn);
|
|
286
|
-
}
|
|
287
|
-
removeAll() {
|
|
288
|
-
this.listeners.clear();
|
|
289
|
-
}
|
|
290
|
-
constructor(type){
|
|
291
|
-
this.type = '';
|
|
292
|
-
this.listeners = new Set();
|
|
293
|
-
if (type) {
|
|
294
|
-
this.type = type;
|
|
295
|
-
}
|
|
296
|
-
}
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
class AsyncHook extends SyncHook {
|
|
300
|
-
emit(...data) {
|
|
301
|
-
let result;
|
|
302
|
-
const ls = Array.from(this.listeners);
|
|
303
|
-
if (ls.length > 0) {
|
|
304
|
-
let i = 0;
|
|
305
|
-
const call = (prev)=>{
|
|
306
|
-
if (prev === false) {
|
|
307
|
-
return false; // Abort process
|
|
308
|
-
} else if (i < ls.length) {
|
|
309
|
-
return Promise.resolve(ls[i++].apply(null, data)).then(call);
|
|
310
|
-
} else {
|
|
311
|
-
return prev;
|
|
312
|
-
}
|
|
313
|
-
};
|
|
314
|
-
result = call();
|
|
315
|
-
}
|
|
316
|
-
return Promise.resolve(result);
|
|
317
|
-
}
|
|
318
|
-
}
|
|
319
|
-
|
|
320
|
-
// eslint-disable-next-line @typescript-eslint/explicit-module-boundary-types
|
|
321
|
-
function checkReturnData(originalData, returnedData) {
|
|
322
|
-
if (!share.isObject(returnedData)) {
|
|
323
|
-
return false;
|
|
324
|
-
}
|
|
325
|
-
if (originalData !== returnedData) {
|
|
326
|
-
// eslint-disable-next-line no-restricted-syntax
|
|
327
|
-
for(const key in originalData){
|
|
328
|
-
if (!(key in returnedData)) {
|
|
329
|
-
return false;
|
|
330
|
-
}
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
return true;
|
|
334
|
-
}
|
|
335
|
-
class SyncWaterfallHook extends SyncHook {
|
|
336
|
-
emit(data) {
|
|
337
|
-
if (!share.isObject(data)) {
|
|
338
|
-
share.error(`The data for the "${this.type}" hook should be an object.`);
|
|
339
|
-
}
|
|
340
|
-
for (const fn of this.listeners){
|
|
341
|
-
try {
|
|
342
|
-
const tempData = fn(data);
|
|
343
|
-
if (checkReturnData(data, tempData)) {
|
|
344
|
-
data = tempData;
|
|
345
|
-
} else {
|
|
346
|
-
this.onerror(`A plugin returned an unacceptable value for the "${this.type}" type.`);
|
|
347
|
-
break;
|
|
348
|
-
}
|
|
349
|
-
} catch (e) {
|
|
350
|
-
share.warn(e);
|
|
351
|
-
this.onerror(e);
|
|
352
|
-
}
|
|
353
|
-
}
|
|
354
|
-
return data;
|
|
355
|
-
}
|
|
356
|
-
constructor(type){
|
|
357
|
-
super();
|
|
358
|
-
this.onerror = share.error;
|
|
359
|
-
this.type = type;
|
|
360
|
-
}
|
|
361
|
-
}
|
|
362
|
-
|
|
363
|
-
class AsyncWaterfallHook extends SyncHook {
|
|
364
|
-
emit(data) {
|
|
365
|
-
if (!share.isObject(data)) {
|
|
366
|
-
share.error(`The response data for the "${this.type}" hook must be an object.`);
|
|
367
|
-
}
|
|
368
|
-
const ls = Array.from(this.listeners);
|
|
369
|
-
if (ls.length > 0) {
|
|
370
|
-
let i = 0;
|
|
371
|
-
const processError = (e)=>{
|
|
372
|
-
share.warn(e);
|
|
373
|
-
this.onerror(e);
|
|
374
|
-
return data;
|
|
375
|
-
};
|
|
376
|
-
const call = (prevData)=>{
|
|
377
|
-
if (checkReturnData(data, prevData)) {
|
|
378
|
-
data = prevData;
|
|
379
|
-
if (i < ls.length) {
|
|
380
|
-
try {
|
|
381
|
-
return Promise.resolve(ls[i++](data)).then(call, processError);
|
|
382
|
-
} catch (e) {
|
|
383
|
-
return processError(e);
|
|
384
|
-
}
|
|
385
|
-
}
|
|
386
|
-
} else {
|
|
387
|
-
this.onerror(`A plugin returned an incorrect value for the "${this.type}" type.`);
|
|
388
|
-
}
|
|
389
|
-
return data;
|
|
390
|
-
};
|
|
391
|
-
return Promise.resolve(call(data));
|
|
392
|
-
}
|
|
393
|
-
return Promise.resolve(data);
|
|
394
|
-
}
|
|
395
|
-
constructor(type){
|
|
396
|
-
super();
|
|
397
|
-
this.onerror = share.error;
|
|
398
|
-
this.type = type;
|
|
399
|
-
}
|
|
400
|
-
}
|
|
401
|
-
|
|
402
|
-
class PluginSystem {
|
|
403
|
-
usePlugin(plugin) {
|
|
404
|
-
share.assert(share.isPlainObject(plugin), 'Plugin configuration is invalid.');
|
|
405
|
-
// The plugin's name is mandatory and must be unique
|
|
406
|
-
const pluginName = plugin.name;
|
|
407
|
-
share.assert(pluginName, 'A name must be provided by the plugin.');
|
|
408
|
-
if (!this.registerPlugins[pluginName]) {
|
|
409
|
-
this.registerPlugins[pluginName] = plugin;
|
|
410
|
-
Object.keys(this.lifecycle).forEach((key)=>{
|
|
411
|
-
const pluginLife = plugin[key];
|
|
412
|
-
if (pluginLife) {
|
|
413
|
-
this.lifecycle[key].on(pluginLife);
|
|
414
|
-
}
|
|
415
|
-
});
|
|
416
|
-
}
|
|
417
|
-
}
|
|
418
|
-
removePlugin(pluginName) {
|
|
419
|
-
share.assert(pluginName, 'A name is required.');
|
|
420
|
-
const plugin = this.registerPlugins[pluginName];
|
|
421
|
-
share.assert(plugin, `The plugin "${pluginName}" is not registered.`);
|
|
422
|
-
Object.keys(plugin).forEach((key)=>{
|
|
423
|
-
if (key !== 'name') {
|
|
424
|
-
this.lifecycle[key].remove(plugin[key]);
|
|
425
|
-
}
|
|
426
|
-
});
|
|
427
|
-
}
|
|
428
|
-
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
429
|
-
inherit({ lifecycle, registerPlugins }) {
|
|
430
|
-
Object.keys(lifecycle).forEach((hookName)=>{
|
|
431
|
-
share.assert(!this.lifecycle[hookName], `The hook "${hookName}" has a conflict and cannot be inherited.`);
|
|
432
|
-
this.lifecycle[hookName] = lifecycle[hookName];
|
|
433
|
-
});
|
|
434
|
-
Object.keys(registerPlugins).forEach((pluginName)=>{
|
|
435
|
-
share.assert(!this.registerPlugins[pluginName], `The plugin "${pluginName}" has a conflict and cannot be inherited.`);
|
|
436
|
-
this.usePlugin(registerPlugins[pluginName]);
|
|
437
|
-
});
|
|
438
|
-
}
|
|
439
|
-
constructor(lifecycle){
|
|
440
|
-
this.registerPlugins = {};
|
|
441
|
-
this.lifecycle = lifecycle;
|
|
442
|
-
this.lifecycleKeys = Object.keys(lifecycle);
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
|
|
446
|
-
function _extends$3() {
|
|
447
|
-
_extends$3 = Object.assign || function(target) {
|
|
448
|
-
for(var i = 1; i < arguments.length; i++){
|
|
449
|
-
var source = arguments[i];
|
|
450
|
-
for(var key in source){
|
|
451
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
452
|
-
target[key] = source[key];
|
|
453
|
-
}
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
return target;
|
|
457
|
-
};
|
|
458
|
-
return _extends$3.apply(this, arguments);
|
|
459
|
-
}
|
|
460
|
-
function defaultPreloadArgs(preloadConfig) {
|
|
461
|
-
return _extends$3({
|
|
462
|
-
resourceCategory: 'sync',
|
|
463
|
-
share: true,
|
|
464
|
-
depsRemote: true,
|
|
465
|
-
prefetchInterface: false
|
|
466
|
-
}, preloadConfig);
|
|
467
|
-
}
|
|
468
|
-
function formatPreloadArgs(remotes, preloadArgs) {
|
|
469
|
-
return preloadArgs.map((args)=>{
|
|
470
|
-
const remoteInfo = matchRemote(remotes, args.nameOrAlias);
|
|
471
|
-
share.assert(remoteInfo, `Unable to preload ${args.nameOrAlias} as it is not included in ${!remoteInfo && share.safeToString({
|
|
472
|
-
remoteInfo,
|
|
473
|
-
remotes
|
|
474
|
-
})}`);
|
|
475
|
-
return {
|
|
476
|
-
remote: remoteInfo,
|
|
477
|
-
preloadConfig: defaultPreloadArgs(args)
|
|
478
|
-
};
|
|
479
|
-
});
|
|
480
|
-
}
|
|
481
|
-
function normalizePreloadExposes(exposes) {
|
|
482
|
-
if (!exposes) {
|
|
483
|
-
return [];
|
|
484
|
-
}
|
|
485
|
-
return exposes.map((expose)=>{
|
|
486
|
-
if (expose === '.') {
|
|
487
|
-
return expose;
|
|
488
|
-
}
|
|
489
|
-
if (expose.startsWith('./')) {
|
|
490
|
-
return expose.replace('./', '');
|
|
491
|
-
}
|
|
492
|
-
return expose;
|
|
493
|
-
});
|
|
494
|
-
}
|
|
495
|
-
function preloadAssets(remoteInfo, host, assets) {
|
|
496
|
-
const { cssAssets, jsAssetsWithoutEntry, entryAssets } = assets;
|
|
497
|
-
if (host.options.inBrowser) {
|
|
498
|
-
entryAssets.forEach((asset)=>{
|
|
499
|
-
const { moduleInfo } = asset;
|
|
500
|
-
const module = host.moduleCache.get(remoteInfo.name);
|
|
501
|
-
if (module) {
|
|
502
|
-
getRemoteEntry({
|
|
503
|
-
remoteInfo: moduleInfo,
|
|
504
|
-
remoteEntryExports: module.remoteEntryExports,
|
|
505
|
-
createScriptHook: (url)=>{
|
|
506
|
-
const res = host.loaderHook.lifecycle.createScript.emit({
|
|
507
|
-
url
|
|
508
|
-
});
|
|
509
|
-
if (res instanceof HTMLScriptElement) {
|
|
510
|
-
return res;
|
|
511
|
-
}
|
|
512
|
-
return;
|
|
513
|
-
}
|
|
514
|
-
});
|
|
515
|
-
} else {
|
|
516
|
-
getRemoteEntry({
|
|
517
|
-
remoteInfo: moduleInfo,
|
|
518
|
-
remoteEntryExports: undefined,
|
|
519
|
-
createScriptHook: (url)=>{
|
|
520
|
-
const res = host.loaderHook.lifecycle.createScript.emit({
|
|
521
|
-
url
|
|
522
|
-
});
|
|
523
|
-
if (res instanceof HTMLScriptElement) {
|
|
524
|
-
return res;
|
|
525
|
-
}
|
|
526
|
-
return;
|
|
527
|
-
}
|
|
528
|
-
});
|
|
529
|
-
}
|
|
530
|
-
});
|
|
531
|
-
const fragment = document.createDocumentFragment();
|
|
532
|
-
cssAssets.forEach((cssUrl)=>{
|
|
533
|
-
const cssEl = document.createElement('link');
|
|
534
|
-
cssEl.setAttribute('rel', 'preload');
|
|
535
|
-
cssEl.setAttribute('href', cssUrl);
|
|
536
|
-
cssEl.setAttribute('as', 'style');
|
|
537
|
-
fragment.appendChild(cssEl);
|
|
538
|
-
});
|
|
539
|
-
document.head.appendChild(fragment);
|
|
540
|
-
jsAssetsWithoutEntry.forEach((jsUrl)=>{
|
|
541
|
-
const { script: scriptEl } = sdk.createScript(jsUrl, ()=>{
|
|
542
|
-
// noop
|
|
543
|
-
}, {}, (url)=>{
|
|
544
|
-
const res = host.loaderHook.lifecycle.createScript.emit({
|
|
545
|
-
url
|
|
546
|
-
});
|
|
547
|
-
if (res instanceof HTMLScriptElement) {
|
|
548
|
-
return res;
|
|
549
|
-
}
|
|
550
|
-
return;
|
|
551
|
-
});
|
|
552
|
-
document.head.appendChild(scriptEl);
|
|
553
|
-
});
|
|
554
|
-
}
|
|
555
|
-
}
|
|
556
|
-
|
|
557
|
-
function _extends$2() {
|
|
558
|
-
_extends$2 = Object.assign || function(target) {
|
|
559
|
-
for(var i = 1; i < arguments.length; i++){
|
|
560
|
-
var source = arguments[i];
|
|
561
|
-
for(var key in source){
|
|
562
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
563
|
-
target[key] = source[key];
|
|
564
|
-
}
|
|
565
|
-
}
|
|
566
|
-
}
|
|
567
|
-
return target;
|
|
568
|
-
};
|
|
569
|
-
return _extends$2.apply(this, arguments);
|
|
570
|
-
}
|
|
571
|
-
function assignRemoteInfo(remoteInfo, remoteSnapshot) {
|
|
572
|
-
if (!('remoteEntry' in remoteSnapshot) || !remoteSnapshot.remoteEntry) {
|
|
573
|
-
share.error(`The attribute remoteEntry of ${name} must not be undefined.`);
|
|
574
|
-
}
|
|
575
|
-
const { remoteEntry } = remoteSnapshot;
|
|
576
|
-
const entryUrl = sdk.getResourceUrl(remoteSnapshot, remoteEntry);
|
|
577
|
-
remoteInfo.type = remoteSnapshot.remoteEntryType;
|
|
578
|
-
remoteInfo.entryGlobalName = remoteSnapshot.globalName;
|
|
579
|
-
remoteInfo.entry = entryUrl;
|
|
580
|
-
remoteInfo.version = remoteSnapshot.version;
|
|
581
|
-
remoteInfo.buildVersion = remoteSnapshot.buildVersion;
|
|
582
|
-
}
|
|
583
|
-
function snapshotPlugin() {
|
|
584
|
-
return {
|
|
585
|
-
name: 'snapshot-plugin',
|
|
586
|
-
async loadRemoteMatch (args) {
|
|
587
|
-
const { remote, pkgNameOrAlias, expose, origin, remoteInfo } = args;
|
|
588
|
-
if (!share.isRemoteInfoWithEntry(remote) || !share.isPureRemoteEntry(remote)) {
|
|
589
|
-
const { remoteSnapshot, globalSnapshot } = await origin.snapshotHandler.loadRemoteSnapshotInfo(remote);
|
|
590
|
-
assignRemoteInfo(remoteInfo, remoteSnapshot);
|
|
591
|
-
// preloading assets
|
|
592
|
-
const preloadOptions = {
|
|
593
|
-
remote,
|
|
594
|
-
preloadConfig: {
|
|
595
|
-
nameOrAlias: pkgNameOrAlias,
|
|
596
|
-
exposes: [
|
|
597
|
-
expose
|
|
598
|
-
],
|
|
599
|
-
resourceCategory: 'sync',
|
|
600
|
-
share: false,
|
|
601
|
-
depsRemote: false
|
|
602
|
-
}
|
|
603
|
-
};
|
|
604
|
-
const assets = await origin.hooks.lifecycle.generatePreloadAssets.emit({
|
|
605
|
-
origin,
|
|
606
|
-
preloadOptions,
|
|
607
|
-
remoteInfo,
|
|
608
|
-
remote,
|
|
609
|
-
remoteSnapshot,
|
|
610
|
-
globalSnapshot
|
|
611
|
-
});
|
|
612
|
-
if (assets) {
|
|
613
|
-
preloadAssets(remoteInfo, origin, assets);
|
|
614
|
-
}
|
|
615
|
-
return _extends$2({}, args, {
|
|
616
|
-
remoteSnapshot
|
|
617
|
-
});
|
|
618
|
-
}
|
|
619
|
-
return args;
|
|
620
|
-
}
|
|
621
|
-
};
|
|
622
|
-
}
|
|
623
|
-
|
|
624
|
-
// name
|
|
625
|
-
// name:version
|
|
626
|
-
function splitId(id) {
|
|
627
|
-
const splitInfo = id.split(':');
|
|
628
|
-
if (splitInfo.length === 1) {
|
|
629
|
-
return {
|
|
630
|
-
name: splitInfo[0],
|
|
631
|
-
version: undefined
|
|
632
|
-
};
|
|
633
|
-
} else if (splitInfo.length === 2) {
|
|
634
|
-
return {
|
|
635
|
-
name: splitInfo[0],
|
|
636
|
-
version: splitInfo[1]
|
|
637
|
-
};
|
|
638
|
-
} else {
|
|
639
|
-
return {
|
|
640
|
-
name: splitInfo[1],
|
|
641
|
-
version: splitInfo[2]
|
|
642
|
-
};
|
|
643
|
-
}
|
|
644
|
-
}
|
|
645
|
-
// Traverse all nodes in moduleInfo and traverse the entire snapshot
|
|
646
|
-
function traverseModuleInfo(globalSnapshot, remoteInfo, traverse, isRoot, memo = {}, remoteSnapshot, getModuleInfoHook) {
|
|
647
|
-
const id = share.getFMId(remoteInfo);
|
|
648
|
-
const { value: snapshotValue } = share.getInfoWithoutType(globalSnapshot, id, getModuleInfoHook);
|
|
649
|
-
const effectiveRemoteSnapshot = remoteSnapshot || snapshotValue;
|
|
650
|
-
if (effectiveRemoteSnapshot && !sdk.isManifestProvider(effectiveRemoteSnapshot)) {
|
|
651
|
-
traverse(effectiveRemoteSnapshot, remoteInfo, isRoot);
|
|
652
|
-
if (effectiveRemoteSnapshot.remotesInfo) {
|
|
653
|
-
const remoteKeys = Object.keys(effectiveRemoteSnapshot.remotesInfo);
|
|
654
|
-
for (const key of remoteKeys){
|
|
655
|
-
if (memo[key]) {
|
|
656
|
-
continue;
|
|
657
|
-
}
|
|
658
|
-
memo[key] = true;
|
|
659
|
-
const subRemoteInfo = splitId(key);
|
|
660
|
-
const remoteValue = effectiveRemoteSnapshot.remotesInfo[key];
|
|
661
|
-
traverseModuleInfo(globalSnapshot, {
|
|
662
|
-
name: subRemoteInfo.name,
|
|
663
|
-
version: remoteValue.matchedVersion
|
|
664
|
-
}, traverse, false, memo, undefined, getModuleInfoHook);
|
|
665
|
-
}
|
|
666
|
-
}
|
|
667
|
-
}
|
|
668
|
-
}
|
|
669
|
-
// eslint-disable-next-line max-lines-per-function
|
|
670
|
-
function generatePreloadAssets(origin, preloadOptions, remote, globalSnapshot, remoteSnapshot) {
|
|
671
|
-
const cssAssets = [];
|
|
672
|
-
const jsAssets = [];
|
|
673
|
-
const entryAssets = [];
|
|
674
|
-
const loadedSharedJsAssets = new Set();
|
|
675
|
-
const loadedSharedCssAssets = new Set();
|
|
676
|
-
const { options } = origin;
|
|
677
|
-
const { preloadConfig: rootPreloadConfig } = preloadOptions;
|
|
678
|
-
const { depsRemote } = rootPreloadConfig;
|
|
679
|
-
const memo = {};
|
|
680
|
-
traverseModuleInfo(globalSnapshot, remote, (moduleInfoSnapshot, remoteInfo, isRoot)=>{
|
|
681
|
-
let preloadConfig;
|
|
682
|
-
if (isRoot) {
|
|
683
|
-
preloadConfig = rootPreloadConfig;
|
|
684
|
-
} else {
|
|
685
|
-
if (Array.isArray(depsRemote)) {
|
|
686
|
-
// eslint-disable-next-line array-callback-return
|
|
687
|
-
const findPreloadConfig = depsRemote.find((remoteConfig)=>{
|
|
688
|
-
if (remoteConfig.nameOrAlias === remoteInfo.name || remoteConfig.nameOrAlias === remoteInfo.alias) {
|
|
689
|
-
return true;
|
|
690
|
-
}
|
|
691
|
-
return false;
|
|
692
|
-
});
|
|
693
|
-
if (!findPreloadConfig) {
|
|
694
|
-
return;
|
|
695
|
-
}
|
|
696
|
-
preloadConfig = defaultPreloadArgs(findPreloadConfig);
|
|
697
|
-
} else if (depsRemote === true) {
|
|
698
|
-
preloadConfig = rootPreloadConfig;
|
|
699
|
-
} else {
|
|
700
|
-
return;
|
|
701
|
-
}
|
|
702
|
-
}
|
|
703
|
-
const remoteEntryUrl = sdk.getResourceUrl(moduleInfoSnapshot, 'remoteEntry' in moduleInfoSnapshot ? moduleInfoSnapshot.remoteEntry : '');
|
|
704
|
-
if (remoteEntryUrl) {
|
|
705
|
-
entryAssets.push({
|
|
706
|
-
name: remoteInfo.name,
|
|
707
|
-
moduleInfo: {
|
|
708
|
-
name: remoteInfo.name,
|
|
709
|
-
entry: remoteEntryUrl,
|
|
710
|
-
type: 'remoteEntryType' in moduleInfoSnapshot ? moduleInfoSnapshot.remoteEntryType : 'global',
|
|
711
|
-
entryGlobalName: 'globalName' in moduleInfoSnapshot ? moduleInfoSnapshot.globalName : remoteInfo.name,
|
|
712
|
-
shareScope: '',
|
|
713
|
-
version: 'version' in moduleInfoSnapshot ? moduleInfoSnapshot.version : undefined
|
|
714
|
-
},
|
|
715
|
-
url: remoteEntryUrl
|
|
716
|
-
});
|
|
717
|
-
}
|
|
718
|
-
let moduleAssetsInfo = 'modules' in moduleInfoSnapshot ? moduleInfoSnapshot.modules : [];
|
|
719
|
-
const normalizedPreloadExposes = normalizePreloadExposes(preloadConfig.exposes);
|
|
720
|
-
if (normalizedPreloadExposes.length && 'modules' in moduleInfoSnapshot) {
|
|
721
|
-
var _moduleInfoSnapshot_modules;
|
|
722
|
-
moduleAssetsInfo = moduleInfoSnapshot == null ? void 0 : (_moduleInfoSnapshot_modules = moduleInfoSnapshot.modules) == null ? void 0 : _moduleInfoSnapshot_modules.reduce((assets, moduleAssetInfo)=>{
|
|
723
|
-
if ((normalizedPreloadExposes == null ? void 0 : normalizedPreloadExposes.indexOf(moduleAssetInfo.moduleName)) !== -1) {
|
|
724
|
-
assets.push(moduleAssetInfo);
|
|
725
|
-
}
|
|
726
|
-
return assets;
|
|
727
|
-
}, []);
|
|
728
|
-
}
|
|
729
|
-
function handleAssets(assets) {
|
|
730
|
-
const assetsRes = assets.map((asset)=>sdk.getResourceUrl(moduleInfoSnapshot, asset));
|
|
731
|
-
if (preloadConfig.filter) {
|
|
732
|
-
return assetsRes.filter(preloadConfig.filter);
|
|
733
|
-
}
|
|
734
|
-
return assetsRes;
|
|
735
|
-
}
|
|
736
|
-
if (moduleAssetsInfo) {
|
|
737
|
-
const assetsLength = moduleAssetsInfo.length;
|
|
738
|
-
for(let index = 0; index < assetsLength; index++){
|
|
739
|
-
const assetsInfo = moduleAssetsInfo[index];
|
|
740
|
-
const exposeFullPath = `${remoteInfo.name}/${assetsInfo.moduleName}`;
|
|
741
|
-
origin.hooks.lifecycle.handlePreloadModule.emit({
|
|
742
|
-
id: assetsInfo.moduleName === '.' ? remoteInfo.name : exposeFullPath,
|
|
743
|
-
name: remoteInfo.name,
|
|
744
|
-
remoteSnapshot: moduleInfoSnapshot,
|
|
745
|
-
preloadConfig
|
|
746
|
-
});
|
|
747
|
-
const preloaded = share.getPreloaded(exposeFullPath);
|
|
748
|
-
if (preloaded) {
|
|
749
|
-
continue;
|
|
750
|
-
}
|
|
751
|
-
if (preloadConfig.resourceCategory === 'all') {
|
|
752
|
-
cssAssets.push(...handleAssets(assetsInfo.assets.css.async));
|
|
753
|
-
cssAssets.push(...handleAssets(assetsInfo.assets.css.sync));
|
|
754
|
-
jsAssets.push(...handleAssets(assetsInfo.assets.js.async));
|
|
755
|
-
jsAssets.push(...handleAssets(assetsInfo.assets.js.sync));
|
|
756
|
-
// eslint-disable-next-line no-constant-condition
|
|
757
|
-
} else if (preloadConfig.resourceCategory = 'sync') {
|
|
758
|
-
cssAssets.push(...handleAssets(assetsInfo.assets.css.sync));
|
|
759
|
-
jsAssets.push(...handleAssets(assetsInfo.assets.js.sync));
|
|
760
|
-
}
|
|
761
|
-
share.setPreloaded(exposeFullPath);
|
|
762
|
-
}
|
|
763
|
-
}
|
|
764
|
-
}, true, memo, remoteSnapshot, (target, key)=>{
|
|
765
|
-
const res = origin.loaderHook.lifecycle.getModuleInfo.emit({
|
|
766
|
-
target,
|
|
767
|
-
key
|
|
768
|
-
});
|
|
769
|
-
if (res && !(res instanceof Promise)) {
|
|
770
|
-
return res;
|
|
771
|
-
}
|
|
772
|
-
return;
|
|
773
|
-
});
|
|
774
|
-
if (remoteSnapshot.shared) {
|
|
775
|
-
remoteSnapshot.shared.forEach((shared)=>{
|
|
776
|
-
var _options_shared;
|
|
777
|
-
const shareInfo = (_options_shared = options.shared) == null ? void 0 : _options_shared[shared.sharedName];
|
|
778
|
-
// When data is downgraded, the shared configuration may be different.
|
|
779
|
-
if (!shareInfo) {
|
|
780
|
-
return;
|
|
781
|
-
}
|
|
782
|
-
const globalShare = share.getGlobalShare(shared.sharedName, shareInfo);
|
|
783
|
-
// 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.
|
|
784
|
-
if (globalShare && typeof globalShare.lib === 'function') {
|
|
785
|
-
shared.assets.js.sync.forEach((asset)=>{
|
|
786
|
-
loadedSharedJsAssets.add(asset);
|
|
787
|
-
});
|
|
788
|
-
shared.assets.css.sync.forEach((asset)=>{
|
|
789
|
-
loadedSharedCssAssets.add(asset);
|
|
790
|
-
});
|
|
791
|
-
}
|
|
792
|
-
});
|
|
793
|
-
}
|
|
794
|
-
const needPreloadJsAssets = jsAssets.filter((asset)=>!loadedSharedJsAssets.has(asset));
|
|
795
|
-
const needPreloadCssAssets = cssAssets.filter((asset)=>!loadedSharedCssAssets.has(asset));
|
|
796
|
-
return {
|
|
797
|
-
cssAssets: needPreloadCssAssets,
|
|
798
|
-
jsAssetsWithoutEntry: needPreloadJsAssets,
|
|
799
|
-
entryAssets
|
|
800
|
-
};
|
|
801
|
-
}
|
|
802
|
-
const generatePreloadAssetsPlugin = function() {
|
|
803
|
-
return {
|
|
804
|
-
name: 'generate-preload-assets-plugin',
|
|
805
|
-
async generatePreloadAssets (args) {
|
|
806
|
-
const { origin, preloadOptions, remoteInfo, remote, globalSnapshot, remoteSnapshot } = args;
|
|
807
|
-
if (share.isRemoteInfoWithEntry(remote) && share.isPureRemoteEntry(remote)) {
|
|
808
|
-
return {
|
|
809
|
-
cssAssets: [],
|
|
810
|
-
jsAssetsWithoutEntry: [],
|
|
811
|
-
entryAssets: [
|
|
812
|
-
{
|
|
813
|
-
name: remote.name,
|
|
814
|
-
url: remote.entry,
|
|
815
|
-
moduleInfo: {
|
|
816
|
-
name: remoteInfo.name,
|
|
817
|
-
entry: remote.entry,
|
|
818
|
-
type: 'global',
|
|
819
|
-
entryGlobalName: '',
|
|
820
|
-
shareScope: ''
|
|
821
|
-
}
|
|
822
|
-
}
|
|
823
|
-
]
|
|
824
|
-
};
|
|
825
|
-
}
|
|
826
|
-
assignRemoteInfo(remoteInfo, remoteSnapshot);
|
|
827
|
-
const assets = generatePreloadAssets(origin, preloadOptions, remoteInfo, globalSnapshot, remoteSnapshot);
|
|
828
|
-
return assets;
|
|
829
|
-
}
|
|
830
|
-
};
|
|
831
|
-
};
|
|
832
|
-
|
|
833
|
-
function _extends$1() {
|
|
834
|
-
_extends$1 = Object.assign || function(target) {
|
|
835
|
-
for(var i = 1; i < arguments.length; i++){
|
|
836
|
-
var source = arguments[i];
|
|
837
|
-
for(var key in source){
|
|
838
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
839
|
-
target[key] = source[key];
|
|
840
|
-
}
|
|
841
|
-
}
|
|
842
|
-
}
|
|
843
|
-
return target;
|
|
844
|
-
};
|
|
845
|
-
return _extends$1.apply(this, arguments);
|
|
846
|
-
}
|
|
847
|
-
class SnapshotHandler {
|
|
848
|
-
async loadSnapshot(moduleInfo) {
|
|
849
|
-
const { options } = this.HostInstance;
|
|
850
|
-
const { hostGlobalSnapshot, remoteSnapshot, globalSnapshot } = this.getGlobalRemoteInfo(moduleInfo);
|
|
851
|
-
const { remoteSnapshot: globalRemoteSnapshot, globalSnapshot: globalSnapshotRes } = await this.hooks.lifecycle.loadSnapshot.emit({
|
|
852
|
-
options,
|
|
853
|
-
moduleInfo,
|
|
854
|
-
hostGlobalSnapshot,
|
|
855
|
-
remoteSnapshot,
|
|
856
|
-
globalSnapshot
|
|
857
|
-
});
|
|
858
|
-
return {
|
|
859
|
-
remoteSnapshot: globalRemoteSnapshot,
|
|
860
|
-
globalSnapshot: globalSnapshotRes
|
|
861
|
-
};
|
|
862
|
-
}
|
|
863
|
-
// eslint-disable-next-line max-lines-per-function
|
|
864
|
-
async loadRemoteSnapshotInfo(moduleInfo) {
|
|
865
|
-
const { options } = this.HostInstance;
|
|
866
|
-
const hostSnapshot = share.getGlobalSnapshotInfoByModuleInfo({
|
|
867
|
-
name: this.HostInstance.options.name,
|
|
868
|
-
version: this.HostInstance.options.version
|
|
869
|
-
}, {
|
|
870
|
-
getModuleInfoHook: (target, key)=>{
|
|
871
|
-
const res = this.HostInstance.loaderHook.lifecycle.getModuleInfo.emit({
|
|
872
|
-
target,
|
|
873
|
-
key
|
|
874
|
-
});
|
|
875
|
-
if (res && !(res instanceof Promise)) {
|
|
876
|
-
return res;
|
|
877
|
-
}
|
|
878
|
-
return;
|
|
879
|
-
}
|
|
880
|
-
});
|
|
881
|
-
await this.hooks.lifecycle.beforeLoadRemoteSnapshot.emit({
|
|
882
|
-
options,
|
|
883
|
-
moduleInfo
|
|
884
|
-
});
|
|
885
|
-
// In dynamic loadRemote scenarios, incomplete remotesInfo delivery may occur. In such cases, the remotesInfo in the host needs to be completed in the snapshot at runtime.
|
|
886
|
-
// This ensures the snapshot's integrity and helps the chrome plugin correctly identify all producer modules, ensuring that proxyable producer modules will not be missing.
|
|
887
|
-
if (hostSnapshot && 'remotesInfo' in hostSnapshot && !share.getInfoWithoutType(hostSnapshot.remotesInfo, moduleInfo.name, (target, key)=>{
|
|
888
|
-
const res = this.HostInstance.loaderHook.lifecycle.getModuleInfo.emit({
|
|
889
|
-
target,
|
|
890
|
-
key
|
|
891
|
-
});
|
|
892
|
-
if (res && !(res instanceof Promise)) {
|
|
893
|
-
return res;
|
|
894
|
-
}
|
|
895
|
-
return;
|
|
896
|
-
}).value) {
|
|
897
|
-
if ('version' in moduleInfo || 'entry' in moduleInfo) {
|
|
898
|
-
hostSnapshot.remotesInfo = _extends$1({}, hostSnapshot == null ? void 0 : hostSnapshot.remotesInfo, {
|
|
899
|
-
[moduleInfo.name]: {
|
|
900
|
-
matchedVersion: 'version' in moduleInfo ? moduleInfo.version : moduleInfo.entry
|
|
901
|
-
}
|
|
902
|
-
});
|
|
903
|
-
}
|
|
904
|
-
}
|
|
905
|
-
const { hostGlobalSnapshot, remoteSnapshot, globalSnapshot } = this.getGlobalRemoteInfo(moduleInfo);
|
|
906
|
-
const { remoteSnapshot: globalRemoteSnapshot, globalSnapshot: globalSnapshotRes } = await this.hooks.lifecycle.loadSnapshot.emit({
|
|
907
|
-
options,
|
|
908
|
-
moduleInfo,
|
|
909
|
-
hostGlobalSnapshot,
|
|
910
|
-
remoteSnapshot,
|
|
911
|
-
globalSnapshot
|
|
912
|
-
});
|
|
913
|
-
// global snapshot includes manifest or module info includes manifest
|
|
914
|
-
if (globalRemoteSnapshot) {
|
|
915
|
-
if (sdk.isManifestProvider(globalRemoteSnapshot)) {
|
|
916
|
-
const moduleSnapshot = await this.getManifestJson(globalRemoteSnapshot.remoteEntry, moduleInfo, {});
|
|
917
|
-
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
918
|
-
const globalSnapshotRes = share.setGlobalSnapshotInfoByModuleInfo(_extends$1({}, moduleInfo), moduleSnapshot);
|
|
919
|
-
return {
|
|
920
|
-
remoteSnapshot: moduleSnapshot,
|
|
921
|
-
globalSnapshot: globalSnapshotRes
|
|
922
|
-
};
|
|
923
|
-
} else {
|
|
924
|
-
const { remoteSnapshot: remoteSnapshotRes } = await this.hooks.lifecycle.loadRemoteSnapshot.emit({
|
|
925
|
-
options: this.HostInstance.options,
|
|
926
|
-
moduleInfo,
|
|
927
|
-
remoteSnapshot: globalRemoteSnapshot,
|
|
928
|
-
from: 'global'
|
|
929
|
-
});
|
|
930
|
-
return {
|
|
931
|
-
remoteSnapshot: remoteSnapshotRes,
|
|
932
|
-
globalSnapshot: globalSnapshotRes
|
|
933
|
-
};
|
|
934
|
-
}
|
|
935
|
-
} else {
|
|
936
|
-
if (share.isRemoteInfoWithEntry(moduleInfo)) {
|
|
937
|
-
// get from manifest.json and merge remote info from remote server
|
|
938
|
-
const moduleSnapshot = await this.getManifestJson(moduleInfo.entry, moduleInfo, {});
|
|
939
|
-
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
940
|
-
const globalSnapshotRes = share.setGlobalSnapshotInfoByModuleInfo(moduleInfo, moduleSnapshot);
|
|
941
|
-
const { remoteSnapshot: remoteSnapshotRes } = await this.hooks.lifecycle.loadRemoteSnapshot.emit({
|
|
942
|
-
options: this.HostInstance.options,
|
|
943
|
-
moduleInfo,
|
|
944
|
-
remoteSnapshot: moduleSnapshot,
|
|
945
|
-
from: 'global'
|
|
946
|
-
});
|
|
947
|
-
return {
|
|
948
|
-
remoteSnapshot: remoteSnapshotRes,
|
|
949
|
-
globalSnapshot: globalSnapshotRes
|
|
950
|
-
};
|
|
951
|
-
} else {
|
|
952
|
-
share.error(`
|
|
953
|
-
Cannot get remoteSnapshot with the name: '${moduleInfo.name}', version: '${moduleInfo.version}' from __FEDERATION__.moduleInfo. The following reasons may be causing the problem:\n
|
|
954
|
-
1. The Deploy platform did not deliver the correct data. You can use __FEDERATION__.moduleInfo to check the remoteInfo.\n
|
|
955
|
-
2. The remote '${moduleInfo.name}' version '${moduleInfo.version}' is not released.\n
|
|
956
|
-
The transformed module info: ${JSON.stringify(globalSnapshotRes)}
|
|
957
|
-
`);
|
|
958
|
-
}
|
|
959
|
-
}
|
|
960
|
-
}
|
|
961
|
-
getGlobalRemoteInfo(moduleInfo) {
|
|
962
|
-
const hostGlobalSnapshot = share.getGlobalSnapshotInfoByModuleInfo({
|
|
963
|
-
name: this.HostInstance.options.name,
|
|
964
|
-
version: this.HostInstance.options.version
|
|
965
|
-
}, {
|
|
966
|
-
getModuleInfoHook: (target, key)=>{
|
|
967
|
-
const res = this.HostInstance.loaderHook.lifecycle.getModuleInfo.emit({
|
|
968
|
-
target,
|
|
969
|
-
key
|
|
970
|
-
});
|
|
971
|
-
if (res && !(res instanceof Promise)) {
|
|
972
|
-
return res;
|
|
973
|
-
}
|
|
974
|
-
return;
|
|
975
|
-
}
|
|
976
|
-
});
|
|
977
|
-
// get remote detail info from global
|
|
978
|
-
const globalRemoteInfo = hostGlobalSnapshot && 'remotesInfo' in hostGlobalSnapshot && hostGlobalSnapshot.remotesInfo && share.getInfoWithoutType(hostGlobalSnapshot.remotesInfo, moduleInfo.name, (target, key)=>{
|
|
979
|
-
const res = this.HostInstance.loaderHook.lifecycle.getModuleInfo.emit({
|
|
980
|
-
target,
|
|
981
|
-
key
|
|
982
|
-
});
|
|
983
|
-
if (res && !(res instanceof Promise)) {
|
|
984
|
-
return res;
|
|
985
|
-
}
|
|
986
|
-
return;
|
|
987
|
-
}).value;
|
|
988
|
-
if (globalRemoteInfo && globalRemoteInfo.matchedVersion) {
|
|
989
|
-
return {
|
|
990
|
-
hostGlobalSnapshot,
|
|
991
|
-
globalSnapshot: share.getGlobalSnapshot(),
|
|
992
|
-
remoteSnapshot: share.getGlobalSnapshotInfoByModuleInfo({
|
|
993
|
-
name: moduleInfo.name,
|
|
994
|
-
version: globalRemoteInfo.matchedVersion
|
|
995
|
-
}, {
|
|
996
|
-
getModuleInfoHook: (target, key)=>{
|
|
997
|
-
const res = this.HostInstance.loaderHook.lifecycle.getModuleInfo.emit({
|
|
998
|
-
target,
|
|
999
|
-
key
|
|
1000
|
-
});
|
|
1001
|
-
if (res && !(res instanceof Promise)) {
|
|
1002
|
-
return res;
|
|
1003
|
-
}
|
|
1004
|
-
return;
|
|
1005
|
-
}
|
|
1006
|
-
})
|
|
1007
|
-
};
|
|
1008
|
-
}
|
|
1009
|
-
return {
|
|
1010
|
-
hostGlobalSnapshot: undefined,
|
|
1011
|
-
globalSnapshot: share.getGlobalSnapshot(),
|
|
1012
|
-
remoteSnapshot: share.getGlobalSnapshotInfoByModuleInfo({
|
|
1013
|
-
name: moduleInfo.name,
|
|
1014
|
-
version: 'version' in moduleInfo ? moduleInfo.version : undefined
|
|
1015
|
-
}, {
|
|
1016
|
-
getModuleInfoHook: (target, key)=>{
|
|
1017
|
-
const res = this.HostInstance.loaderHook.lifecycle.getModuleInfo.emit({
|
|
1018
|
-
target,
|
|
1019
|
-
key
|
|
1020
|
-
});
|
|
1021
|
-
if (res && !(res instanceof Promise)) {
|
|
1022
|
-
return res;
|
|
1023
|
-
}
|
|
1024
|
-
return;
|
|
1025
|
-
}
|
|
1026
|
-
})
|
|
1027
|
-
};
|
|
1028
|
-
}
|
|
1029
|
-
async getManifestJson(manifestUrl, moduleInfo, extraOptions) {
|
|
1030
|
-
const getManifest = async ()=>{
|
|
1031
|
-
let manifestJson = this.manifestCache.get(manifestUrl);
|
|
1032
|
-
if (manifestJson) {
|
|
1033
|
-
return manifestJson;
|
|
1034
|
-
}
|
|
1035
|
-
try {
|
|
1036
|
-
const res = await fetch(manifestUrl);
|
|
1037
|
-
manifestJson = await res.json();
|
|
1038
|
-
share.assert(manifestJson.metaData && manifestJson.exposes && manifestJson.shared, `${manifestUrl} is not a federation manifest`);
|
|
1039
|
-
this.manifestCache.set(manifestUrl, manifestJson);
|
|
1040
|
-
return manifestJson;
|
|
1041
|
-
} catch (err) {
|
|
1042
|
-
share.error(`Failed to get manifestJson for ${moduleInfo.name}. The manifest URL is ${manifestUrl}. Please ensure that the manifestUrl is accessible.
|
|
1043
|
-
\n Error message:
|
|
1044
|
-
\n ${err}`);
|
|
1045
|
-
}
|
|
1046
|
-
};
|
|
1047
|
-
const asyncLoadProcess = async ()=>{
|
|
1048
|
-
const manifestJson = await getManifest();
|
|
1049
|
-
const remoteSnapshot = sdk.generateSnapshotFromManifest(manifestJson, {
|
|
1050
|
-
version: manifestUrl
|
|
1051
|
-
});
|
|
1052
|
-
const { remoteSnapshot: remoteSnapshotRes } = await this.hooks.lifecycle.loadRemoteSnapshot.emit({
|
|
1053
|
-
options: this.HostInstance.options,
|
|
1054
|
-
moduleInfo,
|
|
1055
|
-
manifestJson,
|
|
1056
|
-
remoteSnapshot,
|
|
1057
|
-
manifestUrl,
|
|
1058
|
-
from: 'manifest'
|
|
1059
|
-
});
|
|
1060
|
-
return remoteSnapshotRes;
|
|
1061
|
-
};
|
|
1062
|
-
if (!this.manifestLoading[manifestUrl]) {
|
|
1063
|
-
this.manifestLoading[manifestUrl] = asyncLoadProcess().then((res)=>res);
|
|
1064
|
-
}
|
|
1065
|
-
return this.manifestLoading[manifestUrl];
|
|
1066
|
-
}
|
|
1067
|
-
constructor(HostInstance){
|
|
1068
|
-
this.loadingHostSnapshot = null;
|
|
1069
|
-
this.manifestCache = new Map();
|
|
1070
|
-
this.hooks = new PluginSystem({
|
|
1071
|
-
beforeLoadRemoteSnapshot: new AsyncHook('beforeLoadRemoteSnapshot'),
|
|
1072
|
-
loadSnapshot: new AsyncWaterfallHook('loadGlobalSnapshot'),
|
|
1073
|
-
loadRemoteSnapshot: new AsyncWaterfallHook('loadRemoteSnapshot')
|
|
1074
|
-
});
|
|
1075
|
-
this.manifestLoading = share.Global.__FEDERATION__.__MANIFEST_LOADING__;
|
|
1076
|
-
this.HostInstance = HostInstance;
|
|
1077
|
-
}
|
|
1078
|
-
}
|
|
1079
|
-
|
|
1080
|
-
function _extends() {
|
|
1081
|
-
_extends = Object.assign || function(target) {
|
|
1082
|
-
for(var i = 1; i < arguments.length; i++){
|
|
1083
|
-
var source = arguments[i];
|
|
1084
|
-
for(var key in source){
|
|
1085
|
-
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
1086
|
-
target[key] = source[key];
|
|
1087
|
-
}
|
|
1088
|
-
}
|
|
1089
|
-
}
|
|
1090
|
-
return target;
|
|
1091
|
-
};
|
|
1092
|
-
return _extends.apply(this, arguments);
|
|
1093
|
-
}
|
|
1094
|
-
function _object_without_properties_loose(source, excluded) {
|
|
1095
|
-
if (source == null) return {};
|
|
1096
|
-
var target = {};
|
|
1097
|
-
var sourceKeys = Object.keys(source);
|
|
1098
|
-
var key, i;
|
|
1099
|
-
for(i = 0; i < sourceKeys.length; i++){
|
|
1100
|
-
key = sourceKeys[i];
|
|
1101
|
-
if (excluded.indexOf(key) >= 0) continue;
|
|
1102
|
-
target[key] = source[key];
|
|
1103
|
-
}
|
|
1104
|
-
return target;
|
|
1105
|
-
}
|
|
1106
|
-
class FederationHost {
|
|
1107
|
-
initOptions(userOptions) {
|
|
1108
|
-
this.registerPlugins(userOptions.plugins);
|
|
1109
|
-
const options = this.formatOptions(this.options, userOptions);
|
|
1110
|
-
this.options = options;
|
|
1111
|
-
return options;
|
|
1112
|
-
}
|
|
1113
|
-
// overrideSharedOptions(shareScope: GlobalShareScope[string]): void {}
|
|
1114
|
-
async loadShare(pkgName, customShareInfo) {
|
|
1115
|
-
var _this_options_shared;
|
|
1116
|
-
// This function performs the following steps:
|
|
1117
|
-
// 1. Checks if the currently loaded share already exists, if not, it throws an error
|
|
1118
|
-
// 2. Searches globally for a matching share, if found, it uses it directly
|
|
1119
|
-
// 3. If not found, it retrieves it from the current share and stores the obtained share globally.
|
|
1120
|
-
const shareInfo = Object.assign({}, (_this_options_shared = this.options.shared) == null ? void 0 : _this_options_shared[pkgName], customShareInfo);
|
|
1121
|
-
const loadShareRes = await this.hooks.lifecycle.beforeLoadShare.emit({
|
|
1122
|
-
pkgName,
|
|
1123
|
-
shareInfo,
|
|
1124
|
-
shared: this.options.shared,
|
|
1125
|
-
origin: this
|
|
1126
|
-
});
|
|
1127
|
-
const { shareInfo: shareInfoRes } = loadShareRes;
|
|
1128
|
-
// Assert that shareInfoRes exists, if not, throw an error
|
|
1129
|
-
share.assert(shareInfoRes, `Cannot find ${pkgName} Share in the ${this.options.name}. Please ensure that the ${pkgName} Share parameters have been injected`);
|
|
1130
|
-
// Retrieve from cache
|
|
1131
|
-
const globalShare = share.getGlobalShare(pkgName, shareInfoRes);
|
|
1132
|
-
if (globalShare && globalShare.lib) {
|
|
1133
|
-
share.addUniqueItem(globalShare.useIn, this.options.name);
|
|
1134
|
-
return globalShare.lib;
|
|
1135
|
-
} else if (globalShare && globalShare.loading) {
|
|
1136
|
-
const factory = await globalShare.loading;
|
|
1137
|
-
share.addUniqueItem(globalShare.useIn, this.options.name);
|
|
1138
|
-
return factory;
|
|
1139
|
-
} else if (globalShare) {
|
|
1140
|
-
const asyncLoadProcess = async ()=>{
|
|
1141
|
-
const factory = await globalShare.get();
|
|
1142
|
-
shareInfoRes.lib = factory;
|
|
1143
|
-
share.addUniqueItem(shareInfoRes.useIn, this.options.name);
|
|
1144
|
-
const gShared = share.getGlobalShare(pkgName, shareInfoRes);
|
|
1145
|
-
if (gShared) {
|
|
1146
|
-
gShared.lib = factory;
|
|
1147
|
-
}
|
|
1148
|
-
return factory;
|
|
1149
|
-
};
|
|
1150
|
-
const loading = asyncLoadProcess();
|
|
1151
|
-
this.setShared({
|
|
1152
|
-
pkgName,
|
|
1153
|
-
loaded: true,
|
|
1154
|
-
shared: shareInfoRes,
|
|
1155
|
-
from: this.options.name,
|
|
1156
|
-
lib: null,
|
|
1157
|
-
loading
|
|
1158
|
-
});
|
|
1159
|
-
return loading;
|
|
1160
|
-
} else {
|
|
1161
|
-
if (customShareInfo) {
|
|
1162
|
-
return false;
|
|
1163
|
-
}
|
|
1164
|
-
const asyncLoadProcess = async ()=>{
|
|
1165
|
-
const factory = await shareInfoRes.get();
|
|
1166
|
-
shareInfoRes.lib = factory;
|
|
1167
|
-
share.addUniqueItem(shareInfoRes.useIn, this.options.name);
|
|
1168
|
-
const gShared = share.getGlobalShare(pkgName, shareInfoRes);
|
|
1169
|
-
if (gShared) {
|
|
1170
|
-
gShared.lib = factory;
|
|
1171
|
-
}
|
|
1172
|
-
return factory;
|
|
1173
|
-
};
|
|
1174
|
-
const loading = asyncLoadProcess();
|
|
1175
|
-
this.setShared({
|
|
1176
|
-
pkgName,
|
|
1177
|
-
loaded: true,
|
|
1178
|
-
shared: shareInfoRes,
|
|
1179
|
-
from: this.options.name,
|
|
1180
|
-
lib: null,
|
|
1181
|
-
loading
|
|
1182
|
-
});
|
|
1183
|
-
return loading;
|
|
1184
|
-
}
|
|
1185
|
-
}
|
|
1186
|
-
// The lib function will only be available if the shared set by eager or runtime init is set or the shared is successfully loaded.
|
|
1187
|
-
// 1. If the loaded shared already exists globally, then it will be reused
|
|
1188
|
-
// 2. If lib exists in local shared, it will be used directly
|
|
1189
|
-
// 3. If the local get returns something other than Promise, then it will be used directly
|
|
1190
|
-
loadShareSync(pkgName) {
|
|
1191
|
-
var _this_options_shared;
|
|
1192
|
-
const shareInfo = (_this_options_shared = this.options.shared) == null ? void 0 : _this_options_shared[pkgName];
|
|
1193
|
-
const globalShare = share.getGlobalShare(pkgName, shareInfo);
|
|
1194
|
-
if (globalShare && typeof globalShare.lib === 'function') {
|
|
1195
|
-
share.addUniqueItem(globalShare.useIn, this.options.name);
|
|
1196
|
-
if (!globalShare.loaded) {
|
|
1197
|
-
globalShare.loaded = true;
|
|
1198
|
-
if (globalShare.from === this.options.name) {
|
|
1199
|
-
shareInfo.loaded = true;
|
|
1200
|
-
}
|
|
1201
|
-
}
|
|
1202
|
-
return globalShare.lib;
|
|
1203
|
-
}
|
|
1204
|
-
if (shareInfo.lib) {
|
|
1205
|
-
if (!shareInfo.loaded) {
|
|
1206
|
-
shareInfo.loaded = true;
|
|
1207
|
-
}
|
|
1208
|
-
return shareInfo.lib;
|
|
1209
|
-
}
|
|
1210
|
-
if (shareInfo.get) {
|
|
1211
|
-
const module = shareInfo.get();
|
|
1212
|
-
if (module instanceof Promise) {
|
|
1213
|
-
throw new Error(`
|
|
1214
|
-
The loadShareSync function was unable to load ${pkgName}. The ${pkgName} could not be found in ${this.options.name}.
|
|
1215
|
-
Possible reasons for failure: \n
|
|
1216
|
-
1. The ${pkgName} share was registered with the 'get' attribute, but loadShare was not used beforehand.\n
|
|
1217
|
-
2. The ${pkgName} share was not registered with the 'lib' attribute.\n
|
|
1218
|
-
`);
|
|
1219
|
-
}
|
|
1220
|
-
shareInfo.lib = module;
|
|
1221
|
-
this.setShared({
|
|
1222
|
-
pkgName,
|
|
1223
|
-
loaded: true,
|
|
1224
|
-
from: this.options.name,
|
|
1225
|
-
lib: shareInfo.lib,
|
|
1226
|
-
shared: shareInfo
|
|
1227
|
-
});
|
|
1228
|
-
return shareInfo.lib;
|
|
1229
|
-
}
|
|
1230
|
-
throw new Error(`
|
|
1231
|
-
The loadShareSync function was unable to load ${pkgName}. The ${pkgName} could not be found in ${this.options.name}.
|
|
1232
|
-
Possible reasons for failure: \n
|
|
1233
|
-
1. The ${pkgName} share was registered with the 'get' attribute, but loadShare was not used beforehand.\n
|
|
1234
|
-
2. The ${pkgName} share was not registered with the 'lib' attribute.\n
|
|
1235
|
-
`);
|
|
1236
|
-
}
|
|
1237
|
-
async _getRemoteModuleAndOptions(id) {
|
|
1238
|
-
const loadRemoteArgs = await this.hooks.lifecycle.beforeLoadRemote.emit({
|
|
1239
|
-
id,
|
|
1240
|
-
options: this.options,
|
|
1241
|
-
origin: this
|
|
1242
|
-
});
|
|
1243
|
-
const { id: idRes } = loadRemoteArgs;
|
|
1244
|
-
const remoteSplitInfo = matchRemoteWithNameAndExpose(this.options.remotes, idRes);
|
|
1245
|
-
share.assert(remoteSplitInfo, `
|
|
1246
|
-
Unable to locate ${idRes} in ${this.options.name}. Potential reasons for failure include:\n
|
|
1247
|
-
1. ${idRes} was not included in the 'remotes' parameter of ${this.options.name || 'the host'}.\n
|
|
1248
|
-
2. ${idRes} could not be found in the 'remotes' of ${this.options.name} with either 'name' or 'alias' attributes.
|
|
1249
|
-
3. ${idRes} is not online, injected, or loaded.
|
|
1250
|
-
4. ${idRes} cannot be accessed on the expected.
|
|
1251
|
-
5. The 'beforeLoadRemote' hook was provided but did not return the correct 'remoteInfo' when attempting to load ${idRes}.
|
|
1252
|
-
`);
|
|
1253
|
-
const { remote: rawRemote } = remoteSplitInfo;
|
|
1254
|
-
const remoteInfo = getRemoteInfo(rawRemote);
|
|
1255
|
-
const matchInfo = await this.hooks.lifecycle.loadRemoteMatch.emit(_extends({
|
|
1256
|
-
id: idRes
|
|
1257
|
-
}, remoteSplitInfo, {
|
|
1258
|
-
options: this.options,
|
|
1259
|
-
origin: this,
|
|
1260
|
-
remoteInfo
|
|
1261
|
-
}));
|
|
1262
|
-
const { remote, expose } = matchInfo;
|
|
1263
|
-
share.assert(remote && expose, `The 'beforeLoadRemote' hook was executed, but it failed to return the correct 'remote' and 'expose' values while loading ${idRes}.`);
|
|
1264
|
-
let module = this.moduleCache.get(remote.name);
|
|
1265
|
-
const moduleOptions = {
|
|
1266
|
-
hostInfo: {
|
|
1267
|
-
name: this.options.name,
|
|
1268
|
-
version: this.options.version || 'custom'
|
|
1269
|
-
},
|
|
1270
|
-
remoteInfo,
|
|
1271
|
-
shared: this.options.shared || {},
|
|
1272
|
-
plugins: this.options.plugins,
|
|
1273
|
-
loaderHook: this.loaderHook
|
|
1274
|
-
};
|
|
1275
|
-
if (!module) {
|
|
1276
|
-
module = new Module(moduleOptions);
|
|
1277
|
-
this.moduleCache.set(remote.name, module);
|
|
1278
|
-
}
|
|
1279
|
-
return {
|
|
1280
|
-
module,
|
|
1281
|
-
moduleOptions,
|
|
1282
|
-
remoteMatchInfo: matchInfo
|
|
1283
|
-
};
|
|
1284
|
-
}
|
|
1285
|
-
// eslint-disable-next-line max-lines-per-function
|
|
1286
|
-
// eslint-disable-next-line @typescript-eslint/member-ordering
|
|
1287
|
-
async loadRemote(id, options) {
|
|
1288
|
-
try {
|
|
1289
|
-
const { loadFactory = true } = options || {
|
|
1290
|
-
loadFactory: true
|
|
1291
|
-
};
|
|
1292
|
-
// 1. Validate the parameters of the retrieved module. There are two module request methods: pkgName + expose and alias + expose.
|
|
1293
|
-
// 2. Request the snapshot information of the current host and globally store the obtained snapshot information. The retrieved module information is partially offline and partially online. The online module information will retrieve the modules used online.
|
|
1294
|
-
// 3. Retrieve the detailed information of the current module from global (remoteEntry address, expose resource address)
|
|
1295
|
-
// 4. After retrieving remoteEntry, call the init of the module, and then retrieve the exported content of the module through get
|
|
1296
|
-
// id: pkgName(@federation/app1) + expose(button) = @federation/app1/button
|
|
1297
|
-
// id: alias(app1) + expose(button) = app1/button
|
|
1298
|
-
// id: alias(app1/utils) + expose(loadash/sort) = app1/utils/loadash/sort
|
|
1299
|
-
const { module, moduleOptions, remoteMatchInfo } = await this._getRemoteModuleAndOptions(id);
|
|
1300
|
-
const { pkgNameOrAlias, remote, expose, id: idRes } = remoteMatchInfo;
|
|
1301
|
-
const moduleOrFactory = await module.get(expose, options);
|
|
1302
|
-
await this.hooks.lifecycle.loadRemote.emit({
|
|
1303
|
-
id: idRes,
|
|
1304
|
-
pkgNameOrAlias,
|
|
1305
|
-
expose,
|
|
1306
|
-
exposeModule: loadFactory ? moduleOrFactory : undefined,
|
|
1307
|
-
exposeModuleFactory: loadFactory ? undefined : moduleOrFactory,
|
|
1308
|
-
remote,
|
|
1309
|
-
options: moduleOptions,
|
|
1310
|
-
moduleInstance: module,
|
|
1311
|
-
origin: this
|
|
1312
|
-
});
|
|
1313
|
-
return moduleOrFactory;
|
|
1314
|
-
} catch (error) {
|
|
1315
|
-
this.hooks.lifecycle.errorLoadRemote.emit({
|
|
1316
|
-
id,
|
|
1317
|
-
error
|
|
1318
|
-
});
|
|
1319
|
-
throw error;
|
|
1320
|
-
}
|
|
1321
|
-
}
|
|
1322
|
-
// eslint-disable-next-line @typescript-eslint/member-ordering
|
|
1323
|
-
async preloadRemote(preloadOptions) {
|
|
1324
|
-
await this.hooks.lifecycle.beforePreloadRemote.emit({
|
|
1325
|
-
preloadOptions,
|
|
1326
|
-
options: this.options,
|
|
1327
|
-
origin: this
|
|
1328
|
-
});
|
|
1329
|
-
const preloadOps = formatPreloadArgs(this.options.remotes, preloadOptions);
|
|
1330
|
-
await Promise.all(preloadOps.map(async (ops)=>{
|
|
1331
|
-
const { remote } = ops;
|
|
1332
|
-
const remoteInfo = getRemoteInfo(remote);
|
|
1333
|
-
const { globalSnapshot, remoteSnapshot } = await this.snapshotHandler.loadRemoteSnapshotInfo(remote);
|
|
1334
|
-
const assets = await this.hooks.lifecycle.generatePreloadAssets.emit({
|
|
1335
|
-
origin: this,
|
|
1336
|
-
preloadOptions: ops,
|
|
1337
|
-
remote,
|
|
1338
|
-
remoteInfo,
|
|
1339
|
-
globalSnapshot,
|
|
1340
|
-
remoteSnapshot
|
|
1341
|
-
});
|
|
1342
|
-
if (!assets) {
|
|
1343
|
-
return;
|
|
1344
|
-
}
|
|
1345
|
-
preloadAssets(remoteInfo, this, assets);
|
|
1346
|
-
}));
|
|
1347
|
-
}
|
|
1348
|
-
/**
|
|
1349
|
-
* This function initializes the sharing sequence (executed only once per share scope).
|
|
1350
|
-
* It accepts one argument, the name of the share scope.
|
|
1351
|
-
* If the share scope does not exist, it creates one.
|
|
1352
|
-
*/ // eslint-disable-next-line @typescript-eslint/member-ordering
|
|
1353
|
-
initializeSharing(shareScopeName = share.DEFAULT_SCOPE) {
|
|
1354
|
-
const shareScopeLoading = share.Global.__FEDERATION__.__SHARE_SCOPE_LOADING__;
|
|
1355
|
-
const shareScope = share.Global.__FEDERATION__.__SHARE__;
|
|
1356
|
-
const hostName = this.options.name;
|
|
1357
|
-
// Executes only once
|
|
1358
|
-
if (shareScopeLoading[shareScopeName]) {
|
|
1359
|
-
return shareScopeLoading[shareScopeName];
|
|
1360
|
-
}
|
|
1361
|
-
// Creates a new share scope if necessary
|
|
1362
|
-
if (!shareScope[shareScopeName]) {
|
|
1363
|
-
shareScope[shareScopeName] = {};
|
|
1364
|
-
}
|
|
1365
|
-
// Executes all initialization snippets from all accessible modules
|
|
1366
|
-
const scope = shareScope[shareScopeName];
|
|
1367
|
-
const register = (name, shared)=>{
|
|
1368
|
-
const { version, eager } = shared;
|
|
1369
|
-
scope[name] = scope[name] || {};
|
|
1370
|
-
const versions = scope[name];
|
|
1371
|
-
const activeVersion = versions[version];
|
|
1372
|
-
const activeVersionEager = Boolean(activeVersion && (activeVersion.eager || activeVersion.shareConfig.eager));
|
|
1373
|
-
if (!activeVersion || !activeVersion.loaded && (Boolean(!eager) !== !activeVersionEager ? eager : hostName > activeVersion.from)) {
|
|
1374
|
-
versions[version] = shared;
|
|
1375
|
-
}
|
|
1376
|
-
};
|
|
1377
|
-
const promises = [];
|
|
1378
|
-
const initRemoteModule = async (key)=>{
|
|
1379
|
-
const { module } = await this._getRemoteModuleAndOptions(key);
|
|
1380
|
-
const initFn = (mod)=>mod && mod.init && mod.init(shareScope[shareScopeName]);
|
|
1381
|
-
const entry = await module.getEntry();
|
|
1382
|
-
initFn(entry);
|
|
1383
|
-
};
|
|
1384
|
-
Object.keys(this.options.shared).forEach((shareName)=>{
|
|
1385
|
-
const shared = this.options.shared[shareName];
|
|
1386
|
-
if (shared.scope.includes(shareScopeName)) {
|
|
1387
|
-
register(shareName, shared);
|
|
1388
|
-
}
|
|
1389
|
-
});
|
|
1390
|
-
this.options.remotes.forEach((remote)=>{
|
|
1391
|
-
if (remote.shareScope === shareScopeName) {
|
|
1392
|
-
promises.push(initRemoteModule(remote.name));
|
|
1393
|
-
}
|
|
1394
|
-
});
|
|
1395
|
-
if (!promises.length) {
|
|
1396
|
-
return shareScopeLoading[shareScopeName] = true;
|
|
1397
|
-
}
|
|
1398
|
-
return shareScopeLoading[shareScopeName] = Promise.all(promises).then(()=>shareScopeLoading[shareScopeName] = true);
|
|
1399
|
-
}
|
|
1400
|
-
formatOptions(globalOptions, userOptions) {
|
|
1401
|
-
const formatShareOptions = share.formatShareConfigs(userOptions.shared || {}, userOptions.name);
|
|
1402
|
-
const shared = _extends({}, globalOptions.shared, formatShareOptions);
|
|
1403
|
-
const { userOptions: userOptionsRes, options: globalOptionsRes } = this.hooks.lifecycle.beforeInit.emit({
|
|
1404
|
-
origin: this,
|
|
1405
|
-
userOptions,
|
|
1406
|
-
options: globalOptions,
|
|
1407
|
-
shareInfo: shared
|
|
1408
|
-
});
|
|
1409
|
-
const userRemotes = userOptionsRes.remotes || [];
|
|
1410
|
-
const remotes = userRemotes.reduce((res, remote)=>{
|
|
1411
|
-
if (!res.find((item)=>item.name === remote.name)) {
|
|
1412
|
-
if (remote.alias) {
|
|
1413
|
-
// Validate if alias equals the prefix of remote.name and remote.alias, if so, throw an error
|
|
1414
|
-
// As multi-level path references cannot guarantee unique names, alias being a prefix of remote.name is not supported
|
|
1415
|
-
const findEqual = res.find((item)=>{
|
|
1416
|
-
var _item_alias;
|
|
1417
|
-
return remote.alias && (item.name.startsWith(remote.alias) || ((_item_alias = item.alias) == null ? void 0 : _item_alias.startsWith(remote.alias)));
|
|
1418
|
-
});
|
|
1419
|
-
share.assert(!findEqual, `The alias ${remote.alias} of remote ${remote.name} is not allowed to be the prefix of ${findEqual && findEqual.name} name or alias`);
|
|
1420
|
-
}
|
|
1421
|
-
// Set the remote entry to a complete path
|
|
1422
|
-
if ('entry' in remote) {
|
|
1423
|
-
if (share.isBrowserEnv()) {
|
|
1424
|
-
remote.entry = new URL(remote.entry, window.location.origin).href;
|
|
1425
|
-
}
|
|
1426
|
-
}
|
|
1427
|
-
if (!remote.shareScope) {
|
|
1428
|
-
remote.shareScope = share.DEFAULT_SCOPE;
|
|
1429
|
-
}
|
|
1430
|
-
if (!remote.type) {
|
|
1431
|
-
// FIXME: The build plugin needs to support this field
|
|
1432
|
-
remote.type = share.DEFAULT_REMOTE_TYPE;
|
|
1433
|
-
}
|
|
1434
|
-
res.push(remote);
|
|
1435
|
-
}
|
|
1436
|
-
return res;
|
|
1437
|
-
}, globalOptionsRes.remotes);
|
|
1438
|
-
// register shared include lib
|
|
1439
|
-
const sharedKeys = Object.keys(formatShareOptions);
|
|
1440
|
-
sharedKeys.forEach((sharedKey)=>{
|
|
1441
|
-
const sharedVal = formatShareOptions[sharedKey];
|
|
1442
|
-
const globalShare = share.getGlobalShare(sharedKey, sharedVal);
|
|
1443
|
-
if (!globalShare && sharedVal && sharedVal.lib) {
|
|
1444
|
-
this.setShared({
|
|
1445
|
-
pkgName: sharedKey,
|
|
1446
|
-
lib: sharedVal.lib,
|
|
1447
|
-
get: sharedVal.get,
|
|
1448
|
-
shared: sharedVal,
|
|
1449
|
-
from: userOptions.name
|
|
1450
|
-
});
|
|
1451
|
-
}
|
|
1452
|
-
});
|
|
1453
|
-
const plugins = [
|
|
1454
|
-
...globalOptionsRes.plugins
|
|
1455
|
-
];
|
|
1456
|
-
if (userOptionsRes.plugins) {
|
|
1457
|
-
userOptionsRes.plugins.forEach((plugin)=>{
|
|
1458
|
-
if (!plugins.includes(plugin)) {
|
|
1459
|
-
plugins.push(plugin);
|
|
1460
|
-
}
|
|
1461
|
-
});
|
|
1462
|
-
}
|
|
1463
|
-
const optionsRes = _extends({}, globalOptions, userOptions, {
|
|
1464
|
-
plugins,
|
|
1465
|
-
remotes,
|
|
1466
|
-
shared
|
|
1467
|
-
});
|
|
1468
|
-
this.hooks.lifecycle.init.emit({
|
|
1469
|
-
origin: this,
|
|
1470
|
-
options: optionsRes
|
|
1471
|
-
});
|
|
1472
|
-
return optionsRes;
|
|
1473
|
-
}
|
|
1474
|
-
registerPlugins(plugins) {
|
|
1475
|
-
registerPlugins(plugins, [
|
|
1476
|
-
this.hooks,
|
|
1477
|
-
this.snapshotHandler.hooks,
|
|
1478
|
-
this.loaderHook
|
|
1479
|
-
]);
|
|
1480
|
-
}
|
|
1481
|
-
setShared({ pkgName, shared, from, lib, loading, loaded, get }) {
|
|
1482
|
-
const target = share.getGlobalShareScope();
|
|
1483
|
-
const { version, scope = 'default' } = shared, shareInfo = _object_without_properties_loose(shared, [
|
|
1484
|
-
"version",
|
|
1485
|
-
"scope"
|
|
1486
|
-
]);
|
|
1487
|
-
const scopes = Array.isArray(scope) ? scope : [
|
|
1488
|
-
scope
|
|
1489
|
-
];
|
|
1490
|
-
scopes.forEach((sc)=>{
|
|
1491
|
-
if (!target[sc]) {
|
|
1492
|
-
target[sc] = {};
|
|
1493
|
-
}
|
|
1494
|
-
if (!target[sc][pkgName]) {
|
|
1495
|
-
target[sc][pkgName] = {};
|
|
1496
|
-
}
|
|
1497
|
-
if (target[sc][pkgName][version]) {
|
|
1498
|
-
share.warn(// eslint-disable-next-line max-len
|
|
1499
|
-
`The share \n ${share.safeToString({
|
|
1500
|
-
scope: sc,
|
|
1501
|
-
pkgName,
|
|
1502
|
-
version,
|
|
1503
|
-
from: target[sc][pkgName][version].from
|
|
1504
|
-
})} has been registered`);
|
|
1505
|
-
return;
|
|
1506
|
-
}
|
|
1507
|
-
target[sc][pkgName][version] = _extends({
|
|
1508
|
-
version,
|
|
1509
|
-
scope: [
|
|
1510
|
-
'default'
|
|
1511
|
-
]
|
|
1512
|
-
}, shareInfo, {
|
|
1513
|
-
lib,
|
|
1514
|
-
loaded,
|
|
1515
|
-
loading
|
|
1516
|
-
});
|
|
1517
|
-
if (get) {
|
|
1518
|
-
target[sc][pkgName][version].get = get;
|
|
1519
|
-
}
|
|
1520
|
-
});
|
|
1521
|
-
}
|
|
1522
|
-
constructor(userOptions){
|
|
1523
|
-
this.hooks = new PluginSystem({
|
|
1524
|
-
beforeInit: new SyncWaterfallHook('beforeInit'),
|
|
1525
|
-
init: new SyncHook(),
|
|
1526
|
-
beforeLoadRemote: new AsyncWaterfallHook('beforeLoadRemote'),
|
|
1527
|
-
loadRemoteMatch: new AsyncWaterfallHook('loadRemoteMatch'),
|
|
1528
|
-
loadRemote: new AsyncHook('loadRemote'),
|
|
1529
|
-
handlePreloadModule: new SyncHook('handlePreloadModule'),
|
|
1530
|
-
errorLoadRemote: new AsyncHook('errorLoadRemote'),
|
|
1531
|
-
beforeLoadShare: new AsyncWaterfallHook('beforeLoadShare'),
|
|
1532
|
-
loadShare: new AsyncHook(),
|
|
1533
|
-
beforePreloadRemote: new AsyncHook(),
|
|
1534
|
-
generatePreloadAssets: new AsyncHook('generatePreloadAssets'),
|
|
1535
|
-
afterPreloadRemote: new AsyncHook()
|
|
1536
|
-
});
|
|
1537
|
-
this.version = '1.0.0-canary.1';
|
|
1538
|
-
this.moduleCache = new Map();
|
|
1539
|
-
this.loaderHook = new PluginSystem({
|
|
1540
|
-
// FIXME: may not be suitable
|
|
1541
|
-
getModuleInfo: new SyncHook(),
|
|
1542
|
-
createScript: new SyncHook()
|
|
1543
|
-
});
|
|
1544
|
-
this.loadingShare = {};
|
|
1545
|
-
// TODO: Validate the details of the options
|
|
1546
|
-
// Initialize options with default values
|
|
1547
|
-
const defaultOptions = {
|
|
1548
|
-
id: share.getBuilderId(),
|
|
1549
|
-
name: userOptions.name,
|
|
1550
|
-
plugins: [
|
|
1551
|
-
snapshotPlugin(),
|
|
1552
|
-
generatePreloadAssetsPlugin()
|
|
1553
|
-
],
|
|
1554
|
-
remotes: [],
|
|
1555
|
-
shared: {},
|
|
1556
|
-
inBrowser: share.isBrowserEnv()
|
|
1557
|
-
};
|
|
1558
|
-
this.name = userOptions.name;
|
|
1559
|
-
this.options = defaultOptions;
|
|
1560
|
-
this.snapshotHandler = new SnapshotHandler(this);
|
|
1561
|
-
this.registerPlugins([
|
|
1562
|
-
...defaultOptions.plugins,
|
|
1563
|
-
...userOptions.plugins || []
|
|
1564
|
-
]);
|
|
1565
|
-
this.options = this.formatOptions(defaultOptions, userOptions);
|
|
1566
|
-
}
|
|
1567
|
-
}
|
|
1568
|
-
|
|
1569
|
-
let FederationInstance = null;
|
|
1570
|
-
function init(options) {
|
|
1571
|
-
// Retrieve the same instance with the same name
|
|
1572
|
-
const instance = share.getGlobalFederationInstance(options.name, options.version);
|
|
1573
|
-
if (!instance) {
|
|
1574
|
-
// Retrieve debug constructor
|
|
1575
|
-
const FederationConstructor = share.getGlobalFederationConstructor() || FederationHost;
|
|
1576
|
-
FederationInstance = new FederationConstructor(options);
|
|
1577
|
-
share.setGlobalFederationInstance(FederationInstance);
|
|
1578
|
-
return FederationInstance;
|
|
1579
|
-
} else {
|
|
1580
|
-
// Merge options
|
|
1581
|
-
instance.initOptions(options);
|
|
1582
|
-
return instance;
|
|
1583
|
-
}
|
|
1584
|
-
}
|
|
1585
|
-
function loadRemote(...args) {
|
|
1586
|
-
share.assert(FederationInstance, 'Please call init first');
|
|
1587
|
-
// eslint-disable-next-line prefer-spread
|
|
1588
|
-
return FederationInstance.loadRemote.apply(FederationInstance, args);
|
|
1589
|
-
}
|
|
1590
|
-
function loadShare(...args) {
|
|
1591
|
-
share.assert(FederationInstance, 'Please call init first');
|
|
1592
|
-
// eslint-disable-next-line prefer-spread
|
|
1593
|
-
return FederationInstance.loadShare.apply(FederationInstance, args);
|
|
1594
|
-
}
|
|
1595
|
-
function loadShareSync(...args) {
|
|
1596
|
-
share.assert(FederationInstance, 'Please call init first');
|
|
1597
|
-
// eslint-disable-next-line prefer-spread
|
|
1598
|
-
return FederationInstance.loadShareSync.apply(FederationInstance, args);
|
|
1599
|
-
}
|
|
1600
|
-
function preloadRemote(...args) {
|
|
1601
|
-
share.assert(FederationInstance, 'Please call init first');
|
|
1602
|
-
// eslint-disable-next-line prefer-spread
|
|
1603
|
-
return FederationInstance.preloadRemote.apply(FederationInstance, args);
|
|
1604
|
-
}
|
|
1605
|
-
// Inject for debug
|
|
1606
|
-
share.setGlobalFederationConstructor(FederationHost);
|
|
1607
|
-
|
|
1608
|
-
exports.registerGlobalPlugins = share.registerGlobalPlugins;
|
|
1609
|
-
exports.FederationHost = FederationHost;
|
|
1610
|
-
exports.init = init;
|
|
1611
|
-
exports.loadRemote = loadRemote;
|
|
1612
|
-
exports.loadShare = loadShare;
|
|
1613
|
-
exports.loadShareSync = loadShareSync;
|
|
1614
|
-
exports.preloadRemote = preloadRemote;
|