webpack 5.58.0 → 5.59.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.
Potentially problematic release.
This version of webpack might be problematic. Click here for more details.
- package/lib/ChunkGraph.js +16 -30
- package/lib/Compilation.js +175 -109
- package/lib/Compiler.js +2 -2
- package/lib/DefinePlugin.js +1 -1
- package/lib/FileSystemInfo.js +112 -30
- package/lib/NormalModule.js +31 -11
- package/lib/NormalModuleFactory.js +57 -55
- package/lib/RuntimeTemplate.js +1 -1
- package/lib/WebpackOptionsApply.js +0 -2
- package/lib/cache/AddManagedPathsPlugin.js +2 -2
- package/lib/cache/PackFileCacheStrategy.js +2 -2
- package/lib/config/defaults.js +65 -43
- package/lib/config/normalization.js +6 -1
- package/lib/optimize/ConcatenatedModule.js +1 -1
- package/lib/optimize/SplitChunksPlugin.js +289 -136
- package/lib/schemes/HttpUriPlugin.js +108 -31
- package/lib/serialization/Serializer.js +2 -4
- package/lib/util/fs.js +2 -0
- package/lib/util/propertyAccess.js +2 -2
- package/lib/wasm-sync/WebAssemblyInInitialChunkError.js +1 -6
- package/package.json +1 -1
- package/schemas/WebpackOptions.check.js +1 -1
- package/schemas/WebpackOptions.json +258 -55
- package/schemas/plugins/schemes/HttpUriPlugin.check.js +1 -1
- package/schemas/plugins/schemes/HttpUriPlugin.json +28 -0
- package/types.d.ts +110 -101
- package/lib/ChunkCombination.js +0 -187
@@ -5,10 +5,11 @@
|
|
5
5
|
|
6
6
|
"use strict";
|
7
7
|
|
8
|
-
const
|
8
|
+
const Chunk = require("../Chunk");
|
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");
|
12
13
|
const SortableSet = require("../util/SortableSet");
|
13
14
|
const {
|
14
15
|
compareModulesByIdentifier,
|
@@ -25,7 +26,6 @@ const MinMaxSizeWarning = require("./MinMaxSizeWarning");
|
|
25
26
|
/** @typedef {import("../../declarations/WebpackOptions").OptimizationSplitChunksOptions} OptimizationSplitChunksOptions */
|
26
27
|
/** @typedef {import("../../declarations/WebpackOptions").OptimizationSplitChunksSizes} OptimizationSplitChunksSizes */
|
27
28
|
/** @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 */
|
@@ -59,6 +59,7 @@ const MinMaxSizeWarning = require("./MinMaxSizeWarning");
|
|
59
59
|
* @property {ChunkFilterFunction=} chunksFilter
|
60
60
|
* @property {boolean=} enforce
|
61
61
|
* @property {SplitChunksSizes} minSize
|
62
|
+
* @property {SplitChunksSizes} minSizeReduction
|
62
63
|
* @property {SplitChunksSizes} minRemainingSize
|
63
64
|
* @property {SplitChunksSizes} enforceSizeThreshold
|
64
65
|
* @property {SplitChunksSizes} maxAsyncSize
|
@@ -80,6 +81,7 @@ const MinMaxSizeWarning = require("./MinMaxSizeWarning");
|
|
80
81
|
* @property {GetName=} getName
|
81
82
|
* @property {ChunkFilterFunction=} chunksFilter
|
82
83
|
* @property {SplitChunksSizes} minSize
|
84
|
+
* @property {SplitChunksSizes} minSizeReduction
|
83
85
|
* @property {SplitChunksSizes} minRemainingSize
|
84
86
|
* @property {SplitChunksSizes} enforceSizeThreshold
|
85
87
|
* @property {SplitChunksSizes} maxAsyncSize
|
@@ -132,6 +134,7 @@ const MinMaxSizeWarning = require("./MinMaxSizeWarning");
|
|
132
134
|
* @property {ChunkFilterFunction} chunksFilter
|
133
135
|
* @property {string[]} defaultSizeTypes
|
134
136
|
* @property {SplitChunksSizes} minSize
|
137
|
+
* @property {SplitChunksSizes} minSizeReduction
|
135
138
|
* @property {SplitChunksSizes} minRemainingSize
|
136
139
|
* @property {SplitChunksSizes} enforceSizeThreshold
|
137
140
|
* @property {SplitChunksSizes} maxInitialSize
|
@@ -155,9 +158,9 @@ const MinMaxSizeWarning = require("./MinMaxSizeWarning");
|
|
155
158
|
* @property {number} cacheGroupIndex
|
156
159
|
* @property {string} name
|
157
160
|
* @property {Record<string, number>} sizes
|
158
|
-
* @property {
|
161
|
+
* @property {Set<Chunk>} chunks
|
159
162
|
* @property {Set<Chunk>} reuseableChunks
|
160
|
-
* @property {Set<
|
163
|
+
* @property {Set<bigint | Chunk>} chunksKeys
|
161
164
|
*/
|
162
165
|
|
163
166
|
const defaultGetName = /** @type {GetName} */ (() => {});
|
@@ -204,6 +207,19 @@ const mapObject = (obj, fn) => {
|
|
204
207
|
return newObj;
|
205
208
|
};
|
206
209
|
|
210
|
+
/**
|
211
|
+
* @template T
|
212
|
+
* @param {Set<T>} a set
|
213
|
+
* @param {Set<T>} b other set
|
214
|
+
* @returns {boolean} true if at least one item of a is in b
|
215
|
+
*/
|
216
|
+
const isOverlap = (a, b) => {
|
217
|
+
for (const item of a) {
|
218
|
+
if (b.has(item)) return true;
|
219
|
+
}
|
220
|
+
return false;
|
221
|
+
};
|
222
|
+
|
207
223
|
const compareModuleIterables = compareIterables(compareModulesByIdentifier);
|
208
224
|
|
209
225
|
/**
|
@@ -323,6 +339,21 @@ const checkMinSize = (sizes, minSize) => {
|
|
323
339
|
return true;
|
324
340
|
};
|
325
341
|
|
342
|
+
/**
|
343
|
+
* @param {SplitChunksSizes} sizes the sizes
|
344
|
+
* @param {SplitChunksSizes} minSizeReduction the min sizes
|
345
|
+
* @param {number} chunkCount number of chunks
|
346
|
+
* @returns {boolean} true if there are sizes and all existing sizes are at least `minSizeReduction`
|
347
|
+
*/
|
348
|
+
const checkMinSizeReduction = (sizes, minSizeReduction, chunkCount) => {
|
349
|
+
for (const key of Object.keys(minSizeReduction)) {
|
350
|
+
const size = sizes[key];
|
351
|
+
if (size === undefined || size === 0) continue;
|
352
|
+
if (size * chunkCount < minSizeReduction[key]) return false;
|
353
|
+
}
|
354
|
+
return true;
|
355
|
+
};
|
356
|
+
|
326
357
|
/**
|
327
358
|
* @param {SplitChunksSizes} sizes the sizes
|
328
359
|
* @param {SplitChunksSizes} minSize the min sizes
|
@@ -535,6 +566,10 @@ const checkModuleLayer = (test, module) => {
|
|
535
566
|
*/
|
536
567
|
const createCacheGroupSource = (options, key, defaultSizeTypes) => {
|
537
568
|
const minSize = normalizeSizes(options.minSize, defaultSizeTypes);
|
569
|
+
const minSizeReduction = normalizeSizes(
|
570
|
+
options.minSizeReduction,
|
571
|
+
defaultSizeTypes
|
572
|
+
);
|
538
573
|
const maxSize = normalizeSizes(options.maxSize, defaultSizeTypes);
|
539
574
|
return {
|
540
575
|
key,
|
@@ -543,6 +578,7 @@ const createCacheGroupSource = (options, key, defaultSizeTypes) => {
|
|
543
578
|
chunksFilter: normalizeChunksFilter(options.chunks),
|
544
579
|
enforce: options.enforce,
|
545
580
|
minSize,
|
581
|
+
minSizeReduction,
|
546
582
|
minRemainingSize: mergeSizes(
|
547
583
|
normalizeSizes(options.minRemainingSize, defaultSizeTypes),
|
548
584
|
minSize
|
@@ -581,6 +617,10 @@ module.exports = class SplitChunksPlugin {
|
|
581
617
|
];
|
582
618
|
const fallbackCacheGroup = options.fallbackCacheGroup || {};
|
583
619
|
const minSize = normalizeSizes(options.minSize, defaultSizeTypes);
|
620
|
+
const minSizeReduction = normalizeSizes(
|
621
|
+
options.minSizeReduction,
|
622
|
+
defaultSizeTypes
|
623
|
+
);
|
584
624
|
const maxSize = normalizeSizes(options.maxSize, defaultSizeTypes);
|
585
625
|
|
586
626
|
/** @type {SplitChunksOptions} */
|
@@ -588,6 +628,7 @@ module.exports = class SplitChunksPlugin {
|
|
588
628
|
chunksFilter: normalizeChunksFilter(options.chunks || "all"),
|
589
629
|
defaultSizeTypes,
|
590
630
|
minSize,
|
631
|
+
minSizeReduction,
|
591
632
|
minRemainingSize: mergeSizes(
|
592
633
|
normalizeSizes(options.minRemainingSize, defaultSizeTypes),
|
593
634
|
minSize
|
@@ -655,6 +696,10 @@ module.exports = class SplitChunksPlugin {
|
|
655
696
|
cacheGroupSource.minSize,
|
656
697
|
cacheGroupSource.enforce ? undefined : this.options.minSize
|
657
698
|
);
|
699
|
+
const minSizeReduction = mergeSizes(
|
700
|
+
cacheGroupSource.minSizeReduction,
|
701
|
+
cacheGroupSource.enforce ? undefined : this.options.minSizeReduction
|
702
|
+
);
|
658
703
|
const minRemainingSize = mergeSizes(
|
659
704
|
cacheGroupSource.minRemainingSize,
|
660
705
|
cacheGroupSource.enforce ? undefined : this.options.minRemainingSize
|
@@ -668,6 +713,7 @@ module.exports = class SplitChunksPlugin {
|
|
668
713
|
priority: cacheGroupSource.priority || 0,
|
669
714
|
chunksFilter: cacheGroupSource.chunksFilter || this.options.chunksFilter,
|
670
715
|
minSize,
|
716
|
+
minSizeReduction,
|
671
717
|
minRemainingSize,
|
672
718
|
enforceSizeThreshold,
|
673
719
|
maxAsyncSize: mergeSizes(
|
@@ -756,132 +802,212 @@ module.exports = class SplitChunksPlugin {
|
|
756
802
|
logger.time("prepare");
|
757
803
|
const chunkGraph = compilation.chunkGraph;
|
758
804
|
const moduleGraph = compilation.moduleGraph;
|
805
|
+
// Give each selected chunk an index (to create strings from chunks)
|
806
|
+
/** @type {Map<Chunk, bigint>} */
|
807
|
+
const chunkIndexMap = new Map();
|
808
|
+
const ZERO = BigInt("0");
|
809
|
+
const ONE = BigInt("1");
|
810
|
+
const START = ONE << BigInt("31");
|
811
|
+
let index = START;
|
812
|
+
for (const chunk of chunks) {
|
813
|
+
chunkIndexMap.set(
|
814
|
+
chunk,
|
815
|
+
index | BigInt((Math.random() * 0x7fffffff) | 0)
|
816
|
+
);
|
817
|
+
index = index << ONE;
|
818
|
+
}
|
819
|
+
/**
|
820
|
+
* @param {Iterable<Chunk>} chunks list of chunks
|
821
|
+
* @returns {bigint | Chunk} key of the chunks
|
822
|
+
*/
|
823
|
+
const getKey = chunks => {
|
824
|
+
const iterator = chunks[Symbol.iterator]();
|
825
|
+
let result = iterator.next();
|
826
|
+
if (result.done) return ZERO;
|
827
|
+
const first = result.value;
|
828
|
+
result = iterator.next();
|
829
|
+
if (result.done) return first;
|
830
|
+
let key =
|
831
|
+
chunkIndexMap.get(first) | chunkIndexMap.get(result.value);
|
832
|
+
while (!(result = iterator.next()).done) {
|
833
|
+
const raw = chunkIndexMap.get(result.value);
|
834
|
+
key = key ^ raw;
|
835
|
+
}
|
836
|
+
return key;
|
837
|
+
};
|
838
|
+
const keyToString = key => {
|
839
|
+
if (typeof key === "bigint") return key.toString(16);
|
840
|
+
return chunkIndexMap.get(key).toString(16);
|
841
|
+
};
|
759
842
|
|
760
|
-
const
|
761
|
-
/** @type {Set<
|
762
|
-
const
|
843
|
+
const getChunkSetsInGraph = memoize(() => {
|
844
|
+
/** @type {Map<bigint, Set<Chunk>>} */
|
845
|
+
const chunkSetsInGraph = new Map();
|
846
|
+
/** @type {Set<Chunk>} */
|
847
|
+
const singleChunkSets = new Set();
|
763
848
|
for (const module of compilation.modules) {
|
764
|
-
const
|
765
|
-
|
766
|
-
|
849
|
+
const chunks = chunkGraph.getModuleChunksIterable(module);
|
850
|
+
const chunksKey = getKey(chunks);
|
851
|
+
if (typeof chunksKey === "bigint") {
|
852
|
+
if (!chunkSetsInGraph.has(chunksKey)) {
|
853
|
+
chunkSetsInGraph.set(chunksKey, new Set(chunks));
|
854
|
+
}
|
855
|
+
} else {
|
856
|
+
singleChunkSets.add(chunksKey);
|
857
|
+
}
|
767
858
|
}
|
768
|
-
return
|
859
|
+
return { chunkSetsInGraph, singleChunkSets };
|
769
860
|
});
|
770
861
|
|
771
862
|
/**
|
772
863
|
* @param {Module} module the module
|
773
|
-
* @returns {Iterable<
|
864
|
+
* @returns {Iterable<Chunk[]>} groups of chunks with equal exports
|
774
865
|
*/
|
775
866
|
const groupChunksByExports = module => {
|
776
867
|
const exportsInfo = moduleGraph.getExportsInfo(module);
|
777
868
|
const groupedByUsedExports = new Map();
|
778
869
|
for (const chunk of chunkGraph.getModuleChunksIterable(module)) {
|
779
870
|
const key = exportsInfo.getUsageKey(chunk.runtime);
|
780
|
-
const
|
781
|
-
|
782
|
-
|
871
|
+
const list = groupedByUsedExports.get(key);
|
872
|
+
if (list !== undefined) {
|
873
|
+
list.push(chunk);
|
874
|
+
} else {
|
875
|
+
groupedByUsedExports.set(key, [chunk]);
|
876
|
+
}
|
783
877
|
}
|
784
878
|
return groupedByUsedExports.values();
|
785
879
|
};
|
786
880
|
|
787
|
-
/** @type {Map<Module, Iterable<
|
881
|
+
/** @type {Map<Module, Iterable<Chunk[]>>} */
|
788
882
|
const groupedByExportsMap = new Map();
|
789
883
|
|
790
|
-
const
|
791
|
-
/** @type {Set<
|
792
|
-
const
|
884
|
+
const getExportsChunkSetsInGraph = memoize(() => {
|
885
|
+
/** @type {Map<bigint, Set<Chunk>>} */
|
886
|
+
const chunkSetsInGraph = new Map();
|
887
|
+
/** @type {Set<Chunk>} */
|
888
|
+
const singleChunkSets = new Set();
|
793
889
|
for (const module of compilation.modules) {
|
794
890
|
const groupedChunks = Array.from(groupChunksByExports(module));
|
795
891
|
groupedByExportsMap.set(module, groupedChunks);
|
796
|
-
for (const
|
797
|
-
|
892
|
+
for (const chunks of groupedChunks) {
|
893
|
+
if (chunks.length === 1) {
|
894
|
+
singleChunkSets.add(chunks[0]);
|
895
|
+
} else {
|
896
|
+
const chunksKey = /** @type {bigint} */ (getKey(chunks));
|
897
|
+
if (!chunkSetsInGraph.has(chunksKey)) {
|
898
|
+
chunkSetsInGraph.set(chunksKey, new Set(chunks));
|
899
|
+
}
|
900
|
+
}
|
798
901
|
}
|
799
902
|
}
|
800
|
-
return
|
903
|
+
return { chunkSetsInGraph, singleChunkSets };
|
801
904
|
});
|
802
905
|
|
803
906
|
// group these set of chunks by count
|
804
907
|
// to allow to check less sets via isSubset
|
805
908
|
// (only smaller sets can be subset)
|
806
|
-
const
|
807
|
-
/** @type {Map<number,
|
808
|
-
const
|
809
|
-
for (const chunksSet of
|
909
|
+
const groupChunkSetsByCount = chunkSets => {
|
910
|
+
/** @type {Map<number, Array<Set<Chunk>>>} */
|
911
|
+
const chunkSetsByCount = new Map();
|
912
|
+
for (const chunksSet of chunkSets) {
|
810
913
|
const count = chunksSet.size;
|
811
|
-
let array =
|
914
|
+
let array = chunkSetsByCount.get(count);
|
812
915
|
if (array === undefined) {
|
813
916
|
array = [];
|
814
|
-
|
917
|
+
chunkSetsByCount.set(count, array);
|
815
918
|
}
|
816
919
|
array.push(chunksSet);
|
817
920
|
}
|
818
|
-
return
|
921
|
+
return chunkSetsByCount;
|
819
922
|
};
|
820
|
-
const
|
821
|
-
|
923
|
+
const getChunkSetsByCount = memoize(() =>
|
924
|
+
groupChunkSetsByCount(
|
925
|
+
getChunkSetsInGraph().chunkSetsInGraph.values()
|
926
|
+
)
|
822
927
|
);
|
823
|
-
const
|
824
|
-
|
928
|
+
const getExportsChunkSetsByCount = memoize(() =>
|
929
|
+
groupChunkSetsByCount(
|
930
|
+
getExportsChunkSetsInGraph().chunkSetsInGraph.values()
|
931
|
+
)
|
825
932
|
);
|
826
933
|
|
827
|
-
|
828
|
-
|
829
|
-
|
830
|
-
|
831
|
-
|
832
|
-
|
833
|
-
/** @type {Map<
|
934
|
+
// Create a list of possible combinations
|
935
|
+
const createGetCombinations = (
|
936
|
+
chunkSets,
|
937
|
+
singleChunkSets,
|
938
|
+
chunkSetsByCount
|
939
|
+
) => {
|
940
|
+
/** @type {Map<bigint | Chunk, (Set<Chunk> | Chunk)[]>} */
|
834
941
|
const combinationsCache = new Map();
|
835
942
|
|
836
|
-
|
837
|
-
|
838
|
-
* @returns {ChunkCombination[]} combinations
|
839
|
-
*/
|
840
|
-
return chunkCombination => {
|
841
|
-
const cacheEntry = combinationsCache.get(chunkCombination);
|
943
|
+
return key => {
|
944
|
+
const cacheEntry = combinationsCache.get(key);
|
842
945
|
if (cacheEntry !== undefined) return cacheEntry;
|
843
|
-
if (
|
844
|
-
const result = [
|
845
|
-
combinationsCache.set(
|
946
|
+
if (key instanceof Chunk) {
|
947
|
+
const result = [key];
|
948
|
+
combinationsCache.set(key, result);
|
846
949
|
return result;
|
847
950
|
}
|
848
|
-
|
849
|
-
|
850
|
-
|
951
|
+
const chunksSet = chunkSets.get(key);
|
952
|
+
/** @type {(Set<Chunk> | Chunk)[]} */
|
953
|
+
const array = [chunksSet];
|
954
|
+
for (const [count, setArray] of chunkSetsByCount) {
|
851
955
|
// "equal" is not needed because they would have been merge in the first step
|
852
|
-
if (count <
|
956
|
+
if (count < chunksSet.size) {
|
853
957
|
for (const set of setArray) {
|
854
|
-
if (
|
958
|
+
if (isSubset(chunksSet, set)) {
|
855
959
|
array.push(set);
|
856
960
|
}
|
857
961
|
}
|
858
962
|
}
|
859
963
|
}
|
860
|
-
|
964
|
+
for (const chunk of singleChunkSets) {
|
965
|
+
if (chunksSet.has(chunk)) {
|
966
|
+
array.push(chunk);
|
967
|
+
}
|
968
|
+
}
|
969
|
+
combinationsCache.set(key, array);
|
861
970
|
return array;
|
862
971
|
};
|
863
972
|
};
|
864
973
|
|
865
974
|
const getCombinationsFactory = memoize(() => {
|
866
|
-
|
975
|
+
const { chunkSetsInGraph, singleChunkSets } = getChunkSetsInGraph();
|
976
|
+
return createGetCombinations(
|
977
|
+
chunkSetsInGraph,
|
978
|
+
singleChunkSets,
|
979
|
+
getChunkSetsByCount()
|
980
|
+
);
|
867
981
|
});
|
868
982
|
const getCombinations = key => getCombinationsFactory()(key);
|
869
983
|
|
870
984
|
const getExportsCombinationsFactory = memoize(() => {
|
871
|
-
|
985
|
+
const { chunkSetsInGraph, singleChunkSets } =
|
986
|
+
getExportsChunkSetsInGraph();
|
987
|
+
return createGetCombinations(
|
988
|
+
chunkSetsInGraph,
|
989
|
+
singleChunkSets,
|
990
|
+
getExportsChunkSetsByCount()
|
991
|
+
);
|
872
992
|
});
|
873
993
|
const getExportsCombinations = key =>
|
874
994
|
getExportsCombinationsFactory()(key);
|
875
995
|
|
876
|
-
/**
|
996
|
+
/**
|
997
|
+
* @typedef {Object} SelectedChunksResult
|
998
|
+
* @property {Chunk[]} chunks the list of chunks
|
999
|
+
* @property {bigint | Chunk} key a key of the list
|
1000
|
+
*/
|
1001
|
+
|
1002
|
+
/** @type {WeakMap<Set<Chunk> | Chunk, WeakMap<ChunkFilterFunction, SelectedChunksResult>>} */
|
877
1003
|
const selectedChunksCacheByChunksSet = new WeakMap();
|
878
1004
|
|
879
1005
|
/**
|
880
|
-
* get
|
1006
|
+
* get list and key by applying the filter function to the list
|
881
1007
|
* It is cached for performance reasons
|
882
|
-
* @param {
|
1008
|
+
* @param {Set<Chunk> | Chunk} chunks list of chunks
|
883
1009
|
* @param {ChunkFilterFunction} chunkFilter filter function for chunks
|
884
|
-
* @returns {
|
1010
|
+
* @returns {SelectedChunksResult} list and key
|
885
1011
|
*/
|
886
1012
|
const getSelectedChunks = (chunks, chunkFilter) => {
|
887
1013
|
let entry = selectedChunksCacheByChunksSet.get(chunks);
|
@@ -889,16 +1015,22 @@ module.exports = class SplitChunksPlugin {
|
|
889
1015
|
entry = new WeakMap();
|
890
1016
|
selectedChunksCacheByChunksSet.set(chunks, entry);
|
891
1017
|
}
|
892
|
-
/** @type {
|
1018
|
+
/** @type {SelectedChunksResult} */
|
893
1019
|
let entry2 = entry.get(chunkFilter);
|
894
1020
|
if (entry2 === undefined) {
|
895
|
-
/** @type {
|
896
|
-
|
897
|
-
|
898
|
-
if (chunkFilter(
|
899
|
-
|
1021
|
+
/** @type {Chunk[]} */
|
1022
|
+
const selectedChunks = [];
|
1023
|
+
if (chunks instanceof Chunk) {
|
1024
|
+
if (chunkFilter(chunks)) selectedChunks.push(chunks);
|
1025
|
+
} else {
|
1026
|
+
for (const chunk of chunks) {
|
1027
|
+
if (chunkFilter(chunk)) selectedChunks.push(chunk);
|
1028
|
+
}
|
900
1029
|
}
|
901
|
-
entry2 =
|
1030
|
+
entry2 = {
|
1031
|
+
chunks: selectedChunks,
|
1032
|
+
key: getKey(selectedChunks)
|
1033
|
+
};
|
902
1034
|
entry.set(chunkFilter, entry2);
|
903
1035
|
}
|
904
1036
|
return entry2;
|
@@ -917,7 +1049,8 @@ module.exports = class SplitChunksPlugin {
|
|
917
1049
|
/**
|
918
1050
|
* @param {CacheGroup} cacheGroup the current cache group
|
919
1051
|
* @param {number} cacheGroupIndex the index of the cache group of ordering
|
920
|
-
* @param {
|
1052
|
+
* @param {Chunk[]} selectedChunks chunks selected for this module
|
1053
|
+
* @param {bigint | Chunk} selectedChunksKey a key of selectedChunks
|
921
1054
|
* @param {Module} module the current module
|
922
1055
|
* @returns {void}
|
923
1056
|
*/
|
@@ -925,20 +1058,25 @@ module.exports = class SplitChunksPlugin {
|
|
925
1058
|
cacheGroup,
|
926
1059
|
cacheGroupIndex,
|
927
1060
|
selectedChunks,
|
1061
|
+
selectedChunksKey,
|
928
1062
|
module
|
929
1063
|
) => {
|
930
1064
|
// Break if minimum number of chunks is not reached
|
931
|
-
if (selectedChunks.
|
1065
|
+
if (selectedChunks.length < cacheGroup.minChunks) return;
|
932
1066
|
// Determine name for split chunk
|
933
1067
|
const name = cacheGroup.getName(
|
934
1068
|
module,
|
935
|
-
selectedChunks
|
1069
|
+
selectedChunks,
|
936
1070
|
cacheGroup.key
|
937
1071
|
);
|
938
1072
|
// Check if the name is ok
|
939
1073
|
const existingChunk = compilation.namedChunks.get(name);
|
940
1074
|
if (existingChunk) {
|
941
|
-
const parentValidationKey = `${name}|${
|
1075
|
+
const parentValidationKey = `${name}|${
|
1076
|
+
typeof selectedChunksKey === "bigint"
|
1077
|
+
? selectedChunksKey
|
1078
|
+
: selectedChunksKey.debugId
|
1079
|
+
}`;
|
942
1080
|
const valid = alreadyValidatedParents.get(parentValidationKey);
|
943
1081
|
if (valid === false) return;
|
944
1082
|
if (valid === undefined) {
|
@@ -947,7 +1085,7 @@ module.exports = class SplitChunksPlugin {
|
|
947
1085
|
let isInAllParents = true;
|
948
1086
|
/** @type {Set<ChunkGroup>} */
|
949
1087
|
const queue = new Set();
|
950
|
-
for (const chunk of selectedChunks
|
1088
|
+
for (const chunk of selectedChunks) {
|
951
1089
|
for (const group of chunk.groupsIterable) {
|
952
1090
|
queue.add(group);
|
953
1091
|
}
|
@@ -993,7 +1131,9 @@ module.exports = class SplitChunksPlugin {
|
|
993
1131
|
// This automatically merges equal names
|
994
1132
|
const key =
|
995
1133
|
cacheGroup.key +
|
996
|
-
(name
|
1134
|
+
(name
|
1135
|
+
? ` name:${name}`
|
1136
|
+
: ` chunks:${keyToString(selectedChunksKey)}`);
|
997
1137
|
// Add module to maps
|
998
1138
|
let info = chunksInfoMap.get(key);
|
999
1139
|
if (info === undefined) {
|
@@ -1008,9 +1148,9 @@ module.exports = class SplitChunksPlugin {
|
|
1008
1148
|
cacheGroupIndex,
|
1009
1149
|
name,
|
1010
1150
|
sizes: {},
|
1011
|
-
chunks:
|
1151
|
+
chunks: new Set(),
|
1012
1152
|
reuseableChunks: new Set(),
|
1013
|
-
|
1153
|
+
chunksKeys: new Set()
|
1014
1154
|
})
|
1015
1155
|
);
|
1016
1156
|
}
|
@@ -1021,10 +1161,12 @@ module.exports = class SplitChunksPlugin {
|
|
1021
1161
|
info.sizes[type] = (info.sizes[type] || 0) + module.size(type);
|
1022
1162
|
}
|
1023
1163
|
}
|
1024
|
-
const oldChunksKeysSize = info.
|
1025
|
-
info.
|
1026
|
-
if (oldChunksKeysSize !== info.
|
1027
|
-
|
1164
|
+
const oldChunksKeysSize = info.chunksKeys.size;
|
1165
|
+
info.chunksKeys.add(selectedChunksKey);
|
1166
|
+
if (oldChunksKeysSize !== info.chunksKeys.size) {
|
1167
|
+
for (const chunk of selectedChunks) {
|
1168
|
+
info.chunks.add(chunk);
|
1169
|
+
}
|
1028
1170
|
}
|
1029
1171
|
};
|
1030
1172
|
|
@@ -1045,56 +1187,50 @@ module.exports = class SplitChunksPlugin {
|
|
1045
1187
|
continue;
|
1046
1188
|
}
|
1047
1189
|
|
1048
|
-
|
1049
|
-
|
1190
|
+
// Prepare some values (usedExports = false)
|
1191
|
+
const getCombs = memoize(() => {
|
1192
|
+
const chunks = chunkGraph.getModuleChunksIterable(module);
|
1193
|
+
const chunksKey = getKey(chunks);
|
1194
|
+
return getCombinations(chunksKey);
|
1195
|
+
});
|
1196
|
+
|
1197
|
+
// Prepare some values (usedExports = true)
|
1198
|
+
const getCombsByUsedExports = memoize(() => {
|
1199
|
+
// fill the groupedByExportsMap
|
1200
|
+
getExportsChunkSetsInGraph();
|
1201
|
+
/** @type {Set<Set<Chunk> | Chunk>} */
|
1202
|
+
const set = new Set();
|
1203
|
+
const groupedByUsedExports = groupedByExportsMap.get(module);
|
1204
|
+
for (const chunks of groupedByUsedExports) {
|
1205
|
+
const chunksKey = getKey(chunks);
|
1206
|
+
for (const comb of getExportsCombinations(chunksKey))
|
1207
|
+
set.add(comb);
|
1208
|
+
}
|
1209
|
+
return set;
|
1210
|
+
});
|
1050
1211
|
|
1051
1212
|
let cacheGroupIndex = 0;
|
1052
1213
|
for (const cacheGroupSource of cacheGroups) {
|
1053
1214
|
const cacheGroup = this._getCacheGroup(cacheGroupSource);
|
1054
1215
|
|
1055
|
-
|
1056
|
-
|
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
|
-
}
|
1216
|
+
const combs = cacheGroup.usedExports
|
1217
|
+
? getCombsByUsedExports()
|
1218
|
+
: getCombs();
|
1088
1219
|
// For all combination of chunk selection
|
1089
|
-
for (const
|
1220
|
+
for (const chunkCombination of combs) {
|
1090
1221
|
// Break if minimum number of chunks is not reached
|
1091
|
-
const count =
|
1222
|
+
const count =
|
1223
|
+
chunkCombination instanceof Chunk ? 1 : chunkCombination.size;
|
1092
1224
|
if (count < cacheGroup.minChunks) continue;
|
1225
|
+
// Select chunks by configuration
|
1226
|
+
const { chunks: selectedChunks, key: selectedChunksKey } =
|
1227
|
+
getSelectedChunks(chunkCombination, cacheGroup.chunksFilter);
|
1093
1228
|
|
1094
1229
|
addModuleToChunksInfoMap(
|
1095
1230
|
cacheGroup,
|
1096
1231
|
cacheGroupIndex,
|
1097
1232
|
selectedChunks,
|
1233
|
+
selectedChunksKey,
|
1098
1234
|
module
|
1099
1235
|
);
|
1100
1236
|
}
|
@@ -1141,6 +1277,14 @@ module.exports = class SplitChunksPlugin {
|
|
1141
1277
|
for (const [key, info] of chunksInfoMap) {
|
1142
1278
|
if (removeMinSizeViolatingModules(info)) {
|
1143
1279
|
chunksInfoMap.delete(key);
|
1280
|
+
} else if (
|
1281
|
+
!checkMinSizeReduction(
|
1282
|
+
info.sizes,
|
1283
|
+
info.cacheGroup.minSizeReduction,
|
1284
|
+
info.chunks.size
|
1285
|
+
)
|
1286
|
+
) {
|
1287
|
+
chunksInfoMap.delete(key);
|
1144
1288
|
}
|
1145
1289
|
}
|
1146
1290
|
|
@@ -1186,12 +1330,12 @@ module.exports = class SplitChunksPlugin {
|
|
1186
1330
|
const chunkByName = compilation.namedChunks.get(chunkName);
|
1187
1331
|
if (chunkByName !== undefined) {
|
1188
1332
|
newChunk = chunkByName;
|
1189
|
-
const
|
1190
|
-
|
1191
|
-
|
1333
|
+
const oldSize = item.chunks.size;
|
1334
|
+
item.chunks.delete(newChunk);
|
1335
|
+
isExistingChunk = item.chunks.size !== oldSize;
|
1192
1336
|
}
|
1193
1337
|
} else if (item.cacheGroup.reuseExistingChunk) {
|
1194
|
-
outer: for (const chunk of item.chunks
|
1338
|
+
outer: for (const chunk of item.chunks) {
|
1195
1339
|
if (
|
1196
1340
|
chunkGraph.getNumberOfChunkModules(chunk) !==
|
1197
1341
|
item.modules.size
|
@@ -1225,7 +1369,7 @@ module.exports = class SplitChunksPlugin {
|
|
1225
1369
|
}
|
1226
1370
|
}
|
1227
1371
|
if (newChunk) {
|
1228
|
-
item.chunks
|
1372
|
+
item.chunks.delete(newChunk);
|
1229
1373
|
chunkName = undefined;
|
1230
1374
|
isExistingChunk = true;
|
1231
1375
|
isReusedWithAllModules = true;
|
@@ -1236,7 +1380,7 @@ module.exports = class SplitChunksPlugin {
|
|
1236
1380
|
item.cacheGroup._conditionalEnforce &&
|
1237
1381
|
checkMinSize(item.sizes, item.cacheGroup.enforceSizeThreshold);
|
1238
1382
|
|
1239
|
-
|
1383
|
+
const usedChunks = new Set(item.chunks);
|
1240
1384
|
|
1241
1385
|
// Check if maxRequests condition can be fulfilled
|
1242
1386
|
if (
|
@@ -1244,7 +1388,7 @@ module.exports = class SplitChunksPlugin {
|
|
1244
1388
|
(Number.isFinite(item.cacheGroup.maxInitialRequests) ||
|
1245
1389
|
Number.isFinite(item.cacheGroup.maxAsyncRequests))
|
1246
1390
|
) {
|
1247
|
-
for (const chunk of usedChunks
|
1391
|
+
for (const chunk of usedChunks) {
|
1248
1392
|
// respect max requests
|
1249
1393
|
const maxRequests = chunk.isOnlyInitial()
|
1250
1394
|
? item.cacheGroup.maxInitialRequests
|
@@ -1258,28 +1402,30 @@ module.exports = class SplitChunksPlugin {
|
|
1258
1402
|
isFinite(maxRequests) &&
|
1259
1403
|
getRequests(chunk) >= maxRequests
|
1260
1404
|
) {
|
1261
|
-
usedChunks
|
1405
|
+
usedChunks.delete(chunk);
|
1262
1406
|
}
|
1263
1407
|
}
|
1264
1408
|
}
|
1265
1409
|
|
1266
|
-
outer: for (const chunk of usedChunks
|
1410
|
+
outer: for (const chunk of usedChunks) {
|
1267
1411
|
for (const module of item.modules) {
|
1268
1412
|
if (chunkGraph.isModuleInChunk(module, chunk)) continue outer;
|
1269
1413
|
}
|
1270
|
-
usedChunks
|
1414
|
+
usedChunks.delete(chunk);
|
1271
1415
|
}
|
1272
1416
|
|
1273
1417
|
// Were some (invalid) chunks removed from usedChunks?
|
1274
1418
|
// => readd all modules to the queue, as things could have been changed
|
1275
|
-
if (usedChunks
|
1276
|
-
if (isExistingChunk) usedChunks
|
1419
|
+
if (usedChunks.size < item.chunks.size) {
|
1420
|
+
if (isExistingChunk) usedChunks.add(newChunk);
|
1277
1421
|
if (usedChunks.size >= item.cacheGroup.minChunks) {
|
1422
|
+
const chunksArr = Array.from(usedChunks);
|
1278
1423
|
for (const module of item.modules) {
|
1279
1424
|
addModuleToChunksInfoMap(
|
1280
1425
|
item.cacheGroup,
|
1281
1426
|
item.cacheGroupIndex,
|
1282
|
-
|
1427
|
+
chunksArr,
|
1428
|
+
getKey(usedChunks),
|
1283
1429
|
module
|
1284
1430
|
);
|
1285
1431
|
}
|
@@ -1293,7 +1439,7 @@ module.exports = class SplitChunksPlugin {
|
|
1293
1439
|
item.cacheGroup._validateRemainingSize &&
|
1294
1440
|
usedChunks.size === 1
|
1295
1441
|
) {
|
1296
|
-
const [chunk] = usedChunks
|
1442
|
+
const [chunk] = usedChunks;
|
1297
1443
|
let chunkSizes = Object.create(null);
|
1298
1444
|
for (const module of chunkGraph.getChunkModulesIterable(chunk)) {
|
1299
1445
|
if (!item.modules.has(module)) {
|
@@ -1327,7 +1473,7 @@ module.exports = class SplitChunksPlugin {
|
|
1327
1473
|
newChunk = compilation.addChunk(chunkName);
|
1328
1474
|
}
|
1329
1475
|
// Walk through all chunks
|
1330
|
-
for (const chunk of usedChunks
|
1476
|
+
for (const chunk of usedChunks) {
|
1331
1477
|
// Add graph connections for splitted chunk
|
1332
1478
|
chunk.split(newChunk);
|
1333
1479
|
}
|
@@ -1357,14 +1503,14 @@ module.exports = class SplitChunksPlugin {
|
|
1357
1503
|
// Add module to new chunk
|
1358
1504
|
chunkGraph.connectChunkAndModule(newChunk, module);
|
1359
1505
|
// Remove module from used chunks
|
1360
|
-
for (const chunk of usedChunks
|
1506
|
+
for (const chunk of usedChunks) {
|
1361
1507
|
chunkGraph.disconnectChunkAndModule(chunk, module);
|
1362
1508
|
}
|
1363
1509
|
}
|
1364
1510
|
} else {
|
1365
1511
|
// Remove all modules from used chunks
|
1366
1512
|
for (const module of item.modules) {
|
1367
|
-
for (const chunk of usedChunks
|
1513
|
+
for (const chunk of usedChunks) {
|
1368
1514
|
chunkGraph.disconnectChunkAndModule(chunk, module);
|
1369
1515
|
}
|
1370
1516
|
}
|
@@ -1406,7 +1552,7 @@ module.exports = class SplitChunksPlugin {
|
|
1406
1552
|
|
1407
1553
|
// remove all modules from other entries and update size
|
1408
1554
|
for (const [key, info] of chunksInfoMap) {
|
1409
|
-
if (info.chunks
|
1555
|
+
if (isOverlap(info.chunks, usedChunks)) {
|
1410
1556
|
// update modules and total size
|
1411
1557
|
// may remove it from the map when < minSize
|
1412
1558
|
let updated = false;
|
@@ -1426,7 +1572,14 @@ module.exports = class SplitChunksPlugin {
|
|
1426
1572
|
chunksInfoMap.delete(key);
|
1427
1573
|
continue;
|
1428
1574
|
}
|
1429
|
-
if (
|
1575
|
+
if (
|
1576
|
+
removeMinSizeViolatingModules(info) ||
|
1577
|
+
!checkMinSizeReduction(
|
1578
|
+
info.sizes,
|
1579
|
+
info.cacheGroup.minSizeReduction,
|
1580
|
+
info.chunks.size
|
1581
|
+
)
|
1582
|
+
) {
|
1430
1583
|
chunksInfoMap.delete(key);
|
1431
1584
|
continue;
|
1432
1585
|
}
|