webpack 4.14.0 → 4.15.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/bin/webpack.js +7 -2
- package/lib/AsyncDependenciesBlock.js +44 -0
- package/lib/AutomaticPrefetchPlugin.js +1 -1
- package/lib/Chunk.js +53 -3
- package/lib/ChunkGroup.js +1 -1
- package/lib/ChunkTemplate.js +14 -2
- package/lib/CommentCompilationWarning.js +2 -2
- package/lib/Compilation.js +435 -34
- package/lib/Compiler.js +57 -4
- package/lib/ContextModule.js +3 -15
- package/lib/DelegatedModule.js +9 -1
- package/lib/DependenciesBlock.js +36 -3
- package/lib/DependenciesBlockVariable.js +22 -0
- package/lib/Dependency.js +25 -4
- package/lib/DllEntryPlugin.js +4 -1
- package/lib/DynamicEntryPlugin.js +21 -1
- package/lib/EntryOptionPlugin.js +12 -0
- package/lib/ExtendedAPIPlugin.js +8 -4
- package/lib/ExternalModuleFactoryPlugin.js +1 -1
- package/lib/GraphHelpers.js +2 -1
- package/lib/HotModuleReplacement.runtime.js +8 -5
- package/lib/HotModuleReplacementPlugin.js +114 -116
- package/lib/MainTemplate.js +19 -4
- 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/RuleSet.js +3 -3
- package/lib/SingleEntryPlugin.js +14 -0
- package/lib/Stats.js +2 -1
- package/lib/Template.js +4 -1
- package/lib/UmdMainTemplatePlugin.js +12 -12
- package/lib/WebpackError.js +4 -0
- package/lib/WebpackOptionsDefaulter.js +3 -0
- 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/LoaderDependency.js +3 -0
- package/lib/dependencies/LoaderPlugin.js +3 -1
- package/lib/dependencies/ModuleDependency.js +3 -0
- package/lib/dependencies/MultiEntryDependency.js +5 -0
- package/lib/dependencies/SingleEntryDependency.js +3 -0
- package/lib/node/NodeMainTemplateAsync.runtime.js +1 -1
- package/lib/optimize/ConcatenatedModule.js +1 -0
- package/lib/optimize/SplitChunksPlugin.js +142 -2
- package/lib/util/Semaphore.js +12 -0
- package/lib/util/SetHelpers.js +4 -4
- package/lib/util/SortableSet.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/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/webpack.web.js +2 -2
- package/package.json +8 -7
- package/schemas/WebpackOptions.json +37 -1
package/lib/compareLocations.js
CHANGED
|
@@ -4,23 +4,13 @@
|
|
|
4
4
|
*/
|
|
5
5
|
"use strict";
|
|
6
6
|
|
|
7
|
-
/**
|
|
8
|
-
* @typedef {Object} LineAndColumn
|
|
9
|
-
* @property {number=} line
|
|
10
|
-
* @property {number=} column
|
|
11
|
-
*/
|
|
12
|
-
|
|
13
|
-
/**
|
|
14
|
-
* @typedef {Object} NodeLocation
|
|
15
|
-
* @property {LineAndColumn=} start
|
|
16
|
-
* @property {LineAndColumn=} end
|
|
17
|
-
* @property {number=} index
|
|
18
|
-
*/
|
|
7
|
+
/** @typedef {import("./Dependency").DependencyLocation} DependencyLocation */
|
|
19
8
|
|
|
9
|
+
// TODO webpack 5 remove string type from a and b
|
|
20
10
|
/**
|
|
21
11
|
* Compare two locations
|
|
22
|
-
* @param {string|
|
|
23
|
-
* @param {string|
|
|
12
|
+
* @param {string|DependencyLocation} a A location node
|
|
13
|
+
* @param {string|DependencyLocation} b A location node
|
|
24
14
|
* @returns {-1|0|1} sorting comparator value
|
|
25
15
|
*/
|
|
26
16
|
module.exports = (a, b) => {
|
|
@@ -38,7 +28,7 @@ module.exports = (a, b) => {
|
|
|
38
28
|
if (typeof b === "string") {
|
|
39
29
|
return -1;
|
|
40
30
|
} else if (typeof b === "object") {
|
|
41
|
-
if (
|
|
31
|
+
if ("start" in a && "start" in b) {
|
|
42
32
|
const ap = a.start;
|
|
43
33
|
const bp = b.start;
|
|
44
34
|
if (ap.line < bp.line) return -1;
|
|
@@ -46,8 +36,14 @@ module.exports = (a, b) => {
|
|
|
46
36
|
if (ap.column < bp.column) return -1;
|
|
47
37
|
if (ap.column > bp.column) return 1;
|
|
48
38
|
}
|
|
49
|
-
if (a
|
|
50
|
-
|
|
39
|
+
if ("name" in a && "name" in b) {
|
|
40
|
+
if (a.name < b.name) return -1;
|
|
41
|
+
if (a.name > b.name) return 1;
|
|
42
|
+
}
|
|
43
|
+
if ("index" in a && "index" in b) {
|
|
44
|
+
if (a.index < b.index) return -1;
|
|
45
|
+
if (a.index > b.index) return 1;
|
|
46
|
+
}
|
|
51
47
|
return 0;
|
|
52
48
|
} else {
|
|
53
49
|
return 0;
|
|
@@ -5,7 +5,8 @@ const schema = require("../../schemas/plugins/debug/ProfilingPlugin.json");
|
|
|
5
5
|
let inspector = undefined;
|
|
6
6
|
|
|
7
7
|
try {
|
|
8
|
-
|
|
8
|
+
// eslint-disable-next-line node/no-missing-require
|
|
9
|
+
inspector = require("inspector");
|
|
9
10
|
} catch (e) {
|
|
10
11
|
console.log("Unable to CPU profile in < node 8.0");
|
|
11
12
|
}
|
|
@@ -84,7 +85,7 @@ class Profiler {
|
|
|
84
85
|
* @param {string} outputPath The location where to write the log.
|
|
85
86
|
* @returns {Trace} The trace object
|
|
86
87
|
*/
|
|
87
|
-
|
|
88
|
+
const createTrace = outputPath => {
|
|
88
89
|
const trace = new Tracer({
|
|
89
90
|
noStream: true
|
|
90
91
|
});
|
|
@@ -136,10 +137,10 @@ function createTrace(outputPath) {
|
|
|
136
137
|
callback();
|
|
137
138
|
});
|
|
138
139
|
// Tear down the readable trace stream.
|
|
139
|
-
trace.
|
|
140
|
+
trace.push(null);
|
|
140
141
|
}
|
|
141
142
|
};
|
|
142
|
-
}
|
|
143
|
+
};
|
|
143
144
|
|
|
144
145
|
const pluginName = "ProfilingPlugin";
|
|
145
146
|
|
|
@@ -354,7 +355,6 @@ const makeNewProfiledTapFn = (hookName, tracer, { name, type, fn }) => {
|
|
|
354
355
|
switch (type) {
|
|
355
356
|
case "promise":
|
|
356
357
|
return (...args) => {
|
|
357
|
-
// eslint-disable-line
|
|
358
358
|
const id = ++tracer.counter;
|
|
359
359
|
tracer.trace.begin({
|
|
360
360
|
name,
|
|
@@ -373,7 +373,6 @@ const makeNewProfiledTapFn = (hookName, tracer, { name, type, fn }) => {
|
|
|
373
373
|
};
|
|
374
374
|
case "async":
|
|
375
375
|
return (...args) => {
|
|
376
|
-
// eslint-disable-line
|
|
377
376
|
const id = ++tracer.counter;
|
|
378
377
|
tracer.trace.begin({
|
|
379
378
|
name,
|
|
@@ -392,7 +391,6 @@ const makeNewProfiledTapFn = (hookName, tracer, { name, type, fn }) => {
|
|
|
392
391
|
};
|
|
393
392
|
case "sync":
|
|
394
393
|
return (...args) => {
|
|
395
|
-
// eslint-disable-line
|
|
396
394
|
const id = ++tracer.counter;
|
|
397
395
|
// Do not instrument ourself due to the CPU
|
|
398
396
|
// profile needing to be the last event in the trace.
|
|
@@ -23,17 +23,17 @@ const isBoundFunctionExpression = expr => {
|
|
|
23
23
|
return true;
|
|
24
24
|
};
|
|
25
25
|
|
|
26
|
-
|
|
26
|
+
const isUnboundFunctionExpression = expr => {
|
|
27
27
|
if (expr.type === "FunctionExpression") return true;
|
|
28
28
|
if (expr.type === "ArrowFunctionExpression") return true;
|
|
29
29
|
return false;
|
|
30
|
-
}
|
|
30
|
+
};
|
|
31
31
|
|
|
32
|
-
|
|
32
|
+
const isCallable = expr => {
|
|
33
33
|
if (isUnboundFunctionExpression(expr)) return true;
|
|
34
34
|
if (isBoundFunctionExpression(expr)) return true;
|
|
35
35
|
return false;
|
|
36
|
-
}
|
|
36
|
+
};
|
|
37
37
|
|
|
38
38
|
class AMDDefineDependencyParserPlugin {
|
|
39
39
|
constructor(options) {
|
|
@@ -80,7 +80,6 @@ class AMDDefineDependencyParserPlugin {
|
|
|
80
80
|
request
|
|
81
81
|
))
|
|
82
82
|
) {
|
|
83
|
-
// eslint-disable-line no-cond-assign
|
|
84
83
|
dep = new LocalModuleDependency(localModule, undefined, false);
|
|
85
84
|
dep.loc = expr.loc;
|
|
86
85
|
parser.state.current.addDependency(dep);
|
|
@@ -121,7 +120,6 @@ class AMDDefineDependencyParserPlugin {
|
|
|
121
120
|
namedModule
|
|
122
121
|
))
|
|
123
122
|
) {
|
|
124
|
-
// eslint-disable-line no-cond-assign
|
|
125
123
|
dep = new LocalModuleDependency(localModule, param.range, false);
|
|
126
124
|
} else {
|
|
127
125
|
dep = this.newRequireItemDependency(param.string, param.range);
|
|
@@ -79,7 +79,6 @@ class AMDRequireDependenciesBlockParserPlugin {
|
|
|
79
79
|
request
|
|
80
80
|
))
|
|
81
81
|
) {
|
|
82
|
-
// eslint-disable-line no-cond-assign
|
|
83
82
|
dep = new LocalModuleDependency(localModule, undefined, false);
|
|
84
83
|
dep.loc = expr.loc;
|
|
85
84
|
parser.state.current.addDependency(dep);
|
|
@@ -127,7 +126,6 @@ class AMDRequireDependenciesBlockParserPlugin {
|
|
|
127
126
|
param.string
|
|
128
127
|
))
|
|
129
128
|
) {
|
|
130
|
-
// eslint-disable-line no-cond-assign
|
|
131
129
|
dep = new LocalModuleDependency(localModule, param.range, false);
|
|
132
130
|
} else {
|
|
133
131
|
dep = this.newRequireItemDependency(param.string, param.range);
|
|
@@ -5,6 +5,7 @@
|
|
|
5
5
|
"use strict";
|
|
6
6
|
|
|
7
7
|
const LoaderDependency = require("./LoaderDependency");
|
|
8
|
+
const NormalModule = require("../NormalModule");
|
|
8
9
|
|
|
9
10
|
class LoaderPlugin {
|
|
10
11
|
apply(compiler) {
|
|
@@ -57,7 +58,8 @@ class LoaderPlugin {
|
|
|
57
58
|
if (!dep.module) {
|
|
58
59
|
return callback(new Error("Cannot load the module"));
|
|
59
60
|
}
|
|
60
|
-
|
|
61
|
+
// TODO consider removing this in webpack 5
|
|
62
|
+
if (dep.module instanceof NormalModule && dep.module.error) {
|
|
61
63
|
return callback(dep.module.error);
|
|
62
64
|
}
|
|
63
65
|
if (!dep.module._source) {
|
|
@@ -3,9 +3,14 @@
|
|
|
3
3
|
Author Tobias Koppers @sokra
|
|
4
4
|
*/
|
|
5
5
|
"use strict";
|
|
6
|
+
/** @typedef {import("./SingleEntryDependency")} SingleEntryDependency */
|
|
6
7
|
const Dependency = require("../Dependency");
|
|
7
8
|
|
|
8
9
|
class MultiEntryDependency extends Dependency {
|
|
10
|
+
/**
|
|
11
|
+
* @param {SingleEntryDependency[]} dependencies an array of SingleEntryDependencies
|
|
12
|
+
* @param {string} name entry name
|
|
13
|
+
*/
|
|
9
14
|
constructor(dependencies, name) {
|
|
10
15
|
super();
|
|
11
16
|
this.dependencies = dependencies;
|
|
@@ -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()
|
|
@@ -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,6 +111,7 @@ 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,
|
|
@@ -112,17 +120,24 @@ module.exports = class SplitChunksPlugin {
|
|
|
112
120
|
name: options.name,
|
|
113
121
|
automaticNameDelimiter: options.automaticNameDelimiter
|
|
114
122
|
}) || (() => {}),
|
|
123
|
+
hidePathInfo: options.hidePathInfo || false,
|
|
115
124
|
filename: options.filename || undefined,
|
|
116
125
|
getCacheGroups: SplitChunksPlugin.normalizeCacheGroups({
|
|
117
126
|
cacheGroups: options.cacheGroups,
|
|
118
127
|
automaticNameDelimiter: options.automaticNameDelimiter
|
|
119
|
-
})
|
|
128
|
+
}),
|
|
129
|
+
automaticNameDelimiter: options.automaticNameDelimiter,
|
|
130
|
+
fallbackCacheGroup: SplitChunksPlugin.normalizeFallbackCacheGroup(
|
|
131
|
+
options.fallbackCacheGroup || {},
|
|
132
|
+
options
|
|
133
|
+
)
|
|
120
134
|
};
|
|
121
135
|
}
|
|
122
136
|
|
|
123
137
|
static normalizeName({ name, automaticNameDelimiter }) {
|
|
124
138
|
if (name === true) {
|
|
125
|
-
|
|
139
|
+
/** @type {WeakMap<Chunk[], Record<string, string>>} */
|
|
140
|
+
const cache = new WeakMap();
|
|
126
141
|
const fn = (module, chunks, cacheGroup) => {
|
|
127
142
|
let cacheEntry = cache.get(chunks);
|
|
128
143
|
if (cacheEntry === undefined) {
|
|
@@ -177,6 +192,26 @@ module.exports = class SplitChunksPlugin {
|
|
|
177
192
|
if (typeof chunks === "function") return chunks;
|
|
178
193
|
}
|
|
179
194
|
|
|
195
|
+
static normalizeFallbackCacheGroup(
|
|
196
|
+
{
|
|
197
|
+
minSize = undefined,
|
|
198
|
+
maxSize = undefined,
|
|
199
|
+
automaticNameDelimiter = undefined
|
|
200
|
+
},
|
|
201
|
+
{
|
|
202
|
+
minSize: defaultMinSize = undefined,
|
|
203
|
+
maxSize: defaultMaxSize = undefined,
|
|
204
|
+
automaticNameDelimiter: defaultAutomaticNameDelimiter = undefined
|
|
205
|
+
}
|
|
206
|
+
) {
|
|
207
|
+
return {
|
|
208
|
+
minSize: typeof minSize === "number" ? minSize : defaultMinSize || 0,
|
|
209
|
+
maxSize: typeof maxSize === "number" ? maxSize : defaultMaxSize || 0,
|
|
210
|
+
automaticNameDelimiter:
|
|
211
|
+
automaticNameDelimiter || defaultAutomaticNameDelimiter || "~"
|
|
212
|
+
};
|
|
213
|
+
}
|
|
214
|
+
|
|
180
215
|
static normalizeCacheGroups({ cacheGroups, automaticNameDelimiter }) {
|
|
181
216
|
if (typeof cacheGroups === "function") {
|
|
182
217
|
// TODO webpack 5 remove this
|
|
@@ -225,6 +260,7 @@ module.exports = class SplitChunksPlugin {
|
|
|
225
260
|
),
|
|
226
261
|
enforce: option.enforce,
|
|
227
262
|
minSize: option.minSize,
|
|
263
|
+
maxSize: option.maxSize,
|
|
228
264
|
minChunks: option.minChunks,
|
|
229
265
|
maxAsyncRequests: option.maxAsyncRequests,
|
|
230
266
|
maxInitialRequests: option.maxInitialRequests,
|
|
@@ -278,6 +314,10 @@ module.exports = class SplitChunksPlugin {
|
|
|
278
314
|
return false;
|
|
279
315
|
}
|
|
280
316
|
|
|
317
|
+
/**
|
|
318
|
+
* @param {Compiler} compiler webpack compiler
|
|
319
|
+
* @returns {void}
|
|
320
|
+
*/
|
|
281
321
|
apply(compiler) {
|
|
282
322
|
compiler.hooks.thisCompilation.tap("SplitChunksPlugin", compilation => {
|
|
283
323
|
let alreadyOptimized = false;
|
|
@@ -486,6 +526,12 @@ module.exports = class SplitChunksPlugin {
|
|
|
486
526
|
: cacheGroupSource.enforce
|
|
487
527
|
? 0
|
|
488
528
|
: this.options.minSize,
|
|
529
|
+
maxSize:
|
|
530
|
+
cacheGroupSource.maxSize !== undefined
|
|
531
|
+
? cacheGroupSource.maxSize
|
|
532
|
+
: cacheGroupSource.enforce
|
|
533
|
+
? 0
|
|
534
|
+
: this.options.maxSize,
|
|
489
535
|
minChunks:
|
|
490
536
|
cacheGroupSource.minChunks !== undefined
|
|
491
537
|
? cacheGroupSource.minChunks
|
|
@@ -512,6 +558,10 @@ module.exports = class SplitChunksPlugin {
|
|
|
512
558
|
cacheGroupSource.filename !== undefined
|
|
513
559
|
? cacheGroupSource.filename
|
|
514
560
|
: this.options.filename,
|
|
561
|
+
automaticNameDelimiter:
|
|
562
|
+
cacheGroupSource.automaticNameDelimiter !== undefined
|
|
563
|
+
? cacheGroupSource.automaticNameDelimiter
|
|
564
|
+
: this.options.automaticNameDelimiter,
|
|
515
565
|
reuseExistingChunk: cacheGroupSource.reuseExistingChunk
|
|
516
566
|
};
|
|
517
567
|
// For all combination of chunk selection
|
|
@@ -537,6 +587,9 @@ module.exports = class SplitChunksPlugin {
|
|
|
537
587
|
}
|
|
538
588
|
}
|
|
539
589
|
|
|
590
|
+
/** @type {Map<Chunk, {minSize: number, maxSize: number, automaticNameDelimiter: string}>} */
|
|
591
|
+
const maxSizeQueueMap = new Map();
|
|
592
|
+
|
|
540
593
|
while (chunksInfoMap.size > 0) {
|
|
541
594
|
// Find best matching entry
|
|
542
595
|
let bestEntryKey;
|
|
@@ -563,6 +616,7 @@ module.exports = class SplitChunksPlugin {
|
|
|
563
616
|
|
|
564
617
|
let chunkName = item.name;
|
|
565
618
|
// Variable for the new chunk (lazy created)
|
|
619
|
+
/** @type {Chunk} */
|
|
566
620
|
let newChunk;
|
|
567
621
|
// When no chunk name, check if we can reuse a chunk instead of creating a new one
|
|
568
622
|
let isReused = false;
|
|
@@ -689,6 +743,22 @@ module.exports = class SplitChunksPlugin {
|
|
|
689
743
|
}
|
|
690
744
|
}
|
|
691
745
|
}
|
|
746
|
+
|
|
747
|
+
if (item.cacheGroup.maxSize > 0) {
|
|
748
|
+
const oldMaxSizeSettings = maxSizeQueueMap.get(newChunk);
|
|
749
|
+
maxSizeQueueMap.set(newChunk, {
|
|
750
|
+
minSize: Math.max(
|
|
751
|
+
oldMaxSizeSettings ? oldMaxSizeSettings.minSize : 0,
|
|
752
|
+
item.cacheGroup.minSize
|
|
753
|
+
),
|
|
754
|
+
maxSize: Math.min(
|
|
755
|
+
oldMaxSizeSettings ? oldMaxSizeSettings.maxSize : Infinity,
|
|
756
|
+
item.cacheGroup.maxSize
|
|
757
|
+
),
|
|
758
|
+
automaticNameDelimiter: item.cacheGroup.automaticNameDelimiter
|
|
759
|
+
});
|
|
760
|
+
}
|
|
761
|
+
|
|
692
762
|
// remove all modules from other entries and update size
|
|
693
763
|
for (const [key, info] of chunksInfoMap) {
|
|
694
764
|
if (isOverlap(info.chunks, item.chunks)) {
|
|
@@ -709,6 +779,76 @@ module.exports = class SplitChunksPlugin {
|
|
|
709
779
|
}
|
|
710
780
|
}
|
|
711
781
|
}
|
|
782
|
+
|
|
783
|
+
// Make sure that maxSize is fulfilled
|
|
784
|
+
for (const chunk of compilation.chunks.slice()) {
|
|
785
|
+
const { minSize, maxSize, automaticNameDelimiter } =
|
|
786
|
+
maxSizeQueueMap.get(chunk) || this.options.fallbackCacheGroup;
|
|
787
|
+
if (!maxSize) continue;
|
|
788
|
+
const results = deterministicGroupingForModules({
|
|
789
|
+
maxSize,
|
|
790
|
+
minSize,
|
|
791
|
+
items: chunk.modulesIterable,
|
|
792
|
+
getKey(module) {
|
|
793
|
+
const ident = contextify(
|
|
794
|
+
compilation.options.context,
|
|
795
|
+
module.identifier()
|
|
796
|
+
);
|
|
797
|
+
const name = module.nameForCondition
|
|
798
|
+
? contextify(
|
|
799
|
+
compilation.options.context,
|
|
800
|
+
module.nameForCondition()
|
|
801
|
+
)
|
|
802
|
+
: ident.replace(/^.*!|\?[^?!]*$/g, "");
|
|
803
|
+
const fullKey =
|
|
804
|
+
name + automaticNameDelimiter + hashFilename(ident);
|
|
805
|
+
return fullKey.replace(/[\\/?]/g, "_");
|
|
806
|
+
},
|
|
807
|
+
getSize(module) {
|
|
808
|
+
return module.size();
|
|
809
|
+
}
|
|
810
|
+
});
|
|
811
|
+
results.sort((a, b) => {
|
|
812
|
+
if (a.key < b.key) return -1;
|
|
813
|
+
if (a.key > b.key) return 1;
|
|
814
|
+
return 0;
|
|
815
|
+
});
|
|
816
|
+
for (let i = 0; i < results.length; i++) {
|
|
817
|
+
const group = results[i];
|
|
818
|
+
const key = this.options.hidePathInfo
|
|
819
|
+
? hashFilename(group.key)
|
|
820
|
+
: group.key;
|
|
821
|
+
let name = chunk.name
|
|
822
|
+
? chunk.name + automaticNameDelimiter + key
|
|
823
|
+
: null;
|
|
824
|
+
if (name && name.length > 100) {
|
|
825
|
+
name =
|
|
826
|
+
name.slice(0, 100) +
|
|
827
|
+
automaticNameDelimiter +
|
|
828
|
+
hashFilename(name);
|
|
829
|
+
}
|
|
830
|
+
let newPart;
|
|
831
|
+
if (i !== results.length - 1) {
|
|
832
|
+
newPart = compilation.addChunk(name);
|
|
833
|
+
chunk.split(newPart);
|
|
834
|
+
// Add all modules to the new chunk
|
|
835
|
+
for (const module of group.items) {
|
|
836
|
+
if (typeof module.chunkCondition === "function") {
|
|
837
|
+
if (!module.chunkCondition(newPart)) continue;
|
|
838
|
+
}
|
|
839
|
+
// Add module to new chunk
|
|
840
|
+
GraphHelpers.connectChunkAndModule(newPart, module);
|
|
841
|
+
// Remove module from used chunks
|
|
842
|
+
chunk.removeModule(module);
|
|
843
|
+
module.rewriteChunkInReasons(chunk, [newPart]);
|
|
844
|
+
}
|
|
845
|
+
} else {
|
|
846
|
+
// change the chunk to be a part
|
|
847
|
+
newPart = chunk;
|
|
848
|
+
chunk.name = name;
|
|
849
|
+
}
|
|
850
|
+
}
|
|
851
|
+
}
|
|
712
852
|
}
|
|
713
853
|
);
|
|
714
854
|
});
|
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
|
*/
|
package/lib/util/createHash.js
CHANGED
|
@@ -4,8 +4,18 @@
|
|
|
4
4
|
*/
|
|
5
5
|
"use strict";
|
|
6
6
|
|
|
7
|
+
/** @typedef {{new(): Hash}} HashConstructor */
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {Object} Hash
|
|
10
|
+
* @property {function(string|Buffer, string=): Hash} update
|
|
11
|
+
* @property {function(string): string} digest
|
|
12
|
+
*/
|
|
13
|
+
|
|
7
14
|
const BULK_SIZE = 1000;
|
|
8
15
|
|
|
16
|
+
/**
|
|
17
|
+
* @implements {Hash}
|
|
18
|
+
*/
|
|
9
19
|
class BulkUpdateDecorator {
|
|
10
20
|
constructor(hash) {
|
|
11
21
|
this.hash = hash;
|
|
@@ -63,6 +73,11 @@ class DebugHash {
|
|
|
63
73
|
}
|
|
64
74
|
}
|
|
65
75
|
|
|
76
|
+
/**
|
|
77
|
+
* Creates a hash by name or function
|
|
78
|
+
* @param {string | HashConstructor} algorithm the algorithm name or a constructor creating a hash
|
|
79
|
+
* @returns {Hash} the hash
|
|
80
|
+
*/
|
|
66
81
|
module.exports = algorithm => {
|
|
67
82
|
if (typeof algorithm === "function") {
|
|
68
83
|
return new BulkUpdateDecorator(new algorithm());
|