webpack 5.57.1 → 5.58.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.

Potentially problematic release.


This version of webpack might be problematic. Click here for more details.

@@ -5,11 +5,10 @@
5
5
 
6
6
  "use strict";
7
7
 
8
- const Chunk = require("../Chunk");
8
+ const ChunkCombination = require("../ChunkCombination");
9
9
  const { STAGE_ADVANCED } = require("../OptimizationStages");
10
10
  const WebpackError = require("../WebpackError");
11
11
  const { requestToId } = require("../ids/IdHelpers");
12
- const { isSubset } = require("../util/SetHelpers");
13
12
  const SortableSet = require("../util/SortableSet");
14
13
  const {
15
14
  compareModulesByIdentifier,
@@ -26,6 +25,7 @@ const MinMaxSizeWarning = require("./MinMaxSizeWarning");
26
25
  /** @typedef {import("../../declarations/WebpackOptions").OptimizationSplitChunksOptions} OptimizationSplitChunksOptions */
27
26
  /** @typedef {import("../../declarations/WebpackOptions").OptimizationSplitChunksSizes} OptimizationSplitChunksSizes */
28
27
  /** @typedef {import("../../declarations/WebpackOptions").Output} OutputOptions */
28
+ /** @typedef {import("../Chunk")} Chunk */
29
29
  /** @typedef {import("../ChunkGraph")} ChunkGraph */
30
30
  /** @typedef {import("../ChunkGroup")} ChunkGroup */
31
31
  /** @typedef {import("../Compilation").AssetInfo} AssetInfo */
@@ -155,9 +155,9 @@ const MinMaxSizeWarning = require("./MinMaxSizeWarning");
155
155
  * @property {number} cacheGroupIndex
156
156
  * @property {string} name
157
157
  * @property {Record<string, number>} sizes
158
- * @property {Set<Chunk>} chunks
158
+ * @property {ChunkCombination} chunks
159
159
  * @property {Set<Chunk>} reuseableChunks
160
- * @property {Set<bigint | Chunk>} chunksKeys
160
+ * @property {Set<ChunkCombination>} chunkCombinations
161
161
  */
162
162
 
163
163
  const defaultGetName = /** @type {GetName} */ (() => {});
@@ -204,19 +204,6 @@ const mapObject = (obj, fn) => {
204
204
  return newObj;
205
205
  };
206
206
 
207
- /**
208
- * @template T
209
- * @param {Set<T>} a set
210
- * @param {Set<T>} b other set
211
- * @returns {boolean} true if at least one item of a is in b
212
- */
213
- const isOverlap = (a, b) => {
214
- for (const item of a) {
215
- if (b.has(item)) return true;
216
- }
217
- return false;
218
- };
219
-
220
207
  const compareModuleIterables = compareIterables(compareModulesByIdentifier);
221
208
 
222
209
  /**
@@ -769,207 +756,132 @@ module.exports = class SplitChunksPlugin {
769
756
  logger.time("prepare");
770
757
  const chunkGraph = compilation.chunkGraph;
771
758
  const moduleGraph = compilation.moduleGraph;
772
- // Give each selected chunk an index (to create strings from chunks)
773
- /** @type {Map<Chunk, bigint>} */
774
- const chunkIndexMap = new Map();
775
- const ZERO = BigInt("0");
776
- const ONE = BigInt("1");
777
- let index = ONE;
778
- for (const chunk of chunks) {
779
- chunkIndexMap.set(chunk, index);
780
- index = index << ONE;
781
- }
782
- /**
783
- * @param {Iterable<Chunk>} chunks list of chunks
784
- * @returns {bigint | Chunk} key of the chunks
785
- */
786
- const getKey = chunks => {
787
- const iterator = chunks[Symbol.iterator]();
788
- let result = iterator.next();
789
- if (result.done) return ZERO;
790
- const first = result.value;
791
- result = iterator.next();
792
- if (result.done) return first;
793
- let key =
794
- chunkIndexMap.get(first) | chunkIndexMap.get(result.value);
795
- while (!(result = iterator.next()).done) {
796
- key = key | chunkIndexMap.get(result.value);
797
- }
798
- return key;
799
- };
800
- const keyToString = key => {
801
- if (typeof key === "bigint") return key.toString(16);
802
- return chunkIndexMap.get(key).toString(16);
803
- };
804
759
 
805
- const getChunkSetsInGraph = memoize(() => {
806
- /** @type {Map<bigint, Set<Chunk>>} */
807
- const chunkSetsInGraph = new Map();
808
- /** @type {Set<Chunk>} */
809
- const singleChunkSets = new Set();
760
+ const getChunkCombinationsInGraph = memoize(() => {
761
+ /** @type {Set<ChunkCombination>} */
762
+ const chunkCombinationsInGraph = new Set();
810
763
  for (const module of compilation.modules) {
811
- const chunks = chunkGraph.getModuleChunksIterable(module);
812
- const chunksKey = getKey(chunks);
813
- if (typeof chunksKey === "bigint") {
814
- if (!chunkSetsInGraph.has(chunksKey)) {
815
- chunkSetsInGraph.set(chunksKey, new Set(chunks));
816
- }
817
- } else {
818
- singleChunkSets.add(chunksKey);
819
- }
764
+ const chunkCombination =
765
+ chunkGraph.getModuleChunkCombination(module);
766
+ chunkCombinationsInGraph.add(chunkCombination);
820
767
  }
821
- return { chunkSetsInGraph, singleChunkSets };
768
+ return chunkCombinationsInGraph;
822
769
  });
823
770
 
824
771
  /**
825
772
  * @param {Module} module the module
826
- * @returns {Iterable<Chunk[]>} groups of chunks with equal exports
773
+ * @returns {Iterable<ChunkCombination>} groups of chunks with equal exports
827
774
  */
828
775
  const groupChunksByExports = module => {
829
776
  const exportsInfo = moduleGraph.getExportsInfo(module);
830
777
  const groupedByUsedExports = new Map();
831
778
  for (const chunk of chunkGraph.getModuleChunksIterable(module)) {
832
779
  const key = exportsInfo.getUsageKey(chunk.runtime);
833
- const list = groupedByUsedExports.get(key);
834
- if (list !== undefined) {
835
- list.push(chunk);
836
- } else {
837
- groupedByUsedExports.set(key, [chunk]);
838
- }
780
+ const combination =
781
+ groupedByUsedExports.get(key) || ChunkCombination.empty;
782
+ groupedByUsedExports.set(key, combination.with(chunk));
839
783
  }
840
784
  return groupedByUsedExports.values();
841
785
  };
842
786
 
843
- /** @type {Map<Module, Iterable<Chunk[]>>} */
787
+ /** @type {Map<Module, Iterable<ChunkCombination>>} */
844
788
  const groupedByExportsMap = new Map();
845
789
 
846
- const getExportsChunkSetsInGraph = memoize(() => {
847
- /** @type {Map<bigint, Set<Chunk>>} */
848
- const chunkSetsInGraph = new Map();
849
- /** @type {Set<Chunk>} */
850
- const singleChunkSets = new Set();
790
+ const getExportsChunkCombinationsInGraph = memoize(() => {
791
+ /** @type {Set<ChunkCombination>} */
792
+ const chunkCombinationsInGraph = new Set();
851
793
  for (const module of compilation.modules) {
852
794
  const groupedChunks = Array.from(groupChunksByExports(module));
853
795
  groupedByExportsMap.set(module, groupedChunks);
854
- for (const chunks of groupedChunks) {
855
- if (chunks.length === 1) {
856
- singleChunkSets.add(chunks[0]);
857
- } else {
858
- const chunksKey = /** @type {bigint} */ (getKey(chunks));
859
- if (!chunkSetsInGraph.has(chunksKey)) {
860
- chunkSetsInGraph.set(chunksKey, new Set(chunks));
861
- }
862
- }
796
+ for (const chunkCombination of groupedChunks) {
797
+ chunkCombinationsInGraph.add(chunkCombination);
863
798
  }
864
799
  }
865
- return { chunkSetsInGraph, singleChunkSets };
800
+ return chunkCombinationsInGraph;
866
801
  });
867
802
 
868
803
  // group these set of chunks by count
869
804
  // to allow to check less sets via isSubset
870
805
  // (only smaller sets can be subset)
871
- const groupChunkSetsByCount = chunkSets => {
872
- /** @type {Map<number, Array<Set<Chunk>>>} */
873
- const chunkSetsByCount = new Map();
874
- for (const chunksSet of chunkSets) {
806
+ const groupChunkCombinationsByCount = chunkCombinations => {
807
+ /** @type {Map<number, ChunkCombination[]>} */
808
+ const chunkCombinationsByCount = new Map();
809
+ for (const chunksSet of chunkCombinations) {
875
810
  const count = chunksSet.size;
876
- let array = chunkSetsByCount.get(count);
811
+ let array = chunkCombinationsByCount.get(count);
877
812
  if (array === undefined) {
878
813
  array = [];
879
- chunkSetsByCount.set(count, array);
814
+ chunkCombinationsByCount.set(count, array);
880
815
  }
881
816
  array.push(chunksSet);
882
817
  }
883
- return chunkSetsByCount;
818
+ return chunkCombinationsByCount;
884
819
  };
885
- const getChunkSetsByCount = memoize(() =>
886
- groupChunkSetsByCount(
887
- getChunkSetsInGraph().chunkSetsInGraph.values()
888
- )
820
+ const getChunkCombinationsByCount = memoize(() =>
821
+ groupChunkCombinationsByCount(getChunkCombinationsInGraph())
889
822
  );
890
- const getExportsChunkSetsByCount = memoize(() =>
891
- groupChunkSetsByCount(
892
- getExportsChunkSetsInGraph().chunkSetsInGraph.values()
893
- )
823
+ const getExportsChunkCombinationsByCount = memoize(() =>
824
+ groupChunkCombinationsByCount(getExportsChunkCombinationsInGraph())
894
825
  );
895
826
 
896
- // Create a list of possible combinations
897
- const createGetCombinations = (
898
- chunkSets,
899
- singleChunkSets,
900
- chunkSetsByCount
901
- ) => {
902
- /** @type {Map<bigint | Chunk, (Set<Chunk> | Chunk)[]>} */
827
+ /**
828
+ * Create a list of possible combinations
829
+ * @param {Map<number, ChunkCombination[]>} chunkCombinationsByCount by count
830
+ * @returns {function(ChunkCombination): ChunkCombination[]} get combinations function
831
+ */
832
+ const createGetCombinations = chunkCombinationsByCount => {
833
+ /** @type {Map<ChunkCombination, ChunkCombination[]>} */
903
834
  const combinationsCache = new Map();
904
835
 
905
- return key => {
906
- const cacheEntry = combinationsCache.get(key);
836
+ /**
837
+ * @param {ChunkCombination} chunkCombination chunkCombination
838
+ * @returns {ChunkCombination[]} combinations
839
+ */
840
+ return chunkCombination => {
841
+ const cacheEntry = combinationsCache.get(chunkCombination);
907
842
  if (cacheEntry !== undefined) return cacheEntry;
908
- if (key instanceof Chunk) {
909
- const result = [key];
910
- combinationsCache.set(key, result);
843
+ if (chunkCombination.size === 1) {
844
+ const result = [chunkCombination];
845
+ combinationsCache.set(chunkCombination, result);
911
846
  return result;
912
847
  }
913
- const chunksSet = chunkSets.get(key);
914
- /** @type {(Set<Chunk> | Chunk)[]} */
915
- const array = [chunksSet];
916
- for (const [count, setArray] of chunkSetsByCount) {
848
+ /** @type {ChunkCombination[]} */
849
+ const array = [chunkCombination];
850
+ for (const [count, setArray] of chunkCombinationsByCount) {
917
851
  // "equal" is not needed because they would have been merge in the first step
918
- if (count < chunksSet.size) {
852
+ if (count < chunkCombination.size) {
919
853
  for (const set of setArray) {
920
- if (isSubset(chunksSet, set)) {
854
+ if (chunkCombination.isSubset(set)) {
921
855
  array.push(set);
922
856
  }
923
857
  }
924
858
  }
925
859
  }
926
- for (const chunk of singleChunkSets) {
927
- if (chunksSet.has(chunk)) {
928
- array.push(chunk);
929
- }
930
- }
931
- combinationsCache.set(key, array);
860
+ combinationsCache.set(chunkCombination, array);
932
861
  return array;
933
862
  };
934
863
  };
935
864
 
936
865
  const getCombinationsFactory = memoize(() => {
937
- const { chunkSetsInGraph, singleChunkSets } = getChunkSetsInGraph();
938
- return createGetCombinations(
939
- chunkSetsInGraph,
940
- singleChunkSets,
941
- getChunkSetsByCount()
942
- );
866
+ return createGetCombinations(getChunkCombinationsByCount());
943
867
  });
944
868
  const getCombinations = key => getCombinationsFactory()(key);
945
869
 
946
870
  const getExportsCombinationsFactory = memoize(() => {
947
- const { chunkSetsInGraph, singleChunkSets } =
948
- getExportsChunkSetsInGraph();
949
- return createGetCombinations(
950
- chunkSetsInGraph,
951
- singleChunkSets,
952
- getExportsChunkSetsByCount()
953
- );
871
+ return createGetCombinations(getExportsChunkCombinationsByCount());
954
872
  });
955
873
  const getExportsCombinations = key =>
956
874
  getExportsCombinationsFactory()(key);
957
875
 
958
- /**
959
- * @typedef {Object} SelectedChunksResult
960
- * @property {Chunk[]} chunks the list of chunks
961
- * @property {bigint | Chunk} key a key of the list
962
- */
963
-
964
- /** @type {WeakMap<Set<Chunk> | Chunk, WeakMap<ChunkFilterFunction, SelectedChunksResult>>} */
876
+ /** @type {WeakMap<ChunkCombination, WeakMap<ChunkFilterFunction, ChunkCombination>>} */
965
877
  const selectedChunksCacheByChunksSet = new WeakMap();
966
878
 
967
879
  /**
968
- * get list and key by applying the filter function to the list
880
+ * get chunks by applying the filter function to the list
969
881
  * It is cached for performance reasons
970
- * @param {Set<Chunk> | Chunk} chunks list of chunks
882
+ * @param {ChunkCombination} chunks list of chunks
971
883
  * @param {ChunkFilterFunction} chunkFilter filter function for chunks
972
- * @returns {SelectedChunksResult} list and key
884
+ * @returns {ChunkCombination} selected chunks
973
885
  */
974
886
  const getSelectedChunks = (chunks, chunkFilter) => {
975
887
  let entry = selectedChunksCacheByChunksSet.get(chunks);
@@ -977,22 +889,16 @@ module.exports = class SplitChunksPlugin {
977
889
  entry = new WeakMap();
978
890
  selectedChunksCacheByChunksSet.set(chunks, entry);
979
891
  }
980
- /** @type {SelectedChunksResult} */
892
+ /** @type {ChunkCombination} */
981
893
  let entry2 = entry.get(chunkFilter);
982
894
  if (entry2 === undefined) {
983
- /** @type {Chunk[]} */
984
- const selectedChunks = [];
985
- if (chunks instanceof Chunk) {
986
- if (chunkFilter(chunks)) selectedChunks.push(chunks);
987
- } else {
988
- for (const chunk of chunks) {
989
- if (chunkFilter(chunk)) selectedChunks.push(chunk);
990
- }
895
+ /** @type {ChunkCombination} */
896
+ let selectedChunks = ChunkCombination.empty;
897
+ for (const chunk of chunks.chunksIterable) {
898
+ if (chunkFilter(chunk))
899
+ selectedChunks = selectedChunks.with(chunk);
991
900
  }
992
- entry2 = {
993
- chunks: selectedChunks,
994
- key: getKey(selectedChunks)
995
- };
901
+ entry2 = selectedChunks;
996
902
  entry.set(chunkFilter, entry2);
997
903
  }
998
904
  return entry2;
@@ -1011,8 +917,7 @@ module.exports = class SplitChunksPlugin {
1011
917
  /**
1012
918
  * @param {CacheGroup} cacheGroup the current cache group
1013
919
  * @param {number} cacheGroupIndex the index of the cache group of ordering
1014
- * @param {Chunk[]} selectedChunks chunks selected for this module
1015
- * @param {bigint | Chunk} selectedChunksKey a key of selectedChunks
920
+ * @param {ChunkCombination} selectedChunks chunks selected for this module
1016
921
  * @param {Module} module the current module
1017
922
  * @returns {void}
1018
923
  */
@@ -1020,25 +925,20 @@ module.exports = class SplitChunksPlugin {
1020
925
  cacheGroup,
1021
926
  cacheGroupIndex,
1022
927
  selectedChunks,
1023
- selectedChunksKey,
1024
928
  module
1025
929
  ) => {
1026
930
  // Break if minimum number of chunks is not reached
1027
- if (selectedChunks.length < cacheGroup.minChunks) return;
931
+ if (selectedChunks.size < cacheGroup.minChunks) return;
1028
932
  // Determine name for split chunk
1029
933
  const name = cacheGroup.getName(
1030
934
  module,
1031
- selectedChunks,
935
+ selectedChunks.getChunks(),
1032
936
  cacheGroup.key
1033
937
  );
1034
938
  // Check if the name is ok
1035
939
  const existingChunk = compilation.namedChunks.get(name);
1036
940
  if (existingChunk) {
1037
- const parentValidationKey = `${name}|${
1038
- typeof selectedChunksKey === "bigint"
1039
- ? selectedChunksKey
1040
- : selectedChunksKey.debugId
1041
- }`;
941
+ const parentValidationKey = `${name}|${selectedChunks.debugId}`;
1042
942
  const valid = alreadyValidatedParents.get(parentValidationKey);
1043
943
  if (valid === false) return;
1044
944
  if (valid === undefined) {
@@ -1047,7 +947,7 @@ module.exports = class SplitChunksPlugin {
1047
947
  let isInAllParents = true;
1048
948
  /** @type {Set<ChunkGroup>} */
1049
949
  const queue = new Set();
1050
- for (const chunk of selectedChunks) {
950
+ for (const chunk of selectedChunks.chunksIterable) {
1051
951
  for (const group of chunk.groupsIterable) {
1052
952
  queue.add(group);
1053
953
  }
@@ -1093,9 +993,7 @@ module.exports = class SplitChunksPlugin {
1093
993
  // This automatically merges equal names
1094
994
  const key =
1095
995
  cacheGroup.key +
1096
- (name
1097
- ? ` name:${name}`
1098
- : ` chunks:${keyToString(selectedChunksKey)}`);
996
+ (name ? ` name:${name}` : ` chunks:${selectedChunks.debugId}`);
1099
997
  // Add module to maps
1100
998
  let info = chunksInfoMap.get(key);
1101
999
  if (info === undefined) {
@@ -1110,9 +1008,9 @@ module.exports = class SplitChunksPlugin {
1110
1008
  cacheGroupIndex,
1111
1009
  name,
1112
1010
  sizes: {},
1113
- chunks: new Set(),
1011
+ chunks: ChunkCombination.empty,
1114
1012
  reuseableChunks: new Set(),
1115
- chunksKeys: new Set()
1013
+ chunkCombinations: new Set()
1116
1014
  })
1117
1015
  );
1118
1016
  }
@@ -1123,12 +1021,10 @@ module.exports = class SplitChunksPlugin {
1123
1021
  info.sizes[type] = (info.sizes[type] || 0) + module.size(type);
1124
1022
  }
1125
1023
  }
1126
- const oldChunksKeysSize = info.chunksKeys.size;
1127
- info.chunksKeys.add(selectedChunksKey);
1128
- if (oldChunksKeysSize !== info.chunksKeys.size) {
1129
- for (const chunk of selectedChunks) {
1130
- info.chunks.add(chunk);
1131
- }
1024
+ const oldChunksKeysSize = info.chunkCombinations.size;
1025
+ info.chunkCombinations.add(selectedChunks);
1026
+ if (oldChunksKeysSize !== info.chunkCombinations.size) {
1027
+ info.chunks = info.chunks.withAll(selectedChunks);
1132
1028
  }
1133
1029
  };
1134
1030
 
@@ -1149,50 +1045,56 @@ module.exports = class SplitChunksPlugin {
1149
1045
  continue;
1150
1046
  }
1151
1047
 
1152
- // Prepare some values (usedExports = false)
1153
- const getCombs = memoize(() => {
1154
- const chunks = chunkGraph.getModuleChunksIterable(module);
1155
- const chunksKey = getKey(chunks);
1156
- return getCombinations(chunksKey);
1157
- });
1158
-
1159
- // Prepare some values (usedExports = true)
1160
- const getCombsByUsedExports = memoize(() => {
1161
- // fill the groupedByExportsMap
1162
- getExportsChunkSetsInGraph();
1163
- /** @type {Set<Set<Chunk> | Chunk>} */
1164
- const set = new Set();
1165
- const groupedByUsedExports = groupedByExportsMap.get(module);
1166
- for (const chunks of groupedByUsedExports) {
1167
- const chunksKey = getKey(chunks);
1168
- for (const comb of getExportsCombinations(chunksKey))
1169
- set.add(comb);
1170
- }
1171
- return set;
1172
- });
1048
+ const chunkCombination =
1049
+ chunkGraph.getModuleChunkCombination(module);
1173
1050
 
1174
1051
  let cacheGroupIndex = 0;
1175
1052
  for (const cacheGroupSource of cacheGroups) {
1176
1053
  const cacheGroup = this._getCacheGroup(cacheGroupSource);
1177
1054
 
1178
- const combs = cacheGroup.usedExports
1179
- ? getCombsByUsedExports()
1180
- : getCombs();
1055
+ // Break if minimum number of chunks is not reached
1056
+ if (chunkCombination.size < cacheGroup.minChunks) continue;
1057
+
1058
+ /** @type {Iterable<ChunkCombination>} */
1059
+ let combs;
1060
+ if (cacheGroup.usedExports) {
1061
+ // fill the groupedByExportsMap
1062
+ getExportsChunkCombinationsInGraph();
1063
+ /** @type {Set<ChunkCombination>} */
1064
+ const set = new Set();
1065
+ const groupedByUsedExports = groupedByExportsMap.get(module);
1066
+ for (const chunkCombination of groupedByUsedExports) {
1067
+ const preSelectedChunks = getSelectedChunks(
1068
+ chunkCombination,
1069
+ cacheGroup.chunksFilter
1070
+ );
1071
+ // Break if minimum number of chunks is not reached
1072
+ if (preSelectedChunks.size < cacheGroup.minChunks) continue;
1073
+
1074
+ for (const comb of getExportsCombinations(preSelectedChunks))
1075
+ set.add(comb);
1076
+ }
1077
+ combs = set;
1078
+ } else {
1079
+ const preSelectedChunks = getSelectedChunks(
1080
+ chunkCombination,
1081
+ cacheGroup.chunksFilter
1082
+ );
1083
+ // Break if minimum number of chunks is not reached
1084
+ if (preSelectedChunks.size < cacheGroup.minChunks) continue;
1085
+
1086
+ combs = getCombinations(preSelectedChunks);
1087
+ }
1181
1088
  // For all combination of chunk selection
1182
- for (const chunkCombination of combs) {
1089
+ for (const selectedChunks of combs) {
1183
1090
  // Break if minimum number of chunks is not reached
1184
- const count =
1185
- chunkCombination instanceof Chunk ? 1 : chunkCombination.size;
1091
+ const count = chunkCombination.size;
1186
1092
  if (count < cacheGroup.minChunks) continue;
1187
- // Select chunks by configuration
1188
- const { chunks: selectedChunks, key: selectedChunksKey } =
1189
- getSelectedChunks(chunkCombination, cacheGroup.chunksFilter);
1190
1093
 
1191
1094
  addModuleToChunksInfoMap(
1192
1095
  cacheGroup,
1193
1096
  cacheGroupIndex,
1194
1097
  selectedChunks,
1195
- selectedChunksKey,
1196
1098
  module
1197
1099
  );
1198
1100
  }
@@ -1284,12 +1186,12 @@ module.exports = class SplitChunksPlugin {
1284
1186
  const chunkByName = compilation.namedChunks.get(chunkName);
1285
1187
  if (chunkByName !== undefined) {
1286
1188
  newChunk = chunkByName;
1287
- const oldSize = item.chunks.size;
1288
- item.chunks.delete(newChunk);
1289
- isExistingChunk = item.chunks.size !== oldSize;
1189
+ const newChunks = item.chunks.without(newChunk);
1190
+ isExistingChunk = newChunks !== item.chunks;
1191
+ if (isExistingChunk) item.chunks = newChunks;
1290
1192
  }
1291
1193
  } else if (item.cacheGroup.reuseExistingChunk) {
1292
- outer: for (const chunk of item.chunks) {
1194
+ outer: for (const chunk of item.chunks.chunksIterable) {
1293
1195
  if (
1294
1196
  chunkGraph.getNumberOfChunkModules(chunk) !==
1295
1197
  item.modules.size
@@ -1323,7 +1225,7 @@ module.exports = class SplitChunksPlugin {
1323
1225
  }
1324
1226
  }
1325
1227
  if (newChunk) {
1326
- item.chunks.delete(newChunk);
1228
+ item.chunks = item.chunks.without(newChunk);
1327
1229
  chunkName = undefined;
1328
1230
  isExistingChunk = true;
1329
1231
  isReusedWithAllModules = true;
@@ -1334,7 +1236,7 @@ module.exports = class SplitChunksPlugin {
1334
1236
  item.cacheGroup._conditionalEnforce &&
1335
1237
  checkMinSize(item.sizes, item.cacheGroup.enforceSizeThreshold);
1336
1238
 
1337
- const usedChunks = new Set(item.chunks);
1239
+ let usedChunks = item.chunks;
1338
1240
 
1339
1241
  // Check if maxRequests condition can be fulfilled
1340
1242
  if (
@@ -1342,7 +1244,7 @@ module.exports = class SplitChunksPlugin {
1342
1244
  (Number.isFinite(item.cacheGroup.maxInitialRequests) ||
1343
1245
  Number.isFinite(item.cacheGroup.maxAsyncRequests))
1344
1246
  ) {
1345
- for (const chunk of usedChunks) {
1247
+ for (const chunk of usedChunks.chunksIterable) {
1346
1248
  // respect max requests
1347
1249
  const maxRequests = chunk.isOnlyInitial()
1348
1250
  ? item.cacheGroup.maxInitialRequests
@@ -1356,30 +1258,28 @@ module.exports = class SplitChunksPlugin {
1356
1258
  isFinite(maxRequests) &&
1357
1259
  getRequests(chunk) >= maxRequests
1358
1260
  ) {
1359
- usedChunks.delete(chunk);
1261
+ usedChunks = usedChunks.without(chunk);
1360
1262
  }
1361
1263
  }
1362
1264
  }
1363
1265
 
1364
- outer: for (const chunk of usedChunks) {
1266
+ outer: for (const chunk of usedChunks.chunksIterable) {
1365
1267
  for (const module of item.modules) {
1366
1268
  if (chunkGraph.isModuleInChunk(module, chunk)) continue outer;
1367
1269
  }
1368
- usedChunks.delete(chunk);
1270
+ usedChunks = usedChunks.without(chunk);
1369
1271
  }
1370
1272
 
1371
1273
  // Were some (invalid) chunks removed from usedChunks?
1372
1274
  // => readd all modules to the queue, as things could have been changed
1373
- if (usedChunks.size < item.chunks.size) {
1374
- if (isExistingChunk) usedChunks.add(newChunk);
1275
+ if (usedChunks !== item.chunks) {
1276
+ if (isExistingChunk) usedChunks = usedChunks.with(newChunk);
1375
1277
  if (usedChunks.size >= item.cacheGroup.minChunks) {
1376
- const chunksArr = Array.from(usedChunks);
1377
1278
  for (const module of item.modules) {
1378
1279
  addModuleToChunksInfoMap(
1379
1280
  item.cacheGroup,
1380
1281
  item.cacheGroupIndex,
1381
- chunksArr,
1382
- getKey(usedChunks),
1282
+ usedChunks,
1383
1283
  module
1384
1284
  );
1385
1285
  }
@@ -1393,7 +1293,7 @@ module.exports = class SplitChunksPlugin {
1393
1293
  item.cacheGroup._validateRemainingSize &&
1394
1294
  usedChunks.size === 1
1395
1295
  ) {
1396
- const [chunk] = usedChunks;
1296
+ const [chunk] = usedChunks.chunksIterable;
1397
1297
  let chunkSizes = Object.create(null);
1398
1298
  for (const module of chunkGraph.getChunkModulesIterable(chunk)) {
1399
1299
  if (!item.modules.has(module)) {
@@ -1427,7 +1327,7 @@ module.exports = class SplitChunksPlugin {
1427
1327
  newChunk = compilation.addChunk(chunkName);
1428
1328
  }
1429
1329
  // Walk through all chunks
1430
- for (const chunk of usedChunks) {
1330
+ for (const chunk of usedChunks.chunksIterable) {
1431
1331
  // Add graph connections for splitted chunk
1432
1332
  chunk.split(newChunk);
1433
1333
  }
@@ -1457,14 +1357,14 @@ module.exports = class SplitChunksPlugin {
1457
1357
  // Add module to new chunk
1458
1358
  chunkGraph.connectChunkAndModule(newChunk, module);
1459
1359
  // Remove module from used chunks
1460
- for (const chunk of usedChunks) {
1360
+ for (const chunk of usedChunks.chunksIterable) {
1461
1361
  chunkGraph.disconnectChunkAndModule(chunk, module);
1462
1362
  }
1463
1363
  }
1464
1364
  } else {
1465
1365
  // Remove all modules from used chunks
1466
1366
  for (const module of item.modules) {
1467
- for (const chunk of usedChunks) {
1367
+ for (const chunk of usedChunks.chunksIterable) {
1468
1368
  chunkGraph.disconnectChunkAndModule(chunk, module);
1469
1369
  }
1470
1370
  }
@@ -1506,7 +1406,7 @@ module.exports = class SplitChunksPlugin {
1506
1406
 
1507
1407
  // remove all modules from other entries and update size
1508
1408
  for (const [key, info] of chunksInfoMap) {
1509
- if (isOverlap(info.chunks, usedChunks)) {
1409
+ if (info.chunks.hasSharedChunks(usedChunks)) {
1510
1410
  // update modules and total size
1511
1411
  // may remove it from the map when < minSize
1512
1412
  let updated = false;
@@ -6,6 +6,7 @@
6
6
  "use strict";
7
7
 
8
8
  const { URL, fileURLToPath } = require("url");
9
+ const { NormalModule } = require("..");
9
10
 
10
11
  /** @typedef {import("../Compiler")} Compiler */
11
12
 
@@ -32,6 +33,14 @@ class FileUriPlugin {
32
33
  resourceData.resource = path + query + fragment;
33
34
  return true;
34
35
  });
36
+ const hooks = NormalModule.getCompilationHooks(compilation);
37
+ hooks.readResource
38
+ .for(undefined)
39
+ .tapAsync("FileUriPlugin", (loaderContext, callback) => {
40
+ const { resourcePath } = loaderContext;
41
+ loaderContext.addDependency(resourcePath);
42
+ loaderContext.fs.readFile(resourcePath, callback);
43
+ });
35
44
  }
36
45
  );
37
46
  }