webpack 4.25.1 → 4.27.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/buildin/global.js +1 -1
- package/declarations/WebpackOptions.d.ts +1 -0
- package/lib/Chunk.js +10 -7
- package/lib/FlagDependencyExportsPlugin.js +10 -1
- package/lib/NormalModule.js +15 -0
- package/lib/ResolverFactory.js +13 -0
- package/lib/WebpackOptionsDefaulter.js +3 -3
- package/lib/optimize/MinMaxSizeWarning.js +29 -0
- package/lib/optimize/SplitChunksPlugin.js +101 -58
- package/lib/util/deterministicGrouping.js +92 -69
- package/lib/webpack.js +1 -1
- package/package.json +2 -2
- package/schemas/WebpackOptions.json +1 -1
package/buildin/global.js
CHANGED
@@ -7,7 +7,7 @@ g = (function() {
|
|
7
7
|
|
8
8
|
try {
|
9
9
|
// This works if eval is allowed (see CSP)
|
10
|
-
g = g || Function("return this")()
|
10
|
+
g = g || new Function("return this")();
|
11
11
|
} catch (e) {
|
12
12
|
// This works if the window reference is available
|
13
13
|
if (typeof window === "object") g = window;
|
@@ -225,6 +225,7 @@ export type ArrayOfStringOrStringArrayValues = (string | string[])[];
|
|
225
225
|
* via the `definition` "WebpackPluginFunction".
|
226
226
|
*/
|
227
227
|
export type WebpackPluginFunction = (
|
228
|
+
this: import("../lib/Compiler"),
|
228
229
|
compiler: import("../lib/Compiler")
|
229
230
|
) => void;
|
230
231
|
/**
|
package/lib/Chunk.js
CHANGED
@@ -430,7 +430,7 @@ class Chunk {
|
|
430
430
|
}
|
431
431
|
|
432
432
|
/**
|
433
|
-
* @param {Chunk} newChunk the new chunk that will be split out of
|
433
|
+
* @param {Chunk} newChunk the new chunk that will be split out of the current chunk
|
434
434
|
* @returns {void}
|
435
435
|
*/
|
436
436
|
split(newChunk) {
|
@@ -454,6 +454,10 @@ class Chunk {
|
|
454
454
|
}
|
455
455
|
|
456
456
|
canBeIntegrated(otherChunk) {
|
457
|
+
if (this.preventIntegration || otherChunk.preventIntegration) {
|
458
|
+
return false;
|
459
|
+
}
|
460
|
+
|
457
461
|
const isAvailable = (a, b) => {
|
458
462
|
const queue = new Set(b.groupsIterable);
|
459
463
|
for (const chunkGroup of queue) {
|
@@ -466,14 +470,13 @@ class Chunk {
|
|
466
470
|
return true;
|
467
471
|
};
|
468
472
|
|
469
|
-
|
470
|
-
|
471
|
-
}
|
473
|
+
const selfHasRuntime = this.hasRuntime();
|
474
|
+
const otherChunkHasRuntime = otherChunk.hasRuntime();
|
472
475
|
|
473
|
-
if (
|
474
|
-
if (
|
476
|
+
if (selfHasRuntime !== otherChunkHasRuntime) {
|
477
|
+
if (selfHasRuntime) {
|
475
478
|
return isAvailable(this, otherChunk);
|
476
|
-
} else if (
|
479
|
+
} else if (otherChunkHasRuntime) {
|
477
480
|
return isAvailable(otherChunk, this);
|
478
481
|
} else {
|
479
482
|
return false;
|
@@ -32,6 +32,7 @@ class FlagDependencyExportsPlugin {
|
|
32
32
|
let module;
|
33
33
|
let moduleWithExports;
|
34
34
|
let moduleProvidedExports;
|
35
|
+
let providedExportsAreTemporary;
|
35
36
|
|
36
37
|
const processDependenciesBlock = depBlock => {
|
37
38
|
for (const dep of depBlock.dependencies) {
|
@@ -72,6 +73,7 @@ class FlagDependencyExportsPlugin {
|
|
72
73
|
// store dependencies
|
73
74
|
const exportDeps = exportDesc.dependencies;
|
74
75
|
if (exportDeps) {
|
76
|
+
providedExportsAreTemporary = true;
|
75
77
|
for (const exportDependency of exportDeps) {
|
76
78
|
// add dependency for this module
|
77
79
|
const set = dependencies.get(exportDependency);
|
@@ -96,7 +98,12 @@ class FlagDependencyExportsPlugin {
|
|
96
98
|
|
97
99
|
// Start with all modules without provided exports
|
98
100
|
for (const module of modules) {
|
99
|
-
if (
|
101
|
+
if (module.buildInfo.temporaryProvidedExports) {
|
102
|
+
// Clear exports when they are temporary
|
103
|
+
// and recreate them
|
104
|
+
module.buildMeta.providedExports = null;
|
105
|
+
queue.enqueue(module);
|
106
|
+
} else if (!module.buildMeta.providedExports) {
|
100
107
|
queue.enqueue(module);
|
101
108
|
}
|
102
109
|
}
|
@@ -112,7 +119,9 @@ class FlagDependencyExportsPlugin {
|
|
112
119
|
)
|
113
120
|
? new Set(module.buildMeta.providedExports)
|
114
121
|
: new Set();
|
122
|
+
providedExportsAreTemporary = false;
|
115
123
|
processDependenciesBlock(module);
|
124
|
+
module.buildInfo.temporaryProvidedExports = providedExportsAreTemporary;
|
116
125
|
if (!moduleWithExports) {
|
117
126
|
module.buildMeta.providedExports = true;
|
118
127
|
notifyDependencies();
|
package/lib/NormalModule.js
CHANGED
@@ -184,6 +184,21 @@ class NormalModule extends Module {
|
|
184
184
|
resolve(context, request, callback) {
|
185
185
|
resolver.resolve({}, context, request, {}, callback);
|
186
186
|
},
|
187
|
+
getResolve(options) {
|
188
|
+
const child = options ? resolver.withOptions(options) : resolver;
|
189
|
+
return (context, request, callback) => {
|
190
|
+
if (callback) {
|
191
|
+
child.resolve({}, context, request, {}, callback);
|
192
|
+
} else {
|
193
|
+
return new Promise((resolve, reject) => {
|
194
|
+
child.resolve({}, context, request, {}, (err, result) => {
|
195
|
+
if (err) reject(err);
|
196
|
+
else resolve(result);
|
197
|
+
});
|
198
|
+
});
|
199
|
+
}
|
200
|
+
};
|
201
|
+
},
|
187
202
|
emitFile: (name, content, sourceMap) => {
|
188
203
|
if (!this.buildInfo.assets) {
|
189
204
|
this.buildInfo.assets = Object.create(null);
|
package/lib/ResolverFactory.js
CHANGED
@@ -7,6 +7,8 @@
|
|
7
7
|
const { Tapable, HookMap, SyncHook, SyncWaterfallHook } = require("tapable");
|
8
8
|
const Factory = require("enhanced-resolve").ResolverFactory;
|
9
9
|
|
10
|
+
/** @typedef {import("enhanced-resolve").Resolver} Resolver */
|
11
|
+
|
10
12
|
module.exports = class ResolverFactory extends Tapable {
|
11
13
|
constructor() {
|
12
14
|
super();
|
@@ -53,11 +55,22 @@ module.exports = class ResolverFactory extends Tapable {
|
|
53
55
|
}
|
54
56
|
|
55
57
|
_create(type, resolveOptions) {
|
58
|
+
const originalResolveOptions = Object.assign({}, resolveOptions);
|
56
59
|
resolveOptions = this.hooks.resolveOptions.for(type).call(resolveOptions);
|
57
60
|
const resolver = Factory.createResolver(resolveOptions);
|
58
61
|
if (!resolver) {
|
59
62
|
throw new Error("No resolver created");
|
60
63
|
}
|
64
|
+
/** @type {Map<Object, Resolver>} */
|
65
|
+
const childCache = new Map();
|
66
|
+
resolver.withOptions = options => {
|
67
|
+
const cacheEntry = childCache.get(options);
|
68
|
+
if (cacheEntry !== undefined) return cacheEntry;
|
69
|
+
const mergedOptions = Object.assign({}, originalResolveOptions, options);
|
70
|
+
const resolver = this.get(type, mergedOptions);
|
71
|
+
childCache.set(options, resolver);
|
72
|
+
return resolver;
|
73
|
+
};
|
61
74
|
this.hooks.resolver.for(type).call(resolver, resolveOptions);
|
62
75
|
return resolver;
|
63
76
|
}
|
@@ -302,10 +302,10 @@ class WebpackOptionsDefaulter extends OptionsDefaulter {
|
|
302
302
|
this.set("optimization.minimizer", "make", options => [
|
303
303
|
{
|
304
304
|
apply: compiler => {
|
305
|
-
// Lazy load the
|
306
|
-
const
|
305
|
+
// Lazy load the Terser plugin
|
306
|
+
const TerserPlugin = require("terser-webpack-plugin");
|
307
307
|
const SourceMapDevToolPlugin = require("./SourceMapDevToolPlugin");
|
308
|
-
new
|
308
|
+
new TerserPlugin({
|
309
309
|
cache: true,
|
310
310
|
parallel: true,
|
311
311
|
sourceMap:
|
@@ -0,0 +1,29 @@
|
|
1
|
+
/*
|
2
|
+
MIT License http://www.opensource.org/licenses/mit-license.php
|
3
|
+
Author Tobias Koppers @sokra
|
4
|
+
*/
|
5
|
+
"use strict";
|
6
|
+
|
7
|
+
const WebpackError = require("../WebpackError");
|
8
|
+
const SizeFormatHelpers = require("../SizeFormatHelpers");
|
9
|
+
|
10
|
+
class MinMaxSizeWarning extends WebpackError {
|
11
|
+
constructor(keys, minSize, maxSize) {
|
12
|
+
let keysMessage = "Fallback cache group";
|
13
|
+
if (keys) {
|
14
|
+
keysMessage =
|
15
|
+
keys.length > 1
|
16
|
+
? `Cache groups ${keys.sort().join(", ")}`
|
17
|
+
: `Cache group ${keys[0]}`;
|
18
|
+
}
|
19
|
+
super(
|
20
|
+
`SplitChunksPlugin\n` +
|
21
|
+
`${keysMessage}\n` +
|
22
|
+
`Configured minSize (${SizeFormatHelpers.formatSize(minSize)}) is ` +
|
23
|
+
`bigger than maxSize (${SizeFormatHelpers.formatSize(maxSize)}).\n` +
|
24
|
+
"This seem to be a invalid optimiziation.splitChunks configuration."
|
25
|
+
);
|
26
|
+
}
|
27
|
+
}
|
28
|
+
|
29
|
+
module.exports = MinMaxSizeWarning;
|
@@ -9,6 +9,7 @@ const SortableSet = require("../util/SortableSet");
|
|
9
9
|
const GraphHelpers = require("../GraphHelpers");
|
10
10
|
const { isSubset } = require("../util/SetHelpers");
|
11
11
|
const deterministicGrouping = require("../util/deterministicGrouping");
|
12
|
+
const MinMaxSizeWarning = require("./MinMaxSizeWarning");
|
12
13
|
const contextify = require("../util/identifier").contextify;
|
13
14
|
|
14
15
|
/** @typedef {import("../Compiler")} Compiler */
|
@@ -96,6 +97,8 @@ const compareEntries = (a, b) => {
|
|
96
97
|
}
|
97
98
|
};
|
98
99
|
|
100
|
+
const compareNumbers = (a, b) => a - b;
|
101
|
+
|
99
102
|
const INITIAL_CHUNK_FILTER = chunk => chunk.canBeInitial();
|
100
103
|
const ASYNC_CHUNK_FILTER = chunk => !chunk.canBeInitial();
|
101
104
|
const ALL_CHUNK_FILTER = chunk => true;
|
@@ -340,7 +343,7 @@ module.exports = class SplitChunksPlugin {
|
|
340
343
|
}
|
341
344
|
const getKey = chunks => {
|
342
345
|
return Array.from(chunks, c => indexMap.get(c))
|
343
|
-
.sort()
|
346
|
+
.sort(compareNumbers)
|
344
347
|
.join();
|
345
348
|
};
|
346
349
|
/** @type {Map<string, Set<Chunk>>} */
|
@@ -436,6 +439,7 @@ module.exports = class SplitChunksPlugin {
|
|
436
439
|
* @property {SortableSet} modules
|
437
440
|
* @property {TODO} cacheGroup
|
438
441
|
* @property {string} name
|
442
|
+
* @property {boolean} validateSize
|
439
443
|
* @property {number} size
|
440
444
|
* @property {Set<Chunk>} chunks
|
441
445
|
* @property {Set<Chunk>} reuseableChunks
|
@@ -473,8 +477,8 @@ module.exports = class SplitChunksPlugin {
|
|
473
477
|
// Elsewise we create the key from chunks and cache group key
|
474
478
|
// This automatically merges equal names
|
475
479
|
const key =
|
476
|
-
|
477
|
-
`
|
480
|
+
cacheGroup.key +
|
481
|
+
(name ? ` name:${name}` : ` chunks:${selectedChunksKey}`);
|
478
482
|
// Add module to maps
|
479
483
|
let info = chunksInfoMap.get(key);
|
480
484
|
if (info === undefined) {
|
@@ -484,21 +488,18 @@ module.exports = class SplitChunksPlugin {
|
|
484
488
|
modules: new SortableSet(undefined, sortByIdentifier),
|
485
489
|
cacheGroup,
|
486
490
|
name,
|
491
|
+
validateSize: cacheGroup.minSize > 0,
|
487
492
|
size: 0,
|
488
493
|
chunks: new Set(),
|
489
494
|
reuseableChunks: new Set(),
|
490
495
|
chunksKeys: new Set()
|
491
496
|
})
|
492
497
|
);
|
493
|
-
} else {
|
494
|
-
if (info.cacheGroup !== cacheGroup) {
|
495
|
-
if (info.cacheGroup.priority < cacheGroup.priority) {
|
496
|
-
info.cacheGroup = cacheGroup;
|
497
|
-
}
|
498
|
-
}
|
499
498
|
}
|
500
499
|
info.modules.add(module);
|
501
|
-
info.
|
500
|
+
if (info.validateSize) {
|
501
|
+
info.size += module.size();
|
502
|
+
}
|
502
503
|
if (!info.chunksKeys.has(selectedChunksKey)) {
|
503
504
|
info.chunksKeys.add(selectedChunksKey);
|
504
505
|
for (const chunk of selectedChunks) {
|
@@ -535,6 +536,10 @@ module.exports = class SplitChunksPlugin {
|
|
535
536
|
: cacheGroupSource.enforce
|
536
537
|
? 0
|
537
538
|
: this.options.minSize,
|
539
|
+
minSizeForMaxSize:
|
540
|
+
cacheGroupSource.minSize !== undefined
|
541
|
+
? cacheGroupSource.minSize
|
542
|
+
: this.options.minSize,
|
538
543
|
maxSize:
|
539
544
|
cacheGroupSource.maxSize !== undefined
|
540
545
|
? cacheGroupSource.maxSize
|
@@ -596,7 +601,15 @@ module.exports = class SplitChunksPlugin {
|
|
596
601
|
}
|
597
602
|
}
|
598
603
|
|
599
|
-
|
604
|
+
// Filter items were size < minSize
|
605
|
+
for (const pair of chunksInfoMap) {
|
606
|
+
const info = pair[1];
|
607
|
+
if (info.validateSize && info.size < info.cacheGroup.minSize) {
|
608
|
+
chunksInfoMap.delete(pair[0]);
|
609
|
+
}
|
610
|
+
}
|
611
|
+
|
612
|
+
/** @type {Map<Chunk, {minSize: number, maxSize: number, automaticNameDelimiter: string, keys: string[]}>} */
|
600
613
|
const maxSizeQueueMap = new Map();
|
601
614
|
|
602
615
|
while (chunksInfoMap.size > 0) {
|
@@ -606,20 +619,15 @@ module.exports = class SplitChunksPlugin {
|
|
606
619
|
for (const pair of chunksInfoMap) {
|
607
620
|
const key = pair[0];
|
608
621
|
const info = pair[1];
|
609
|
-
if (
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
bestEntryKey = key;
|
616
|
-
}
|
622
|
+
if (bestEntry === undefined) {
|
623
|
+
bestEntry = info;
|
624
|
+
bestEntryKey = key;
|
625
|
+
} else if (compareEntries(bestEntry, info) < 0) {
|
626
|
+
bestEntry = info;
|
627
|
+
bestEntryKey = key;
|
617
628
|
}
|
618
629
|
}
|
619
630
|
|
620
|
-
// No suitable item left
|
621
|
-
if (bestEntry === undefined) break;
|
622
|
-
|
623
631
|
const item = bestEntry;
|
624
632
|
chunksInfoMap.delete(bestEntryKey);
|
625
633
|
|
@@ -666,29 +674,38 @@ module.exports = class SplitChunksPlugin {
|
|
666
674
|
// Skip when no chunk selected
|
667
675
|
if (usedChunks.length === 0) continue;
|
668
676
|
|
669
|
-
|
670
|
-
|
671
|
-
|
672
|
-
|
673
|
-
|
674
|
-
|
675
|
-
|
676
|
-
|
677
|
-
|
678
|
-
|
679
|
-
|
680
|
-
|
681
|
-
|
682
|
-
|
683
|
-
|
684
|
-
|
685
|
-
item.cacheGroup,
|
686
|
-
chunkInLimit,
|
687
|
-
getKey(chunkInLimit),
|
688
|
-
module
|
677
|
+
if (
|
678
|
+
Number.isFinite(item.cacheGroup.maxInitialRequests) ||
|
679
|
+
Number.isFinite(item.cacheGroup.maxAsyncRequests)
|
680
|
+
) {
|
681
|
+
const chunkInLimit = usedChunks.filter(chunk => {
|
682
|
+
// respect max requests when not enforced
|
683
|
+
const maxRequests = chunk.isOnlyInitial()
|
684
|
+
? item.cacheGroup.maxInitialRequests
|
685
|
+
: chunk.canBeInitial()
|
686
|
+
? Math.min(
|
687
|
+
item.cacheGroup.maxInitialRequests,
|
688
|
+
item.cacheGroup.maxAsyncRequests
|
689
|
+
)
|
690
|
+
: item.cacheGroup.maxAsyncRequests;
|
691
|
+
return (
|
692
|
+
!isFinite(maxRequests) || getRequests(chunk) < maxRequests
|
689
693
|
);
|
694
|
+
});
|
695
|
+
|
696
|
+
if (chunkInLimit.length < usedChunks.length) {
|
697
|
+
if (chunkInLimit.length >= item.cacheGroup.minChunks) {
|
698
|
+
for (const module of item.modules) {
|
699
|
+
addModuleToChunksInfoMap(
|
700
|
+
item.cacheGroup,
|
701
|
+
chunkInLimit,
|
702
|
+
getKey(chunkInLimit),
|
703
|
+
module
|
704
|
+
);
|
705
|
+
}
|
706
|
+
}
|
707
|
+
continue;
|
690
708
|
}
|
691
|
-
continue;
|
692
709
|
}
|
693
710
|
|
694
711
|
// Create the new chunk if not reusing one
|
@@ -758,30 +775,45 @@ module.exports = class SplitChunksPlugin {
|
|
758
775
|
maxSizeQueueMap.set(newChunk, {
|
759
776
|
minSize: Math.max(
|
760
777
|
oldMaxSizeSettings ? oldMaxSizeSettings.minSize : 0,
|
761
|
-
item.cacheGroup.
|
778
|
+
item.cacheGroup.minSizeForMaxSize
|
762
779
|
),
|
763
780
|
maxSize: Math.min(
|
764
781
|
oldMaxSizeSettings ? oldMaxSizeSettings.maxSize : Infinity,
|
765
782
|
item.cacheGroup.maxSize
|
766
783
|
),
|
767
|
-
automaticNameDelimiter: item.cacheGroup.automaticNameDelimiter
|
784
|
+
automaticNameDelimiter: item.cacheGroup.automaticNameDelimiter,
|
785
|
+
keys: oldMaxSizeSettings
|
786
|
+
? oldMaxSizeSettings.keys.concat(item.cacheGroup.key)
|
787
|
+
: [item.cacheGroup.key]
|
768
788
|
});
|
769
789
|
}
|
770
790
|
|
771
791
|
// remove all modules from other entries and update size
|
772
792
|
for (const [key, info] of chunksInfoMap) {
|
773
793
|
if (isOverlap(info.chunks, item.chunks)) {
|
774
|
-
|
775
|
-
|
776
|
-
|
777
|
-
|
778
|
-
|
779
|
-
|
780
|
-
|
781
|
-
|
782
|
-
|
783
|
-
|
784
|
-
|
794
|
+
if (info.validateSize) {
|
795
|
+
// update modules and total size
|
796
|
+
// may remove it from the map when < minSize
|
797
|
+
const oldSize = info.modules.size;
|
798
|
+
for (const module of item.modules) {
|
799
|
+
info.modules.delete(module);
|
800
|
+
}
|
801
|
+
if (info.modules.size === 0) {
|
802
|
+
chunksInfoMap.delete(key);
|
803
|
+
continue;
|
804
|
+
}
|
805
|
+
if (info.modules.size !== oldSize) {
|
806
|
+
info.size = getModulesSize(info.modules);
|
807
|
+
if (info.size < info.cacheGroup.minSize) {
|
808
|
+
chunksInfoMap.delete(key);
|
809
|
+
}
|
810
|
+
}
|
811
|
+
} else {
|
812
|
+
// only update the modules
|
813
|
+
for (const module of item.modules) {
|
814
|
+
info.modules.delete(module);
|
815
|
+
}
|
816
|
+
if (info.modules.size === 0) {
|
785
817
|
chunksInfoMap.delete(key);
|
786
818
|
}
|
787
819
|
}
|
@@ -789,13 +821,24 @@ module.exports = class SplitChunksPlugin {
|
|
789
821
|
}
|
790
822
|
}
|
791
823
|
|
824
|
+
const incorrectMinMaxSizeSet = new Set();
|
825
|
+
|
792
826
|
// Make sure that maxSize is fulfilled
|
793
827
|
for (const chunk of compilation.chunks.slice()) {
|
794
|
-
const { minSize, maxSize, automaticNameDelimiter } =
|
828
|
+
const { minSize, maxSize, automaticNameDelimiter, keys } =
|
795
829
|
maxSizeQueueMap.get(chunk) || this.options.fallbackCacheGroup;
|
796
830
|
if (!maxSize) continue;
|
831
|
+
if (minSize > maxSize) {
|
832
|
+
const warningKey = `${keys && keys.join()} ${minSize} ${maxSize}`;
|
833
|
+
if (!incorrectMinMaxSizeSet.has(warningKey)) {
|
834
|
+
incorrectMinMaxSizeSet.add(warningKey);
|
835
|
+
compilation.warnings.push(
|
836
|
+
new MinMaxSizeWarning(keys, minSize, maxSize)
|
837
|
+
);
|
838
|
+
}
|
839
|
+
}
|
797
840
|
const results = deterministicGroupingForModules({
|
798
|
-
maxSize,
|
841
|
+
maxSize: Math.max(minSize, maxSize),
|
799
842
|
minSize,
|
800
843
|
items: chunk.modulesIterable,
|
801
844
|
getKey(module) {
|
@@ -124,6 +124,13 @@ module.exports = ({ maxSize, minSize, items, getSize, getKey }) => {
|
|
124
124
|
/** @type {Node<T>[]} */
|
125
125
|
const initialNodes = [];
|
126
126
|
|
127
|
+
// lexically ordering of keys
|
128
|
+
nodes.sort((a, b) => {
|
129
|
+
if (a.key < b.key) return -1;
|
130
|
+
if (a.key > b.key) return 1;
|
131
|
+
return 0;
|
132
|
+
});
|
133
|
+
|
127
134
|
// return nodes bigger than maxSize directly as group
|
128
135
|
for (const node of nodes) {
|
129
136
|
if (node.size >= maxSize) {
|
@@ -134,13 +141,6 @@ module.exports = ({ maxSize, minSize, items, getSize, getKey }) => {
|
|
134
141
|
}
|
135
142
|
|
136
143
|
if (initialNodes.length > 0) {
|
137
|
-
// lexically ordering of keys
|
138
|
-
initialNodes.sort((a, b) => {
|
139
|
-
if (a.key < b.key) return -1;
|
140
|
-
if (a.key > b.key) return 1;
|
141
|
-
return 0;
|
142
|
-
});
|
143
|
-
|
144
144
|
// calculate similarities between lexically adjacent nodes
|
145
145
|
/** @type {number[]} */
|
146
146
|
const similarities = [];
|
@@ -150,76 +150,99 @@ module.exports = ({ maxSize, minSize, items, getSize, getKey }) => {
|
|
150
150
|
similarities.push(similarity(a.key, b.key));
|
151
151
|
}
|
152
152
|
|
153
|
-
const
|
153
|
+
const initialGroup = new Group(initialNodes, similarities);
|
154
154
|
|
155
|
-
|
156
|
-
|
157
|
-
//
|
158
|
-
if (
|
159
|
-
result.
|
160
|
-
|
155
|
+
if (initialGroup.size < minSize) {
|
156
|
+
// We hit an edgecase where the working set is already smaller than minSize
|
157
|
+
// We merge it with the smallest result node to keep minSize intact
|
158
|
+
if (result.length > 0) {
|
159
|
+
const smallestGroup = result.reduce(
|
160
|
+
(min, group) => (min.size > group.size ? group : min)
|
161
|
+
);
|
162
|
+
for (const node of initialGroup.nodes) smallestGroup.nodes.push(node);
|
163
|
+
smallestGroup.nodes.sort((a, b) => {
|
164
|
+
if (a.key < b.key) return -1;
|
165
|
+
if (a.key > b.key) return 1;
|
166
|
+
return 0;
|
167
|
+
});
|
168
|
+
} else {
|
169
|
+
// There are no other nodes
|
170
|
+
// We use all nodes and have to accept that it's smaller than minSize
|
171
|
+
result.push(initialGroup);
|
161
172
|
}
|
173
|
+
} else {
|
174
|
+
const queue = [initialGroup];
|
162
175
|
|
163
|
-
|
164
|
-
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
}
|
171
|
-
let right = group.nodes.length - 1;
|
172
|
-
let rightSize = 0;
|
173
|
-
while (rightSize < minSize) {
|
174
|
-
rightSize += group.nodes[right].size;
|
175
|
-
right--;
|
176
|
-
}
|
176
|
+
while (queue.length) {
|
177
|
+
const group = queue.pop();
|
178
|
+
// only groups bigger than maxSize need to be splitted
|
179
|
+
if (group.size < maxSize) {
|
180
|
+
result.push(group);
|
181
|
+
continue;
|
182
|
+
}
|
177
183
|
|
178
|
-
|
179
|
-
//
|
180
|
-
//
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
184
|
+
// find unsplittable area from left and right
|
185
|
+
// going minSize from left and right
|
186
|
+
// at least one node need to be included otherwise we get stuck
|
187
|
+
let left = 0;
|
188
|
+
let leftSize = 0;
|
189
|
+
while (leftSize <= minSize) {
|
190
|
+
leftSize += group.nodes[left].size;
|
191
|
+
left++;
|
192
|
+
}
|
193
|
+
let right = group.nodes.length - 1;
|
194
|
+
let rightSize = 0;
|
195
|
+
while (rightSize <= minSize) {
|
196
|
+
rightSize += group.nodes[right].size;
|
197
|
+
right--;
|
198
|
+
}
|
199
|
+
|
200
|
+
if (left - 1 > right) {
|
201
|
+
// can't split group while holding minSize
|
202
|
+
// because minSize is preferred of maxSize we return
|
203
|
+
// the group here even while it's too big
|
204
|
+
// To avoid this make sure maxSize > minSize * 3
|
205
|
+
result.push(group);
|
206
|
+
continue;
|
207
|
+
}
|
208
|
+
if (left <= right) {
|
209
|
+
// when there is a area between left and right
|
210
|
+
// we look for best split point
|
211
|
+
// we split at the minimum similarity
|
212
|
+
// here key space is separated the most
|
213
|
+
let best = left - 1;
|
214
|
+
let bestSimilarity = group.similarities[best];
|
215
|
+
for (let i = left; i <= right; i++) {
|
216
|
+
const similarity = group.similarities[i];
|
217
|
+
if (similarity < bestSimilarity) {
|
218
|
+
best = i;
|
219
|
+
bestSimilarity = similarity;
|
220
|
+
}
|
198
221
|
}
|
222
|
+
left = best + 1;
|
223
|
+
right = best;
|
199
224
|
}
|
200
|
-
left = best + 1;
|
201
|
-
right = best;
|
202
|
-
}
|
203
225
|
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
226
|
+
// create two new groups for left and right area
|
227
|
+
// and queue them up
|
228
|
+
const rightNodes = [group.nodes[right + 1]];
|
229
|
+
/** @type {number[]} */
|
230
|
+
const rightSimilaries = [];
|
231
|
+
for (let i = right + 2; i < group.nodes.length; i++) {
|
232
|
+
rightSimilaries.push(group.similarities[i - 1]);
|
233
|
+
rightNodes.push(group.nodes[i]);
|
234
|
+
}
|
235
|
+
queue.push(new Group(rightNodes, rightSimilaries));
|
236
|
+
|
237
|
+
const leftNodes = [group.nodes[0]];
|
238
|
+
/** @type {number[]} */
|
239
|
+
const leftSimilaries = [];
|
240
|
+
for (let i = 1; i < left; i++) {
|
241
|
+
leftSimilaries.push(group.similarities[i - 1]);
|
242
|
+
leftNodes.push(group.nodes[i]);
|
243
|
+
}
|
244
|
+
queue.push(new Group(leftNodes, leftSimilaries));
|
221
245
|
}
|
222
|
-
queue.push(new Group(leftNodes, leftSimilaries));
|
223
246
|
}
|
224
247
|
}
|
225
248
|
|
package/lib/webpack.js
CHANGED
@@ -42,7 +42,7 @@ const webpack = (options, callback) => {
|
|
42
42
|
if (options.plugins && Array.isArray(options.plugins)) {
|
43
43
|
for (const plugin of options.plugins) {
|
44
44
|
if (typeof plugin === "function") {
|
45
|
-
plugin.
|
45
|
+
plugin.call(compiler, compiler);
|
46
46
|
} else {
|
47
47
|
plugin.apply(compiler);
|
48
48
|
}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "webpack",
|
3
|
-
"version": "4.
|
3
|
+
"version": "4.27.1",
|
4
4
|
"author": "Tobias Koppers @sokra",
|
5
5
|
"description": "Packs CommonJs/AMD modules for the browser. Allows to split your codebase into multiple bundles, which can be loaded on demand. Support loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.",
|
6
6
|
"license": "MIT",
|
@@ -26,7 +26,7 @@
|
|
26
26
|
"node-libs-browser": "^2.0.0",
|
27
27
|
"schema-utils": "^0.4.4",
|
28
28
|
"tapable": "^1.1.0",
|
29
|
-
"
|
29
|
+
"terser-webpack-plugin": "^1.1.0",
|
30
30
|
"watchpack": "^1.5.0",
|
31
31
|
"webpack-sources": "^1.3.0"
|
32
32
|
},
|
@@ -1879,7 +1879,7 @@
|
|
1879
1879
|
"WebpackPluginFunction": {
|
1880
1880
|
"description": "Function acting as plugin",
|
1881
1881
|
"instanceof": "Function",
|
1882
|
-
"tsType": "(compiler: import('../lib/Compiler')) => void"
|
1882
|
+
"tsType": "(this: import('../lib/Compiler'), compiler: import('../lib/Compiler')) => void"
|
1883
1883
|
},
|
1884
1884
|
"WebpackPluginInstance": {
|
1885
1885
|
"description": "Plugin instance",
|