@module-federation/runtime 0.3.5 → 0.5.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/dist/index.cjs.js +135 -124
- package/dist/index.esm.js +141 -130
- package/dist/package.json +9 -1
- package/dist/retry-plugin.cjs.d.ts +2 -0
- package/dist/retry-plugin.cjs.js +68 -0
- package/dist/retry-plugin.esm.js +66 -0
- package/dist/share.cjs.js +2 -2
- package/dist/share.esm.js +2 -2
- package/dist/src/core.d.ts +1 -0
- package/dist/src/plugins/retry-plugin.d.ts +9 -0
- package/dist/src/remote/index.d.ts +6 -1
- package/dist/src/type/config.d.ts +1 -0
- package/dist/src/utils/load.d.ts +4 -18
- package/package.json +10 -2
package/dist/index.cjs.js
CHANGED
|
@@ -142,29 +142,80 @@ async function loadEntryScript({ name, globalName, entry, createScriptHook }) {
|
|
|
142
142
|
if (remoteEntryExports) {
|
|
143
143
|
return remoteEntryExports;
|
|
144
144
|
}
|
|
145
|
-
if (typeof document === 'undefined') {
|
|
146
|
-
return sdk.loadScriptNode(entry, {
|
|
147
|
-
attrs: {
|
|
148
|
-
name,
|
|
149
|
-
globalName
|
|
150
|
-
},
|
|
151
|
-
createScriptHook
|
|
152
|
-
}).then(()=>{
|
|
153
|
-
const { remoteEntryKey, entryExports } = share.getRemoteEntryExports(name, globalName);
|
|
154
|
-
share.assert(entryExports, `
|
|
155
|
-
Unable to use the ${name}'s '${entry}' URL with ${remoteEntryKey}'s globalName to get remoteEntry exports.
|
|
156
|
-
Possible reasons could be:\n
|
|
157
|
-
1. '${entry}' is not the correct URL, or the remoteEntry resource or name is incorrect.\n
|
|
158
|
-
2. ${remoteEntryKey} cannot be used to get remoteEntry exports in the window object.
|
|
159
|
-
`);
|
|
160
|
-
return entryExports;
|
|
161
|
-
}).catch((e)=>{
|
|
162
|
-
throw e;
|
|
163
|
-
});
|
|
164
|
-
}
|
|
165
145
|
return sdk.loadScript(entry, {
|
|
166
146
|
attrs: {},
|
|
167
|
-
createScriptHook
|
|
147
|
+
createScriptHook: (url, attrs)=>{
|
|
148
|
+
const res = createScriptHook.emit({
|
|
149
|
+
url,
|
|
150
|
+
attrs
|
|
151
|
+
});
|
|
152
|
+
if (!res) return;
|
|
153
|
+
if (res instanceof HTMLScriptElement) {
|
|
154
|
+
return res;
|
|
155
|
+
}
|
|
156
|
+
if ('script' in res || 'timeout' in res) {
|
|
157
|
+
return res;
|
|
158
|
+
}
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
}).then(()=>{
|
|
162
|
+
const { remoteEntryKey, entryExports } = share.getRemoteEntryExports(name, globalName);
|
|
163
|
+
share.assert(entryExports, `
|
|
164
|
+
Unable to use the ${name}'s '${entry}' URL with ${remoteEntryKey}'s globalName to get remoteEntry exports.
|
|
165
|
+
Possible reasons could be:\n
|
|
166
|
+
1. '${entry}' is not the correct URL, or the remoteEntry resource or name is incorrect.\n
|
|
167
|
+
2. ${remoteEntryKey} cannot be used to get remoteEntry exports in the window object.
|
|
168
|
+
`);
|
|
169
|
+
return entryExports;
|
|
170
|
+
}).catch((e)=>{
|
|
171
|
+
throw e;
|
|
172
|
+
});
|
|
173
|
+
}
|
|
174
|
+
async function loadEntryDom({ remoteInfo, remoteEntryExports, createScriptHook }) {
|
|
175
|
+
const { entry, entryGlobalName: globalName, name, type } = remoteInfo;
|
|
176
|
+
switch(type){
|
|
177
|
+
case 'esm':
|
|
178
|
+
case 'module':
|
|
179
|
+
return loadEsmEntry({
|
|
180
|
+
entry,
|
|
181
|
+
remoteEntryExports
|
|
182
|
+
});
|
|
183
|
+
case 'system':
|
|
184
|
+
return loadSystemJsEntry({
|
|
185
|
+
entry,
|
|
186
|
+
remoteEntryExports
|
|
187
|
+
});
|
|
188
|
+
default:
|
|
189
|
+
return loadEntryScript({
|
|
190
|
+
entry,
|
|
191
|
+
globalName,
|
|
192
|
+
name,
|
|
193
|
+
createScriptHook
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
async function loadEntryNode({ remoteInfo, createScriptHook }) {
|
|
198
|
+
const { entry, entryGlobalName: globalName, name } = remoteInfo;
|
|
199
|
+
const { entryExports: remoteEntryExports } = share.getRemoteEntryExports(name, globalName);
|
|
200
|
+
if (remoteEntryExports) {
|
|
201
|
+
return remoteEntryExports;
|
|
202
|
+
}
|
|
203
|
+
return sdk.loadScriptNode(entry, {
|
|
204
|
+
attrs: {
|
|
205
|
+
name,
|
|
206
|
+
globalName
|
|
207
|
+
},
|
|
208
|
+
createScriptHook: (url, attrs)=>{
|
|
209
|
+
const res = createScriptHook.emit({
|
|
210
|
+
url,
|
|
211
|
+
attrs
|
|
212
|
+
});
|
|
213
|
+
if (!res) return;
|
|
214
|
+
if ('url' in res) {
|
|
215
|
+
return res;
|
|
216
|
+
}
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
168
219
|
}).then(()=>{
|
|
169
220
|
const { remoteEntryKey, entryExports } = share.getRemoteEntryExports(name, globalName);
|
|
170
221
|
share.assert(entryExports, `
|
|
@@ -182,33 +233,33 @@ function getRemoteEntryUniqueKey(remoteInfo) {
|
|
|
182
233
|
const { entry, name } = remoteInfo;
|
|
183
234
|
return sdk.composeKeyWithSeparator(name, entry);
|
|
184
235
|
}
|
|
185
|
-
async function getRemoteEntry({ remoteEntryExports, remoteInfo
|
|
186
|
-
const { entry, name, type, entryGlobalName } = remoteInfo;
|
|
236
|
+
async function getRemoteEntry({ origin, remoteEntryExports, remoteInfo }) {
|
|
187
237
|
const uniqueKey = getRemoteEntryUniqueKey(remoteInfo);
|
|
188
238
|
if (remoteEntryExports) {
|
|
189
239
|
return remoteEntryExports;
|
|
190
240
|
}
|
|
191
241
|
if (!share.globalLoading[uniqueKey]) {
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
entry,
|
|
198
|
-
remoteEntryExports
|
|
199
|
-
});
|
|
200
|
-
} else if (type === 'system') {
|
|
201
|
-
share.globalLoading[uniqueKey] = loadSystemJsEntry({
|
|
202
|
-
entry,
|
|
242
|
+
const loadEntryHook = origin.remoteHandler.hooks.lifecycle.loadEntry;
|
|
243
|
+
if (loadEntryHook.listeners.size) {
|
|
244
|
+
share.globalLoading[uniqueKey] = loadEntryHook.emit({
|
|
245
|
+
createScriptHook: origin.loaderHook.lifecycle.createScript,
|
|
246
|
+
remoteInfo,
|
|
203
247
|
remoteEntryExports
|
|
204
|
-
});
|
|
248
|
+
}).then((res)=>res || undefined);
|
|
205
249
|
} else {
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
250
|
+
const createScriptHook = origin.loaderHook.lifecycle.createScript;
|
|
251
|
+
if (!sdk.isBrowserEnv()) {
|
|
252
|
+
share.globalLoading[uniqueKey] = loadEntryNode({
|
|
253
|
+
remoteInfo,
|
|
254
|
+
createScriptHook
|
|
255
|
+
});
|
|
256
|
+
} else {
|
|
257
|
+
share.globalLoading[uniqueKey] = loadEntryDom({
|
|
258
|
+
remoteInfo,
|
|
259
|
+
remoteEntryExports,
|
|
260
|
+
createScriptHook
|
|
261
|
+
});
|
|
262
|
+
}
|
|
212
263
|
}
|
|
213
264
|
}
|
|
214
265
|
return share.globalLoading[uniqueKey];
|
|
@@ -243,26 +294,9 @@ let Module = class Module {
|
|
|
243
294
|
}
|
|
244
295
|
// Get remoteEntry.js
|
|
245
296
|
const remoteEntryExports = await getRemoteEntry({
|
|
297
|
+
origin: this.host,
|
|
246
298
|
remoteInfo: this.remoteInfo,
|
|
247
|
-
remoteEntryExports: this.remoteEntryExports
|
|
248
|
-
createScriptHook: (url, attrs)=>{
|
|
249
|
-
const res = this.host.loaderHook.lifecycle.createScript.emit({
|
|
250
|
-
url,
|
|
251
|
-
attrs
|
|
252
|
-
});
|
|
253
|
-
if (!res) return;
|
|
254
|
-
if (typeof document === 'undefined') {
|
|
255
|
-
//todo: needs real fix
|
|
256
|
-
return res;
|
|
257
|
-
}
|
|
258
|
-
if (res instanceof HTMLScriptElement) {
|
|
259
|
-
return res;
|
|
260
|
-
}
|
|
261
|
-
if ('script' in res || 'timeout' in res) {
|
|
262
|
-
return res;
|
|
263
|
-
}
|
|
264
|
-
return;
|
|
265
|
-
}
|
|
299
|
+
remoteEntryExports: this.remoteEntryExports
|
|
266
300
|
});
|
|
267
301
|
share.assert(remoteEntryExports, `remoteEntryExports is undefined \n ${share.safeToString(this.remoteInfo)}`);
|
|
268
302
|
this.remoteEntryExports = remoteEntryExports;
|
|
@@ -300,6 +334,9 @@ let Module = class Module {
|
|
|
300
334
|
remoteInfo: this.remoteInfo,
|
|
301
335
|
origin: this.host
|
|
302
336
|
});
|
|
337
|
+
if (typeof (remoteEntryExports == null ? void 0 : remoteEntryExports.init) === 'undefined') {
|
|
338
|
+
console.error('The remote entry interface does not contain "init"', '\n', 'Ensure the name of this remote is not reserved or in use. Check if anything already exists on window[nameOfRemote]', '\n', 'Ensure that window[nameOfRemote] is returning a {get,init} object.');
|
|
339
|
+
}
|
|
303
340
|
await remoteEntryExports.init(initContainerOptions.shareScope, initContainerOptions.initScope, initContainerOptions.remoteEntryInitOptions);
|
|
304
341
|
await this.host.hooks.lifecycle.initContainer.emit(_extends$6({}, initContainerOptions, {
|
|
305
342
|
remoteEntryExports
|
|
@@ -595,65 +632,33 @@ useLinkPreload = true) {
|
|
|
595
632
|
const module = host.moduleCache.get(remoteInfo.name);
|
|
596
633
|
if (module) {
|
|
597
634
|
getRemoteEntry({
|
|
635
|
+
origin: host,
|
|
598
636
|
remoteInfo: moduleInfo,
|
|
599
|
-
remoteEntryExports: module.remoteEntryExports
|
|
600
|
-
createScriptHook: (url, attrs)=>{
|
|
601
|
-
const res = host.loaderHook.lifecycle.createScript.emit({
|
|
602
|
-
url,
|
|
603
|
-
attrs
|
|
604
|
-
});
|
|
605
|
-
if (!res) return;
|
|
606
|
-
if (typeof document === 'undefined') {
|
|
607
|
-
//todo: needs real fix
|
|
608
|
-
return res;
|
|
609
|
-
}
|
|
610
|
-
if (res instanceof HTMLScriptElement) {
|
|
611
|
-
return res;
|
|
612
|
-
}
|
|
613
|
-
if ('script' in res || 'timeout' in res) {
|
|
614
|
-
return res;
|
|
615
|
-
}
|
|
616
|
-
return;
|
|
617
|
-
}
|
|
637
|
+
remoteEntryExports: module.remoteEntryExports
|
|
618
638
|
});
|
|
619
639
|
} else {
|
|
620
640
|
getRemoteEntry({
|
|
641
|
+
origin: host,
|
|
621
642
|
remoteInfo: moduleInfo,
|
|
622
|
-
remoteEntryExports: undefined
|
|
623
|
-
createScriptHook: (url, attrs)=>{
|
|
624
|
-
const res = host.loaderHook.lifecycle.createScript.emit({
|
|
625
|
-
url,
|
|
626
|
-
attrs
|
|
627
|
-
});
|
|
628
|
-
if (!res) return;
|
|
629
|
-
if (typeof document === 'undefined') {
|
|
630
|
-
//todo: needs real fix
|
|
631
|
-
return res;
|
|
632
|
-
}
|
|
633
|
-
if (res instanceof HTMLScriptElement) {
|
|
634
|
-
return res;
|
|
635
|
-
}
|
|
636
|
-
if ('script' in res || 'timeout' in res) {
|
|
637
|
-
return res;
|
|
638
|
-
}
|
|
639
|
-
return;
|
|
640
|
-
}
|
|
643
|
+
remoteEntryExports: undefined
|
|
641
644
|
});
|
|
642
645
|
}
|
|
643
646
|
});
|
|
644
647
|
if (useLinkPreload) {
|
|
648
|
+
const defaultAttrs = {
|
|
649
|
+
rel: 'preload',
|
|
650
|
+
as: 'style',
|
|
651
|
+
crossorigin: 'anonymous'
|
|
652
|
+
};
|
|
645
653
|
cssAssets.forEach((cssUrl)=>{
|
|
646
654
|
const { link: cssEl, needAttach } = sdk.createLink({
|
|
647
655
|
url: cssUrl,
|
|
648
656
|
cb: ()=>{},
|
|
649
|
-
attrs:
|
|
650
|
-
|
|
651
|
-
as: 'style',
|
|
652
|
-
crossorigin: 'anonymous'
|
|
653
|
-
},
|
|
654
|
-
createLinkHook: (url)=>{
|
|
657
|
+
attrs: defaultAttrs,
|
|
658
|
+
createLinkHook: (url, attrs)=>{
|
|
655
659
|
const res = host.loaderHook.lifecycle.createLink.emit({
|
|
656
|
-
url
|
|
660
|
+
url,
|
|
661
|
+
attrs
|
|
657
662
|
});
|
|
658
663
|
if (res instanceof HTMLLinkElement) {
|
|
659
664
|
return res;
|
|
@@ -664,17 +669,19 @@ useLinkPreload = true) {
|
|
|
664
669
|
needAttach && document.head.appendChild(cssEl);
|
|
665
670
|
});
|
|
666
671
|
} else {
|
|
672
|
+
const defaultAttrs = {
|
|
673
|
+
rel: 'stylesheet',
|
|
674
|
+
type: 'text/css'
|
|
675
|
+
};
|
|
667
676
|
cssAssets.forEach((cssUrl)=>{
|
|
668
677
|
const { link: cssEl, needAttach } = sdk.createLink({
|
|
669
678
|
url: cssUrl,
|
|
670
679
|
cb: ()=>{},
|
|
671
|
-
attrs:
|
|
672
|
-
|
|
673
|
-
type: 'text/css'
|
|
674
|
-
},
|
|
675
|
-
createLinkHook: (url)=>{
|
|
680
|
+
attrs: defaultAttrs,
|
|
681
|
+
createLinkHook: (url, attrs)=>{
|
|
676
682
|
const res = host.loaderHook.lifecycle.createLink.emit({
|
|
677
|
-
url
|
|
683
|
+
url,
|
|
684
|
+
attrs
|
|
678
685
|
});
|
|
679
686
|
if (res instanceof HTMLLinkElement) {
|
|
680
687
|
return res;
|
|
@@ -687,18 +694,20 @@ useLinkPreload = true) {
|
|
|
687
694
|
});
|
|
688
695
|
}
|
|
689
696
|
if (useLinkPreload) {
|
|
697
|
+
const defaultAttrs = {
|
|
698
|
+
rel: 'preload',
|
|
699
|
+
as: 'script',
|
|
700
|
+
crossorigin: 'anonymous'
|
|
701
|
+
};
|
|
690
702
|
jsAssetsWithoutEntry.forEach((jsUrl)=>{
|
|
691
703
|
const { link: linkEl, needAttach } = sdk.createLink({
|
|
692
704
|
url: jsUrl,
|
|
693
705
|
cb: ()=>{},
|
|
694
|
-
attrs:
|
|
695
|
-
|
|
696
|
-
as: 'script',
|
|
697
|
-
crossorigin: 'anonymous'
|
|
698
|
-
},
|
|
699
|
-
createLinkHook: (url)=>{
|
|
706
|
+
attrs: defaultAttrs,
|
|
707
|
+
createLinkHook: (url, attrs)=>{
|
|
700
708
|
const res = host.loaderHook.lifecycle.createLink.emit({
|
|
701
|
-
url
|
|
709
|
+
url,
|
|
710
|
+
attrs
|
|
702
711
|
});
|
|
703
712
|
if (res instanceof HTMLLinkElement) {
|
|
704
713
|
return res;
|
|
@@ -709,14 +718,15 @@ useLinkPreload = true) {
|
|
|
709
718
|
needAttach && document.head.appendChild(linkEl);
|
|
710
719
|
});
|
|
711
720
|
} else {
|
|
721
|
+
const defaultAttrs = {
|
|
722
|
+
fetchpriority: 'high',
|
|
723
|
+
type: (remoteInfo == null ? void 0 : remoteInfo.type) === 'module' ? 'module' : 'text/javascript'
|
|
724
|
+
};
|
|
712
725
|
jsAssetsWithoutEntry.forEach((jsUrl)=>{
|
|
713
726
|
const { script: scriptEl, needAttach } = sdk.createScript({
|
|
714
727
|
url: jsUrl,
|
|
715
728
|
cb: ()=>{},
|
|
716
|
-
attrs:
|
|
717
|
-
fetchpriority: 'high',
|
|
718
|
-
type: (remoteInfo == null ? void 0 : remoteInfo.type) === 'module' ? 'module' : 'text/javascript'
|
|
719
|
-
},
|
|
729
|
+
attrs: defaultAttrs,
|
|
720
730
|
createScriptHook: (url, attrs)=>{
|
|
721
731
|
const res = host.loaderHook.lifecycle.createScript.emit({
|
|
722
732
|
url,
|
|
@@ -1940,7 +1950,8 @@ class RemoteHandler {
|
|
|
1940
1950
|
beforePreloadRemote: new AsyncHook('beforePreloadRemote'),
|
|
1941
1951
|
generatePreloadAssets: new AsyncHook('generatePreloadAssets'),
|
|
1942
1952
|
// not used yet
|
|
1943
|
-
afterPreloadRemote: new AsyncHook()
|
|
1953
|
+
afterPreloadRemote: new AsyncHook(),
|
|
1954
|
+
loadEntry: new AsyncHook()
|
|
1944
1955
|
});
|
|
1945
1956
|
this.host = host;
|
|
1946
1957
|
this.idToRemoteMap = {};
|
|
@@ -2066,7 +2077,7 @@ class FederationHost {
|
|
|
2066
2077
|
// maybe will change, temporarily for internal use only
|
|
2067
2078
|
initContainer: new AsyncWaterfallHook('initContainer')
|
|
2068
2079
|
});
|
|
2069
|
-
this.version = "0.
|
|
2080
|
+
this.version = "0.5.0";
|
|
2070
2081
|
this.moduleCache = new Map();
|
|
2071
2082
|
this.loaderHook = new PluginSystem({
|
|
2072
2083
|
// FIXME: may not be suitable , not open to the public yet
|
package/dist/index.esm.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { g as getGlobalHostPlugins, a as globalLoading, D as DEFAULT_REMOTE_TYPE, b as DEFAULT_SCOPE, c as getRemoteEntryExports, d as assert, s as safeToString, e as getFMId, i as isObject, f as error, w as warn, h as isPlainObject, j as isRemoteInfoWithEntry, k as isPureRemoteEntry, l as getRemoteEntryInfoFromSnapshot, m as isBrowserEnv, n as getInfoWithoutType, o as getPreloaded, p as setPreloaded, q as getRegisteredShare, r as arrayOptions, t as getGlobalSnapshotInfoByModuleInfo, u as addGlobalSnapshot, v as setGlobalSnapshotInfoByModuleInfo, G as Global, x as getGlobalSnapshot, y as formatShareConfigs, z as getTargetSharedOptions, A as getGlobalShareScope, B as addUniqueItem, C as getBuilderId, E as setGlobalFederationConstructor, F as getGlobalFederationInstance, H as getGlobalFederationConstructor, I as setGlobalFederationInstance } from './share.esm.js';
|
|
1
|
+
import { g as getGlobalHostPlugins, a as globalLoading, D as DEFAULT_REMOTE_TYPE, b as DEFAULT_SCOPE, c as getRemoteEntryExports, d as assert, s as safeToString, e as getFMId, i as isObject, f as error, w as warn, h as isPlainObject, j as isRemoteInfoWithEntry, k as isPureRemoteEntry, l as getRemoteEntryInfoFromSnapshot, m as isBrowserEnv$1, n as getInfoWithoutType, o as getPreloaded, p as setPreloaded, q as getRegisteredShare, r as arrayOptions, t as getGlobalSnapshotInfoByModuleInfo, u as addGlobalSnapshot, v as setGlobalSnapshotInfoByModuleInfo, G as Global, x as getGlobalSnapshot, y as formatShareConfigs, z as getTargetSharedOptions, A as getGlobalShareScope, B as addUniqueItem, C as getBuilderId, E as setGlobalFederationConstructor, F as getGlobalFederationInstance, H as getGlobalFederationConstructor, I as setGlobalFederationInstance } from './share.esm.js';
|
|
2
2
|
export { J as registerGlobalPlugins } from './share.esm.js';
|
|
3
|
-
import {
|
|
3
|
+
import { isBrowserEnv, loadScriptNode, composeKeyWithSeparator, loadScript, createLink, createScript, getResourceUrl, isManifestProvider, generateSnapshotFromManifest, warn as warn$1 } from '@module-federation/sdk';
|
|
4
4
|
export { loadScript, loadScriptNode } from '@module-federation/sdk';
|
|
5
5
|
|
|
6
6
|
// Function to match a remote with its name and expose
|
|
@@ -140,29 +140,80 @@ async function loadEntryScript({ name, globalName, entry, createScriptHook }) {
|
|
|
140
140
|
if (remoteEntryExports) {
|
|
141
141
|
return remoteEntryExports;
|
|
142
142
|
}
|
|
143
|
-
if (typeof document === 'undefined') {
|
|
144
|
-
return loadScriptNode(entry, {
|
|
145
|
-
attrs: {
|
|
146
|
-
name,
|
|
147
|
-
globalName
|
|
148
|
-
},
|
|
149
|
-
createScriptHook
|
|
150
|
-
}).then(()=>{
|
|
151
|
-
const { remoteEntryKey, entryExports } = getRemoteEntryExports(name, globalName);
|
|
152
|
-
assert(entryExports, `
|
|
153
|
-
Unable to use the ${name}'s '${entry}' URL with ${remoteEntryKey}'s globalName to get remoteEntry exports.
|
|
154
|
-
Possible reasons could be:\n
|
|
155
|
-
1. '${entry}' is not the correct URL, or the remoteEntry resource or name is incorrect.\n
|
|
156
|
-
2. ${remoteEntryKey} cannot be used to get remoteEntry exports in the window object.
|
|
157
|
-
`);
|
|
158
|
-
return entryExports;
|
|
159
|
-
}).catch((e)=>{
|
|
160
|
-
throw e;
|
|
161
|
-
});
|
|
162
|
-
}
|
|
163
143
|
return loadScript(entry, {
|
|
164
144
|
attrs: {},
|
|
165
|
-
createScriptHook
|
|
145
|
+
createScriptHook: (url, attrs)=>{
|
|
146
|
+
const res = createScriptHook.emit({
|
|
147
|
+
url,
|
|
148
|
+
attrs
|
|
149
|
+
});
|
|
150
|
+
if (!res) return;
|
|
151
|
+
if (res instanceof HTMLScriptElement) {
|
|
152
|
+
return res;
|
|
153
|
+
}
|
|
154
|
+
if ('script' in res || 'timeout' in res) {
|
|
155
|
+
return res;
|
|
156
|
+
}
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
}).then(()=>{
|
|
160
|
+
const { remoteEntryKey, entryExports } = getRemoteEntryExports(name, globalName);
|
|
161
|
+
assert(entryExports, `
|
|
162
|
+
Unable to use the ${name}'s '${entry}' URL with ${remoteEntryKey}'s globalName to get remoteEntry exports.
|
|
163
|
+
Possible reasons could be:\n
|
|
164
|
+
1. '${entry}' is not the correct URL, or the remoteEntry resource or name is incorrect.\n
|
|
165
|
+
2. ${remoteEntryKey} cannot be used to get remoteEntry exports in the window object.
|
|
166
|
+
`);
|
|
167
|
+
return entryExports;
|
|
168
|
+
}).catch((e)=>{
|
|
169
|
+
throw e;
|
|
170
|
+
});
|
|
171
|
+
}
|
|
172
|
+
async function loadEntryDom({ remoteInfo, remoteEntryExports, createScriptHook }) {
|
|
173
|
+
const { entry, entryGlobalName: globalName, name, type } = remoteInfo;
|
|
174
|
+
switch(type){
|
|
175
|
+
case 'esm':
|
|
176
|
+
case 'module':
|
|
177
|
+
return loadEsmEntry({
|
|
178
|
+
entry,
|
|
179
|
+
remoteEntryExports
|
|
180
|
+
});
|
|
181
|
+
case 'system':
|
|
182
|
+
return loadSystemJsEntry({
|
|
183
|
+
entry,
|
|
184
|
+
remoteEntryExports
|
|
185
|
+
});
|
|
186
|
+
default:
|
|
187
|
+
return loadEntryScript({
|
|
188
|
+
entry,
|
|
189
|
+
globalName,
|
|
190
|
+
name,
|
|
191
|
+
createScriptHook
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
async function loadEntryNode({ remoteInfo, createScriptHook }) {
|
|
196
|
+
const { entry, entryGlobalName: globalName, name } = remoteInfo;
|
|
197
|
+
const { entryExports: remoteEntryExports } = getRemoteEntryExports(name, globalName);
|
|
198
|
+
if (remoteEntryExports) {
|
|
199
|
+
return remoteEntryExports;
|
|
200
|
+
}
|
|
201
|
+
return loadScriptNode(entry, {
|
|
202
|
+
attrs: {
|
|
203
|
+
name,
|
|
204
|
+
globalName
|
|
205
|
+
},
|
|
206
|
+
createScriptHook: (url, attrs)=>{
|
|
207
|
+
const res = createScriptHook.emit({
|
|
208
|
+
url,
|
|
209
|
+
attrs
|
|
210
|
+
});
|
|
211
|
+
if (!res) return;
|
|
212
|
+
if ('url' in res) {
|
|
213
|
+
return res;
|
|
214
|
+
}
|
|
215
|
+
return;
|
|
216
|
+
}
|
|
166
217
|
}).then(()=>{
|
|
167
218
|
const { remoteEntryKey, entryExports } = getRemoteEntryExports(name, globalName);
|
|
168
219
|
assert(entryExports, `
|
|
@@ -180,33 +231,33 @@ function getRemoteEntryUniqueKey(remoteInfo) {
|
|
|
180
231
|
const { entry, name } = remoteInfo;
|
|
181
232
|
return composeKeyWithSeparator(name, entry);
|
|
182
233
|
}
|
|
183
|
-
async function getRemoteEntry({ remoteEntryExports, remoteInfo
|
|
184
|
-
const { entry, name, type, entryGlobalName } = remoteInfo;
|
|
234
|
+
async function getRemoteEntry({ origin, remoteEntryExports, remoteInfo }) {
|
|
185
235
|
const uniqueKey = getRemoteEntryUniqueKey(remoteInfo);
|
|
186
236
|
if (remoteEntryExports) {
|
|
187
237
|
return remoteEntryExports;
|
|
188
238
|
}
|
|
189
239
|
if (!globalLoading[uniqueKey]) {
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
entry,
|
|
196
|
-
remoteEntryExports
|
|
197
|
-
});
|
|
198
|
-
} else if (type === 'system') {
|
|
199
|
-
globalLoading[uniqueKey] = loadSystemJsEntry({
|
|
200
|
-
entry,
|
|
240
|
+
const loadEntryHook = origin.remoteHandler.hooks.lifecycle.loadEntry;
|
|
241
|
+
if (loadEntryHook.listeners.size) {
|
|
242
|
+
globalLoading[uniqueKey] = loadEntryHook.emit({
|
|
243
|
+
createScriptHook: origin.loaderHook.lifecycle.createScript,
|
|
244
|
+
remoteInfo,
|
|
201
245
|
remoteEntryExports
|
|
202
|
-
});
|
|
246
|
+
}).then((res)=>res || undefined);
|
|
203
247
|
} else {
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
248
|
+
const createScriptHook = origin.loaderHook.lifecycle.createScript;
|
|
249
|
+
if (!isBrowserEnv()) {
|
|
250
|
+
globalLoading[uniqueKey] = loadEntryNode({
|
|
251
|
+
remoteInfo,
|
|
252
|
+
createScriptHook
|
|
253
|
+
});
|
|
254
|
+
} else {
|
|
255
|
+
globalLoading[uniqueKey] = loadEntryDom({
|
|
256
|
+
remoteInfo,
|
|
257
|
+
remoteEntryExports,
|
|
258
|
+
createScriptHook
|
|
259
|
+
});
|
|
260
|
+
}
|
|
210
261
|
}
|
|
211
262
|
}
|
|
212
263
|
return globalLoading[uniqueKey];
|
|
@@ -241,26 +292,9 @@ let Module = class Module {
|
|
|
241
292
|
}
|
|
242
293
|
// Get remoteEntry.js
|
|
243
294
|
const remoteEntryExports = await getRemoteEntry({
|
|
295
|
+
origin: this.host,
|
|
244
296
|
remoteInfo: this.remoteInfo,
|
|
245
|
-
remoteEntryExports: this.remoteEntryExports
|
|
246
|
-
createScriptHook: (url, attrs)=>{
|
|
247
|
-
const res = this.host.loaderHook.lifecycle.createScript.emit({
|
|
248
|
-
url,
|
|
249
|
-
attrs
|
|
250
|
-
});
|
|
251
|
-
if (!res) return;
|
|
252
|
-
if (typeof document === 'undefined') {
|
|
253
|
-
//todo: needs real fix
|
|
254
|
-
return res;
|
|
255
|
-
}
|
|
256
|
-
if (res instanceof HTMLScriptElement) {
|
|
257
|
-
return res;
|
|
258
|
-
}
|
|
259
|
-
if ('script' in res || 'timeout' in res) {
|
|
260
|
-
return res;
|
|
261
|
-
}
|
|
262
|
-
return;
|
|
263
|
-
}
|
|
297
|
+
remoteEntryExports: this.remoteEntryExports
|
|
264
298
|
});
|
|
265
299
|
assert(remoteEntryExports, `remoteEntryExports is undefined \n ${safeToString(this.remoteInfo)}`);
|
|
266
300
|
this.remoteEntryExports = remoteEntryExports;
|
|
@@ -298,6 +332,9 @@ let Module = class Module {
|
|
|
298
332
|
remoteInfo: this.remoteInfo,
|
|
299
333
|
origin: this.host
|
|
300
334
|
});
|
|
335
|
+
if (typeof (remoteEntryExports == null ? void 0 : remoteEntryExports.init) === 'undefined') {
|
|
336
|
+
console.error('The remote entry interface does not contain "init"', '\n', 'Ensure the name of this remote is not reserved or in use. Check if anything already exists on window[nameOfRemote]', '\n', 'Ensure that window[nameOfRemote] is returning a {get,init} object.');
|
|
337
|
+
}
|
|
301
338
|
await remoteEntryExports.init(initContainerOptions.shareScope, initContainerOptions.initScope, initContainerOptions.remoteEntryInitOptions);
|
|
302
339
|
await this.host.hooks.lifecycle.initContainer.emit(_extends$6({}, initContainerOptions, {
|
|
303
340
|
remoteEntryExports
|
|
@@ -593,65 +630,33 @@ useLinkPreload = true) {
|
|
|
593
630
|
const module = host.moduleCache.get(remoteInfo.name);
|
|
594
631
|
if (module) {
|
|
595
632
|
getRemoteEntry({
|
|
633
|
+
origin: host,
|
|
596
634
|
remoteInfo: moduleInfo,
|
|
597
|
-
remoteEntryExports: module.remoteEntryExports
|
|
598
|
-
createScriptHook: (url, attrs)=>{
|
|
599
|
-
const res = host.loaderHook.lifecycle.createScript.emit({
|
|
600
|
-
url,
|
|
601
|
-
attrs
|
|
602
|
-
});
|
|
603
|
-
if (!res) return;
|
|
604
|
-
if (typeof document === 'undefined') {
|
|
605
|
-
//todo: needs real fix
|
|
606
|
-
return res;
|
|
607
|
-
}
|
|
608
|
-
if (res instanceof HTMLScriptElement) {
|
|
609
|
-
return res;
|
|
610
|
-
}
|
|
611
|
-
if ('script' in res || 'timeout' in res) {
|
|
612
|
-
return res;
|
|
613
|
-
}
|
|
614
|
-
return;
|
|
615
|
-
}
|
|
635
|
+
remoteEntryExports: module.remoteEntryExports
|
|
616
636
|
});
|
|
617
637
|
} else {
|
|
618
638
|
getRemoteEntry({
|
|
639
|
+
origin: host,
|
|
619
640
|
remoteInfo: moduleInfo,
|
|
620
|
-
remoteEntryExports: undefined
|
|
621
|
-
createScriptHook: (url, attrs)=>{
|
|
622
|
-
const res = host.loaderHook.lifecycle.createScript.emit({
|
|
623
|
-
url,
|
|
624
|
-
attrs
|
|
625
|
-
});
|
|
626
|
-
if (!res) return;
|
|
627
|
-
if (typeof document === 'undefined') {
|
|
628
|
-
//todo: needs real fix
|
|
629
|
-
return res;
|
|
630
|
-
}
|
|
631
|
-
if (res instanceof HTMLScriptElement) {
|
|
632
|
-
return res;
|
|
633
|
-
}
|
|
634
|
-
if ('script' in res || 'timeout' in res) {
|
|
635
|
-
return res;
|
|
636
|
-
}
|
|
637
|
-
return;
|
|
638
|
-
}
|
|
641
|
+
remoteEntryExports: undefined
|
|
639
642
|
});
|
|
640
643
|
}
|
|
641
644
|
});
|
|
642
645
|
if (useLinkPreload) {
|
|
646
|
+
const defaultAttrs = {
|
|
647
|
+
rel: 'preload',
|
|
648
|
+
as: 'style',
|
|
649
|
+
crossorigin: 'anonymous'
|
|
650
|
+
};
|
|
643
651
|
cssAssets.forEach((cssUrl)=>{
|
|
644
652
|
const { link: cssEl, needAttach } = createLink({
|
|
645
653
|
url: cssUrl,
|
|
646
654
|
cb: ()=>{},
|
|
647
|
-
attrs:
|
|
648
|
-
|
|
649
|
-
as: 'style',
|
|
650
|
-
crossorigin: 'anonymous'
|
|
651
|
-
},
|
|
652
|
-
createLinkHook: (url)=>{
|
|
655
|
+
attrs: defaultAttrs,
|
|
656
|
+
createLinkHook: (url, attrs)=>{
|
|
653
657
|
const res = host.loaderHook.lifecycle.createLink.emit({
|
|
654
|
-
url
|
|
658
|
+
url,
|
|
659
|
+
attrs
|
|
655
660
|
});
|
|
656
661
|
if (res instanceof HTMLLinkElement) {
|
|
657
662
|
return res;
|
|
@@ -662,17 +667,19 @@ useLinkPreload = true) {
|
|
|
662
667
|
needAttach && document.head.appendChild(cssEl);
|
|
663
668
|
});
|
|
664
669
|
} else {
|
|
670
|
+
const defaultAttrs = {
|
|
671
|
+
rel: 'stylesheet',
|
|
672
|
+
type: 'text/css'
|
|
673
|
+
};
|
|
665
674
|
cssAssets.forEach((cssUrl)=>{
|
|
666
675
|
const { link: cssEl, needAttach } = createLink({
|
|
667
676
|
url: cssUrl,
|
|
668
677
|
cb: ()=>{},
|
|
669
|
-
attrs:
|
|
670
|
-
|
|
671
|
-
type: 'text/css'
|
|
672
|
-
},
|
|
673
|
-
createLinkHook: (url)=>{
|
|
678
|
+
attrs: defaultAttrs,
|
|
679
|
+
createLinkHook: (url, attrs)=>{
|
|
674
680
|
const res = host.loaderHook.lifecycle.createLink.emit({
|
|
675
|
-
url
|
|
681
|
+
url,
|
|
682
|
+
attrs
|
|
676
683
|
});
|
|
677
684
|
if (res instanceof HTMLLinkElement) {
|
|
678
685
|
return res;
|
|
@@ -685,18 +692,20 @@ useLinkPreload = true) {
|
|
|
685
692
|
});
|
|
686
693
|
}
|
|
687
694
|
if (useLinkPreload) {
|
|
695
|
+
const defaultAttrs = {
|
|
696
|
+
rel: 'preload',
|
|
697
|
+
as: 'script',
|
|
698
|
+
crossorigin: 'anonymous'
|
|
699
|
+
};
|
|
688
700
|
jsAssetsWithoutEntry.forEach((jsUrl)=>{
|
|
689
701
|
const { link: linkEl, needAttach } = createLink({
|
|
690
702
|
url: jsUrl,
|
|
691
703
|
cb: ()=>{},
|
|
692
|
-
attrs:
|
|
693
|
-
|
|
694
|
-
as: 'script',
|
|
695
|
-
crossorigin: 'anonymous'
|
|
696
|
-
},
|
|
697
|
-
createLinkHook: (url)=>{
|
|
704
|
+
attrs: defaultAttrs,
|
|
705
|
+
createLinkHook: (url, attrs)=>{
|
|
698
706
|
const res = host.loaderHook.lifecycle.createLink.emit({
|
|
699
|
-
url
|
|
707
|
+
url,
|
|
708
|
+
attrs
|
|
700
709
|
});
|
|
701
710
|
if (res instanceof HTMLLinkElement) {
|
|
702
711
|
return res;
|
|
@@ -707,14 +716,15 @@ useLinkPreload = true) {
|
|
|
707
716
|
needAttach && document.head.appendChild(linkEl);
|
|
708
717
|
});
|
|
709
718
|
} else {
|
|
719
|
+
const defaultAttrs = {
|
|
720
|
+
fetchpriority: 'high',
|
|
721
|
+
type: (remoteInfo == null ? void 0 : remoteInfo.type) === 'module' ? 'module' : 'text/javascript'
|
|
722
|
+
};
|
|
710
723
|
jsAssetsWithoutEntry.forEach((jsUrl)=>{
|
|
711
724
|
const { script: scriptEl, needAttach } = createScript({
|
|
712
725
|
url: jsUrl,
|
|
713
726
|
cb: ()=>{},
|
|
714
|
-
attrs:
|
|
715
|
-
fetchpriority: 'high',
|
|
716
|
-
type: (remoteInfo == null ? void 0 : remoteInfo.type) === 'module' ? 'module' : 'text/javascript'
|
|
717
|
-
},
|
|
727
|
+
attrs: defaultAttrs,
|
|
718
728
|
createScriptHook: (url, attrs)=>{
|
|
719
729
|
const res = host.loaderHook.lifecycle.createScript.emit({
|
|
720
730
|
url,
|
|
@@ -753,7 +763,7 @@ function assignRemoteInfo(remoteInfo, remoteSnapshot) {
|
|
|
753
763
|
error(`The attribute remoteEntry of ${remoteInfo.name} must not be undefined.`);
|
|
754
764
|
}
|
|
755
765
|
let entryUrl = getResourceUrl(remoteSnapshot, remoteEntryInfo.url);
|
|
756
|
-
if (!isBrowserEnv() && !entryUrl.startsWith('http')) {
|
|
766
|
+
if (!isBrowserEnv$1() && !entryUrl.startsWith('http')) {
|
|
757
767
|
entryUrl = `https:${entryUrl}`;
|
|
758
768
|
}
|
|
759
769
|
remoteInfo.type = remoteEntryInfo.type;
|
|
@@ -1114,7 +1124,7 @@ class SnapshotHandler {
|
|
|
1114
1124
|
// global snapshot includes manifest or module info includes manifest
|
|
1115
1125
|
if (globalRemoteSnapshot) {
|
|
1116
1126
|
if (isManifestProvider(globalRemoteSnapshot)) {
|
|
1117
|
-
const remoteEntry = isBrowserEnv() ? globalRemoteSnapshot.remoteEntry : globalRemoteSnapshot.ssrRemoteEntry || globalRemoteSnapshot.remoteEntry || '';
|
|
1127
|
+
const remoteEntry = isBrowserEnv$1() ? globalRemoteSnapshot.remoteEntry : globalRemoteSnapshot.ssrRemoteEntry || globalRemoteSnapshot.remoteEntry || '';
|
|
1118
1128
|
const moduleSnapshot = await this.getManifestJson(remoteEntry, moduleInfo, {});
|
|
1119
1129
|
// eslint-disable-next-line @typescript-eslint/no-shadow
|
|
1120
1130
|
const globalSnapshotRes = setGlobalSnapshotInfoByModuleInfo(_extends$3({}, moduleInfo, {
|
|
@@ -1785,7 +1795,7 @@ class RemoteHandler {
|
|
|
1785
1795
|
}
|
|
1786
1796
|
// Set the remote entry to a complete path
|
|
1787
1797
|
if ('entry' in remote) {
|
|
1788
|
-
if (isBrowserEnv
|
|
1798
|
+
if (isBrowserEnv() && !remote.entry.startsWith('http')) {
|
|
1789
1799
|
remote.entry = new URL(remote.entry, window.location.origin).href;
|
|
1790
1800
|
}
|
|
1791
1801
|
}
|
|
@@ -1938,7 +1948,8 @@ class RemoteHandler {
|
|
|
1938
1948
|
beforePreloadRemote: new AsyncHook('beforePreloadRemote'),
|
|
1939
1949
|
generatePreloadAssets: new AsyncHook('generatePreloadAssets'),
|
|
1940
1950
|
// not used yet
|
|
1941
|
-
afterPreloadRemote: new AsyncHook()
|
|
1951
|
+
afterPreloadRemote: new AsyncHook(),
|
|
1952
|
+
loadEntry: new AsyncHook()
|
|
1942
1953
|
});
|
|
1943
1954
|
this.host = host;
|
|
1944
1955
|
this.idToRemoteMap = {};
|
|
@@ -2064,7 +2075,7 @@ class FederationHost {
|
|
|
2064
2075
|
// maybe will change, temporarily for internal use only
|
|
2065
2076
|
initContainer: new AsyncWaterfallHook('initContainer')
|
|
2066
2077
|
});
|
|
2067
|
-
this.version = "0.
|
|
2078
|
+
this.version = "0.5.0";
|
|
2068
2079
|
this.moduleCache = new Map();
|
|
2069
2080
|
this.loaderHook = new PluginSystem({
|
|
2070
2081
|
// FIXME: may not be suitable , not open to the public yet
|
|
@@ -2085,7 +2096,7 @@ class FederationHost {
|
|
|
2085
2096
|
],
|
|
2086
2097
|
remotes: [],
|
|
2087
2098
|
shared: {},
|
|
2088
|
-
inBrowser: isBrowserEnv()
|
|
2099
|
+
inBrowser: isBrowserEnv$1()
|
|
2089
2100
|
};
|
|
2090
2101
|
this.name = userOptions.name;
|
|
2091
2102
|
this.options = defaultOptions;
|
package/dist/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@module-federation/runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"author": "zhouxiao <codingzx@gmail.com>",
|
|
5
5
|
"main": "./index.cjs.js",
|
|
6
6
|
"module": "./index.esm.js",
|
|
@@ -29,6 +29,11 @@
|
|
|
29
29
|
"import": "./dist/types.esm.js",
|
|
30
30
|
"require": "./dist/types.cjs.js"
|
|
31
31
|
},
|
|
32
|
+
"./retry-plugin": {
|
|
33
|
+
"types": "./dist/retry-plugin.cjs.d.ts",
|
|
34
|
+
"import": "./dist/retry-plugin.esm.js",
|
|
35
|
+
"require": "./dist/retry-plugin.cjs.js"
|
|
36
|
+
},
|
|
32
37
|
"./*": "./*"
|
|
33
38
|
},
|
|
34
39
|
"typesVersions": {
|
|
@@ -41,6 +46,9 @@
|
|
|
41
46
|
],
|
|
42
47
|
"types": [
|
|
43
48
|
"./dist/types.cjs.d.ts"
|
|
49
|
+
],
|
|
50
|
+
"retry-plugin": [
|
|
51
|
+
"./dist/retry-plugin.cjs.d.ts"
|
|
44
52
|
]
|
|
45
53
|
}
|
|
46
54
|
},
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
function _extends() {
|
|
4
|
+
_extends = Object.assign || function(target) {
|
|
5
|
+
for(var i = 1; i < arguments.length; i++){
|
|
6
|
+
var source = arguments[i];
|
|
7
|
+
for(var key in source){
|
|
8
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
9
|
+
target[key] = source[key];
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
return target;
|
|
14
|
+
};
|
|
15
|
+
return _extends.apply(this, arguments);
|
|
16
|
+
}
|
|
17
|
+
const defaultRetries = 3;
|
|
18
|
+
async function fetchWithRetry({ url, options = {}, retryTimes = defaultRetries, fallbackUrl = '' }) {
|
|
19
|
+
try {
|
|
20
|
+
const response = await fetch(url, options);
|
|
21
|
+
// To prevent the response object from being read multiple times and causing errors, clone it
|
|
22
|
+
const responseClone = response.clone();
|
|
23
|
+
// Network error
|
|
24
|
+
if (!response.ok) {
|
|
25
|
+
throw new Error(`Server error:${response.status}`);
|
|
26
|
+
}
|
|
27
|
+
// parse json error
|
|
28
|
+
await responseClone.json().catch((error)=>{
|
|
29
|
+
throw new Error(`Json parse error: ${error}, url is: ${url}`);
|
|
30
|
+
});
|
|
31
|
+
return response;
|
|
32
|
+
} catch (error) {
|
|
33
|
+
if (retryTimes <= 0) {
|
|
34
|
+
console.log(`>>>>>>>>> retry failed after ${defaultRetries} times for url: ${url}, now will try fallbackUrl url: ${fallbackUrl} <<<<<<<<<`);
|
|
35
|
+
if (fallbackUrl && fallbackUrl !== url) {
|
|
36
|
+
return fetchWithRetry({
|
|
37
|
+
url: fallbackUrl,
|
|
38
|
+
options,
|
|
39
|
+
retryTimes: 1,
|
|
40
|
+
fallbackUrl
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
throw new Error('The request failed three times and has now been abandoned');
|
|
44
|
+
}
|
|
45
|
+
// If there are remaining times, delay 1 second and try again
|
|
46
|
+
await new Promise((resolve)=>setTimeout(resolve, 1000));
|
|
47
|
+
console.log(`Trying again. Number of retries available:${retryTimes - 1}`);
|
|
48
|
+
return await fetchWithRetry({
|
|
49
|
+
url,
|
|
50
|
+
options,
|
|
51
|
+
retryTimes: retryTimes - 1,
|
|
52
|
+
fallbackUrl
|
|
53
|
+
});
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const RetryPlugin = (params)=>({
|
|
57
|
+
name: 'retry-plugin',
|
|
58
|
+
async fetch (url, options) {
|
|
59
|
+
return fetchWithRetry({
|
|
60
|
+
url,
|
|
61
|
+
options: _extends({}, options, params == null ? void 0 : params.options),
|
|
62
|
+
retryTimes: params == null ? void 0 : params.retryTimes,
|
|
63
|
+
fallbackUrl: params == null ? void 0 : params.fallbackUrl
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
module.exports = RetryPlugin;
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
function _extends() {
|
|
2
|
+
_extends = Object.assign || function(target) {
|
|
3
|
+
for(var i = 1; i < arguments.length; i++){
|
|
4
|
+
var source = arguments[i];
|
|
5
|
+
for(var key in source){
|
|
6
|
+
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
|
7
|
+
target[key] = source[key];
|
|
8
|
+
}
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
return target;
|
|
12
|
+
};
|
|
13
|
+
return _extends.apply(this, arguments);
|
|
14
|
+
}
|
|
15
|
+
const defaultRetries = 3;
|
|
16
|
+
async function fetchWithRetry({ url, options = {}, retryTimes = defaultRetries, fallbackUrl = '' }) {
|
|
17
|
+
try {
|
|
18
|
+
const response = await fetch(url, options);
|
|
19
|
+
// To prevent the response object from being read multiple times and causing errors, clone it
|
|
20
|
+
const responseClone = response.clone();
|
|
21
|
+
// Network error
|
|
22
|
+
if (!response.ok) {
|
|
23
|
+
throw new Error(`Server error:${response.status}`);
|
|
24
|
+
}
|
|
25
|
+
// parse json error
|
|
26
|
+
await responseClone.json().catch((error)=>{
|
|
27
|
+
throw new Error(`Json parse error: ${error}, url is: ${url}`);
|
|
28
|
+
});
|
|
29
|
+
return response;
|
|
30
|
+
} catch (error) {
|
|
31
|
+
if (retryTimes <= 0) {
|
|
32
|
+
console.log(`>>>>>>>>> retry failed after ${defaultRetries} times for url: ${url}, now will try fallbackUrl url: ${fallbackUrl} <<<<<<<<<`);
|
|
33
|
+
if (fallbackUrl && fallbackUrl !== url) {
|
|
34
|
+
return fetchWithRetry({
|
|
35
|
+
url: fallbackUrl,
|
|
36
|
+
options,
|
|
37
|
+
retryTimes: 1,
|
|
38
|
+
fallbackUrl
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
throw new Error('The request failed three times and has now been abandoned');
|
|
42
|
+
}
|
|
43
|
+
// If there are remaining times, delay 1 second and try again
|
|
44
|
+
await new Promise((resolve)=>setTimeout(resolve, 1000));
|
|
45
|
+
console.log(`Trying again. Number of retries available:${retryTimes - 1}`);
|
|
46
|
+
return await fetchWithRetry({
|
|
47
|
+
url,
|
|
48
|
+
options,
|
|
49
|
+
retryTimes: retryTimes - 1,
|
|
50
|
+
fallbackUrl
|
|
51
|
+
});
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
const RetryPlugin = (params)=>({
|
|
55
|
+
name: 'retry-plugin',
|
|
56
|
+
async fetch (url, options) {
|
|
57
|
+
return fetchWithRetry({
|
|
58
|
+
url,
|
|
59
|
+
options: _extends({}, options, params == null ? void 0 : params.options),
|
|
60
|
+
retryTimes: params == null ? void 0 : params.retryTimes,
|
|
61
|
+
fallbackUrl: params == null ? void 0 : params.fallbackUrl
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
});
|
|
65
|
+
|
|
66
|
+
export { RetryPlugin as default };
|
package/dist/share.cjs.js
CHANGED
|
@@ -212,7 +212,7 @@ function getGlobalFederationConstructor() {
|
|
|
212
212
|
function setGlobalFederationConstructor(FederationConstructor, isDebug = isDebugMode()) {
|
|
213
213
|
if (isDebug) {
|
|
214
214
|
globalThis.__FEDERATION__.__DEBUG_CONSTRUCTOR__ = FederationConstructor;
|
|
215
|
-
globalThis.__FEDERATION__.__DEBUG_CONSTRUCTOR_VERSION__ = "0.
|
|
215
|
+
globalThis.__FEDERATION__.__DEBUG_CONSTRUCTOR_VERSION__ = "0.5.0";
|
|
216
216
|
}
|
|
217
217
|
}
|
|
218
218
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
@@ -711,7 +711,7 @@ function formatShare(shareArgs, from, name) {
|
|
|
711
711
|
strictVersion: false
|
|
712
712
|
}, shareArgs.shareConfig),
|
|
713
713
|
get,
|
|
714
|
-
loaded: 'lib' in shareArgs ? true : undefined,
|
|
714
|
+
loaded: (shareArgs == null ? void 0 : shareArgs.loaded) || 'lib' in shareArgs ? true : undefined,
|
|
715
715
|
version: (_shareArgs_version = shareArgs.version) != null ? _shareArgs_version : '0',
|
|
716
716
|
scope: Array.isArray(shareArgs.scope) ? shareArgs.scope : [
|
|
717
717
|
(_shareArgs_scope = shareArgs.scope) != null ? _shareArgs_scope : 'default'
|
package/dist/share.esm.js
CHANGED
|
@@ -210,7 +210,7 @@ function getGlobalFederationConstructor() {
|
|
|
210
210
|
function setGlobalFederationConstructor(FederationConstructor, isDebug = isDebugMode()) {
|
|
211
211
|
if (isDebug) {
|
|
212
212
|
globalThis.__FEDERATION__.__DEBUG_CONSTRUCTOR__ = FederationConstructor;
|
|
213
|
-
globalThis.__FEDERATION__.__DEBUG_CONSTRUCTOR_VERSION__ = "0.
|
|
213
|
+
globalThis.__FEDERATION__.__DEBUG_CONSTRUCTOR_VERSION__ = "0.5.0";
|
|
214
214
|
}
|
|
215
215
|
}
|
|
216
216
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
|
@@ -709,7 +709,7 @@ function formatShare(shareArgs, from, name) {
|
|
|
709
709
|
strictVersion: false
|
|
710
710
|
}, shareArgs.shareConfig),
|
|
711
711
|
get,
|
|
712
|
-
loaded: 'lib' in shareArgs ? true : undefined,
|
|
712
|
+
loaded: (shareArgs == null ? void 0 : shareArgs.loaded) || 'lib' in shareArgs ? true : undefined,
|
|
713
713
|
version: (_shareArgs_version = shareArgs.version) != null ? _shareArgs_version : '0',
|
|
714
714
|
scope: Array.isArray(shareArgs.scope) ? shareArgs.scope : [
|
|
715
715
|
(_shareArgs_scope = shareArgs.scope) != null ? _shareArgs_scope : 'default'
|
package/dist/src/core.d.ts
CHANGED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { FederationRuntimePlugin } from '../type/plugin';
|
|
2
|
+
interface FetchWithRetryOptions {
|
|
3
|
+
url: string;
|
|
4
|
+
options?: RequestInit;
|
|
5
|
+
retryTimes?: number;
|
|
6
|
+
fallbackUrl?: string;
|
|
7
|
+
}
|
|
8
|
+
declare const RetryPlugin: (params?: Omit<FetchWithRetryOptions, 'url'>) => FederationRuntimePlugin;
|
|
9
|
+
export default RetryPlugin;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import type { ModuleInfo, GlobalModuleInfo } from '@module-federation/sdk';
|
|
2
|
-
import { Options, UserOptions, PreloadAssets, PreloadOptions, PreloadRemoteArgs, Remote, RemoteInfo } from '../type';
|
|
2
|
+
import { Options, UserOptions, PreloadAssets, PreloadOptions, PreloadRemoteArgs, Remote, RemoteInfo, RemoteEntryExports } from '../type';
|
|
3
3
|
import { FederationHost } from '../core';
|
|
4
4
|
import { PluginSystem, AsyncHook, AsyncWaterfallHook, SyncHook, SyncWaterfallHook } from '../utils/hooks';
|
|
5
5
|
import { Module, ModuleOptions } from '../module';
|
|
@@ -78,6 +78,11 @@ export declare class RemoteHandler {
|
|
|
78
78
|
options: Options;
|
|
79
79
|
origin: FederationHost;
|
|
80
80
|
}, false | void | Promise<false | void>>;
|
|
81
|
+
loadEntry: AsyncHook<[{
|
|
82
|
+
createScriptHook: FederationHost["loaderHook"]["lifecycle"]["createScript"];
|
|
83
|
+
remoteInfo: RemoteInfo;
|
|
84
|
+
remoteEntryExports?: RemoteEntryExports;
|
|
85
|
+
}], Promise<RemoteEntryExports>>;
|
|
81
86
|
}>;
|
|
82
87
|
constructor(host: FederationHost);
|
|
83
88
|
formatAndRegisterRemote(globalOptions: Options, userOptions: UserOptions): Remote[];
|
|
@@ -41,6 +41,7 @@ type SharedBaseArgs = {
|
|
|
41
41
|
scope?: string | Array<string>;
|
|
42
42
|
deps?: Array<string>;
|
|
43
43
|
strategy?: 'version-first' | 'loaded-first';
|
|
44
|
+
loaded?: boolean;
|
|
44
45
|
};
|
|
45
46
|
export type SharedGetter = (() => () => Module) | (() => Promise<() => Module>);
|
|
46
47
|
export type ShareArgs = (SharedBaseArgs & {
|
package/dist/src/utils/load.d.ts
CHANGED
|
@@ -1,23 +1,9 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { FederationHost } from '../core';
|
|
2
2
|
import { Remote, RemoteEntryExports, RemoteInfo } from '../type';
|
|
3
|
-
export declare function loadEsmEntry({ entry, remoteEntryExports, }: {
|
|
4
|
-
entry: string;
|
|
5
|
-
remoteEntryExports: RemoteEntryExports | undefined;
|
|
6
|
-
}): Promise<RemoteEntryExports>;
|
|
7
|
-
export declare function loadSystemJsEntry({ entry, remoteEntryExports, }: {
|
|
8
|
-
entry: string;
|
|
9
|
-
remoteEntryExports: RemoteEntryExports | undefined;
|
|
10
|
-
}): Promise<RemoteEntryExports>;
|
|
11
|
-
export declare function loadEntryScript({ name, globalName, entry, createScriptHook, }: {
|
|
12
|
-
name: string;
|
|
13
|
-
globalName: string;
|
|
14
|
-
entry: string;
|
|
15
|
-
createScriptHook?: (url: string, attrs?: Record<string, any> | undefined) => CreateScriptHookReturn;
|
|
16
|
-
}): Promise<RemoteEntryExports>;
|
|
17
3
|
export declare function getRemoteEntryUniqueKey(remoteInfo: RemoteInfo): string;
|
|
18
|
-
export declare function getRemoteEntry({ remoteEntryExports, remoteInfo,
|
|
4
|
+
export declare function getRemoteEntry({ origin, remoteEntryExports, remoteInfo, }: {
|
|
5
|
+
origin: FederationHost;
|
|
19
6
|
remoteInfo: RemoteInfo;
|
|
20
7
|
remoteEntryExports?: RemoteEntryExports | undefined;
|
|
21
|
-
|
|
22
|
-
}): Promise<RemoteEntryExports | void>;
|
|
8
|
+
}): Promise<RemoteEntryExports | false | void>;
|
|
23
9
|
export declare function getRemoteInfo(remote: Remote): RemoteInfo;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@module-federation/runtime",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0",
|
|
4
4
|
"author": "zhouxiao <codingzx@gmail.com>",
|
|
5
5
|
"main": "./dist/index.cjs.js",
|
|
6
6
|
"module": "./dist/index.esm.js",
|
|
@@ -29,6 +29,11 @@
|
|
|
29
29
|
"import": "./dist/types.esm.js",
|
|
30
30
|
"require": "./dist/types.cjs.js"
|
|
31
31
|
},
|
|
32
|
+
"./retry-plugin": {
|
|
33
|
+
"types": "./dist/retry-plugin.cjs.d.ts",
|
|
34
|
+
"import": "./dist/retry-plugin.esm.js",
|
|
35
|
+
"require": "./dist/retry-plugin.cjs.js"
|
|
36
|
+
},
|
|
32
37
|
"./*": "./*"
|
|
33
38
|
},
|
|
34
39
|
"typesVersions": {
|
|
@@ -41,10 +46,13 @@
|
|
|
41
46
|
],
|
|
42
47
|
"types": [
|
|
43
48
|
"./dist/types.cjs.d.ts"
|
|
49
|
+
],
|
|
50
|
+
"retry-plugin": [
|
|
51
|
+
"./dist/retry-plugin.cjs.d.ts"
|
|
44
52
|
]
|
|
45
53
|
}
|
|
46
54
|
},
|
|
47
55
|
"dependencies": {
|
|
48
|
-
"@module-federation/sdk": "0.
|
|
56
|
+
"@module-federation/sdk": "0.5.0"
|
|
49
57
|
}
|
|
50
58
|
}
|