@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 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,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
- rel: 'preload',
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
- rel: 'stylesheet',
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
- rel: 'preload',
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.3.5";
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 { 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,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
- rel: 'preload',
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
- rel: 'stylesheet',
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
- rel: 'preload',
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$1() && !remote.entry.startsWith('http')) {
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.3.5";
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.5",
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,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.3.5";
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.3.5";
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'
@@ -55,6 +55,7 @@ export declare class FederationHost {
55
55
  }], CreateScriptHookReturn>;
56
56
  createLink: SyncHook<[{
57
57
  url: string;
58
+ attrs?: Record<string, any>;
58
59
  }], void | HTMLLinkElement>;
59
60
  fetch: AsyncHook<[string, RequestInit], false | void | Promise<Response>>;
60
61
  }>;
@@ -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 & {
@@ -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.3.5",
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.3.5"
56
+ "@module-federation/sdk": "0.5.0"
49
57
  }
50
58
  }