webpack 4.14.0 → 4.16.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.
- package/LICENSE +20 -20
- package/README.md +5 -2
- package/bin/webpack.js +7 -2
- package/buildin/amd-define.js +3 -3
- package/buildin/amd-options.js +2 -2
- package/buildin/system.js +7 -7
- package/hot/dev-server.js +2 -2
- package/hot/emitter.js +2 -2
- package/hot/only-dev-server.js +2 -2
- package/hot/poll.js +5 -2
- package/hot/signal.js +2 -2
- package/lib/AsyncDependenciesBlock.js +44 -0
- package/lib/AutomaticPrefetchPlugin.js +2 -2
- package/lib/Chunk.js +56 -6
- package/lib/ChunkGroup.js +2 -2
- package/lib/ChunkTemplate.js +14 -2
- package/lib/CommentCompilationWarning.js +3 -3
- package/lib/CompatibilityPlugin.js +1 -1
- package/lib/Compilation.js +442 -37
- package/lib/Compiler.js +57 -4
- package/lib/ContextModule.js +23 -16
- package/lib/DefinePlugin.js +49 -0
- package/lib/DelegatedModule.js +9 -1
- package/lib/DelegatedModuleFactoryPlugin.js +7 -1
- package/lib/DependenciesBlock.js +36 -3
- package/lib/DependenciesBlockVariable.js +22 -0
- package/lib/Dependency.js +33 -6
- package/lib/DllEntryPlugin.js +4 -1
- package/lib/DynamicEntryPlugin.js +21 -1
- package/lib/EntryOptionPlugin.js +12 -0
- package/lib/Entrypoint.js +1 -1
- package/lib/EnvironmentPlugin.js +8 -1
- package/lib/ExtendedAPIPlugin.js +8 -4
- package/lib/ExternalModuleFactoryPlugin.js +1 -1
- package/lib/Generator.js +1 -1
- package/lib/GraphHelpers.js +2 -1
- package/lib/HotModuleReplacement.runtime.js +8 -5
- package/lib/HotModuleReplacementPlugin.js +115 -117
- package/lib/IgnorePlugin.js +1 -1
- package/lib/MainTemplate.js +19 -4
- package/lib/MemoryOutputFileSystem.js +5 -5
- package/lib/Module.js +9 -3
- package/lib/ModuleReason.js +8 -0
- package/lib/MultiEntryPlugin.js +25 -3
- package/lib/NormalModule.js +5 -23
- package/lib/NullFactory.js +12 -12
- package/lib/OptionsApply.js +10 -10
- package/lib/RuleSet.js +3 -3
- package/lib/SingleEntryPlugin.js +20 -1
- package/lib/Stats.js +12 -5
- package/lib/Template.js +4 -1
- package/lib/UmdMainTemplatePlugin.js +12 -12
- package/lib/UseStrictPlugin.js +1 -1
- package/lib/WebpackError.js +4 -0
- package/lib/WebpackOptionsApply.js +92 -10
- package/lib/WebpackOptionsDefaulter.js +23 -6
- package/lib/WebpackOptionsValidationError.js +0 -1
- package/lib/compareLocations.js +13 -17
- package/lib/debug/ProfilingPlugin.js +5 -7
- package/lib/dependencies/AMDDefineDependencyParserPlugin.js +4 -6
- package/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +0 -2
- package/lib/dependencies/AMDRequireItemDependency.js +22 -22
- package/lib/dependencies/CommonJsRequireDependency.js +22 -22
- package/lib/dependencies/CriticalDependencyWarning.js +20 -20
- package/lib/dependencies/DelegatedSourceDependency.js +18 -18
- package/lib/dependencies/DllEntryDependency.js +20 -20
- package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +2 -1
- package/lib/dependencies/LoaderDependency.js +3 -0
- package/lib/dependencies/LoaderPlugin.js +21 -2
- package/lib/dependencies/LocalModule.js +23 -23
- package/lib/dependencies/ModuleDependency.js +3 -0
- package/lib/dependencies/ModuleHotAcceptDependency.js +23 -23
- package/lib/dependencies/ModuleHotDeclineDependency.js +23 -23
- package/lib/dependencies/MultiEntryDependency.js +5 -0
- package/lib/dependencies/PrefetchDependency.js +18 -18
- package/lib/dependencies/RequireEnsureItemDependency.js +21 -21
- package/lib/dependencies/RequireResolveDependency.js +22 -22
- package/lib/dependencies/SingleEntryDependency.js +3 -0
- package/lib/dependencies/SystemPlugin.js +1 -1
- package/lib/formatLocation.js +55 -41
- package/lib/node/NodeMainTemplateAsync.runtime.js +1 -1
- package/lib/node/NodeMainTemplatePlugin.js +2 -2
- package/lib/node/NodeOutputFileSystem.js +22 -22
- package/lib/node/NodeSourcePlugin.js +1 -1
- package/lib/optimize/ConcatenatedModule.js +1 -0
- package/lib/optimize/NaturalChunkOrderPlugin.js +41 -0
- package/lib/optimize/OccurrenceChunkOrderPlugin.js +61 -0
- package/lib/optimize/OccurrenceModuleOrderPlugin.js +103 -0
- package/lib/optimize/OccurrenceOrderPlugin.js +4 -2
- package/lib/optimize/SplitChunksPlugin.js +168 -18
- package/lib/util/Semaphore.js +12 -0
- package/lib/util/SetHelpers.js +4 -4
- package/lib/util/SortableSet.js +1 -1
- package/lib/util/cachedMerge.js +1 -1
- package/lib/util/createHash.js +15 -0
- package/lib/util/deterministicGrouping.js +251 -0
- package/lib/util/identifier.js +27 -0
- package/lib/wasm/WasmFinalizeExportsPlugin.js +1 -1
- package/lib/wasm/WasmMainTemplatePlugin.js +10 -4
- package/lib/wasm/WebAssemblyGenerator.js +12 -12
- package/lib/wasm/WebAssemblyInInitialChunkError.js +88 -0
- package/lib/wasm/WebAssemblyModulesPlugin.js +28 -0
- package/lib/web/JsonpMainTemplatePlugin.js +1 -1
- package/lib/web/WebEnvironmentPlugin.js +18 -18
- package/lib/webpack.js +4 -0
- package/lib/webpack.web.js +2 -2
- package/lib/webworker/WebWorkerMainTemplatePlugin.js +1 -1
- package/package.json +27 -17
- package/schemas/WebpackOptions.json +71 -9
- package/schemas/plugins/optimize/OccurrenceOrderChunkIdsPlugin.json +10 -0
- package/schemas/plugins/optimize/OccurrenceOrderModuleIdsPlugin.json +10 -0
@@ -305,8 +305,8 @@ module.exports = class NodeMainTemplatePlugin {
|
|
305
305
|
);
|
306
306
|
return Template.getFunctionContent(
|
307
307
|
asyncChunkLoading
|
308
|
-
? require("./NodeMainTemplateAsync.runtime
|
309
|
-
: require("./NodeMainTemplate.runtime
|
308
|
+
? require("./NodeMainTemplateAsync.runtime")
|
309
|
+
: require("./NodeMainTemplate.runtime")
|
310
310
|
)
|
311
311
|
.replace(/\$require\$/g, mainTemplate.requireFn)
|
312
312
|
.replace(/\$hotMainFilename\$/g, currentHotUpdateMainFilename)
|
@@ -1,22 +1,22 @@
|
|
1
|
-
/*
|
2
|
-
MIT License http://www.opensource.org/licenses/mit-license.php
|
3
|
-
Author Tobias Koppers @sokra
|
4
|
-
*/
|
5
|
-
"use strict";
|
6
|
-
|
7
|
-
const fs = require("fs");
|
8
|
-
const path = require("path");
|
9
|
-
const mkdirp = require("mkdirp");
|
10
|
-
|
11
|
-
class NodeOutputFileSystem {
|
12
|
-
constructor() {
|
13
|
-
this.mkdirp = mkdirp;
|
14
|
-
this.mkdir = fs.mkdir.bind(fs);
|
15
|
-
this.rmdir = fs.rmdir.bind(fs);
|
16
|
-
this.unlink = fs.unlink.bind(fs);
|
17
|
-
this.writeFile = fs.writeFile.bind(fs);
|
18
|
-
this.join = path.join.bind(path);
|
19
|
-
}
|
20
|
-
}
|
21
|
-
|
22
|
-
module.exports = NodeOutputFileSystem;
|
1
|
+
/*
|
2
|
+
MIT License http://www.opensource.org/licenses/mit-license.php
|
3
|
+
Author Tobias Koppers @sokra
|
4
|
+
*/
|
5
|
+
"use strict";
|
6
|
+
|
7
|
+
const fs = require("fs");
|
8
|
+
const path = require("path");
|
9
|
+
const mkdirp = require("mkdirp");
|
10
|
+
|
11
|
+
class NodeOutputFileSystem {
|
12
|
+
constructor() {
|
13
|
+
this.mkdirp = mkdirp;
|
14
|
+
this.mkdir = fs.mkdir.bind(fs);
|
15
|
+
this.rmdir = fs.rmdir.bind(fs);
|
16
|
+
this.unlink = fs.unlink.bind(fs);
|
17
|
+
this.writeFile = fs.writeFile.bind(fs);
|
18
|
+
this.join = path.join.bind(path);
|
19
|
+
}
|
20
|
+
}
|
21
|
+
|
22
|
+
module.exports = NodeOutputFileSystem;
|
@@ -71,7 +71,7 @@ module.exports = class NodeSourcePlugin {
|
|
71
71
|
.tap("NodeSourcePlugin", () => {
|
72
72
|
const retrieveGlobalModule = ParserHelpers.requireFileAsExpression(
|
73
73
|
parser.state.module.context,
|
74
|
-
require.resolve("../../buildin/global
|
74
|
+
require.resolve("../../buildin/global")
|
75
75
|
);
|
76
76
|
return ParserHelpers.addParsedVariableToModule(
|
77
77
|
parser,
|
@@ -639,6 +639,7 @@ class ConcatenatedModule extends Module {
|
|
639
639
|
|
640
640
|
// Must use full identifier in our cache here to ensure that the source
|
641
641
|
// is updated should our dependencies list change.
|
642
|
+
// TODO webpack 5 refactor
|
642
643
|
innerDependencyTemplates.set(
|
643
644
|
"hash",
|
644
645
|
innerDependencyTemplates.get("hash") + this.identifier()
|
@@ -0,0 +1,41 @@
|
|
1
|
+
/*
|
2
|
+
MIT License http://www.opensource.org/licenses/mit-license.php
|
3
|
+
Author Tobias Koppers @sokra
|
4
|
+
*/
|
5
|
+
"use strict";
|
6
|
+
|
7
|
+
/** @typedef {import("../Compiler")} Compiler */
|
8
|
+
|
9
|
+
class NaturalChunkOrderPlugin {
|
10
|
+
/**
|
11
|
+
* @param {Compiler} compiler webpack compiler
|
12
|
+
* @returns {void}
|
13
|
+
*/
|
14
|
+
apply(compiler) {
|
15
|
+
compiler.hooks.compilation.tap("NaturalChunkOrderPlugin", compilation => {
|
16
|
+
compilation.hooks.optimizeChunkOrder.tap(
|
17
|
+
"NaturalChunkOrderPlugin",
|
18
|
+
chunks => {
|
19
|
+
chunks.sort((chunkA, chunkB) => {
|
20
|
+
const a = chunkA.modulesIterable[Symbol.iterator]();
|
21
|
+
const b = chunkB.modulesIterable[Symbol.iterator]();
|
22
|
+
// eslint-disable-next-line no-constant-condition
|
23
|
+
while (true) {
|
24
|
+
const aItem = a.next();
|
25
|
+
const bItem = b.next();
|
26
|
+
if (aItem.done && bItem.done) return 0;
|
27
|
+
if (aItem.done) return -1;
|
28
|
+
if (bItem.done) return 1;
|
29
|
+
const aModuleId = aItem.value.id;
|
30
|
+
const bModuleId = bItem.value.id;
|
31
|
+
if (aModuleId < bModuleId) return -1;
|
32
|
+
if (aModuleId > bModuleId) return 1;
|
33
|
+
}
|
34
|
+
});
|
35
|
+
}
|
36
|
+
);
|
37
|
+
});
|
38
|
+
}
|
39
|
+
}
|
40
|
+
|
41
|
+
module.exports = NaturalChunkOrderPlugin;
|
@@ -0,0 +1,61 @@
|
|
1
|
+
/*
|
2
|
+
MIT License http://www.opensource.org/licenses/mit-license.php
|
3
|
+
Author Tobias Koppers @sokra
|
4
|
+
*/
|
5
|
+
"use strict";
|
6
|
+
|
7
|
+
const validateOptions = require("schema-utils");
|
8
|
+
const schema = require("../../schemas/plugins/optimize/OccurrenceOrderChunkIdsPlugin.json");
|
9
|
+
|
10
|
+
class OccurrenceOrderChunkIdsPlugin {
|
11
|
+
constructor(options = {}) {
|
12
|
+
validateOptions(schema, options, "Occurrence Order Chunk Ids Plugin");
|
13
|
+
this.options = options;
|
14
|
+
}
|
15
|
+
|
16
|
+
apply(compiler) {
|
17
|
+
const prioritiseInitial = this.options.prioritiseInitial;
|
18
|
+
compiler.hooks.compilation.tap(
|
19
|
+
"OccurrenceOrderChunkIdsPlugin",
|
20
|
+
compilation => {
|
21
|
+
compilation.hooks.optimizeChunkOrder.tap(
|
22
|
+
"OccurrenceOrderChunkIdsPlugin",
|
23
|
+
chunks => {
|
24
|
+
const occursInInitialChunksMap = new Map();
|
25
|
+
const originalOrder = new Map();
|
26
|
+
|
27
|
+
let i = 0;
|
28
|
+
for (const c of chunks) {
|
29
|
+
let occurs = 0;
|
30
|
+
for (const chunkGroup of c.groupsIterable) {
|
31
|
+
for (const parent of chunkGroup.parentsIterable) {
|
32
|
+
if (parent.isInitial()) occurs++;
|
33
|
+
}
|
34
|
+
}
|
35
|
+
occursInInitialChunksMap.set(c, occurs);
|
36
|
+
originalOrder.set(c, i++);
|
37
|
+
}
|
38
|
+
|
39
|
+
chunks.sort((a, b) => {
|
40
|
+
if (prioritiseInitial) {
|
41
|
+
const aEntryOccurs = occursInInitialChunksMap.get(a);
|
42
|
+
const bEntryOccurs = occursInInitialChunksMap.get(b);
|
43
|
+
if (aEntryOccurs > bEntryOccurs) return -1;
|
44
|
+
if (aEntryOccurs < bEntryOccurs) return 1;
|
45
|
+
}
|
46
|
+
const aOccurs = a.getNumberOfGroups();
|
47
|
+
const bOccurs = b.getNumberOfGroups();
|
48
|
+
if (aOccurs > bOccurs) return -1;
|
49
|
+
if (aOccurs < bOccurs) return 1;
|
50
|
+
const orgA = originalOrder.get(a);
|
51
|
+
const orgB = originalOrder.get(b);
|
52
|
+
return orgA - orgB;
|
53
|
+
});
|
54
|
+
}
|
55
|
+
);
|
56
|
+
}
|
57
|
+
);
|
58
|
+
}
|
59
|
+
}
|
60
|
+
|
61
|
+
module.exports = OccurrenceOrderChunkIdsPlugin;
|
@@ -0,0 +1,103 @@
|
|
1
|
+
/*
|
2
|
+
MIT License http://www.opensource.org/licenses/mit-license.php
|
3
|
+
Author Tobias Koppers @sokra
|
4
|
+
*/
|
5
|
+
"use strict";
|
6
|
+
|
7
|
+
const validateOptions = require("schema-utils");
|
8
|
+
const schema = require("../../schemas/plugins/optimize/OccurrenceOrderModuleIdsPlugin.json");
|
9
|
+
|
10
|
+
class OccurrenceOrderModuleIdsPlugin {
|
11
|
+
constructor(options = {}) {
|
12
|
+
validateOptions(schema, options, "Occurrence Order Module Ids Plugin");
|
13
|
+
this.options = options;
|
14
|
+
}
|
15
|
+
|
16
|
+
apply(compiler) {
|
17
|
+
const prioritiseInitial = this.options.prioritiseInitial;
|
18
|
+
compiler.hooks.compilation.tap(
|
19
|
+
"OccurrenceOrderModuleIdsPlugin",
|
20
|
+
compilation => {
|
21
|
+
compilation.hooks.optimizeModuleOrder.tap(
|
22
|
+
"OccurrenceOrderModuleIdsPlugin",
|
23
|
+
modules => {
|
24
|
+
const occursInInitialChunksMap = new Map();
|
25
|
+
const occursInAllChunksMap = new Map();
|
26
|
+
|
27
|
+
const initialChunkChunkMap = new Map();
|
28
|
+
const entryCountMap = new Map();
|
29
|
+
for (const m of modules) {
|
30
|
+
let initial = 0;
|
31
|
+
let entry = 0;
|
32
|
+
for (const c of m.chunksIterable) {
|
33
|
+
if (c.canBeInitial()) initial++;
|
34
|
+
if (c.entryModule === m) entry++;
|
35
|
+
}
|
36
|
+
initialChunkChunkMap.set(m, initial);
|
37
|
+
entryCountMap.set(m, entry);
|
38
|
+
}
|
39
|
+
|
40
|
+
const countOccursInEntry = (sum, r) => {
|
41
|
+
if (!r.module) {
|
42
|
+
return sum;
|
43
|
+
}
|
44
|
+
return sum + initialChunkChunkMap.get(r.module);
|
45
|
+
};
|
46
|
+
const countOccurs = (sum, r) => {
|
47
|
+
if (!r.module) {
|
48
|
+
return sum;
|
49
|
+
}
|
50
|
+
let factor = 1;
|
51
|
+
if (typeof r.dependency.getNumberOfIdOccurrences === "function") {
|
52
|
+
factor = r.dependency.getNumberOfIdOccurrences();
|
53
|
+
}
|
54
|
+
if (factor === 0) {
|
55
|
+
return sum;
|
56
|
+
}
|
57
|
+
return sum + factor * r.module.getNumberOfChunks();
|
58
|
+
};
|
59
|
+
|
60
|
+
if (prioritiseInitial) {
|
61
|
+
for (const m of modules) {
|
62
|
+
const result =
|
63
|
+
m.reasons.reduce(countOccursInEntry, 0) +
|
64
|
+
initialChunkChunkMap.get(m) +
|
65
|
+
entryCountMap.get(m);
|
66
|
+
occursInInitialChunksMap.set(m, result);
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
70
|
+
const originalOrder = new Map();
|
71
|
+
let i = 0;
|
72
|
+
for (const m of modules) {
|
73
|
+
const result =
|
74
|
+
m.reasons.reduce(countOccurs, 0) +
|
75
|
+
m.getNumberOfChunks() +
|
76
|
+
entryCountMap.get(m);
|
77
|
+
occursInAllChunksMap.set(m, result);
|
78
|
+
originalOrder.set(m, i++);
|
79
|
+
}
|
80
|
+
|
81
|
+
modules.sort((a, b) => {
|
82
|
+
if (prioritiseInitial) {
|
83
|
+
const aEntryOccurs = occursInInitialChunksMap.get(a);
|
84
|
+
const bEntryOccurs = occursInInitialChunksMap.get(b);
|
85
|
+
if (aEntryOccurs > bEntryOccurs) return -1;
|
86
|
+
if (aEntryOccurs < bEntryOccurs) return 1;
|
87
|
+
}
|
88
|
+
const aOccurs = occursInAllChunksMap.get(a);
|
89
|
+
const bOccurs = occursInAllChunksMap.get(b);
|
90
|
+
if (aOccurs > bOccurs) return -1;
|
91
|
+
if (aOccurs < bOccurs) return 1;
|
92
|
+
const orgA = originalOrder.get(a);
|
93
|
+
const orgB = originalOrder.get(b);
|
94
|
+
return orgA - orgB;
|
95
|
+
});
|
96
|
+
}
|
97
|
+
);
|
98
|
+
}
|
99
|
+
);
|
100
|
+
}
|
101
|
+
}
|
102
|
+
|
103
|
+
module.exports = OccurrenceOrderModuleIdsPlugin;
|
@@ -4,6 +4,8 @@
|
|
4
4
|
*/
|
5
5
|
"use strict";
|
6
6
|
|
7
|
+
// TODO webpack 5 remove this plugin
|
8
|
+
// It has been splitted into separate plugins for modules and chunks
|
7
9
|
class OccurrenceOrderPlugin {
|
8
10
|
constructor(preferEntry) {
|
9
11
|
if (preferEntry !== undefined && typeof preferEntry !== "boolean") {
|
@@ -89,7 +91,7 @@ class OccurrenceOrderPlugin {
|
|
89
91
|
if (aOccurs < bOccurs) return 1;
|
90
92
|
const orgA = originalOrder.get(a);
|
91
93
|
const orgB = originalOrder.get(b);
|
92
|
-
return
|
94
|
+
return orgA - orgB;
|
93
95
|
});
|
94
96
|
}
|
95
97
|
);
|
@@ -122,7 +124,7 @@ class OccurrenceOrderPlugin {
|
|
122
124
|
if (aOccurs < bOccurs) return 1;
|
123
125
|
const orgA = originalOrder.get(a);
|
124
126
|
const orgB = originalOrder.get(b);
|
125
|
-
return
|
127
|
+
return orgA - orgB;
|
126
128
|
});
|
127
129
|
}
|
128
130
|
);
|
@@ -8,9 +8,16 @@ const crypto = require("crypto");
|
|
8
8
|
const SortableSet = require("../util/SortableSet");
|
9
9
|
const GraphHelpers = require("../GraphHelpers");
|
10
10
|
const { isSubset } = require("../util/SetHelpers");
|
11
|
+
const deterministicGrouping = require("../util/deterministicGrouping");
|
12
|
+
const contextify = require("../util/identifier").contextify;
|
11
13
|
|
14
|
+
/** @typedef {import("../Compiler")} Compiler */
|
12
15
|
/** @typedef {import("../Chunk")} Chunk */
|
13
16
|
/** @typedef {import("../Module")} Module */
|
17
|
+
/** @typedef {import("../util/deterministicGrouping").Options<Module>} DeterministicGroupingOptionsForModule */
|
18
|
+
/** @typedef {import("../util/deterministicGrouping").GroupedItems<Module>} DeterministicGroupingGroupedItemsForModule */
|
19
|
+
|
20
|
+
const deterministicGroupingForModules = /** @type {function(DeterministicGroupingOptionsForModule): DeterministicGroupingGroupedItemsForModule[]} */ (deterministicGrouping);
|
14
21
|
|
15
22
|
const hashFilename = name => {
|
16
23
|
return crypto
|
@@ -104,25 +111,29 @@ module.exports = class SplitChunksPlugin {
|
|
104
111
|
options.chunks || "all"
|
105
112
|
),
|
106
113
|
minSize: options.minSize || 0,
|
114
|
+
maxSize: options.maxSize || 0,
|
107
115
|
minChunks: options.minChunks || 1,
|
108
116
|
maxAsyncRequests: options.maxAsyncRequests || 1,
|
109
117
|
maxInitialRequests: options.maxInitialRequests || 1,
|
110
|
-
|
111
|
-
SplitChunksPlugin.normalizeName({
|
112
|
-
name: options.name,
|
113
|
-
automaticNameDelimiter: options.automaticNameDelimiter
|
114
|
-
}) || (() => {}),
|
118
|
+
hidePathInfo: options.hidePathInfo || false,
|
115
119
|
filename: options.filename || undefined,
|
116
120
|
getCacheGroups: SplitChunksPlugin.normalizeCacheGroups({
|
117
121
|
cacheGroups: options.cacheGroups,
|
122
|
+
name: options.name,
|
118
123
|
automaticNameDelimiter: options.automaticNameDelimiter
|
119
|
-
})
|
124
|
+
}),
|
125
|
+
automaticNameDelimiter: options.automaticNameDelimiter,
|
126
|
+
fallbackCacheGroup: SplitChunksPlugin.normalizeFallbackCacheGroup(
|
127
|
+
options.fallbackCacheGroup || {},
|
128
|
+
options
|
129
|
+
)
|
120
130
|
};
|
121
131
|
}
|
122
132
|
|
123
|
-
static normalizeName({ name, automaticNameDelimiter }) {
|
133
|
+
static normalizeName({ name, automaticNameDelimiter, automaticNamePrefix }) {
|
124
134
|
if (name === true) {
|
125
|
-
|
135
|
+
/** @type {WeakMap<Chunk[], Record<string, string>>} */
|
136
|
+
const cache = new WeakMap();
|
126
137
|
const fn = (module, chunks, cacheGroup) => {
|
127
138
|
let cacheEntry = cache.get(chunks);
|
128
139
|
if (cacheEntry === undefined) {
|
@@ -137,10 +148,12 @@ module.exports = class SplitChunksPlugin {
|
|
137
148
|
return;
|
138
149
|
}
|
139
150
|
names.sort();
|
140
|
-
|
141
|
-
|
142
|
-
?
|
143
|
-
:
|
151
|
+
const prefix =
|
152
|
+
typeof automaticNamePrefix === "string"
|
153
|
+
? automaticNamePrefix
|
154
|
+
: cacheGroup;
|
155
|
+
const namePrefix = prefix ? prefix + automaticNameDelimiter : "";
|
156
|
+
let name = namePrefix + names.join(automaticNameDelimiter);
|
144
157
|
// Filenames and paths can't be too long otherwise an
|
145
158
|
// ENAMETOOLONG error is raised. If the generated name if too
|
146
159
|
// long, it is truncated and a hash is appended. The limit has
|
@@ -177,7 +190,27 @@ module.exports = class SplitChunksPlugin {
|
|
177
190
|
if (typeof chunks === "function") return chunks;
|
178
191
|
}
|
179
192
|
|
180
|
-
static
|
193
|
+
static normalizeFallbackCacheGroup(
|
194
|
+
{
|
195
|
+
minSize = undefined,
|
196
|
+
maxSize = undefined,
|
197
|
+
automaticNameDelimiter = undefined
|
198
|
+
},
|
199
|
+
{
|
200
|
+
minSize: defaultMinSize = undefined,
|
201
|
+
maxSize: defaultMaxSize = undefined,
|
202
|
+
automaticNameDelimiter: defaultAutomaticNameDelimiter = undefined
|
203
|
+
}
|
204
|
+
) {
|
205
|
+
return {
|
206
|
+
minSize: typeof minSize === "number" ? minSize : defaultMinSize || 0,
|
207
|
+
maxSize: typeof maxSize === "number" ? maxSize : defaultMaxSize || 0,
|
208
|
+
automaticNameDelimiter:
|
209
|
+
automaticNameDelimiter || defaultAutomaticNameDelimiter || "~"
|
210
|
+
};
|
211
|
+
}
|
212
|
+
|
213
|
+
static normalizeCacheGroups({ cacheGroups, name, automaticNameDelimiter }) {
|
181
214
|
if (typeof cacheGroups === "function") {
|
182
215
|
// TODO webpack 5 remove this
|
183
216
|
if (cacheGroups.length !== 1) {
|
@@ -216,15 +249,21 @@ module.exports = class SplitChunksPlugin {
|
|
216
249
|
results.push({
|
217
250
|
key: key,
|
218
251
|
priority: option.priority,
|
219
|
-
getName:
|
220
|
-
|
221
|
-
|
222
|
-
|
252
|
+
getName:
|
253
|
+
SplitChunksPlugin.normalizeName({
|
254
|
+
name: option.name || name,
|
255
|
+
automaticNameDelimiter:
|
256
|
+
typeof option.automaticNameDelimiter === "string"
|
257
|
+
? option.automaticNameDelimiter
|
258
|
+
: automaticNameDelimiter,
|
259
|
+
automaticNamePrefix: option.automaticNamePrefix
|
260
|
+
}) || (() => {}),
|
223
261
|
chunksFilter: SplitChunksPlugin.normalizeChunksFilter(
|
224
262
|
option.chunks
|
225
263
|
),
|
226
264
|
enforce: option.enforce,
|
227
265
|
minSize: option.minSize,
|
266
|
+
maxSize: option.maxSize,
|
228
267
|
minChunks: option.minChunks,
|
229
268
|
maxAsyncRequests: option.maxAsyncRequests,
|
230
269
|
maxInitialRequests: option.maxInitialRequests,
|
@@ -278,6 +317,10 @@ module.exports = class SplitChunksPlugin {
|
|
278
317
|
return false;
|
279
318
|
}
|
280
319
|
|
320
|
+
/**
|
321
|
+
* @param {Compiler} compiler webpack compiler
|
322
|
+
* @returns {void}
|
323
|
+
*/
|
281
324
|
apply(compiler) {
|
282
325
|
compiler.hooks.thisCompilation.tap("SplitChunksPlugin", compilation => {
|
283
326
|
let alreadyOptimized = false;
|
@@ -447,6 +490,12 @@ module.exports = class SplitChunksPlugin {
|
|
447
490
|
chunksKeys: new Set()
|
448
491
|
})
|
449
492
|
);
|
493
|
+
} else {
|
494
|
+
if (info.cacheGroup !== cacheGroup) {
|
495
|
+
if (info.cacheGroup.priority < cacheGroup.priority) {
|
496
|
+
info.cacheGroup = cacheGroup;
|
497
|
+
}
|
498
|
+
}
|
450
499
|
}
|
451
500
|
info.modules.add(module);
|
452
501
|
info.size += module.size();
|
@@ -486,6 +535,12 @@ module.exports = class SplitChunksPlugin {
|
|
486
535
|
: cacheGroupSource.enforce
|
487
536
|
? 0
|
488
537
|
: this.options.minSize,
|
538
|
+
maxSize:
|
539
|
+
cacheGroupSource.maxSize !== undefined
|
540
|
+
? cacheGroupSource.maxSize
|
541
|
+
: cacheGroupSource.enforce
|
542
|
+
? 0
|
543
|
+
: this.options.maxSize,
|
489
544
|
minChunks:
|
490
545
|
cacheGroupSource.minChunks !== undefined
|
491
546
|
? cacheGroupSource.minChunks
|
@@ -512,6 +567,10 @@ module.exports = class SplitChunksPlugin {
|
|
512
567
|
cacheGroupSource.filename !== undefined
|
513
568
|
? cacheGroupSource.filename
|
514
569
|
: this.options.filename,
|
570
|
+
automaticNameDelimiter:
|
571
|
+
cacheGroupSource.automaticNameDelimiter !== undefined
|
572
|
+
? cacheGroupSource.automaticNameDelimiter
|
573
|
+
: this.options.automaticNameDelimiter,
|
515
574
|
reuseExistingChunk: cacheGroupSource.reuseExistingChunk
|
516
575
|
};
|
517
576
|
// For all combination of chunk selection
|
@@ -537,6 +596,9 @@ module.exports = class SplitChunksPlugin {
|
|
537
596
|
}
|
538
597
|
}
|
539
598
|
|
599
|
+
/** @type {Map<Chunk, {minSize: number, maxSize: number, automaticNameDelimiter: string}>} */
|
600
|
+
const maxSizeQueueMap = new Map();
|
601
|
+
|
540
602
|
while (chunksInfoMap.size > 0) {
|
541
603
|
// Find best matching entry
|
542
604
|
let bestEntryKey;
|
@@ -563,6 +625,7 @@ module.exports = class SplitChunksPlugin {
|
|
563
625
|
|
564
626
|
let chunkName = item.name;
|
565
627
|
// Variable for the new chunk (lazy created)
|
628
|
+
/** @type {Chunk} */
|
566
629
|
let newChunk;
|
567
630
|
// When no chunk name, check if we can reuse a chunk instead of creating a new one
|
568
631
|
let isReused = false;
|
@@ -591,7 +654,7 @@ module.exports = class SplitChunksPlugin {
|
|
591
654
|
isReused = true;
|
592
655
|
}
|
593
656
|
}
|
594
|
-
// Check if maxRequests condition can be
|
657
|
+
// Check if maxRequests condition can be fulfilled
|
595
658
|
|
596
659
|
const usedChunks = Array.from(item.chunks).filter(chunk => {
|
597
660
|
// skip if we address ourself
|
@@ -689,6 +752,22 @@ module.exports = class SplitChunksPlugin {
|
|
689
752
|
}
|
690
753
|
}
|
691
754
|
}
|
755
|
+
|
756
|
+
if (item.cacheGroup.maxSize > 0) {
|
757
|
+
const oldMaxSizeSettings = maxSizeQueueMap.get(newChunk);
|
758
|
+
maxSizeQueueMap.set(newChunk, {
|
759
|
+
minSize: Math.max(
|
760
|
+
oldMaxSizeSettings ? oldMaxSizeSettings.minSize : 0,
|
761
|
+
item.cacheGroup.minSize
|
762
|
+
),
|
763
|
+
maxSize: Math.min(
|
764
|
+
oldMaxSizeSettings ? oldMaxSizeSettings.maxSize : Infinity,
|
765
|
+
item.cacheGroup.maxSize
|
766
|
+
),
|
767
|
+
automaticNameDelimiter: item.cacheGroup.automaticNameDelimiter
|
768
|
+
});
|
769
|
+
}
|
770
|
+
|
692
771
|
// remove all modules from other entries and update size
|
693
772
|
for (const [key, info] of chunksInfoMap) {
|
694
773
|
if (isOverlap(info.chunks, item.chunks)) {
|
@@ -709,6 +788,77 @@ module.exports = class SplitChunksPlugin {
|
|
709
788
|
}
|
710
789
|
}
|
711
790
|
}
|
791
|
+
|
792
|
+
// Make sure that maxSize is fulfilled
|
793
|
+
for (const chunk of compilation.chunks.slice()) {
|
794
|
+
const { minSize, maxSize, automaticNameDelimiter } =
|
795
|
+
maxSizeQueueMap.get(chunk) || this.options.fallbackCacheGroup;
|
796
|
+
if (!maxSize) continue;
|
797
|
+
const results = deterministicGroupingForModules({
|
798
|
+
maxSize,
|
799
|
+
minSize,
|
800
|
+
items: chunk.modulesIterable,
|
801
|
+
getKey(module) {
|
802
|
+
const ident = contextify(
|
803
|
+
compilation.options.context,
|
804
|
+
module.identifier()
|
805
|
+
);
|
806
|
+
const name = module.nameForCondition
|
807
|
+
? contextify(
|
808
|
+
compilation.options.context,
|
809
|
+
module.nameForCondition()
|
810
|
+
)
|
811
|
+
: ident.replace(/^.*!|\?[^?!]*$/g, "");
|
812
|
+
const fullKey =
|
813
|
+
name + automaticNameDelimiter + hashFilename(ident);
|
814
|
+
return fullKey.replace(/[\\/?]/g, "_");
|
815
|
+
},
|
816
|
+
getSize(module) {
|
817
|
+
return module.size();
|
818
|
+
}
|
819
|
+
});
|
820
|
+
results.sort((a, b) => {
|
821
|
+
if (a.key < b.key) return -1;
|
822
|
+
if (a.key > b.key) return 1;
|
823
|
+
return 0;
|
824
|
+
});
|
825
|
+
for (let i = 0; i < results.length; i++) {
|
826
|
+
const group = results[i];
|
827
|
+
const key = this.options.hidePathInfo
|
828
|
+
? hashFilename(group.key)
|
829
|
+
: group.key;
|
830
|
+
let name = chunk.name
|
831
|
+
? chunk.name + automaticNameDelimiter + key
|
832
|
+
: null;
|
833
|
+
if (name && name.length > 100) {
|
834
|
+
name =
|
835
|
+
name.slice(0, 100) +
|
836
|
+
automaticNameDelimiter +
|
837
|
+
hashFilename(name);
|
838
|
+
}
|
839
|
+
let newPart;
|
840
|
+
if (i !== results.length - 1) {
|
841
|
+
newPart = compilation.addChunk(name);
|
842
|
+
chunk.split(newPart);
|
843
|
+
newPart.chunkReason = chunk.chunkReason;
|
844
|
+
// Add all modules to the new chunk
|
845
|
+
for (const module of group.items) {
|
846
|
+
if (typeof module.chunkCondition === "function") {
|
847
|
+
if (!module.chunkCondition(newPart)) continue;
|
848
|
+
}
|
849
|
+
// Add module to new chunk
|
850
|
+
GraphHelpers.connectChunkAndModule(newPart, module);
|
851
|
+
// Remove module from used chunks
|
852
|
+
chunk.removeModule(module);
|
853
|
+
module.rewriteChunkInReasons(chunk, [newPart]);
|
854
|
+
}
|
855
|
+
} else {
|
856
|
+
// change the chunk to be a part
|
857
|
+
newPart = chunk;
|
858
|
+
chunk.name = name;
|
859
|
+
}
|
860
|
+
}
|
861
|
+
}
|
712
862
|
}
|
713
863
|
);
|
714
864
|
});
|
package/lib/util/Semaphore.js
CHANGED
@@ -5,12 +5,24 @@
|
|
5
5
|
"use strict";
|
6
6
|
|
7
7
|
class Semaphore {
|
8
|
+
/**
|
9
|
+
* Creates an instance of Semaphore.
|
10
|
+
*
|
11
|
+
* @param {number} available the amount available number of "tasks"
|
12
|
+
* in the Semaphore
|
13
|
+
*/
|
8
14
|
constructor(available) {
|
9
15
|
this.available = available;
|
16
|
+
/** @type {(function(): void)[]} */
|
10
17
|
this.waiters = [];
|
18
|
+
/** @private */
|
11
19
|
this._continue = this._continue.bind(this);
|
12
20
|
}
|
13
21
|
|
22
|
+
/**
|
23
|
+
* @param {function(): void} callback function block to capture and run
|
24
|
+
* @returns {void}
|
25
|
+
*/
|
14
26
|
acquire(callback) {
|
15
27
|
if (this.available > 0) {
|
16
28
|
this.available--;
|
package/lib/util/SetHelpers.js
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
* @param {Set[]} sets an array of sets being checked for shared elements
|
6
6
|
* @returns {Set<TODO>} returns a new Set containing the intersecting items
|
7
7
|
*/
|
8
|
-
|
8
|
+
const intersect = sets => {
|
9
9
|
if (sets.length === 0) return new Set();
|
10
10
|
if (sets.length === 1) return new Set(sets[0]);
|
11
11
|
let minSize = Infinity;
|
@@ -28,7 +28,7 @@ function intersect(sets) {
|
|
28
28
|
}
|
29
29
|
}
|
30
30
|
return current;
|
31
|
-
}
|
31
|
+
};
|
32
32
|
|
33
33
|
/**
|
34
34
|
* Checks if a set is the subset of another set
|
@@ -36,13 +36,13 @@ function intersect(sets) {
|
|
36
36
|
* @param {Set<TODO>} smallSet the set whos elements might be contained inside of bigSet
|
37
37
|
* @returns {boolean} returns true if smallSet contains all elements inside of the bigSet
|
38
38
|
*/
|
39
|
-
|
39
|
+
const isSubset = (bigSet, smallSet) => {
|
40
40
|
if (bigSet.size < smallSet.size) return false;
|
41
41
|
for (const item of smallSet) {
|
42
42
|
if (!bigSet.has(item)) return false;
|
43
43
|
}
|
44
44
|
return true;
|
45
|
-
}
|
45
|
+
};
|
46
46
|
|
47
47
|
exports.intersect = intersect;
|
48
48
|
exports.isSubset = isSubset;
|
package/lib/util/SortableSet.js
CHANGED
@@ -7,7 +7,7 @@
|
|
7
7
|
class SortableSet extends Set {
|
8
8
|
/**
|
9
9
|
* Create a new sortable set
|
10
|
-
* @param {
|
10
|
+
* @param {Iterable<T>=} initialIterable The initial iterable value
|
11
11
|
* @typedef {function(T, T): number} SortFunction
|
12
12
|
* @param {SortFunction=} defaultSort Default sorting function
|
13
13
|
*/
|