@module-federation/runtime-core 0.0.0-feat-modern-3-0-20260113090730 → 0.0.0-feat-shared-treeshake-poc-20260114065000

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.esm.js CHANGED
@@ -200,7 +200,7 @@ function getGlobalFederationConstructor() {
200
200
  function setGlobalFederationConstructor(FederationConstructor, isDebug = isDebugMode()) {
201
201
  if (isDebug) {
202
202
  CurrentGlobal.__FEDERATION__.__DEBUG_CONSTRUCTOR__ = FederationConstructor;
203
- CurrentGlobal.__FEDERATION__.__DEBUG_CONSTRUCTOR_VERSION__ = "0.0.0-feat-modern-3-0-20260113090730";
203
+ CurrentGlobal.__FEDERATION__.__DEBUG_CONSTRUCTOR_VERSION__ = "0.0.0-feat-shared-treeshake-poc-20260114065000";
204
204
  }
205
205
  }
206
206
  // eslint-disable-next-line @typescript-eslint/ban-types
@@ -807,6 +807,9 @@ function formatShare(shareArgs, from, name, shareStrategy) {
807
807
  throw new Error(`Can not get shared '${name}'!`);
808
808
  });
809
809
  }
810
+ if (shareArgs.shareConfig?.eager && shareArgs.treeShaking) {
811
+ throw new Error('Can not set "eager:true" and "treeShaking" at the same time!');
812
+ }
810
813
  return {
811
814
  deps: [],
812
815
  useIn: [],
@@ -827,37 +830,67 @@ function formatShare(shareArgs, from, name, shareStrategy) {
827
830
  ? shareArgs.scope
828
831
  : [shareArgs.scope ?? 'default'],
829
832
  strategy: (shareArgs.strategy ?? shareStrategy) || 'version-first',
833
+ treeShaking: shareArgs.treeShaking
834
+ ? {
835
+ ...shareArgs.treeShaking,
836
+ mode: shareArgs.treeShaking.mode ?? 'server-calc',
837
+ status: shareArgs.treeShaking.status ?? 1 /* TreeShakingStatus.UNKNOWN */,
838
+ useIn: [],
839
+ }
840
+ : undefined,
830
841
  };
831
842
  }
832
- function formatShareConfigs(globalOptions, userOptions) {
833
- const shareArgs = userOptions.shared || {};
834
- const from = userOptions.name;
835
- const shareInfos = Object.keys(shareArgs).reduce((res, pkgName) => {
843
+ function formatShareConfigs(prevOptions, newOptions) {
844
+ const shareArgs = newOptions.shared || {};
845
+ const from = newOptions.name;
846
+ const newShareInfos = Object.keys(shareArgs).reduce((res, pkgName) => {
836
847
  const arrayShareArgs = arrayOptions(shareArgs[pkgName]);
837
848
  res[pkgName] = res[pkgName] || [];
838
849
  arrayShareArgs.forEach((shareConfig) => {
839
- res[pkgName].push(formatShare(shareConfig, from, pkgName, userOptions.shareStrategy));
850
+ res[pkgName].push(formatShare(shareConfig, from, pkgName, newOptions.shareStrategy));
840
851
  });
841
852
  return res;
842
853
  }, {});
843
- const shared = {
844
- ...globalOptions.shared,
854
+ const allShareInfos = {
855
+ ...prevOptions.shared,
845
856
  };
846
- Object.keys(shareInfos).forEach((shareKey) => {
847
- if (!shared[shareKey]) {
848
- shared[shareKey] = shareInfos[shareKey];
857
+ Object.keys(newShareInfos).forEach((shareKey) => {
858
+ if (!allShareInfos[shareKey]) {
859
+ allShareInfos[shareKey] = newShareInfos[shareKey];
849
860
  }
850
861
  else {
851
- shareInfos[shareKey].forEach((newUserSharedOptions) => {
852
- const isSameVersion = shared[shareKey].find((sharedVal) => sharedVal.version === newUserSharedOptions.version);
862
+ newShareInfos[shareKey].forEach((newUserSharedOptions) => {
863
+ const isSameVersion = allShareInfos[shareKey].find((sharedVal) => sharedVal.version === newUserSharedOptions.version);
853
864
  if (!isSameVersion) {
854
- shared[shareKey].push(newUserSharedOptions);
865
+ allShareInfos[shareKey].push(newUserSharedOptions);
855
866
  }
856
867
  });
857
868
  }
858
869
  });
859
- return { shared, shareInfos };
870
+ return { allShareInfos, newShareInfos };
860
871
  }
872
+ function shouldUseTreeShaking(treeShaking, usedExports) {
873
+ if (!treeShaking) {
874
+ return false;
875
+ }
876
+ const { status, mode } = treeShaking;
877
+ if (status === 0 /* TreeShakingStatus.NO_USE */) {
878
+ return false;
879
+ }
880
+ if (status === 2 /* TreeShakingStatus.CALCULATED */) {
881
+ return true;
882
+ }
883
+ if (mode === 'runtime-infer') {
884
+ if (!usedExports) {
885
+ return true;
886
+ }
887
+ return isMatchUsedExports(treeShaking, usedExports);
888
+ }
889
+ return false;
890
+ }
891
+ /**
892
+ * compare version a and b, return true if a is less than b
893
+ */
861
894
  function versionLt(a, b) {
862
895
  const transformInvalidVersion = (version) => {
863
896
  const isNumberVersion = !Number.isNaN(Number(version));
@@ -903,19 +936,79 @@ const isLoaded = (shared) => {
903
936
  const isLoading = (shared) => {
904
937
  return Boolean(shared.loading);
905
938
  };
906
- function findSingletonVersionOrderByVersion(shareScopeMap, scope, pkgName) {
939
+ const isMatchUsedExports = (treeShaking, usedExports) => {
940
+ if (!treeShaking || !usedExports) {
941
+ return false;
942
+ }
943
+ const { usedExports: treeShakingUsedExports } = treeShaking;
944
+ if (!treeShakingUsedExports) {
945
+ return false;
946
+ }
947
+ if (usedExports.every((e) => treeShakingUsedExports.includes(e))) {
948
+ return true;
949
+ }
950
+ return false;
951
+ };
952
+ function findSingletonVersionOrderByVersion(shareScopeMap, scope, pkgName, treeShaking) {
907
953
  const versions = shareScopeMap[scope][pkgName];
954
+ let version = '';
955
+ let useTreesShaking = shouldUseTreeShaking(treeShaking);
956
+ // return false means use prev version
908
957
  const callback = function (prev, cur) {
958
+ if (useTreesShaking) {
959
+ if (!versions[prev].treeShaking) {
960
+ return true;
961
+ }
962
+ if (!versions[cur].treeShaking) {
963
+ return false;
964
+ }
965
+ return !isLoaded(versions[prev].treeShaking) && versionLt(prev, cur);
966
+ }
909
967
  return !isLoaded(versions[prev]) && versionLt(prev, cur);
910
968
  };
911
- return findVersion(shareScopeMap[scope][pkgName], callback);
969
+ if (useTreesShaking) {
970
+ version = findVersion(shareScopeMap[scope][pkgName], callback);
971
+ if (version) {
972
+ return {
973
+ version,
974
+ useTreesShaking,
975
+ };
976
+ }
977
+ useTreesShaking = false;
978
+ }
979
+ return {
980
+ version: findVersion(shareScopeMap[scope][pkgName], callback),
981
+ useTreesShaking,
982
+ };
912
983
  }
913
- function findSingletonVersionOrderByLoaded(shareScopeMap, scope, pkgName) {
984
+ const isLoadingOrLoaded = (shared) => {
985
+ return isLoaded(shared) || isLoading(shared);
986
+ };
987
+ function findSingletonVersionOrderByLoaded(shareScopeMap, scope, pkgName, treeShaking) {
914
988
  const versions = shareScopeMap[scope][pkgName];
989
+ let version = '';
990
+ let useTreesShaking = shouldUseTreeShaking(treeShaking);
991
+ // return false means use prev version
915
992
  const callback = function (prev, cur) {
916
- const isLoadingOrLoaded = (shared) => {
917
- return isLoaded(shared) || isLoading(shared);
918
- };
993
+ if (useTreesShaking) {
994
+ if (!versions[prev].treeShaking) {
995
+ return true;
996
+ }
997
+ if (!versions[cur].treeShaking) {
998
+ return false;
999
+ }
1000
+ if (isLoadingOrLoaded(versions[cur].treeShaking)) {
1001
+ if (isLoadingOrLoaded(versions[prev].treeShaking)) {
1002
+ return Boolean(versionLt(prev, cur));
1003
+ }
1004
+ else {
1005
+ return true;
1006
+ }
1007
+ }
1008
+ if (isLoadingOrLoaded(versions[prev].treeShaking)) {
1009
+ return false;
1010
+ }
1011
+ }
919
1012
  if (isLoadingOrLoaded(versions[cur])) {
920
1013
  if (isLoadingOrLoaded(versions[prev])) {
921
1014
  return Boolean(versionLt(prev, cur));
@@ -929,7 +1022,20 @@ function findSingletonVersionOrderByLoaded(shareScopeMap, scope, pkgName) {
929
1022
  }
930
1023
  return versionLt(prev, cur);
931
1024
  };
932
- return findVersion(shareScopeMap[scope][pkgName], callback);
1025
+ if (useTreesShaking) {
1026
+ version = findVersion(shareScopeMap[scope][pkgName], callback);
1027
+ if (version) {
1028
+ return {
1029
+ version,
1030
+ useTreesShaking,
1031
+ };
1032
+ }
1033
+ useTreesShaking = false;
1034
+ }
1035
+ return {
1036
+ version: findVersion(shareScopeMap[scope][pkgName], callback),
1037
+ useTreesShaking,
1038
+ };
933
1039
  }
934
1040
  function getFindShareFunction(strategy) {
935
1041
  if (strategy === 'loaded-first') {
@@ -941,7 +1047,7 @@ function getRegisteredShare(localShareScopeMap, pkgName, shareInfo, resolveShare
941
1047
  if (!localShareScopeMap) {
942
1048
  return;
943
1049
  }
944
- const { shareConfig, scope = DEFAULT_SCOPE, strategy } = shareInfo;
1050
+ const { shareConfig, scope = DEFAULT_SCOPE, strategy, treeShaking, } = shareInfo;
945
1051
  const scopes = Array.isArray(scope) ? scope : [scope];
946
1052
  for (const sc of scopes) {
947
1053
  if (shareConfig &&
@@ -949,14 +1055,13 @@ function getRegisteredShare(localShareScopeMap, pkgName, shareInfo, resolveShare
949
1055
  localShareScopeMap[sc][pkgName]) {
950
1056
  const { requiredVersion } = shareConfig;
951
1057
  const findShareFunction = getFindShareFunction(strategy);
952
- const maxOrSingletonVersion = findShareFunction(localShareScopeMap, sc, pkgName);
953
- //@ts-ignore
1058
+ const { version: maxOrSingletonVersion, useTreesShaking } = findShareFunction(localShareScopeMap, sc, pkgName, treeShaking);
954
1059
  const defaultResolver = () => {
1060
+ const shared = localShareScopeMap[sc][pkgName][maxOrSingletonVersion];
955
1061
  if (shareConfig.singleton) {
956
1062
  if (typeof requiredVersion === 'string' &&
957
1063
  !satisfy(maxOrSingletonVersion, requiredVersion)) {
958
- const msg = `Version ${maxOrSingletonVersion} from ${maxOrSingletonVersion &&
959
- localShareScopeMap[sc][pkgName][maxOrSingletonVersion].from} of shared singleton module ${pkgName} does not satisfy the requirement of ${shareInfo.from} which needs ${requiredVersion})`;
1064
+ const msg = `Version ${maxOrSingletonVersion} from ${maxOrSingletonVersion && shared.from} of shared singleton module ${pkgName} does not satisfy the requirement of ${shareInfo.from} which needs ${requiredVersion})`;
960
1065
  if (shareConfig.strictVersion) {
961
1066
  error(msg);
962
1067
  }
@@ -964,21 +1069,48 @@ function getRegisteredShare(localShareScopeMap, pkgName, shareInfo, resolveShare
964
1069
  warn(msg);
965
1070
  }
966
1071
  }
967
- return localShareScopeMap[sc][pkgName][maxOrSingletonVersion];
1072
+ return {
1073
+ shared,
1074
+ useTreesShaking,
1075
+ };
968
1076
  }
969
1077
  else {
970
1078
  if (requiredVersion === false || requiredVersion === '*') {
971
- return localShareScopeMap[sc][pkgName][maxOrSingletonVersion];
1079
+ return {
1080
+ shared,
1081
+ useTreesShaking,
1082
+ };
972
1083
  }
973
1084
  if (satisfy(maxOrSingletonVersion, requiredVersion)) {
974
- return localShareScopeMap[sc][pkgName][maxOrSingletonVersion];
1085
+ return {
1086
+ shared,
1087
+ useTreesShaking,
1088
+ };
1089
+ }
1090
+ const _usedTreeShaking = shouldUseTreeShaking(treeShaking);
1091
+ if (_usedTreeShaking) {
1092
+ for (const [versionKey, versionValue] of Object.entries(localShareScopeMap[sc][pkgName])) {
1093
+ if (!shouldUseTreeShaking(versionValue.treeShaking, treeShaking?.usedExports)) {
1094
+ continue;
1095
+ }
1096
+ if (satisfy(versionKey, requiredVersion)) {
1097
+ return {
1098
+ shared: versionValue,
1099
+ useTreesShaking: _usedTreeShaking,
1100
+ };
1101
+ }
1102
+ }
975
1103
  }
976
1104
  for (const [versionKey, versionValue] of Object.entries(localShareScopeMap[sc][pkgName])) {
977
1105
  if (satisfy(versionKey, requiredVersion)) {
978
- return versionValue;
1106
+ return {
1107
+ shared: versionValue,
1108
+ useTreesShaking: false,
1109
+ };
979
1110
  }
980
1111
  }
981
1112
  }
1113
+ return;
982
1114
  };
983
1115
  const params = {
984
1116
  shareScopeMap: localShareScopeMap,
@@ -986,6 +1118,7 @@ function getRegisteredShare(localShareScopeMap, pkgName, shareInfo, resolveShare
986
1118
  pkgName,
987
1119
  version: maxOrSingletonVersion,
988
1120
  GlobalFederation: Global.__FEDERATION__,
1121
+ shareInfo,
989
1122
  resolver: defaultResolver,
990
1123
  };
991
1124
  const resolveShared = resolveShare.emit(params) || params;
@@ -1007,13 +1140,47 @@ function getTargetSharedOptions(options) {
1007
1140
  shareVersionMap[shared.version] = shared;
1008
1141
  });
1009
1142
  const callback = function (prev, cur) {
1010
- return !isLoaded(shareVersionMap[prev]) && versionLt(prev, cur);
1143
+ return (
1144
+ // TODO: consider multiple treeShaking shared scenes
1145
+ !isLoaded(shareVersionMap[prev]) && versionLt(prev, cur));
1011
1146
  };
1012
1147
  const maxVersion = findVersion(shareVersionMap, callback);
1013
1148
  return shareVersionMap[maxVersion];
1014
1149
  };
1015
1150
  const resolver = extraOptions?.resolver ?? defaultResolver;
1016
- return Object.assign({}, resolver(shareInfos[pkgName]), extraOptions?.customShareInfo);
1151
+ const isPlainObject = (val) => {
1152
+ return val !== null && typeof val === 'object' && !Array.isArray(val);
1153
+ };
1154
+ const merge = (...sources) => {
1155
+ const out = {};
1156
+ for (const src of sources) {
1157
+ if (!src)
1158
+ continue;
1159
+ for (const [key, value] of Object.entries(src)) {
1160
+ const prev = out[key];
1161
+ if (isPlainObject(prev) && isPlainObject(value)) {
1162
+ out[key] = merge(prev, value);
1163
+ }
1164
+ else if (value !== undefined) {
1165
+ out[key] = value;
1166
+ }
1167
+ }
1168
+ }
1169
+ return out;
1170
+ };
1171
+ return merge(resolver(shareInfos[pkgName]), extraOptions?.customShareInfo);
1172
+ }
1173
+ const addUseIn = (shared, from) => {
1174
+ if (!shared.useIn) {
1175
+ shared.useIn = [];
1176
+ }
1177
+ addUniqueItem(shared.useIn, from);
1178
+ };
1179
+ function directShare(shared, useTreesShaking) {
1180
+ if (useTreesShaking && shared.treeShaking) {
1181
+ return shared.treeShaking;
1182
+ }
1183
+ return shared;
1017
1184
  }
1018
1185
 
1019
1186
  function getBuilderId() {
@@ -1525,6 +1692,40 @@ var helpers = {
1525
1692
  },
1526
1693
  };
1527
1694
 
1695
+ function createRemoteEntryInitOptions(remoteInfo, hostShareScopeMap) {
1696
+ const localShareScopeMap = hostShareScopeMap;
1697
+ const shareScopeKeys = Array.isArray(remoteInfo.shareScope)
1698
+ ? remoteInfo.shareScope
1699
+ : [remoteInfo.shareScope];
1700
+ if (!shareScopeKeys.length) {
1701
+ shareScopeKeys.push('default');
1702
+ }
1703
+ shareScopeKeys.forEach((shareScopeKey) => {
1704
+ if (!localShareScopeMap[shareScopeKey]) {
1705
+ localShareScopeMap[shareScopeKey] = {};
1706
+ }
1707
+ });
1708
+ const remoteEntryInitOptions = {
1709
+ version: remoteInfo.version || '',
1710
+ shareScopeKeys: Array.isArray(remoteInfo.shareScope)
1711
+ ? shareScopeKeys
1712
+ : remoteInfo.shareScope || 'default',
1713
+ };
1714
+ // Help to find host instance
1715
+ Object.defineProperty(remoteEntryInitOptions, 'shareScopeMap', {
1716
+ value: localShareScopeMap,
1717
+ // remoteEntryInitOptions will be traversed and assigned during container init, ,so this attribute is not allowed to be traversed
1718
+ enumerable: false,
1719
+ });
1720
+ // TODO: compate legacy init params, should use shareScopeMap if exist
1721
+ const shareScope = localShareScopeMap[shareScopeKeys[0]];
1722
+ const initScope = [];
1723
+ return {
1724
+ remoteEntryInitOptions,
1725
+ shareScope,
1726
+ initScope,
1727
+ };
1728
+ }
1528
1729
  class Module {
1529
1730
  constructor({ remoteInfo, host, }) {
1530
1731
  this.inited = false;
@@ -1550,33 +1751,7 @@ class Module {
1550
1751
  // Get remoteEntry.js
1551
1752
  const remoteEntryExports = await this.getEntry();
1552
1753
  if (!this.inited) {
1553
- const localShareScopeMap = this.host.shareScopeMap;
1554
- const shareScopeKeys = Array.isArray(this.remoteInfo.shareScope)
1555
- ? this.remoteInfo.shareScope
1556
- : [this.remoteInfo.shareScope];
1557
- if (!shareScopeKeys.length) {
1558
- shareScopeKeys.push('default');
1559
- }
1560
- shareScopeKeys.forEach((shareScopeKey) => {
1561
- if (!localShareScopeMap[shareScopeKey]) {
1562
- localShareScopeMap[shareScopeKey] = {};
1563
- }
1564
- });
1565
- // TODO: compate legacy init params, should use shareScopeMap if exist
1566
- const shareScope = localShareScopeMap[shareScopeKeys[0]];
1567
- const initScope = [];
1568
- const remoteEntryInitOptions = {
1569
- version: this.remoteInfo.version || '',
1570
- shareScopeKeys: Array.isArray(this.remoteInfo.shareScope)
1571
- ? shareScopeKeys
1572
- : this.remoteInfo.shareScope || 'default',
1573
- };
1574
- // Help to find host instance
1575
- Object.defineProperty(remoteEntryInitOptions, 'shareScopeMap', {
1576
- value: localShareScopeMap,
1577
- // remoteEntryInitOptions will be traversed and assigned during container init, ,so this attribute is not allowed to be traversed
1578
- enumerable: false,
1579
- });
1754
+ const { remoteEntryInitOptions, shareScope, initScope } = createRemoteEntryInitOptions(this.remoteInfo, this.host.shareScopeMap);
1580
1755
  const initContainerOptions = await this.host.hooks.lifecycle.beforeInitContainer.emit({
1581
1756
  shareScope,
1582
1757
  // @ts-ignore shareScopeMap will be set by Object.defineProperty
@@ -1600,6 +1775,7 @@ class Module {
1600
1775
  remoteSnapshot,
1601
1776
  remoteEntryExports,
1602
1777
  });
1778
+ this.inited = true;
1603
1779
  }
1604
1780
  return remoteEntryExports;
1605
1781
  }
@@ -1608,7 +1784,6 @@ class Module {
1608
1784
  const { loadFactory = true } = options || { loadFactory: true };
1609
1785
  const remoteEntryExports = await this.init(id, remoteSnapshot);
1610
1786
  this.lib = remoteEntryExports;
1611
- this.inited = true;
1612
1787
  let moduleFactory;
1613
1788
  moduleFactory = await this.host.loaderHook.lifecycle.getModuleFactory.emit({
1614
1789
  remoteEntryExports,
@@ -2062,7 +2237,7 @@ function generatePreloadAssets(origin, preloadOptions, remote, globalSnapshot, r
2062
2237
  }, true, memo, remoteSnapshot);
2063
2238
  if (remoteSnapshot.shared && remoteSnapshot.shared.length > 0) {
2064
2239
  const collectSharedAssets = (shareInfo, snapshotShared) => {
2065
- const registeredShared = getRegisteredShare(origin.shareScopeMap, snapshotShared.sharedName, shareInfo, origin.sharedHandler.hooks.lifecycle.resolveShare);
2240
+ const { shared: registeredShared } = getRegisteredShare(origin.shareScopeMap, snapshotShared.sharedName, shareInfo, origin.sharedHandler.hooks.lifecycle.resolveShare) || {};
2066
2241
  // 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.
2067
2242
  if (registeredShared && typeof registeredShared.lib === 'function') {
2068
2243
  snapshotShared.assets.js.sync.forEach((asset) => {
@@ -2353,6 +2528,7 @@ class SnapshotHandler {
2353
2528
  class SharedHandler {
2354
2529
  constructor(host) {
2355
2530
  this.hooks = new PluginSystem({
2531
+ beforeRegisterShare: new SyncWaterfallHook('beforeRegisterShare'),
2356
2532
  afterResolve: new AsyncWaterfallHook('afterResolve'),
2357
2533
  beforeLoadShare: new AsyncWaterfallHook('beforeLoadShare'),
2358
2534
  // not used yet
@@ -2368,12 +2544,17 @@ class SharedHandler {
2368
2544
  }
2369
2545
  // register shared in shareScopeMap
2370
2546
  registerShared(globalOptions, userOptions) {
2371
- const { shareInfos, shared } = formatShareConfigs(globalOptions, userOptions);
2372
- const sharedKeys = Object.keys(shareInfos);
2547
+ const { newShareInfos, allShareInfos } = formatShareConfigs(globalOptions, userOptions);
2548
+ const sharedKeys = Object.keys(newShareInfos);
2373
2549
  sharedKeys.forEach((sharedKey) => {
2374
- const sharedVals = shareInfos[sharedKey];
2550
+ const sharedVals = newShareInfos[sharedKey];
2375
2551
  sharedVals.forEach((sharedVal) => {
2376
2552
  sharedVal.scope.forEach((sc) => {
2553
+ this.hooks.lifecycle.beforeRegisterShare.emit({
2554
+ origin: this.host,
2555
+ pkgName: sharedKey,
2556
+ shared: sharedVal,
2557
+ });
2377
2558
  const registeredShared = this.shareScopeMap[sc]?.[sharedKey];
2378
2559
  if (!registeredShared) {
2379
2560
  this.setShared({
@@ -2389,8 +2570,8 @@ class SharedHandler {
2389
2570
  });
2390
2571
  });
2391
2572
  return {
2392
- shareInfos,
2393
- shared,
2573
+ newShareInfos,
2574
+ allShareInfos,
2394
2575
  };
2395
2576
  }
2396
2577
  async loadShare(pkgName, extraOptions) {
@@ -2421,61 +2602,61 @@ class SharedHandler {
2421
2602
  const { shareInfo: shareOptionsRes } = loadShareRes;
2422
2603
  // Assert that shareInfoRes exists, if not, throw an error
2423
2604
  assert(shareOptionsRes, `Cannot find ${pkgName} Share in the ${host.options.name}. Please ensure that the ${pkgName} Share parameters have been injected`);
2424
- // Retrieve from cache
2425
- const registeredShared = getRegisteredShare(this.shareScopeMap, pkgName, shareOptionsRes, this.hooks.lifecycle.resolveShare);
2426
- const addUseIn = (shared) => {
2427
- if (!shared.useIn) {
2428
- shared.useIn = [];
2429
- }
2430
- addUniqueItem(shared.useIn, host.options.name);
2431
- };
2432
- if (registeredShared && registeredShared.lib) {
2433
- addUseIn(registeredShared);
2434
- return registeredShared.lib;
2435
- }
2436
- else if (registeredShared &&
2437
- registeredShared.loading &&
2438
- !registeredShared.loaded) {
2439
- const factory = await registeredShared.loading;
2440
- registeredShared.loaded = true;
2441
- if (!registeredShared.lib) {
2442
- registeredShared.lib = factory;
2443
- }
2444
- addUseIn(registeredShared);
2445
- return factory;
2446
- }
2447
- else if (registeredShared) {
2448
- const asyncLoadProcess = async () => {
2449
- const factory = await registeredShared.get();
2450
- addUseIn(registeredShared);
2451
- registeredShared.loaded = true;
2452
- registeredShared.lib = factory;
2605
+ const { shared: registeredShared, useTreesShaking } = getRegisteredShare(this.shareScopeMap, pkgName, shareOptionsRes, this.hooks.lifecycle.resolveShare) || {};
2606
+ if (registeredShared) {
2607
+ const targetShared = directShare(registeredShared, useTreesShaking);
2608
+ if (targetShared.lib) {
2609
+ addUseIn(targetShared, host.options.name);
2610
+ return targetShared.lib;
2611
+ }
2612
+ else if (targetShared.loading && !targetShared.loaded) {
2613
+ const factory = await targetShared.loading;
2614
+ targetShared.loaded = true;
2615
+ if (!targetShared.lib) {
2616
+ targetShared.lib = factory;
2617
+ }
2618
+ addUseIn(targetShared, host.options.name);
2453
2619
  return factory;
2454
- };
2455
- const loading = asyncLoadProcess();
2456
- this.setShared({
2457
- pkgName,
2458
- loaded: false,
2459
- shared: registeredShared,
2460
- from: host.options.name,
2461
- lib: null,
2462
- loading,
2463
- });
2464
- return loading;
2620
+ }
2621
+ else {
2622
+ const asyncLoadProcess = async () => {
2623
+ const factory = await targetShared.get();
2624
+ addUseIn(targetShared, host.options.name);
2625
+ targetShared.loaded = true;
2626
+ targetShared.lib = factory;
2627
+ return factory;
2628
+ };
2629
+ const loading = asyncLoadProcess();
2630
+ this.setShared({
2631
+ pkgName,
2632
+ loaded: false,
2633
+ shared: registeredShared,
2634
+ from: host.options.name,
2635
+ lib: null,
2636
+ loading,
2637
+ treeShaking: useTreesShaking
2638
+ ? targetShared
2639
+ : undefined,
2640
+ });
2641
+ return loading;
2642
+ }
2465
2643
  }
2466
2644
  else {
2467
2645
  if (extraOptions?.customShareInfo) {
2468
2646
  return false;
2469
2647
  }
2648
+ const _useTreeShaking = shouldUseTreeShaking(shareOptionsRes.treeShaking);
2649
+ const targetShared = directShare(shareOptionsRes, _useTreeShaking);
2470
2650
  const asyncLoadProcess = async () => {
2471
- const factory = await shareOptionsRes.get();
2472
- shareOptionsRes.lib = factory;
2473
- shareOptionsRes.loaded = true;
2474
- addUseIn(shareOptionsRes);
2475
- const gShared = getRegisteredShare(this.shareScopeMap, pkgName, shareOptionsRes, this.hooks.lifecycle.resolveShare);
2651
+ const factory = await targetShared.get();
2652
+ targetShared.lib = factory;
2653
+ targetShared.loaded = true;
2654
+ addUseIn(targetShared, host.options.name);
2655
+ const { shared: gShared, useTreesShaking: gUseTreeShaking } = getRegisteredShare(this.shareScopeMap, pkgName, shareOptionsRes, this.hooks.lifecycle.resolveShare) || {};
2476
2656
  if (gShared) {
2477
- gShared.lib = factory;
2478
- gShared.loaded = true;
2657
+ const targetGShared = directShare(gShared, gUseTreeShaking);
2658
+ targetGShared.lib = factory;
2659
+ targetGShared.loaded = true;
2479
2660
  gShared.from = shareOptionsRes.from;
2480
2661
  }
2481
2662
  return factory;
@@ -2488,6 +2669,9 @@ class SharedHandler {
2488
2669
  from: host.options.name,
2489
2670
  lib: null,
2490
2671
  loading,
2672
+ treeShaking: _useTreeShaking
2673
+ ? targetShared
2674
+ : undefined,
2491
2675
  });
2492
2676
  return loading;
2493
2677
  }
@@ -2527,15 +2711,17 @@ class SharedHandler {
2527
2711
  const { version, eager } = shared;
2528
2712
  scope[name] = scope[name] || {};
2529
2713
  const versions = scope[name];
2530
- const activeVersion = versions[version];
2714
+ const activeVersion = versions[version] && directShare(versions[version]);
2531
2715
  const activeVersionEager = Boolean(activeVersion &&
2532
- (activeVersion.eager || activeVersion.shareConfig?.eager));
2716
+ (('eager' in activeVersion && activeVersion.eager) ||
2717
+ ('shareConfig' in activeVersion &&
2718
+ activeVersion.shareConfig?.eager)));
2533
2719
  if (!activeVersion ||
2534
2720
  (activeVersion.strategy !== 'loaded-first' &&
2535
2721
  !activeVersion.loaded &&
2536
2722
  (Boolean(!eager) !== !activeVersionEager
2537
2723
  ? eager
2538
- : hostName > activeVersion.from))) {
2724
+ : hostName > versions[version].from))) {
2539
2725
  versions[version] = shared;
2540
2726
  }
2541
2727
  };
@@ -2580,16 +2766,10 @@ class SharedHandler {
2580
2766
  this.initializeSharing(shareScope, { strategy: shareOptions.strategy });
2581
2767
  });
2582
2768
  }
2583
- const registeredShared = getRegisteredShare(this.shareScopeMap, pkgName, shareOptions, this.hooks.lifecycle.resolveShare);
2584
- const addUseIn = (shared) => {
2585
- if (!shared.useIn) {
2586
- shared.useIn = [];
2587
- }
2588
- addUniqueItem(shared.useIn, host.options.name);
2589
- };
2769
+ const { shared: registeredShared, useTreesShaking } = getRegisteredShare(this.shareScopeMap, pkgName, shareOptions, this.hooks.lifecycle.resolveShare) || {};
2590
2770
  if (registeredShared) {
2591
2771
  if (typeof registeredShared.lib === 'function') {
2592
- addUseIn(registeredShared);
2772
+ addUseIn(registeredShared, host.options.name);
2593
2773
  if (!registeredShared.loaded) {
2594
2774
  registeredShared.loaded = true;
2595
2775
  if (registeredShared.from === host.options.name) {
@@ -2601,7 +2781,7 @@ class SharedHandler {
2601
2781
  if (typeof registeredShared.get === 'function') {
2602
2782
  const module = registeredShared.get();
2603
2783
  if (!(module instanceof Promise)) {
2604
- addUseIn(registeredShared);
2784
+ addUseIn(registeredShared, host.options.name);
2605
2785
  this.setShared({
2606
2786
  pkgName,
2607
2787
  loaded: true,
@@ -2654,9 +2834,20 @@ class SharedHandler {
2654
2834
  hostShareScopeMap: extraOptions.hostShareScopeMap,
2655
2835
  });
2656
2836
  }
2657
- setShared({ pkgName, shared, from, lib, loading, loaded, get, }) {
2837
+ setShared({ pkgName, shared, from, lib, loading, loaded, get, treeShaking, }) {
2658
2838
  const { version, scope = 'default', ...shareInfo } = shared;
2659
2839
  const scopes = Array.isArray(scope) ? scope : [scope];
2840
+ const mergeAttrs = (shared) => {
2841
+ const merge = (s, key, val) => {
2842
+ if (val && !s[key]) {
2843
+ s[key] = val;
2844
+ }
2845
+ };
2846
+ const targetShared = (treeShaking ? shared.treeShaking : shared);
2847
+ merge(targetShared, 'loaded', loaded);
2848
+ merge(targetShared, 'loading', loading);
2849
+ merge(targetShared, 'get', get);
2850
+ };
2660
2851
  scopes.forEach((sc) => {
2661
2852
  if (!this.shareScopeMap[sc]) {
2662
2853
  this.shareScopeMap[sc] = {};
@@ -2670,21 +2861,10 @@ class SharedHandler {
2670
2861
  scope: [sc],
2671
2862
  ...shareInfo,
2672
2863
  lib,
2673
- loaded,
2674
- loading,
2675
2864
  };
2676
- if (get) {
2677
- this.shareScopeMap[sc][pkgName][version].get = get;
2678
- }
2679
- return;
2680
2865
  }
2681
2866
  const registeredShared = this.shareScopeMap[sc][pkgName][version];
2682
- if (loading && !registeredShared.loading) {
2683
- registeredShared.loading = loading;
2684
- }
2685
- if (loaded && !registeredShared.loaded) {
2686
- registeredShared.loaded = loaded;
2687
- }
2867
+ mergeAttrs(registeredShared);
2688
2868
  if (from && registeredShared.from !== from) {
2689
2869
  registeredShared.from = from;
2690
2870
  }
@@ -2712,6 +2892,7 @@ class RemoteHandler {
2712
2892
  generatePreloadAssets: new AsyncHook('generatePreloadAssets'),
2713
2893
  // not used yet
2714
2894
  afterPreloadRemote: new AsyncHook(),
2895
+ // TODO: Move to loaderHook
2715
2896
  loadEntry: new AsyncHook(),
2716
2897
  });
2717
2898
  this.host = host;
@@ -3060,7 +3241,7 @@ class ModuleFederation {
3060
3241
  // maybe will change, temporarily for internal use only
3061
3242
  initContainer: new AsyncWaterfallHook('initContainer'),
3062
3243
  });
3063
- this.version = "0.0.0-feat-modern-3-0-20260113090730";
3244
+ this.version = "0.0.0-feat-shared-treeshake-poc-20260114065000";
3064
3245
  this.moduleCache = new Map();
3065
3246
  this.loaderHook = new PluginSystem({
3066
3247
  // FIXME: may not be suitable , not open to the public yet
@@ -3141,7 +3322,7 @@ class ModuleFederation {
3141
3322
  this.sharedHandler.initShareScopeMap(scopeName, shareScope, extraOptions);
3142
3323
  }
3143
3324
  formatOptions(globalOptions, userOptions) {
3144
- const { shared } = formatShareConfigs(globalOptions, userOptions);
3325
+ const { allShareInfos: shared} = formatShareConfigs(globalOptions, userOptions);
3145
3326
  const { userOptions: userOptionsRes, options: globalOptionsRes } = this.hooks.lifecycle.beforeInit.emit({
3146
3327
  origin: this,
3147
3328
  userOptions,
@@ -3149,7 +3330,7 @@ class ModuleFederation {
3149
3330
  shareInfo: shared,
3150
3331
  });
3151
3332
  const remotes = this.remoteHandler.formatAndRegisterRemote(globalOptionsRes, userOptionsRes);
3152
- const { shared: handledShared } = this.sharedHandler.registerShared(globalOptionsRes, userOptionsRes);
3333
+ const { allShareInfos } = this.sharedHandler.registerShared(globalOptionsRes, userOptionsRes);
3153
3334
  const plugins = [...globalOptionsRes.plugins];
3154
3335
  if (userOptionsRes.plugins) {
3155
3336
  userOptionsRes.plugins.forEach((plugin) => {
@@ -3163,7 +3344,7 @@ class ModuleFederation {
3163
3344
  ...userOptions,
3164
3345
  plugins,
3165
3346
  remotes,
3166
- shared: handledShared,
3347
+ shared: allShareInfos,
3167
3348
  };
3168
3349
  this.hooks.lifecycle.init.emit({
3169
3350
  origin: this,