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