@module-federation/runtime-core 0.23.0 → 0.24.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.
@@ -201,7 +201,7 @@ function getGlobalFederationConstructor() {
201
201
  function setGlobalFederationConstructor(FederationConstructor, isDebug = sdk.isDebugMode()) {
202
202
  if (isDebug) {
203
203
  CurrentGlobal.__FEDERATION__.__DEBUG_CONSTRUCTOR__ = FederationConstructor;
204
- CurrentGlobal.__FEDERATION__.__DEBUG_CONSTRUCTOR_VERSION__ = "0.23.0";
204
+ CurrentGlobal.__FEDERATION__.__DEBUG_CONSTRUCTOR_VERSION__ = "0.24.1";
205
205
  }
206
206
  }
207
207
  // eslint-disable-next-line @typescript-eslint/ban-types
@@ -808,6 +808,9 @@ function formatShare(shareArgs, from, name, shareStrategy) {
808
808
  throw new Error(`Can not get shared '${name}'!`);
809
809
  });
810
810
  }
811
+ if (shareArgs.shareConfig?.eager && shareArgs.treeShaking) {
812
+ throw new Error('Can not set "eager:true" and "treeShaking" at the same time!');
813
+ }
811
814
  return {
812
815
  deps: [],
813
816
  useIn: [],
@@ -828,37 +831,67 @@ function formatShare(shareArgs, from, name, shareStrategy) {
828
831
  ? shareArgs.scope
829
832
  : [shareArgs.scope ?? 'default'],
830
833
  strategy: (shareArgs.strategy ?? shareStrategy) || 'version-first',
834
+ treeShaking: shareArgs.treeShaking
835
+ ? {
836
+ ...shareArgs.treeShaking,
837
+ mode: shareArgs.treeShaking.mode ?? 'server-calc',
838
+ status: shareArgs.treeShaking.status ?? 1 /* TreeShakingStatus.UNKNOWN */,
839
+ useIn: [],
840
+ }
841
+ : undefined,
831
842
  };
832
843
  }
833
- function formatShareConfigs(globalOptions, userOptions) {
834
- const shareArgs = userOptions.shared || {};
835
- const from = userOptions.name;
836
- const shareInfos = Object.keys(shareArgs).reduce((res, pkgName) => {
844
+ function formatShareConfigs(prevOptions, newOptions) {
845
+ const shareArgs = newOptions.shared || {};
846
+ const from = newOptions.name;
847
+ const newShareInfos = Object.keys(shareArgs).reduce((res, pkgName) => {
837
848
  const arrayShareArgs = arrayOptions(shareArgs[pkgName]);
838
849
  res[pkgName] = res[pkgName] || [];
839
850
  arrayShareArgs.forEach((shareConfig) => {
840
- res[pkgName].push(formatShare(shareConfig, from, pkgName, userOptions.shareStrategy));
851
+ res[pkgName].push(formatShare(shareConfig, from, pkgName, newOptions.shareStrategy));
841
852
  });
842
853
  return res;
843
854
  }, {});
844
- const shared = {
845
- ...globalOptions.shared,
855
+ const allShareInfos = {
856
+ ...prevOptions.shared,
846
857
  };
847
- Object.keys(shareInfos).forEach((shareKey) => {
848
- if (!shared[shareKey]) {
849
- shared[shareKey] = shareInfos[shareKey];
858
+ Object.keys(newShareInfos).forEach((shareKey) => {
859
+ if (!allShareInfos[shareKey]) {
860
+ allShareInfos[shareKey] = newShareInfos[shareKey];
850
861
  }
851
862
  else {
852
- shareInfos[shareKey].forEach((newUserSharedOptions) => {
853
- const isSameVersion = shared[shareKey].find((sharedVal) => sharedVal.version === newUserSharedOptions.version);
863
+ newShareInfos[shareKey].forEach((newUserSharedOptions) => {
864
+ const isSameVersion = allShareInfos[shareKey].find((sharedVal) => sharedVal.version === newUserSharedOptions.version);
854
865
  if (!isSameVersion) {
855
- shared[shareKey].push(newUserSharedOptions);
866
+ allShareInfos[shareKey].push(newUserSharedOptions);
856
867
  }
857
868
  });
858
869
  }
859
870
  });
860
- return { shared, shareInfos };
871
+ return { allShareInfos, newShareInfos };
861
872
  }
873
+ function shouldUseTreeShaking(treeShaking, usedExports) {
874
+ if (!treeShaking) {
875
+ return false;
876
+ }
877
+ const { status, mode } = treeShaking;
878
+ if (status === 0 /* TreeShakingStatus.NO_USE */) {
879
+ return false;
880
+ }
881
+ if (status === 2 /* TreeShakingStatus.CALCULATED */) {
882
+ return true;
883
+ }
884
+ if (mode === 'runtime-infer') {
885
+ if (!usedExports) {
886
+ return true;
887
+ }
888
+ return isMatchUsedExports(treeShaking, usedExports);
889
+ }
890
+ return false;
891
+ }
892
+ /**
893
+ * compare version a and b, return true if a is less than b
894
+ */
862
895
  function versionLt(a, b) {
863
896
  const transformInvalidVersion = (version) => {
864
897
  const isNumberVersion = !Number.isNaN(Number(version));
@@ -904,19 +937,79 @@ const isLoaded = (shared) => {
904
937
  const isLoading = (shared) => {
905
938
  return Boolean(shared.loading);
906
939
  };
907
- function findSingletonVersionOrderByVersion(shareScopeMap, scope, pkgName) {
940
+ const isMatchUsedExports = (treeShaking, usedExports) => {
941
+ if (!treeShaking || !usedExports) {
942
+ return false;
943
+ }
944
+ const { usedExports: treeShakingUsedExports } = treeShaking;
945
+ if (!treeShakingUsedExports) {
946
+ return false;
947
+ }
948
+ if (usedExports.every((e) => treeShakingUsedExports.includes(e))) {
949
+ return true;
950
+ }
951
+ return false;
952
+ };
953
+ function findSingletonVersionOrderByVersion(shareScopeMap, scope, pkgName, treeShaking) {
908
954
  const versions = shareScopeMap[scope][pkgName];
955
+ let version = '';
956
+ let useTreesShaking = shouldUseTreeShaking(treeShaking);
957
+ // return false means use prev version
909
958
  const callback = function (prev, cur) {
959
+ if (useTreesShaking) {
960
+ if (!versions[prev].treeShaking) {
961
+ return true;
962
+ }
963
+ if (!versions[cur].treeShaking) {
964
+ return false;
965
+ }
966
+ return !isLoaded(versions[prev].treeShaking) && versionLt(prev, cur);
967
+ }
910
968
  return !isLoaded(versions[prev]) && versionLt(prev, cur);
911
969
  };
912
- return findVersion(shareScopeMap[scope][pkgName], callback);
970
+ if (useTreesShaking) {
971
+ version = findVersion(shareScopeMap[scope][pkgName], callback);
972
+ if (version) {
973
+ return {
974
+ version,
975
+ useTreesShaking,
976
+ };
977
+ }
978
+ useTreesShaking = false;
979
+ }
980
+ return {
981
+ version: findVersion(shareScopeMap[scope][pkgName], callback),
982
+ useTreesShaking,
983
+ };
913
984
  }
914
- function findSingletonVersionOrderByLoaded(shareScopeMap, scope, pkgName) {
985
+ const isLoadingOrLoaded = (shared) => {
986
+ return isLoaded(shared) || isLoading(shared);
987
+ };
988
+ function findSingletonVersionOrderByLoaded(shareScopeMap, scope, pkgName, treeShaking) {
915
989
  const versions = shareScopeMap[scope][pkgName];
990
+ let version = '';
991
+ let useTreesShaking = shouldUseTreeShaking(treeShaking);
992
+ // return false means use prev version
916
993
  const callback = function (prev, cur) {
917
- const isLoadingOrLoaded = (shared) => {
918
- return isLoaded(shared) || isLoading(shared);
919
- };
994
+ if (useTreesShaking) {
995
+ if (!versions[prev].treeShaking) {
996
+ return true;
997
+ }
998
+ if (!versions[cur].treeShaking) {
999
+ return false;
1000
+ }
1001
+ if (isLoadingOrLoaded(versions[cur].treeShaking)) {
1002
+ if (isLoadingOrLoaded(versions[prev].treeShaking)) {
1003
+ return Boolean(versionLt(prev, cur));
1004
+ }
1005
+ else {
1006
+ return true;
1007
+ }
1008
+ }
1009
+ if (isLoadingOrLoaded(versions[prev].treeShaking)) {
1010
+ return false;
1011
+ }
1012
+ }
920
1013
  if (isLoadingOrLoaded(versions[cur])) {
921
1014
  if (isLoadingOrLoaded(versions[prev])) {
922
1015
  return Boolean(versionLt(prev, cur));
@@ -930,7 +1023,20 @@ function findSingletonVersionOrderByLoaded(shareScopeMap, scope, pkgName) {
930
1023
  }
931
1024
  return versionLt(prev, cur);
932
1025
  };
933
- return findVersion(shareScopeMap[scope][pkgName], callback);
1026
+ if (useTreesShaking) {
1027
+ version = findVersion(shareScopeMap[scope][pkgName], callback);
1028
+ if (version) {
1029
+ return {
1030
+ version,
1031
+ useTreesShaking,
1032
+ };
1033
+ }
1034
+ useTreesShaking = false;
1035
+ }
1036
+ return {
1037
+ version: findVersion(shareScopeMap[scope][pkgName], callback),
1038
+ useTreesShaking,
1039
+ };
934
1040
  }
935
1041
  function getFindShareFunction(strategy) {
936
1042
  if (strategy === 'loaded-first') {
@@ -942,7 +1048,7 @@ function getRegisteredShare(localShareScopeMap, pkgName, shareInfo, resolveShare
942
1048
  if (!localShareScopeMap) {
943
1049
  return;
944
1050
  }
945
- const { shareConfig, scope = DEFAULT_SCOPE, strategy } = shareInfo;
1051
+ const { shareConfig, scope = DEFAULT_SCOPE, strategy, treeShaking, } = shareInfo;
946
1052
  const scopes = Array.isArray(scope) ? scope : [scope];
947
1053
  for (const sc of scopes) {
948
1054
  if (shareConfig &&
@@ -950,14 +1056,13 @@ function getRegisteredShare(localShareScopeMap, pkgName, shareInfo, resolveShare
950
1056
  localShareScopeMap[sc][pkgName]) {
951
1057
  const { requiredVersion } = shareConfig;
952
1058
  const findShareFunction = getFindShareFunction(strategy);
953
- const maxOrSingletonVersion = findShareFunction(localShareScopeMap, sc, pkgName);
954
- //@ts-ignore
1059
+ const { version: maxOrSingletonVersion, useTreesShaking } = findShareFunction(localShareScopeMap, sc, pkgName, treeShaking);
955
1060
  const defaultResolver = () => {
1061
+ const shared = localShareScopeMap[sc][pkgName][maxOrSingletonVersion];
956
1062
  if (shareConfig.singleton) {
957
1063
  if (typeof requiredVersion === 'string' &&
958
1064
  !satisfy(maxOrSingletonVersion, requiredVersion)) {
959
- const msg = `Version ${maxOrSingletonVersion} from ${maxOrSingletonVersion &&
960
- localShareScopeMap[sc][pkgName][maxOrSingletonVersion].from} of shared singleton module ${pkgName} does not satisfy the requirement of ${shareInfo.from} which needs ${requiredVersion})`;
1065
+ const msg = `Version ${maxOrSingletonVersion} from ${maxOrSingletonVersion && shared.from} of shared singleton module ${pkgName} does not satisfy the requirement of ${shareInfo.from} which needs ${requiredVersion})`;
961
1066
  if (shareConfig.strictVersion) {
962
1067
  error(msg);
963
1068
  }
@@ -965,21 +1070,48 @@ function getRegisteredShare(localShareScopeMap, pkgName, shareInfo, resolveShare
965
1070
  warn(msg);
966
1071
  }
967
1072
  }
968
- return localShareScopeMap[sc][pkgName][maxOrSingletonVersion];
1073
+ return {
1074
+ shared,
1075
+ useTreesShaking,
1076
+ };
969
1077
  }
970
1078
  else {
971
1079
  if (requiredVersion === false || requiredVersion === '*') {
972
- return localShareScopeMap[sc][pkgName][maxOrSingletonVersion];
1080
+ return {
1081
+ shared,
1082
+ useTreesShaking,
1083
+ };
973
1084
  }
974
1085
  if (satisfy(maxOrSingletonVersion, requiredVersion)) {
975
- return localShareScopeMap[sc][pkgName][maxOrSingletonVersion];
1086
+ return {
1087
+ shared,
1088
+ useTreesShaking,
1089
+ };
1090
+ }
1091
+ const _usedTreeShaking = shouldUseTreeShaking(treeShaking);
1092
+ if (_usedTreeShaking) {
1093
+ for (const [versionKey, versionValue] of Object.entries(localShareScopeMap[sc][pkgName])) {
1094
+ if (!shouldUseTreeShaking(versionValue.treeShaking, treeShaking?.usedExports)) {
1095
+ continue;
1096
+ }
1097
+ if (satisfy(versionKey, requiredVersion)) {
1098
+ return {
1099
+ shared: versionValue,
1100
+ useTreesShaking: _usedTreeShaking,
1101
+ };
1102
+ }
1103
+ }
976
1104
  }
977
1105
  for (const [versionKey, versionValue] of Object.entries(localShareScopeMap[sc][pkgName])) {
978
1106
  if (satisfy(versionKey, requiredVersion)) {
979
- return versionValue;
1107
+ return {
1108
+ shared: versionValue,
1109
+ useTreesShaking: false,
1110
+ };
980
1111
  }
981
1112
  }
982
1113
  }
1114
+ return;
983
1115
  };
984
1116
  const params = {
985
1117
  shareScopeMap: localShareScopeMap,
@@ -987,6 +1119,7 @@ function getRegisteredShare(localShareScopeMap, pkgName, shareInfo, resolveShare
987
1119
  pkgName,
988
1120
  version: maxOrSingletonVersion,
989
1121
  GlobalFederation: Global.__FEDERATION__,
1122
+ shareInfo,
990
1123
  resolver: defaultResolver,
991
1124
  };
992
1125
  const resolveShared = resolveShare.emit(params) || params;
@@ -1008,13 +1141,47 @@ function getTargetSharedOptions(options) {
1008
1141
  shareVersionMap[shared.version] = shared;
1009
1142
  });
1010
1143
  const callback = function (prev, cur) {
1011
- return !isLoaded(shareVersionMap[prev]) && versionLt(prev, cur);
1144
+ return (
1145
+ // TODO: consider multiple treeShaking shared scenes
1146
+ !isLoaded(shareVersionMap[prev]) && versionLt(prev, cur));
1012
1147
  };
1013
1148
  const maxVersion = findVersion(shareVersionMap, callback);
1014
1149
  return shareVersionMap[maxVersion];
1015
1150
  };
1016
1151
  const resolver = extraOptions?.resolver ?? defaultResolver;
1017
- return Object.assign({}, resolver(shareInfos[pkgName]), extraOptions?.customShareInfo);
1152
+ const isPlainObject = (val) => {
1153
+ return val !== null && typeof val === 'object' && !Array.isArray(val);
1154
+ };
1155
+ const merge = (...sources) => {
1156
+ const out = {};
1157
+ for (const src of sources) {
1158
+ if (!src)
1159
+ continue;
1160
+ for (const [key, value] of Object.entries(src)) {
1161
+ const prev = out[key];
1162
+ if (isPlainObject(prev) && isPlainObject(value)) {
1163
+ out[key] = merge(prev, value);
1164
+ }
1165
+ else if (value !== undefined) {
1166
+ out[key] = value;
1167
+ }
1168
+ }
1169
+ }
1170
+ return out;
1171
+ };
1172
+ return merge(resolver(shareInfos[pkgName]), extraOptions?.customShareInfo);
1173
+ }
1174
+ const addUseIn = (shared, from) => {
1175
+ if (!shared.useIn) {
1176
+ shared.useIn = [];
1177
+ }
1178
+ addUniqueItem(shared.useIn, from);
1179
+ };
1180
+ function directShare(shared, useTreesShaking) {
1181
+ if (useTreesShaking && shared.treeShaking) {
1182
+ return shared.treeShaking;
1183
+ }
1184
+ return shared;
1018
1185
  }
1019
1186
 
1020
1187
  function getBuilderId() {
@@ -1526,9 +1693,44 @@ var helpers = {
1526
1693
  },
1527
1694
  };
1528
1695
 
1696
+ function createRemoteEntryInitOptions(remoteInfo, hostShareScopeMap) {
1697
+ const localShareScopeMap = hostShareScopeMap;
1698
+ const shareScopeKeys = Array.isArray(remoteInfo.shareScope)
1699
+ ? remoteInfo.shareScope
1700
+ : [remoteInfo.shareScope];
1701
+ if (!shareScopeKeys.length) {
1702
+ shareScopeKeys.push('default');
1703
+ }
1704
+ shareScopeKeys.forEach((shareScopeKey) => {
1705
+ if (!localShareScopeMap[shareScopeKey]) {
1706
+ localShareScopeMap[shareScopeKey] = {};
1707
+ }
1708
+ });
1709
+ const remoteEntryInitOptions = {
1710
+ version: remoteInfo.version || '',
1711
+ shareScopeKeys: Array.isArray(remoteInfo.shareScope)
1712
+ ? shareScopeKeys
1713
+ : remoteInfo.shareScope || 'default',
1714
+ };
1715
+ // Help to find host instance
1716
+ Object.defineProperty(remoteEntryInitOptions, 'shareScopeMap', {
1717
+ value: localShareScopeMap,
1718
+ // remoteEntryInitOptions will be traversed and assigned during container init, ,so this attribute is not allowed to be traversed
1719
+ enumerable: false,
1720
+ });
1721
+ // TODO: compate legacy init params, should use shareScopeMap if exist
1722
+ const shareScope = localShareScopeMap[shareScopeKeys[0]];
1723
+ const initScope = [];
1724
+ return {
1725
+ remoteEntryInitOptions,
1726
+ shareScope,
1727
+ initScope,
1728
+ };
1729
+ }
1529
1730
  class Module {
1530
1731
  constructor({ remoteInfo, host, }) {
1531
1732
  this.inited = false;
1733
+ this.initing = false;
1532
1734
  this.lib = undefined;
1533
1735
  this.remoteInfo = remoteInfo;
1534
1736
  this.host = host;
@@ -1550,34 +1752,9 @@ class Module {
1550
1752
  async init(id, remoteSnapshot) {
1551
1753
  // Get remoteEntry.js
1552
1754
  const remoteEntryExports = await this.getEntry();
1553
- if (!this.inited) {
1554
- const localShareScopeMap = this.host.shareScopeMap;
1555
- const shareScopeKeys = Array.isArray(this.remoteInfo.shareScope)
1556
- ? this.remoteInfo.shareScope
1557
- : [this.remoteInfo.shareScope];
1558
- if (!shareScopeKeys.length) {
1559
- shareScopeKeys.push('default');
1560
- }
1561
- shareScopeKeys.forEach((shareScopeKey) => {
1562
- if (!localShareScopeMap[shareScopeKey]) {
1563
- localShareScopeMap[shareScopeKey] = {};
1564
- }
1565
- });
1566
- // TODO: compate legacy init params, should use shareScopeMap if exist
1567
- const shareScope = localShareScopeMap[shareScopeKeys[0]];
1568
- const initScope = [];
1569
- const remoteEntryInitOptions = {
1570
- version: this.remoteInfo.version || '',
1571
- shareScopeKeys: Array.isArray(this.remoteInfo.shareScope)
1572
- ? shareScopeKeys
1573
- : this.remoteInfo.shareScope || 'default',
1574
- };
1575
- // Help to find host instance
1576
- Object.defineProperty(remoteEntryInitOptions, 'shareScopeMap', {
1577
- value: localShareScopeMap,
1578
- // remoteEntryInitOptions will be traversed and assigned during container init, ,so this attribute is not allowed to be traversed
1579
- enumerable: false,
1580
- });
1755
+ if (!this.inited && !this.initing) {
1756
+ this.initing = true;
1757
+ const { remoteEntryInitOptions, shareScope, initScope } = createRemoteEntryInitOptions(this.remoteInfo, this.host.shareScopeMap);
1581
1758
  const initContainerOptions = await this.host.hooks.lifecycle.beforeInitContainer.emit({
1582
1759
  shareScope,
1583
1760
  // @ts-ignore shareScopeMap will be set by Object.defineProperty
@@ -1601,6 +1778,7 @@ class Module {
1601
1778
  remoteSnapshot,
1602
1779
  remoteEntryExports,
1603
1780
  });
1781
+ this.inited = true;
1604
1782
  }
1605
1783
  return remoteEntryExports;
1606
1784
  }
@@ -1609,7 +1787,6 @@ class Module {
1609
1787
  const { loadFactory = true } = options || { loadFactory: true };
1610
1788
  const remoteEntryExports = await this.init(id, remoteSnapshot);
1611
1789
  this.lib = remoteEntryExports;
1612
- this.inited = true;
1613
1790
  let moduleFactory;
1614
1791
  moduleFactory = await this.host.loaderHook.lifecycle.getModuleFactory.emit({
1615
1792
  remoteEntryExports,
@@ -2063,7 +2240,7 @@ function generatePreloadAssets(origin, preloadOptions, remote, globalSnapshot, r
2063
2240
  }, true, memo, remoteSnapshot);
2064
2241
  if (remoteSnapshot.shared && remoteSnapshot.shared.length > 0) {
2065
2242
  const collectSharedAssets = (shareInfo, snapshotShared) => {
2066
- const registeredShared = getRegisteredShare(origin.shareScopeMap, snapshotShared.sharedName, shareInfo, origin.sharedHandler.hooks.lifecycle.resolveShare);
2243
+ const { shared: registeredShared } = getRegisteredShare(origin.shareScopeMap, snapshotShared.sharedName, shareInfo, origin.sharedHandler.hooks.lifecycle.resolveShare) || {};
2067
2244
  // If the global share does not exist, or the lib function does not exist, it means that the shared has not been loaded yet and can be preloaded.
2068
2245
  if (registeredShared && typeof registeredShared.lib === 'function') {
2069
2246
  snapshotShared.assets.js.sync.forEach((asset) => {
@@ -2354,6 +2531,7 @@ class SnapshotHandler {
2354
2531
  class SharedHandler {
2355
2532
  constructor(host) {
2356
2533
  this.hooks = new PluginSystem({
2534
+ beforeRegisterShare: new SyncWaterfallHook('beforeRegisterShare'),
2357
2535
  afterResolve: new AsyncWaterfallHook('afterResolve'),
2358
2536
  beforeLoadShare: new AsyncWaterfallHook('beforeLoadShare'),
2359
2537
  // not used yet
@@ -2369,12 +2547,17 @@ class SharedHandler {
2369
2547
  }
2370
2548
  // register shared in shareScopeMap
2371
2549
  registerShared(globalOptions, userOptions) {
2372
- const { shareInfos, shared } = formatShareConfigs(globalOptions, userOptions);
2373
- const sharedKeys = Object.keys(shareInfos);
2550
+ const { newShareInfos, allShareInfos } = formatShareConfigs(globalOptions, userOptions);
2551
+ const sharedKeys = Object.keys(newShareInfos);
2374
2552
  sharedKeys.forEach((sharedKey) => {
2375
- const sharedVals = shareInfos[sharedKey];
2553
+ const sharedVals = newShareInfos[sharedKey];
2376
2554
  sharedVals.forEach((sharedVal) => {
2377
2555
  sharedVal.scope.forEach((sc) => {
2556
+ this.hooks.lifecycle.beforeRegisterShare.emit({
2557
+ origin: this.host,
2558
+ pkgName: sharedKey,
2559
+ shared: sharedVal,
2560
+ });
2378
2561
  const registeredShared = this.shareScopeMap[sc]?.[sharedKey];
2379
2562
  if (!registeredShared) {
2380
2563
  this.setShared({
@@ -2390,8 +2573,8 @@ class SharedHandler {
2390
2573
  });
2391
2574
  });
2392
2575
  return {
2393
- shareInfos,
2394
- shared,
2576
+ newShareInfos,
2577
+ allShareInfos,
2395
2578
  };
2396
2579
  }
2397
2580
  async loadShare(pkgName, extraOptions) {
@@ -2422,61 +2605,61 @@ class SharedHandler {
2422
2605
  const { shareInfo: shareOptionsRes } = loadShareRes;
2423
2606
  // Assert that shareInfoRes exists, if not, throw an error
2424
2607
  assert(shareOptionsRes, `Cannot find ${pkgName} Share in the ${host.options.name}. Please ensure that the ${pkgName} Share parameters have been injected`);
2425
- // Retrieve from cache
2426
- const registeredShared = getRegisteredShare(this.shareScopeMap, pkgName, shareOptionsRes, this.hooks.lifecycle.resolveShare);
2427
- const addUseIn = (shared) => {
2428
- if (!shared.useIn) {
2429
- shared.useIn = [];
2430
- }
2431
- addUniqueItem(shared.useIn, host.options.name);
2432
- };
2433
- if (registeredShared && registeredShared.lib) {
2434
- addUseIn(registeredShared);
2435
- return registeredShared.lib;
2436
- }
2437
- else if (registeredShared &&
2438
- registeredShared.loading &&
2439
- !registeredShared.loaded) {
2440
- const factory = await registeredShared.loading;
2441
- registeredShared.loaded = true;
2442
- if (!registeredShared.lib) {
2443
- registeredShared.lib = factory;
2444
- }
2445
- addUseIn(registeredShared);
2446
- return factory;
2447
- }
2448
- else if (registeredShared) {
2449
- const asyncLoadProcess = async () => {
2450
- const factory = await registeredShared.get();
2451
- addUseIn(registeredShared);
2452
- registeredShared.loaded = true;
2453
- registeredShared.lib = factory;
2608
+ const { shared: registeredShared, useTreesShaking } = getRegisteredShare(this.shareScopeMap, pkgName, shareOptionsRes, this.hooks.lifecycle.resolveShare) || {};
2609
+ if (registeredShared) {
2610
+ const targetShared = directShare(registeredShared, useTreesShaking);
2611
+ if (targetShared.lib) {
2612
+ addUseIn(targetShared, host.options.name);
2613
+ return targetShared.lib;
2614
+ }
2615
+ else if (targetShared.loading && !targetShared.loaded) {
2616
+ const factory = await targetShared.loading;
2617
+ targetShared.loaded = true;
2618
+ if (!targetShared.lib) {
2619
+ targetShared.lib = factory;
2620
+ }
2621
+ addUseIn(targetShared, host.options.name);
2454
2622
  return factory;
2455
- };
2456
- const loading = asyncLoadProcess();
2457
- this.setShared({
2458
- pkgName,
2459
- loaded: false,
2460
- shared: registeredShared,
2461
- from: host.options.name,
2462
- lib: null,
2463
- loading,
2464
- });
2465
- return loading;
2623
+ }
2624
+ else {
2625
+ const asyncLoadProcess = async () => {
2626
+ const factory = await targetShared.get();
2627
+ addUseIn(targetShared, host.options.name);
2628
+ targetShared.loaded = true;
2629
+ targetShared.lib = factory;
2630
+ return factory;
2631
+ };
2632
+ const loading = asyncLoadProcess();
2633
+ this.setShared({
2634
+ pkgName,
2635
+ loaded: false,
2636
+ shared: registeredShared,
2637
+ from: host.options.name,
2638
+ lib: null,
2639
+ loading,
2640
+ treeShaking: useTreesShaking
2641
+ ? targetShared
2642
+ : undefined,
2643
+ });
2644
+ return loading;
2645
+ }
2466
2646
  }
2467
2647
  else {
2468
2648
  if (extraOptions?.customShareInfo) {
2469
2649
  return false;
2470
2650
  }
2651
+ const _useTreeShaking = shouldUseTreeShaking(shareOptionsRes.treeShaking);
2652
+ const targetShared = directShare(shareOptionsRes, _useTreeShaking);
2471
2653
  const asyncLoadProcess = async () => {
2472
- const factory = await shareOptionsRes.get();
2473
- shareOptionsRes.lib = factory;
2474
- shareOptionsRes.loaded = true;
2475
- addUseIn(shareOptionsRes);
2476
- const gShared = getRegisteredShare(this.shareScopeMap, pkgName, shareOptionsRes, this.hooks.lifecycle.resolveShare);
2654
+ const factory = await targetShared.get();
2655
+ targetShared.lib = factory;
2656
+ targetShared.loaded = true;
2657
+ addUseIn(targetShared, host.options.name);
2658
+ const { shared: gShared, useTreesShaking: gUseTreeShaking } = getRegisteredShare(this.shareScopeMap, pkgName, shareOptionsRes, this.hooks.lifecycle.resolveShare) || {};
2477
2659
  if (gShared) {
2478
- gShared.lib = factory;
2479
- gShared.loaded = true;
2660
+ const targetGShared = directShare(gShared, gUseTreeShaking);
2661
+ targetGShared.lib = factory;
2662
+ targetGShared.loaded = true;
2480
2663
  gShared.from = shareOptionsRes.from;
2481
2664
  }
2482
2665
  return factory;
@@ -2489,6 +2672,9 @@ class SharedHandler {
2489
2672
  from: host.options.name,
2490
2673
  lib: null,
2491
2674
  loading,
2675
+ treeShaking: _useTreeShaking
2676
+ ? targetShared
2677
+ : undefined,
2492
2678
  });
2493
2679
  return loading;
2494
2680
  }
@@ -2528,15 +2714,17 @@ class SharedHandler {
2528
2714
  const { version, eager } = shared;
2529
2715
  scope[name] = scope[name] || {};
2530
2716
  const versions = scope[name];
2531
- const activeVersion = versions[version];
2717
+ const activeVersion = versions[version] && directShare(versions[version]);
2532
2718
  const activeVersionEager = Boolean(activeVersion &&
2533
- (activeVersion.eager || activeVersion.shareConfig?.eager));
2719
+ (('eager' in activeVersion && activeVersion.eager) ||
2720
+ ('shareConfig' in activeVersion &&
2721
+ activeVersion.shareConfig?.eager)));
2534
2722
  if (!activeVersion ||
2535
2723
  (activeVersion.strategy !== 'loaded-first' &&
2536
2724
  !activeVersion.loaded &&
2537
2725
  (Boolean(!eager) !== !activeVersionEager
2538
2726
  ? eager
2539
- : hostName > activeVersion.from))) {
2727
+ : hostName > versions[version].from))) {
2540
2728
  versions[version] = shared;
2541
2729
  }
2542
2730
  };
@@ -2544,7 +2732,26 @@ class SharedHandler {
2544
2732
  const { module } = await host.remoteHandler.getRemoteModuleAndOptions({
2545
2733
  id: key,
2546
2734
  });
2547
- await module.init();
2735
+ let remoteEntryExports = undefined;
2736
+ try {
2737
+ remoteEntryExports = await module.getEntry();
2738
+ }
2739
+ catch (error) {
2740
+ remoteEntryExports =
2741
+ (await host.remoteHandler.hooks.lifecycle.errorLoadRemote.emit({
2742
+ id: key,
2743
+ error,
2744
+ from: 'runtime',
2745
+ lifecycle: 'beforeLoadShare',
2746
+ origin: host,
2747
+ }));
2748
+ }
2749
+ finally {
2750
+ if (remoteEntryExports?.init) {
2751
+ module.remoteEntryExports = remoteEntryExports;
2752
+ await module.init();
2753
+ }
2754
+ }
2548
2755
  };
2549
2756
  Object.keys(host.options.shared).forEach((shareName) => {
2550
2757
  const sharedArr = host.options.shared[shareName];
@@ -2581,16 +2788,10 @@ class SharedHandler {
2581
2788
  this.initializeSharing(shareScope, { strategy: shareOptions.strategy });
2582
2789
  });
2583
2790
  }
2584
- const registeredShared = getRegisteredShare(this.shareScopeMap, pkgName, shareOptions, this.hooks.lifecycle.resolveShare);
2585
- const addUseIn = (shared) => {
2586
- if (!shared.useIn) {
2587
- shared.useIn = [];
2588
- }
2589
- addUniqueItem(shared.useIn, host.options.name);
2590
- };
2791
+ const { shared: registeredShared, useTreesShaking } = getRegisteredShare(this.shareScopeMap, pkgName, shareOptions, this.hooks.lifecycle.resolveShare) || {};
2591
2792
  if (registeredShared) {
2592
2793
  if (typeof registeredShared.lib === 'function') {
2593
- addUseIn(registeredShared);
2794
+ addUseIn(registeredShared, host.options.name);
2594
2795
  if (!registeredShared.loaded) {
2595
2796
  registeredShared.loaded = true;
2596
2797
  if (registeredShared.from === host.options.name) {
@@ -2602,7 +2803,7 @@ class SharedHandler {
2602
2803
  if (typeof registeredShared.get === 'function') {
2603
2804
  const module = registeredShared.get();
2604
2805
  if (!(module instanceof Promise)) {
2605
- addUseIn(registeredShared);
2806
+ addUseIn(registeredShared, host.options.name);
2606
2807
  this.setShared({
2607
2808
  pkgName,
2608
2809
  loaded: true,
@@ -2655,9 +2856,20 @@ class SharedHandler {
2655
2856
  hostShareScopeMap: extraOptions.hostShareScopeMap,
2656
2857
  });
2657
2858
  }
2658
- setShared({ pkgName, shared, from, lib, loading, loaded, get, }) {
2859
+ setShared({ pkgName, shared, from, lib, loading, loaded, get, treeShaking, }) {
2659
2860
  const { version, scope = 'default', ...shareInfo } = shared;
2660
2861
  const scopes = Array.isArray(scope) ? scope : [scope];
2862
+ const mergeAttrs = (shared) => {
2863
+ const merge = (s, key, val) => {
2864
+ if (val && !s[key]) {
2865
+ s[key] = val;
2866
+ }
2867
+ };
2868
+ const targetShared = (treeShaking ? shared.treeShaking : shared);
2869
+ merge(targetShared, 'loaded', loaded);
2870
+ merge(targetShared, 'loading', loading);
2871
+ merge(targetShared, 'get', get);
2872
+ };
2661
2873
  scopes.forEach((sc) => {
2662
2874
  if (!this.shareScopeMap[sc]) {
2663
2875
  this.shareScopeMap[sc] = {};
@@ -2671,21 +2883,10 @@ class SharedHandler {
2671
2883
  scope: [sc],
2672
2884
  ...shareInfo,
2673
2885
  lib,
2674
- loaded,
2675
- loading,
2676
2886
  };
2677
- if (get) {
2678
- this.shareScopeMap[sc][pkgName][version].get = get;
2679
- }
2680
- return;
2681
2887
  }
2682
2888
  const registeredShared = this.shareScopeMap[sc][pkgName][version];
2683
- if (loading && !registeredShared.loading) {
2684
- registeredShared.loading = loading;
2685
- }
2686
- if (loaded && !registeredShared.loaded) {
2687
- registeredShared.loaded = loaded;
2688
- }
2889
+ mergeAttrs(registeredShared);
2689
2890
  if (from && registeredShared.from !== from) {
2690
2891
  registeredShared.from = from;
2691
2892
  }
@@ -2713,6 +2914,7 @@ class RemoteHandler {
2713
2914
  generatePreloadAssets: new AsyncHook('generatePreloadAssets'),
2714
2915
  // not used yet
2715
2916
  afterPreloadRemote: new AsyncHook(),
2917
+ // TODO: Move to loaderHook
2716
2918
  loadEntry: new AsyncHook(),
2717
2919
  });
2718
2920
  this.host = host;
@@ -3061,7 +3263,7 @@ class ModuleFederation {
3061
3263
  // maybe will change, temporarily for internal use only
3062
3264
  initContainer: new AsyncWaterfallHook('initContainer'),
3063
3265
  });
3064
- this.version = "0.23.0";
3266
+ this.version = "0.24.1";
3065
3267
  this.moduleCache = new Map();
3066
3268
  this.loaderHook = new PluginSystem({
3067
3269
  // FIXME: may not be suitable , not open to the public yet
@@ -3142,7 +3344,7 @@ class ModuleFederation {
3142
3344
  this.sharedHandler.initShareScopeMap(scopeName, shareScope, extraOptions);
3143
3345
  }
3144
3346
  formatOptions(globalOptions, userOptions) {
3145
- const { shared } = formatShareConfigs(globalOptions, userOptions);
3347
+ const { allShareInfos: shared} = formatShareConfigs(globalOptions, userOptions);
3146
3348
  const { userOptions: userOptionsRes, options: globalOptionsRes } = this.hooks.lifecycle.beforeInit.emit({
3147
3349
  origin: this,
3148
3350
  userOptions,
@@ -3150,7 +3352,7 @@ class ModuleFederation {
3150
3352
  shareInfo: shared,
3151
3353
  });
3152
3354
  const remotes = this.remoteHandler.formatAndRegisterRemote(globalOptionsRes, userOptionsRes);
3153
- const { shared: handledShared } = this.sharedHandler.registerShared(globalOptionsRes, userOptionsRes);
3355
+ const { allShareInfos } = this.sharedHandler.registerShared(globalOptionsRes, userOptionsRes);
3154
3356
  const plugins = [...globalOptionsRes.plugins];
3155
3357
  if (userOptionsRes.plugins) {
3156
3358
  userOptionsRes.plugins.forEach((plugin) => {
@@ -3164,7 +3366,7 @@ class ModuleFederation {
3164
3366
  ...userOptions,
3165
3367
  plugins,
3166
3368
  remotes,
3167
- shared: handledShared,
3369
+ shared: allShareInfos,
3168
3370
  };
3169
3371
  this.hooks.lifecycle.init.emit({
3170
3372
  origin: this,