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 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")() || (1, eval)("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, and then chunk raphi twil=
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
- if (this.preventIntegration || otherChunk.preventIntegration) {
470
- return false;
471
- }
473
+ const selfHasRuntime = this.hasRuntime();
474
+ const otherChunkHasRuntime = otherChunk.hasRuntime();
472
475
 
473
- if (this.hasRuntime() !== otherChunk.hasRuntime()) {
474
- if (this.hasRuntime()) {
476
+ if (selfHasRuntime !== otherChunkHasRuntime) {
477
+ if (selfHasRuntime) {
475
478
  return isAvailable(this, otherChunk);
476
- } else if (otherChunk.hasRuntime()) {
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 (!module.buildMeta.providedExports) {
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();
@@ -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);
@@ -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 uglifyjs plugin
306
- const UglifyJsPlugin = require("uglifyjs-webpack-plugin");
305
+ // Lazy load the Terser plugin
306
+ const TerserPlugin = require("terser-webpack-plugin");
307
307
  const SourceMapDevToolPlugin = require("./SourceMapDevToolPlugin");
308
- new UglifyJsPlugin({
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
- (name && `name:${name}`) ||
477
- `chunks:${selectedChunksKey} key:${cacheGroup.key}`;
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.size += module.size();
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
- /** @type {Map<Chunk, {minSize: number, maxSize: number, automaticNameDelimiter: string}>} */
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 (info.size >= info.cacheGroup.minSize) {
610
- if (bestEntry === undefined) {
611
- bestEntry = info;
612
- bestEntryKey = key;
613
- } else if (compareEntries(bestEntry, info) < 0) {
614
- bestEntry = info;
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
- const chunkInLimit = usedChunks.filter(chunk => {
670
- // respect max requests when not enforced
671
- const maxRequests = chunk.isOnlyInitial()
672
- ? item.cacheGroup.maxInitialRequests
673
- : chunk.canBeInitial()
674
- ? Math.min(
675
- item.cacheGroup.maxInitialRequests,
676
- item.cacheGroup.maxAsyncRequests
677
- )
678
- : item.cacheGroup.maxAsyncRequests;
679
- return !isFinite(maxRequests) || getRequests(chunk) < maxRequests;
680
- });
681
-
682
- if (chunkInLimit.length < usedChunks.length) {
683
- for (const module of item.modules) {
684
- addModuleToChunksInfoMap(
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.minSize
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
- const oldSize = info.modules.size;
775
- for (const module of item.modules) {
776
- info.modules.delete(module);
777
- }
778
- if (info.modules.size === 0) {
779
- chunksInfoMap.delete(key);
780
- continue;
781
- }
782
- if (info.modules.size !== oldSize) {
783
- info.size = getModulesSize(info.modules);
784
- if (info.size < info.cacheGroup.minSize) {
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 queue = [new Group(initialNodes, similarities)];
153
+ const initialGroup = new Group(initialNodes, similarities);
154
154
 
155
- while (queue.length) {
156
- const group = queue.pop();
157
- // only groups bigger than maxSize need to be splitted
158
- if (group.size < maxSize) {
159
- result.push(group);
160
- continue;
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
- // find unsplittable area from left and right
164
- // going minSize from left and right
165
- let left = 0;
166
- let leftSize = 0;
167
- while (leftSize < minSize) {
168
- leftSize += group.nodes[left].size;
169
- left++;
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
- if (left - 1 > right) {
179
- // can't split group while holding minSize
180
- // because minSize is preferred of maxSize we return
181
- // the group here even while it's too big
182
- // To avoid this make sure maxSize > minSize * 3
183
- result.push(group);
184
- continue;
185
- }
186
- if (left <= right) {
187
- // when there is a area between left and right
188
- // we look for best split point
189
- // we split at the minimum similarity
190
- // here key space is separated the most
191
- let best = left - 1;
192
- let bestSimilarity = group.similarities[best];
193
- for (let i = left; i <= right; i++) {
194
- const similarity = group.similarities[i];
195
- if (similarity < bestSimilarity) {
196
- best = i;
197
- bestSimilarity = similarity;
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
- // create two new groups for left and right area
205
- // and queue them up
206
- const rightNodes = [group.nodes[right + 1]];
207
- /** @type {number[]} */
208
- const rightSimilaries = [];
209
- for (let i = right + 2; i < group.nodes.length; i++) {
210
- rightSimilaries.push(group.similarities[i - 1]);
211
- rightNodes.push(group.nodes[i]);
212
- }
213
- queue.push(new Group(rightNodes, rightSimilaries));
214
-
215
- const leftNodes = [group.nodes[0]];
216
- /** @type {number[]} */
217
- const leftSimilaries = [];
218
- for (let i = 1; i < left; i++) {
219
- leftSimilaries.push(group.similarities[i - 1]);
220
- leftNodes.push(group.nodes[i]);
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.apply(compiler);
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.25.1",
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
- "uglifyjs-webpack-plugin": "^1.2.4",
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",