@module-federation/runtime 0.4.0 → 0.5.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/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, createScriptHook }) {
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
- if ([
193
- 'esm',
194
- 'module'
195
- ].includes(type)) {
196
- share.globalLoading[uniqueKey] = loadEsmEntry({
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
- share.globalLoading[uniqueKey] = loadEntryScript({
207
- name,
208
- globalName: entryGlobalName,
209
- entry,
210
- createScriptHook
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,49 +632,15 @@ 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
  });
@@ -1947,7 +1950,8 @@ class RemoteHandler {
1947
1950
  beforePreloadRemote: new AsyncHook('beforePreloadRemote'),
1948
1951
  generatePreloadAssets: new AsyncHook('generatePreloadAssets'),
1949
1952
  // not used yet
1950
- afterPreloadRemote: new AsyncHook()
1953
+ afterPreloadRemote: new AsyncHook(),
1954
+ loadEntry: new AsyncHook()
1951
1955
  });
1952
1956
  this.host = host;
1953
1957
  this.idToRemoteMap = {};
@@ -2073,7 +2077,7 @@ class FederationHost {
2073
2077
  // maybe will change, temporarily for internal use only
2074
2078
  initContainer: new AsyncWaterfallHook('initContainer')
2075
2079
  });
2076
- this.version = "0.4.0";
2080
+ this.version = "0.5.1";
2077
2081
  this.moduleCache = new Map();
2078
2082
  this.loaderHook = new PluginSystem({
2079
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 { loadScriptNode, loadScript, composeKeyWithSeparator, createLink, createScript, getResourceUrl, isManifestProvider, generateSnapshotFromManifest, warn as warn$1, isBrowserEnv as isBrowserEnv$1 } from '@module-federation/sdk';
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, createScriptHook }) {
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
- if ([
191
- 'esm',
192
- 'module'
193
- ].includes(type)) {
194
- globalLoading[uniqueKey] = loadEsmEntry({
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
- globalLoading[uniqueKey] = loadEntryScript({
205
- name,
206
- globalName: entryGlobalName,
207
- entry,
208
- createScriptHook
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,49 +630,15 @@ 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
  });
@@ -760,7 +763,7 @@ function assignRemoteInfo(remoteInfo, remoteSnapshot) {
760
763
  error(`The attribute remoteEntry of ${remoteInfo.name} must not be undefined.`);
761
764
  }
762
765
  let entryUrl = getResourceUrl(remoteSnapshot, remoteEntryInfo.url);
763
- if (!isBrowserEnv() && !entryUrl.startsWith('http')) {
766
+ if (!isBrowserEnv$1() && !entryUrl.startsWith('http')) {
764
767
  entryUrl = `https:${entryUrl}`;
765
768
  }
766
769
  remoteInfo.type = remoteEntryInfo.type;
@@ -1121,7 +1124,7 @@ class SnapshotHandler {
1121
1124
  // global snapshot includes manifest or module info includes manifest
1122
1125
  if (globalRemoteSnapshot) {
1123
1126
  if (isManifestProvider(globalRemoteSnapshot)) {
1124
- const remoteEntry = isBrowserEnv() ? globalRemoteSnapshot.remoteEntry : globalRemoteSnapshot.ssrRemoteEntry || globalRemoteSnapshot.remoteEntry || '';
1127
+ const remoteEntry = isBrowserEnv$1() ? globalRemoteSnapshot.remoteEntry : globalRemoteSnapshot.ssrRemoteEntry || globalRemoteSnapshot.remoteEntry || '';
1125
1128
  const moduleSnapshot = await this.getManifestJson(remoteEntry, moduleInfo, {});
1126
1129
  // eslint-disable-next-line @typescript-eslint/no-shadow
1127
1130
  const globalSnapshotRes = setGlobalSnapshotInfoByModuleInfo(_extends$3({}, moduleInfo, {
@@ -1792,7 +1795,7 @@ class RemoteHandler {
1792
1795
  }
1793
1796
  // Set the remote entry to a complete path
1794
1797
  if ('entry' in remote) {
1795
- if (isBrowserEnv$1() && !remote.entry.startsWith('http')) {
1798
+ if (isBrowserEnv() && !remote.entry.startsWith('http')) {
1796
1799
  remote.entry = new URL(remote.entry, window.location.origin).href;
1797
1800
  }
1798
1801
  }
@@ -1945,7 +1948,8 @@ class RemoteHandler {
1945
1948
  beforePreloadRemote: new AsyncHook('beforePreloadRemote'),
1946
1949
  generatePreloadAssets: new AsyncHook('generatePreloadAssets'),
1947
1950
  // not used yet
1948
- afterPreloadRemote: new AsyncHook()
1951
+ afterPreloadRemote: new AsyncHook(),
1952
+ loadEntry: new AsyncHook()
1949
1953
  });
1950
1954
  this.host = host;
1951
1955
  this.idToRemoteMap = {};
@@ -2071,7 +2075,7 @@ class FederationHost {
2071
2075
  // maybe will change, temporarily for internal use only
2072
2076
  initContainer: new AsyncWaterfallHook('initContainer')
2073
2077
  });
2074
- this.version = "0.4.0";
2078
+ this.version = "0.5.1";
2075
2079
  this.moduleCache = new Map();
2076
2080
  this.loaderHook = new PluginSystem({
2077
2081
  // FIXME: may not be suitable , not open to the public yet
@@ -2092,7 +2096,7 @@ class FederationHost {
2092
2096
  ],
2093
2097
  remotes: [],
2094
2098
  shared: {},
2095
- inBrowser: isBrowserEnv()
2099
+ inBrowser: isBrowserEnv$1()
2096
2100
  };
2097
2101
  this.name = userOptions.name;
2098
2102
  this.options = defaultOptions;
package/dist/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@module-federation/runtime",
3
- "version": "0.4.0",
3
+ "version": "0.5.1",
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,2 @@
1
+ export * from "./src/plugins/retry-plugin";
2
+ export { default } from "./src/plugins/retry-plugin";
@@ -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.4.0";
215
+ globalThis.__FEDERATION__.__DEBUG_CONSTRUCTOR_VERSION__ = "0.5.1";
216
216
  }
217
217
  }
218
218
  // eslint-disable-next-line @typescript-eslint/ban-types
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.4.0";
213
+ globalThis.__FEDERATION__.__DEBUG_CONSTRUCTOR_VERSION__ = "0.5.1";
214
214
  }
215
215
  }
216
216
  // eslint-disable-next-line @typescript-eslint/ban-types
@@ -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[];
@@ -1,23 +1,9 @@
1
- import { CreateScriptHookReturn } from '@module-federation/sdk';
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, createScriptHook, }: {
4
+ export declare function getRemoteEntry({ origin, remoteEntryExports, remoteInfo, }: {
5
+ origin: FederationHost;
19
6
  remoteInfo: RemoteInfo;
20
7
  remoteEntryExports?: RemoteEntryExports | undefined;
21
- createScriptHook?: (url: string, attrs?: Record<string, any> | undefined) => CreateScriptHookReturn;
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.4.0",
3
+ "version": "0.5.1",
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.4.0"
56
+ "@module-federation/sdk": "0.5.1"
49
57
  }
50
58
  }