webpack 4.1.0 → 4.4.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.
- package/README.md +719 -721
- package/bin/webpack.js +69 -10
- package/lib/APIPlugin.js +84 -84
- package/lib/AmdMainTemplatePlugin.js +75 -77
- package/lib/AsyncDependencyToInitialChunkError.js +21 -23
- package/lib/BannerPlugin.js +101 -101
- package/lib/Chunk.js +477 -469
- package/lib/ChunkTemplate.js +51 -53
- package/lib/Compilation.js +1858 -1851
- package/lib/Compiler.js +493 -478
- package/lib/ConcurrentCompilationError.js +19 -0
- package/lib/ContextModule.js +696 -685
- package/lib/ContextModuleFactory.js +245 -243
- package/lib/DefinePlugin.js +197 -197
- package/lib/DelegatedModule.js +101 -101
- package/lib/DependenciesBlockVariable.js +51 -52
- package/lib/Dependency.js +53 -52
- package/lib/DllModule.js +54 -54
- package/lib/DllModuleFactory.js +29 -29
- package/lib/EnvironmentPlugin.js +65 -67
- package/lib/EvalDevToolModuleTemplatePlugin.js +60 -60
- package/lib/EvalSourceMapDevToolModuleTemplatePlugin.js +105 -105
- package/lib/ExportPropertyMainTemplatePlugin.js +40 -40
- package/lib/ExternalModule.js +159 -159
- package/lib/FunctionModuleTemplatePlugin.js +98 -98
- package/lib/HotModuleReplacement.runtime.js +631 -631
- package/lib/HotModuleReplacementPlugin.js +407 -406
- package/lib/HotUpdateChunkTemplate.js +78 -80
- package/lib/JavascriptGenerator.js +228 -229
- package/lib/JavascriptModulesPlugin.js +184 -158
- package/lib/JsonGenerator.js +42 -42
- package/lib/MainTemplate.js +406 -402
- package/lib/Module.js +343 -340
- package/lib/ModuleBuildError.js +42 -42
- package/lib/ModuleError.js +28 -28
- package/lib/ModuleFilenameHelpers.js +166 -166
- package/lib/ModuleTemplate.js +77 -79
- package/lib/ModuleWarning.js +30 -30
- package/lib/MultiCompiler.js +271 -259
- package/lib/MultiModule.js +78 -75
- package/lib/MultiModuleFactory.js +23 -23
- package/lib/MultiWatching.js +38 -37
- package/lib/NoModeWarning.js +23 -21
- package/lib/NormalModule.js +478 -470
- package/lib/NormalModuleFactory.js +483 -481
- package/lib/OptionsDefaulter.js +80 -86
- package/lib/Parser.js +2074 -2071
- package/lib/ProgressPlugin.js +231 -231
- package/lib/RawModule.js +54 -55
- package/lib/RecordIdsPlugin.js +160 -160
- package/lib/RemovedPluginError.js +13 -13
- package/lib/ResolverFactory.js +64 -67
- package/lib/RuntimeTemplate.js +267 -297
- package/lib/SetVarMainTemplatePlugin.js +57 -57
- package/lib/SourceMapDevToolPlugin.js +302 -308
- package/lib/Stats.js +1234 -1212
- package/lib/Template.js +205 -205
- package/lib/TemplatedPathPlugin.js +170 -143
- package/lib/UmdMainTemplatePlugin.js +264 -269
- package/lib/Watching.js +193 -193
- package/lib/WebAssemblyParser.js +50 -54
- package/lib/WebpackOptionsApply.js +401 -401
- package/lib/WebpackOptionsDefaulter.js +337 -317
- package/lib/WebpackOptionsValidationError.js +316 -319
- package/lib/debug/ProfilingPlugin.js +409 -405
- package/lib/dependencies/AMDDefineDependencyParserPlugin.js +328 -311
- package/lib/dependencies/AMDRequireContextDependency.js +20 -20
- package/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +270 -241
- package/lib/dependencies/HarmonyAcceptImportDependency.js +23 -23
- package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +620 -606
- package/lib/dependencies/HarmonyExportSpecifierDependency.js +53 -53
- package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +214 -214
- package/lib/dependencies/HarmonyImportSpecifierDependency.js +154 -156
- package/lib/dependencies/ImportDependenciesBlock.js +17 -17
- package/lib/dependencies/ImportDependency.js +34 -34
- package/lib/dependencies/ImportEagerDependency.js +32 -32
- package/lib/dependencies/ImportParserPlugin.js +175 -179
- package/lib/dependencies/ImportWeakDependency.js +34 -34
- package/lib/dependencies/JsonExportsDependency.js +25 -25
- package/lib/dependencies/ModuleDependency.js +20 -20
- package/lib/dependencies/NullDependency.js +20 -20
- package/lib/dependencies/RequireContextDependency.js +22 -22
- package/lib/dependencies/RequireIncludeDependency.js +40 -40
- package/lib/dependencies/WebpackMissingModule.js +20 -22
- package/lib/node/NodeChunkTemplatePlugin.js +31 -31
- package/lib/node/NodeHotUpdateChunkTemplatePlugin.js +36 -36
- package/lib/node/NodeMainTemplatePlugin.js +320 -273
- package/lib/node/ReadFileCompileWasmMainTemplatePlugin.js +113 -115
- package/lib/optimize/AggressiveSplittingPlugin.js +281 -281
- package/lib/optimize/ConcatenatedModule.js +1364 -1366
- package/lib/optimize/RemoveParentModulesPlugin.js +114 -114
- package/lib/optimize/SplitChunksPlugin.js +519 -491
- package/lib/performance/SizeLimitsPlugin.js +105 -105
- package/lib/util/TrackingSet.js +35 -35
- package/lib/util/objectToMap.js +10 -10
- package/lib/wasm/WasmModuleTemplatePlugin.js +106 -106
- package/lib/web/JsonpChunkTemplatePlugin.js +47 -47
- package/lib/web/JsonpExportMainTemplatePlugin.js +47 -47
- package/lib/web/JsonpHotUpdateChunkTemplatePlugin.js +39 -39
- package/lib/web/JsonpMainTemplatePlugin.js +425 -403
- package/lib/webpack.js +182 -179
- package/lib/webworker/WebWorkerChunkTemplatePlugin.js +35 -35
- package/lib/webworker/WebWorkerHotUpdateChunkTemplatePlugin.js +40 -40
- package/lib/webworker/WebWorkerMainTemplatePlugin.js +177 -154
- package/package.json +9 -8
- package/schemas/WebpackOptions.json +1973 -1951
- package/schemas/ajv.absolutePath.js +55 -29
- package/schemas/plugins/BannerPlugin.json +85 -85
- package/schemas/plugins/DllPlugin.json +28 -28
- package/schemas/plugins/DllReferencePlugin.json +99 -99
- package/schemas/plugins/HashedModuleIdsPlugin.json +24 -24
- package/schemas/plugins/LoaderOptionsPlugin.json +26 -26
- package/schemas/plugins/SourceMapDevToolPlugin.json +187 -187
- package/schemas/plugins/WatchIgnorePlugin.json +16 -16
- package/schemas/plugins/debug/ProfilingPlugin.json +12 -12
- package/schemas/plugins/optimize/AggressiveSplittingPlugin.json +22 -22
- package/schemas/plugins/optimize/LimitChunkCountPlugin.json +15 -15
- package/schemas/plugins/optimize/MinChunkSizePlugin.json +13 -13
@@ -1,491 +1,519 @@
|
|
1
|
-
/*
|
2
|
-
MIT License http://www.opensource.org/licenses/mit-license.php
|
3
|
-
Author Tobias Koppers @sokra
|
4
|
-
*/
|
5
|
-
"use strict";
|
6
|
-
|
7
|
-
const crypto = require("crypto");
|
8
|
-
const SortableSet = require("../util/SortableSet");
|
9
|
-
const GraphHelpers = require("../GraphHelpers");
|
10
|
-
const isSubset = require("../util/SetHelpers")
|
11
|
-
|
12
|
-
const hashFilename = name => {
|
13
|
-
return crypto
|
14
|
-
.createHash("md4")
|
15
|
-
.update(name)
|
16
|
-
.digest("hex")
|
17
|
-
.slice(0, 8);
|
18
|
-
};
|
19
|
-
|
20
|
-
const sortByIdentifier = (a, b) => {
|
21
|
-
if (a.identifier() > b.identifier()) return 1;
|
22
|
-
if (a.identifier() < b.identifier()) return -1;
|
23
|
-
return 0;
|
24
|
-
};
|
25
|
-
|
26
|
-
const getRequests = chunk => {
|
27
|
-
let requests = 0;
|
28
|
-
for (const chunkGroup of chunk.groupsIterable) {
|
29
|
-
requests = Math.max(requests, chunkGroup.chunks.length);
|
30
|
-
}
|
31
|
-
return requests;
|
32
|
-
};
|
33
|
-
|
34
|
-
const getModulesSize = modules => {
|
35
|
-
let sum = 0;
|
36
|
-
for (const m of modules) sum += m.size();
|
37
|
-
return sum;
|
38
|
-
};
|
39
|
-
|
40
|
-
const isOverlap = (a, b) => {
|
41
|
-
for (const item of a.keys()) {
|
42
|
-
if (b.has(item)) return true;
|
43
|
-
}
|
44
|
-
return false;
|
45
|
-
};
|
46
|
-
|
47
|
-
const compareEntries = (a, b) => {
|
48
|
-
// 1. by priority
|
49
|
-
const diffPriority = a.cacheGroup.priority - b.cacheGroup.priority;
|
50
|
-
if (diffPriority) return diffPriority;
|
51
|
-
// 2. by number of chunks
|
52
|
-
const diffCount = a.chunks.size - b.chunks.size;
|
53
|
-
if (diffCount) return diffCount;
|
54
|
-
// 3. by size reduction
|
55
|
-
const aSizeReduce = a.size * (a.chunks.size - 1);
|
56
|
-
const bSizeReduce = b.size * (b.chunks.size - 1);
|
57
|
-
const diffSizeReduce = aSizeReduce - bSizeReduce;
|
58
|
-
if (diffSizeReduce) return diffSizeReduce;
|
59
|
-
// 4. by number of modules (to be able to compare by identifier)
|
60
|
-
const modulesA = a.modules;
|
61
|
-
const modulesB = b.modules;
|
62
|
-
const diff = modulesA.size - modulesB.size;
|
63
|
-
if (diff) return diff;
|
64
|
-
// 5. by module identifiers
|
65
|
-
modulesA.sort();
|
66
|
-
modulesB.sort();
|
67
|
-
const aI = modulesA[Symbol.iterator]();
|
68
|
-
const bI = modulesB[Symbol.iterator]();
|
69
|
-
// eslint-disable-next-line no-constant-condition
|
70
|
-
while (true) {
|
71
|
-
const aItem = aI.next();
|
72
|
-
const bItem = bI.next();
|
73
|
-
if (aItem.done) return 0;
|
74
|
-
const aModuleIdentifier = aItem.value.identifier();
|
75
|
-
const bModuleIdentifier = bItem.value.identifier();
|
76
|
-
if (aModuleIdentifier > bModuleIdentifier) return -1;
|
77
|
-
if (aModuleIdentifier < bModuleIdentifier) return 1;
|
78
|
-
}
|
79
|
-
};
|
80
|
-
|
81
|
-
module.exports = class SplitChunksPlugin {
|
82
|
-
constructor(options) {
|
83
|
-
this.options = SplitChunksPlugin.normalizeOptions(options);
|
84
|
-
}
|
85
|
-
|
86
|
-
static normalizeOptions(options = {}) {
|
87
|
-
return {
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
301
|
-
|
302
|
-
:
|
303
|
-
?
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
326
|
-
|
327
|
-
|
328
|
-
|
329
|
-
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
398
|
-
|
399
|
-
|
400
|
-
|
401
|
-
|
402
|
-
|
403
|
-
|
404
|
-
|
405
|
-
|
406
|
-
|
407
|
-
|
408
|
-
|
409
|
-
|
410
|
-
|
411
|
-
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
|
416
|
-
|
417
|
-
|
418
|
-
|
419
|
-
|
420
|
-
|
421
|
-
|
422
|
-
|
423
|
-
|
424
|
-
|
425
|
-
|
426
|
-
|
427
|
-
|
428
|
-
|
429
|
-
|
430
|
-
|
431
|
-
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
}
|
1
|
+
/*
|
2
|
+
MIT License http://www.opensource.org/licenses/mit-license.php
|
3
|
+
Author Tobias Koppers @sokra
|
4
|
+
*/
|
5
|
+
"use strict";
|
6
|
+
|
7
|
+
const crypto = require("crypto");
|
8
|
+
const SortableSet = require("../util/SortableSet");
|
9
|
+
const GraphHelpers = require("../GraphHelpers");
|
10
|
+
const { isSubset } = require("../util/SetHelpers");
|
11
|
+
|
12
|
+
const hashFilename = name => {
|
13
|
+
return crypto
|
14
|
+
.createHash("md4")
|
15
|
+
.update(name)
|
16
|
+
.digest("hex")
|
17
|
+
.slice(0, 8);
|
18
|
+
};
|
19
|
+
|
20
|
+
const sortByIdentifier = (a, b) => {
|
21
|
+
if (a.identifier() > b.identifier()) return 1;
|
22
|
+
if (a.identifier() < b.identifier()) return -1;
|
23
|
+
return 0;
|
24
|
+
};
|
25
|
+
|
26
|
+
const getRequests = chunk => {
|
27
|
+
let requests = 0;
|
28
|
+
for (const chunkGroup of chunk.groupsIterable) {
|
29
|
+
requests = Math.max(requests, chunkGroup.chunks.length);
|
30
|
+
}
|
31
|
+
return requests;
|
32
|
+
};
|
33
|
+
|
34
|
+
const getModulesSize = modules => {
|
35
|
+
let sum = 0;
|
36
|
+
for (const m of modules) sum += m.size();
|
37
|
+
return sum;
|
38
|
+
};
|
39
|
+
|
40
|
+
const isOverlap = (a, b) => {
|
41
|
+
for (const item of a.keys()) {
|
42
|
+
if (b.has(item)) return true;
|
43
|
+
}
|
44
|
+
return false;
|
45
|
+
};
|
46
|
+
|
47
|
+
const compareEntries = (a, b) => {
|
48
|
+
// 1. by priority
|
49
|
+
const diffPriority = a.cacheGroup.priority - b.cacheGroup.priority;
|
50
|
+
if (diffPriority) return diffPriority;
|
51
|
+
// 2. by number of chunks
|
52
|
+
const diffCount = a.chunks.size - b.chunks.size;
|
53
|
+
if (diffCount) return diffCount;
|
54
|
+
// 3. by size reduction
|
55
|
+
const aSizeReduce = a.size * (a.chunks.size - 1);
|
56
|
+
const bSizeReduce = b.size * (b.chunks.size - 1);
|
57
|
+
const diffSizeReduce = aSizeReduce - bSizeReduce;
|
58
|
+
if (diffSizeReduce) return diffSizeReduce;
|
59
|
+
// 4. by number of modules (to be able to compare by identifier)
|
60
|
+
const modulesA = a.modules;
|
61
|
+
const modulesB = b.modules;
|
62
|
+
const diff = modulesA.size - modulesB.size;
|
63
|
+
if (diff) return diff;
|
64
|
+
// 5. by module identifiers
|
65
|
+
modulesA.sort();
|
66
|
+
modulesB.sort();
|
67
|
+
const aI = modulesA[Symbol.iterator]();
|
68
|
+
const bI = modulesB[Symbol.iterator]();
|
69
|
+
// eslint-disable-next-line no-constant-condition
|
70
|
+
while (true) {
|
71
|
+
const aItem = aI.next();
|
72
|
+
const bItem = bI.next();
|
73
|
+
if (aItem.done) return 0;
|
74
|
+
const aModuleIdentifier = aItem.value.identifier();
|
75
|
+
const bModuleIdentifier = bItem.value.identifier();
|
76
|
+
if (aModuleIdentifier > bModuleIdentifier) return -1;
|
77
|
+
if (aModuleIdentifier < bModuleIdentifier) return 1;
|
78
|
+
}
|
79
|
+
};
|
80
|
+
|
81
|
+
module.exports = class SplitChunksPlugin {
|
82
|
+
constructor(options) {
|
83
|
+
this.options = SplitChunksPlugin.normalizeOptions(options);
|
84
|
+
}
|
85
|
+
|
86
|
+
static normalizeOptions(options = {}) {
|
87
|
+
return {
|
88
|
+
chunksFilter: SplitChunksPlugin.normalizeChunksFilter(
|
89
|
+
options.chunks || "all"
|
90
|
+
),
|
91
|
+
minSize: options.minSize || 0,
|
92
|
+
minChunks: options.minChunks || 1,
|
93
|
+
maxAsyncRequests: options.maxAsyncRequests || 1,
|
94
|
+
maxInitialRequests: options.maxInitialRequests || 1,
|
95
|
+
getName:
|
96
|
+
SplitChunksPlugin.normalizeName({
|
97
|
+
name: options.name,
|
98
|
+
automaticNameDelimiter: options.automaticNameDelimiter
|
99
|
+
}) || (() => {}),
|
100
|
+
filename: options.filename || undefined,
|
101
|
+
getCacheGroups: SplitChunksPlugin.normalizeCacheGroups({
|
102
|
+
cacheGroups: options.cacheGroups,
|
103
|
+
automaticNameDelimiter: options.automaticNameDelimiter
|
104
|
+
})
|
105
|
+
};
|
106
|
+
}
|
107
|
+
|
108
|
+
static normalizeName({ name, automaticNameDelimiter }) {
|
109
|
+
if (name === true) {
|
110
|
+
const fn = (module, chunks, cacheGroup) => {
|
111
|
+
const names = chunks.map(c => c.name);
|
112
|
+
if (!names.every(Boolean)) return;
|
113
|
+
names.sort();
|
114
|
+
let name =
|
115
|
+
(cacheGroup && cacheGroup !== "default"
|
116
|
+
? cacheGroup + automaticNameDelimiter
|
117
|
+
: "") + names.join(automaticNameDelimiter);
|
118
|
+
// Filenames and paths can't be too long otherwise an
|
119
|
+
// ENAMETOOLONG error is raised. If the generated name if too
|
120
|
+
// long, it is truncated and a hash is appended. The limit has
|
121
|
+
// been set to 100 to prevent `[name].[chunkhash].[ext]` from
|
122
|
+
// generating a 256+ character string.
|
123
|
+
if (name.length > 100) {
|
124
|
+
name =
|
125
|
+
name.slice(0, 100) + automaticNameDelimiter + hashFilename(name);
|
126
|
+
}
|
127
|
+
return name;
|
128
|
+
};
|
129
|
+
return fn;
|
130
|
+
}
|
131
|
+
if (typeof name === "string") {
|
132
|
+
const fn = () => {
|
133
|
+
return name;
|
134
|
+
};
|
135
|
+
return fn;
|
136
|
+
}
|
137
|
+
if (typeof name === "function") return name;
|
138
|
+
}
|
139
|
+
|
140
|
+
static normalizeChunksFilter(chunks) {
|
141
|
+
if (chunks === "initial") {
|
142
|
+
return chunk => chunk.canBeInitial();
|
143
|
+
}
|
144
|
+
if (chunks === "async") {
|
145
|
+
return chunk => !chunk.canBeInitial();
|
146
|
+
}
|
147
|
+
if (chunks === "all") {
|
148
|
+
return () => true;
|
149
|
+
}
|
150
|
+
if (typeof chunks === "function") return chunks;
|
151
|
+
}
|
152
|
+
|
153
|
+
static normalizeCacheGroups({ cacheGroups, automaticNameDelimiter }) {
|
154
|
+
if (typeof cacheGroups === "function") {
|
155
|
+
return cacheGroups;
|
156
|
+
}
|
157
|
+
if (cacheGroups && typeof cacheGroups === "object") {
|
158
|
+
const fn = (module, chunks) => {
|
159
|
+
let results;
|
160
|
+
for (const key of Object.keys(cacheGroups)) {
|
161
|
+
let option = cacheGroups[key];
|
162
|
+
if (option === false) continue;
|
163
|
+
if (option instanceof RegExp || typeof option === "string") {
|
164
|
+
option = {
|
165
|
+
test: option
|
166
|
+
};
|
167
|
+
}
|
168
|
+
if (typeof option === "function") {
|
169
|
+
let result = option(module);
|
170
|
+
if (result) {
|
171
|
+
if (results === undefined) results = [];
|
172
|
+
for (const r of Array.isArray(result) ? result : [result]) {
|
173
|
+
const result = Object.assign(
|
174
|
+
{
|
175
|
+
key
|
176
|
+
},
|
177
|
+
r
|
178
|
+
);
|
179
|
+
if (result.name) result.getName = () => result.name;
|
180
|
+
if (result.chunks) {
|
181
|
+
result.chunksFilter = SplitChunksPlugin.normalizeChunksFilter(
|
182
|
+
result.chunks
|
183
|
+
);
|
184
|
+
}
|
185
|
+
results.push(result);
|
186
|
+
}
|
187
|
+
}
|
188
|
+
} else if (SplitChunksPlugin.checkTest(option.test, module, chunks)) {
|
189
|
+
if (results === undefined) results = [];
|
190
|
+
results.push({
|
191
|
+
key: key,
|
192
|
+
priority: option.priority,
|
193
|
+
getName: SplitChunksPlugin.normalizeName({
|
194
|
+
name: option.name,
|
195
|
+
automaticNameDelimiter
|
196
|
+
}),
|
197
|
+
chunksFilter: SplitChunksPlugin.normalizeChunksFilter(
|
198
|
+
option.chunks
|
199
|
+
),
|
200
|
+
enforce: option.enforce,
|
201
|
+
minSize: option.minSize,
|
202
|
+
minChunks: option.minChunks,
|
203
|
+
maxAsyncRequests: option.maxAsyncRequests,
|
204
|
+
maxInitialRequests: option.maxInitialRequests,
|
205
|
+
filename: option.filename,
|
206
|
+
reuseExistingChunk: option.reuseExistingChunk
|
207
|
+
});
|
208
|
+
}
|
209
|
+
}
|
210
|
+
return results;
|
211
|
+
};
|
212
|
+
return fn;
|
213
|
+
}
|
214
|
+
const fn = () => {};
|
215
|
+
return fn;
|
216
|
+
}
|
217
|
+
|
218
|
+
static checkTest(test, module, chunks) {
|
219
|
+
if (test === undefined) return true;
|
220
|
+
if (typeof test === "function") return test(module, chunks);
|
221
|
+
if (typeof test === "boolean") return test;
|
222
|
+
const names = chunks
|
223
|
+
.map(c => c.name)
|
224
|
+
.concat(module.nameForCondition ? [module.nameForCondition()] : [])
|
225
|
+
.filter(Boolean);
|
226
|
+
if (typeof test === "string") {
|
227
|
+
for (const name of names) if (name.startsWith(test)) return true;
|
228
|
+
return false;
|
229
|
+
}
|
230
|
+
if (test instanceof RegExp) {
|
231
|
+
for (const name of names) if (test.test(name)) return true;
|
232
|
+
return false;
|
233
|
+
}
|
234
|
+
return false;
|
235
|
+
}
|
236
|
+
|
237
|
+
apply(compiler) {
|
238
|
+
compiler.hooks.thisCompilation.tap("SplitChunksPlugin", compilation => {
|
239
|
+
let alreadyOptimized = false;
|
240
|
+
compilation.hooks.unseal.tap("SplitChunksPlugin", () => {
|
241
|
+
alreadyOptimized = false;
|
242
|
+
});
|
243
|
+
compilation.hooks.optimizeChunksAdvanced.tap(
|
244
|
+
"SplitChunksPlugin",
|
245
|
+
chunks => {
|
246
|
+
if (alreadyOptimized) return;
|
247
|
+
alreadyOptimized = true;
|
248
|
+
// Give each selected chunk an index (to create strings from chunks)
|
249
|
+
const indexMap = new Map();
|
250
|
+
let index = 1;
|
251
|
+
for (const chunk of chunks) {
|
252
|
+
indexMap.set(chunk, index++);
|
253
|
+
}
|
254
|
+
const getKey = chunks => {
|
255
|
+
return Array.from(chunks, c => indexMap.get(c))
|
256
|
+
.sort()
|
257
|
+
.join();
|
258
|
+
};
|
259
|
+
// Create a list of possible combinations
|
260
|
+
const chunkSetsInGraph = new Map(); // Map<string, Set<Chunk>>
|
261
|
+
for (const module of compilation.modules) {
|
262
|
+
const chunkIndices = getKey(module.chunksIterable);
|
263
|
+
chunkSetsInGraph.set(chunkIndices, new Set(module.chunksIterable));
|
264
|
+
}
|
265
|
+
const combinations = new Map(); // Map<string, Set<Chunk>[]>
|
266
|
+
for (const [key, chunksSet] of chunkSetsInGraph) {
|
267
|
+
var array = [];
|
268
|
+
for (const set of chunkSetsInGraph.values()) {
|
269
|
+
if (isSubset(chunksSet, set)) {
|
270
|
+
array.push(set);
|
271
|
+
}
|
272
|
+
}
|
273
|
+
combinations.set(key, array);
|
274
|
+
}
|
275
|
+
// Map a list of chunks to a list of modules
|
276
|
+
// For the key the chunk "index" is used, the value is a SortableSet of modules
|
277
|
+
const chunksInfoMap = new Map();
|
278
|
+
// Walk through all modules
|
279
|
+
for (const module of compilation.modules) {
|
280
|
+
// Get array of chunks
|
281
|
+
const chunks = module.getChunks();
|
282
|
+
// Get cache group
|
283
|
+
let cacheGroups = this.options.getCacheGroups(module, chunks);
|
284
|
+
if (!Array.isArray(cacheGroups)) continue;
|
285
|
+
for (const cacheGroupSource of cacheGroups) {
|
286
|
+
const cacheGroup = {
|
287
|
+
key: cacheGroupSource.key,
|
288
|
+
priority: cacheGroupSource.priority || 0,
|
289
|
+
chunksFilter:
|
290
|
+
cacheGroupSource.chunksFilter || this.options.chunksFilter,
|
291
|
+
minSize:
|
292
|
+
cacheGroupSource.minSize !== undefined
|
293
|
+
? cacheGroupSource.minSize
|
294
|
+
: cacheGroupSource.enforce ? 0 : this.options.minSize,
|
295
|
+
minChunks:
|
296
|
+
cacheGroupSource.minChunks !== undefined
|
297
|
+
? cacheGroupSource.minChunks
|
298
|
+
: cacheGroupSource.enforce ? 1 : this.options.minChunks,
|
299
|
+
maxAsyncRequests:
|
300
|
+
cacheGroupSource.maxAsyncRequests !== undefined
|
301
|
+
? cacheGroupSource.maxAsyncRequests
|
302
|
+
: cacheGroupSource.enforce
|
303
|
+
? Infinity
|
304
|
+
: this.options.maxAsyncRequests,
|
305
|
+
maxInitialRequests:
|
306
|
+
cacheGroupSource.maxInitialRequests !== undefined
|
307
|
+
? cacheGroupSource.maxInitialRequests
|
308
|
+
: cacheGroupSource.enforce
|
309
|
+
? Infinity
|
310
|
+
: this.options.maxInitialRequests,
|
311
|
+
getName:
|
312
|
+
cacheGroupSource.getName !== undefined
|
313
|
+
? cacheGroupSource.getName
|
314
|
+
: this.options.getName,
|
315
|
+
filename:
|
316
|
+
cacheGroupSource.filename !== undefined
|
317
|
+
? cacheGroupSource.filename
|
318
|
+
: this.options.filename,
|
319
|
+
reuseExistingChunk: cacheGroupSource.reuseExistingChunk
|
320
|
+
};
|
321
|
+
// For all combination of chunk selection
|
322
|
+
for (const chunkCombination of combinations.get(getKey(chunks))) {
|
323
|
+
// Get indices of chunks in which this module occurs
|
324
|
+
const chunkIndices = Array.from(chunkCombination, chunk =>
|
325
|
+
indexMap.get(chunk)
|
326
|
+
);
|
327
|
+
// Break if minimum number of chunks is not reached
|
328
|
+
if (chunkIndices.length < cacheGroup.minChunks) continue;
|
329
|
+
// Select chunks by configuration
|
330
|
+
const selectedChunks = Array.from(chunkCombination).filter(
|
331
|
+
cacheGroup.chunksFilter
|
332
|
+
);
|
333
|
+
// Break if minimum number of chunks is not reached
|
334
|
+
if (selectedChunks.length < cacheGroup.minChunks) continue;
|
335
|
+
// Determine name for split chunk
|
336
|
+
const name = cacheGroup.getName(
|
337
|
+
module,
|
338
|
+
selectedChunks,
|
339
|
+
cacheGroup.key
|
340
|
+
);
|
341
|
+
// Create key for maps
|
342
|
+
// When it has a name we use the name as key
|
343
|
+
// Elsewise we create the key from chunks and cache group key
|
344
|
+
// This automatically merges equal names
|
345
|
+
const chunksKey = getKey(selectedChunks);
|
346
|
+
const key =
|
347
|
+
(name && `name:${name}`) ||
|
348
|
+
`chunks:${chunksKey} key:${cacheGroup.key}`;
|
349
|
+
// Add module to maps
|
350
|
+
let info = chunksInfoMap.get(key);
|
351
|
+
if (info === undefined) {
|
352
|
+
chunksInfoMap.set(
|
353
|
+
key,
|
354
|
+
(info = {
|
355
|
+
modules: new SortableSet(undefined, sortByIdentifier),
|
356
|
+
cacheGroup,
|
357
|
+
name,
|
358
|
+
chunks: new Map(),
|
359
|
+
reusedableChunks: new Set(),
|
360
|
+
chunksKeys: new Set()
|
361
|
+
})
|
362
|
+
);
|
363
|
+
}
|
364
|
+
info.modules.add(module);
|
365
|
+
if (!info.chunksKeys.has(chunksKey)) {
|
366
|
+
info.chunksKeys.add(chunksKey);
|
367
|
+
for (const chunk of selectedChunks) {
|
368
|
+
info.chunks.set(chunk, chunk.getNumberOfModules());
|
369
|
+
}
|
370
|
+
}
|
371
|
+
}
|
372
|
+
}
|
373
|
+
}
|
374
|
+
for (const [key, info] of chunksInfoMap) {
|
375
|
+
// Get size of module lists
|
376
|
+
info.size = getModulesSize(info.modules);
|
377
|
+
if (info.size < info.cacheGroup.minSize) {
|
378
|
+
chunksInfoMap.delete(key);
|
379
|
+
}
|
380
|
+
}
|
381
|
+
let changed = false;
|
382
|
+
while (chunksInfoMap.size > 0) {
|
383
|
+
// Find best matching entry
|
384
|
+
let bestEntryKey;
|
385
|
+
let bestEntry;
|
386
|
+
for (const pair of chunksInfoMap) {
|
387
|
+
const key = pair[0];
|
388
|
+
const info = pair[1];
|
389
|
+
if (bestEntry === undefined) {
|
390
|
+
bestEntry = info;
|
391
|
+
bestEntryKey = key;
|
392
|
+
} else if (compareEntries(bestEntry, info) < 0) {
|
393
|
+
bestEntry = info;
|
394
|
+
bestEntryKey = key;
|
395
|
+
}
|
396
|
+
}
|
397
|
+
|
398
|
+
const item = bestEntry;
|
399
|
+
chunksInfoMap.delete(bestEntryKey);
|
400
|
+
|
401
|
+
let chunkName = item.name;
|
402
|
+
// Variable for the new chunk (lazy created)
|
403
|
+
let newChunk;
|
404
|
+
// When no chunk name, check if we can reuse a chunk instead of creating a new one
|
405
|
+
let isReused = false;
|
406
|
+
if (item.cacheGroup.reuseExistingChunk) {
|
407
|
+
for (const pair of item.chunks) {
|
408
|
+
if (pair[1] === item.modules.size) {
|
409
|
+
const chunk = pair[0];
|
410
|
+
if (chunk.hasEntryModule()) continue;
|
411
|
+
if (!newChunk || !newChunk.name) newChunk = chunk;
|
412
|
+
else if (
|
413
|
+
chunk.name &&
|
414
|
+
chunk.name.length < newChunk.name.length
|
415
|
+
)
|
416
|
+
newChunk = chunk;
|
417
|
+
else if (
|
418
|
+
chunk.name &&
|
419
|
+
chunk.name.length === newChunk.name.length &&
|
420
|
+
chunk.name < newChunk.name
|
421
|
+
)
|
422
|
+
newChunk = chunk;
|
423
|
+
chunkName = undefined;
|
424
|
+
isReused = true;
|
425
|
+
}
|
426
|
+
}
|
427
|
+
}
|
428
|
+
// Walk through all chunks
|
429
|
+
for (const chunk of item.chunks.keys()) {
|
430
|
+
// skip if we address ourself
|
431
|
+
if (chunk.name === chunkName || chunk === newChunk) continue;
|
432
|
+
// respect max requests when not enforced
|
433
|
+
const maxRequests = chunk.isOnlyInitial()
|
434
|
+
? item.cacheGroup.maxInitialRequests
|
435
|
+
: chunk.canBeInitial()
|
436
|
+
? Math.min(
|
437
|
+
item.cacheGroup.maxInitialRequests,
|
438
|
+
item.cacheGroup.maxAsyncRequests
|
439
|
+
)
|
440
|
+
: item.cacheGroup.maxAsyncRequests;
|
441
|
+
if (isFinite(maxRequests) && getRequests(chunk) >= maxRequests)
|
442
|
+
continue;
|
443
|
+
if (newChunk === undefined) {
|
444
|
+
// Create the new chunk
|
445
|
+
newChunk = compilation.addChunk(chunkName);
|
446
|
+
}
|
447
|
+
// Add graph connections for splitted chunk
|
448
|
+
chunk.split(newChunk);
|
449
|
+
// Remove all selected modules from the chunk
|
450
|
+
for (const module of item.modules) {
|
451
|
+
chunk.removeModule(module);
|
452
|
+
module.rewriteChunkInReasons(chunk, [newChunk]);
|
453
|
+
}
|
454
|
+
}
|
455
|
+
// If we successfully created a new chunk or reused one
|
456
|
+
if (newChunk) {
|
457
|
+
// Add a note to the chunk
|
458
|
+
newChunk.chunkReason = isReused
|
459
|
+
? "reused as split chunk"
|
460
|
+
: "split chunk";
|
461
|
+
if (item.cacheGroup.key) {
|
462
|
+
newChunk.chunkReason += ` (cache group: ${
|
463
|
+
item.cacheGroup.key
|
464
|
+
})`;
|
465
|
+
}
|
466
|
+
if (chunkName) {
|
467
|
+
newChunk.chunkReason += ` (name: ${chunkName})`;
|
468
|
+
// If the chosen name is already an entry point we remove the entry point
|
469
|
+
const entrypoint = compilation.entrypoints.get(chunkName);
|
470
|
+
if (entrypoint) {
|
471
|
+
compilation.entrypoints.delete(chunkName);
|
472
|
+
entrypoint.remove();
|
473
|
+
newChunk.entryModule = undefined;
|
474
|
+
}
|
475
|
+
}
|
476
|
+
if (item.cacheGroup.filename) {
|
477
|
+
if (!newChunk.isOnlyInitial()) {
|
478
|
+
throw new Error(
|
479
|
+
"SplitChunksPlugin: You are trying to set a filename for a chunk which is (also) loaded on demand. " +
|
480
|
+
"The runtime can only handle loading of chunks which match the chunkFilename schema. " +
|
481
|
+
"Using a custom filename would fail at runtime. " +
|
482
|
+
`(cache group: ${item.cacheGroup.key})`
|
483
|
+
);
|
484
|
+
}
|
485
|
+
newChunk.filenameTemplate = item.cacheGroup.filename;
|
486
|
+
}
|
487
|
+
if (!isReused) {
|
488
|
+
// Add all modules to the new chunk
|
489
|
+
for (const module of item.modules) {
|
490
|
+
GraphHelpers.connectChunkAndModule(newChunk, module);
|
491
|
+
}
|
492
|
+
}
|
493
|
+
// remove all modules from other entries and update size
|
494
|
+
for (const [key, info] of chunksInfoMap) {
|
495
|
+
if (isOverlap(info.chunks, item.chunks)) {
|
496
|
+
const oldSize = info.modules.size;
|
497
|
+
for (const module of item.modules) {
|
498
|
+
info.modules.delete(module);
|
499
|
+
}
|
500
|
+
if (info.modules.size === 0) {
|
501
|
+
chunksInfoMap.delete(key);
|
502
|
+
continue;
|
503
|
+
}
|
504
|
+
if (info.modules.size !== oldSize) {
|
505
|
+
info.size = getModulesSize(info.modules);
|
506
|
+
if (info.size < info.cacheGroup.minSize)
|
507
|
+
chunksInfoMap.delete(key);
|
508
|
+
}
|
509
|
+
}
|
510
|
+
}
|
511
|
+
changed = true;
|
512
|
+
}
|
513
|
+
}
|
514
|
+
if (changed) return true;
|
515
|
+
}
|
516
|
+
);
|
517
|
+
});
|
518
|
+
}
|
519
|
+
};
|