webpack 5.51.2 → 5.54.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.

Potentially problematic release.


This version of webpack might be problematic. Click here for more details.

Files changed (62) hide show
  1. package/lib/AsyncDependenciesBlock.js +9 -2
  2. package/lib/CacheFacade.js +10 -3
  3. package/lib/ChunkGraph.js +19 -8
  4. package/lib/CodeGenerationResults.js +7 -2
  5. package/lib/Compilation.js +207 -16
  6. package/lib/Compiler.js +9 -1
  7. package/lib/DependencyTemplates.js +8 -2
  8. package/lib/EvalDevToolModulePlugin.js +2 -1
  9. package/lib/EvalSourceMapDevToolPlugin.js +2 -1
  10. package/lib/ExternalModule.js +36 -18
  11. package/lib/FileSystemInfo.js +101 -170
  12. package/lib/FlagDependencyExportsPlugin.js +43 -16
  13. package/lib/InitFragment.js +23 -0
  14. package/lib/JavascriptMetaInfoPlugin.js +6 -1
  15. package/lib/MemCache.js +45 -0
  16. package/lib/ModuleFilenameHelpers.js +21 -7
  17. package/lib/NodeStuffInWebError.js +34 -0
  18. package/lib/NodeStuffPlugin.js +59 -16
  19. package/lib/NormalModuleFactory.js +7 -4
  20. package/lib/SourceMapDevToolPlugin.js +7 -3
  21. package/lib/WebpackOptionsApply.js +20 -4
  22. package/lib/cache/PackFileCacheStrategy.js +183 -53
  23. package/lib/cache/getLazyHashedEtag.js +35 -8
  24. package/lib/config/defaults.js +32 -13
  25. package/lib/dependencies/CachedConstDependency.js +4 -3
  26. package/lib/dependencies/ConstDependency.js +12 -4
  27. package/lib/dependencies/JsonExportsDependency.js +7 -1
  28. package/lib/dependencies/LoaderPlugin.js +94 -98
  29. package/lib/dependencies/ModuleDecoratorDependency.js +5 -2
  30. package/lib/dependencies/ProvidedDependency.js +6 -2
  31. package/lib/dependencies/PureExpressionDependency.js +5 -1
  32. package/lib/dependencies/RuntimeRequirementsDependency.js +5 -1
  33. package/lib/ids/IdHelpers.js +21 -8
  34. package/lib/ids/NamedChunkIdsPlugin.js +3 -0
  35. package/lib/ids/NamedModuleIdsPlugin.js +3 -1
  36. package/lib/index.js +6 -0
  37. package/lib/javascript/BasicEvaluatedExpression.js +3 -0
  38. package/lib/javascript/JavascriptParser.js +22 -4
  39. package/lib/javascript/JavascriptParserHelpers.js +0 -2
  40. package/lib/node/NodeTargetPlugin.js +1 -0
  41. package/lib/optimize/ConcatenatedModule.js +25 -4
  42. package/lib/optimize/InnerGraph.js +22 -2
  43. package/lib/optimize/MangleExportsPlugin.js +21 -4
  44. package/lib/optimize/ModuleConcatenationPlugin.js +2 -1
  45. package/lib/runtime/RelativeUrlRuntimeModule.js +1 -1
  46. package/lib/schemes/HttpUriPlugin.js +1 -2
  47. package/lib/serialization/BinaryMiddleware.js +11 -2
  48. package/lib/serialization/FileMiddleware.js +24 -7
  49. package/lib/serialization/ObjectMiddleware.js +23 -12
  50. package/lib/util/createHash.js +10 -0
  51. package/lib/util/hash/BatchedHash.js +65 -0
  52. package/lib/util/hash/xxhash64.js +154 -0
  53. package/lib/util/internalSerializables.js +2 -0
  54. package/lib/util/serialization.js +10 -6
  55. package/package.json +13 -9
  56. package/schemas/WebpackOptions.check.js +1 -1
  57. package/schemas/WebpackOptions.json +17 -5
  58. package/schemas/plugins/HashedModuleIdsPlugin.check.js +1 -1
  59. package/schemas/plugins/HashedModuleIdsPlugin.json +20 -2
  60. package/schemas/plugins/IgnorePlugin.check.js +1 -1
  61. package/schemas/plugins/IgnorePlugin.json +4 -2
  62. package/types.d.ts +166 -17
@@ -76,7 +76,9 @@ makeSerializable(
76
76
 
77
77
  const MIN_CONTENT_SIZE = 1024 * 1024; // 1 MB
78
78
  const CONTENT_COUNT_TO_MERGE = 10;
79
+ const MIN_ITEMS_IN_FRESH_PACK = 100;
79
80
  const MAX_ITEMS_IN_FRESH_PACK = 50000;
81
+ const MAX_TIME_IN_FRESH_PACK = 1 * 60 * 1000; // 1 min
80
82
 
81
83
  class PackItemInfo {
82
84
  /**
@@ -99,6 +101,7 @@ class Pack {
99
101
  this.itemInfo = new Map();
100
102
  /** @type {string[]} */
101
103
  this.requests = [];
104
+ this.requestsTimeout = undefined;
102
105
  /** @type {Map<string, PackItemInfo>} */
103
106
  this.freshContent = new Map();
104
107
  /** @type {(undefined | PackContent)[]} */
@@ -108,6 +111,24 @@ class Pack {
108
111
  this.maxAge = maxAge;
109
112
  }
110
113
 
114
+ _addRequest(identifier) {
115
+ this.requests.push(identifier);
116
+ if (this.requestsTimeout === undefined) {
117
+ this.requestsTimeout = setTimeout(() => {
118
+ this.requests.push(undefined);
119
+ this.requestsTimeout = undefined;
120
+ }, MAX_TIME_IN_FRESH_PACK);
121
+ if (this.requestsTimeout.unref) this.requestsTimeout.unref();
122
+ }
123
+ }
124
+
125
+ stopCapturingRequests() {
126
+ if (this.requestsTimeout !== undefined) {
127
+ clearTimeout(this.requestsTimeout);
128
+ this.requestsTimeout = undefined;
129
+ }
130
+ }
131
+
111
132
  /**
112
133
  * @param {string} identifier unique name for the resource
113
134
  * @param {string | null} etag etag of the resource
@@ -115,7 +136,7 @@ class Pack {
115
136
  */
116
137
  get(identifier, etag) {
117
138
  const info = this.itemInfo.get(identifier);
118
- this.requests.push(identifier);
139
+ this._addRequest(identifier);
119
140
  if (info === undefined) {
120
141
  return undefined;
121
142
  }
@@ -147,12 +168,12 @@ class Pack {
147
168
  if (info === undefined) {
148
169
  const newInfo = new PackItemInfo(identifier, etag, data);
149
170
  this.itemInfo.set(identifier, newInfo);
150
- this.requests.push(identifier);
171
+ this._addRequest(identifier);
151
172
  this.freshContent.set(identifier, newInfo);
152
173
  } else {
153
174
  const loc = info.location;
154
175
  if (loc >= 0) {
155
- this.requests.push(identifier);
176
+ this._addRequest(identifier);
156
177
  this.freshContent.set(identifier, info);
157
178
  const content = this.content[loc];
158
179
  content.delete(identifier);
@@ -220,27 +241,39 @@ class Pack {
220
241
  }
221
242
 
222
243
  _persistFreshContent() {
223
- if (this.freshContent.size > 0) {
224
- const packCount = Math.ceil(
225
- this.freshContent.size / MAX_ITEMS_IN_FRESH_PACK
226
- );
227
- const itemsPerPack = Math.ceil(this.freshContent.size / packCount);
228
- this.logger.log(`${this.freshContent.size} fresh items in cache`);
229
- const packs = Array.from({ length: packCount }, () => {
244
+ const itemsCount = this.freshContent.size;
245
+ if (itemsCount > 0) {
246
+ const packCount = Math.ceil(itemsCount / MAX_ITEMS_IN_FRESH_PACK);
247
+ const itemsPerPack = Math.ceil(itemsCount / packCount);
248
+ const packs = [];
249
+ let i = 0;
250
+ let ignoreNextTimeTick = false;
251
+ const createNextPack = () => {
230
252
  const loc = this._findLocation();
231
253
  this.content[loc] = null; // reserve
232
- return {
254
+ const pack = {
233
255
  /** @type {Set<string>} */
234
256
  items: new Set(),
235
257
  /** @type {Map<string, any>} */
236
258
  map: new Map(),
237
259
  loc
238
260
  };
239
- });
240
- let i = 0;
241
- let pack = packs[0];
242
- let packIndex = 0;
261
+ packs.push(pack);
262
+ return pack;
263
+ };
264
+ let pack = createNextPack();
265
+ if (this.requestsTimeout !== undefined)
266
+ clearTimeout(this.requestsTimeout);
243
267
  for (const identifier of this.requests) {
268
+ if (identifier === undefined) {
269
+ if (ignoreNextTimeTick) {
270
+ ignoreNextTimeTick = false;
271
+ } else if (pack.items.size >= MIN_ITEMS_IN_FRESH_PACK) {
272
+ i = 0;
273
+ pack = createNextPack();
274
+ }
275
+ continue;
276
+ }
244
277
  const info = this.freshContent.get(identifier);
245
278
  if (info === undefined) continue;
246
279
  pack.items.add(identifier);
@@ -250,9 +283,11 @@ class Pack {
250
283
  this.freshContent.delete(identifier);
251
284
  if (++i > itemsPerPack) {
252
285
  i = 0;
253
- pack = packs[++packIndex];
286
+ pack = createNextPack();
287
+ ignoreNextTimeTick = true;
254
288
  }
255
289
  }
290
+ this.requests.length = 0;
256
291
  for (const pack of packs) {
257
292
  this.content[pack.loc] = new PackContent(
258
293
  pack.items,
@@ -260,6 +295,15 @@ class Pack {
260
295
  new PackContentItems(pack.map)
261
296
  );
262
297
  }
298
+ this.logger.log(
299
+ `${itemsCount} fresh items in cache put into pack ${
300
+ packs.length > 1
301
+ ? packs
302
+ .map(pack => `${pack.loc} (${pack.items.size} items)`)
303
+ .join(", ")
304
+ : packs[0].loc
305
+ }`
306
+ );
263
307
  }
264
308
  }
265
309
 
@@ -332,7 +376,9 @@ class Pack {
332
376
  addToMergedMap.push(async map => {
333
377
  // unpack existing content
334
378
  // after that values are accessible in .content
335
- await content.unpack();
379
+ await content.unpack(
380
+ "it should be merged with other small pack contents"
381
+ );
336
382
  for (const [identifier, value] of content.content) {
337
383
  map.set(identifier, value);
338
384
  }
@@ -392,7 +438,9 @@ class Pack {
392
438
  usedItems,
393
439
  new Set(usedItems),
394
440
  async () => {
395
- await content.unpack();
441
+ await content.unpack(
442
+ "it should be splitted into used and unused items"
443
+ );
396
444
  const map = new Map();
397
445
  for (const identifier of usedItems) {
398
446
  map.set(identifier, content.content.get(identifier));
@@ -417,7 +465,9 @@ class Pack {
417
465
  unusedItems,
418
466
  usedOfUnusedItems,
419
467
  async () => {
420
- await content.unpack();
468
+ await content.unpack(
469
+ "it should be splitted into used and unused items"
470
+ );
421
471
  const map = new Map();
422
472
  for (const identifier of unusedItems) {
423
473
  map.set(identifier, content.content.get(identifier));
@@ -466,7 +516,9 @@ class Pack {
466
516
  this.content[loc] =
467
517
  items.size > 0
468
518
  ? new PackContent(items, usedItems, async () => {
469
- await content.unpack();
519
+ await content.unpack(
520
+ "it contains old items that should be garbage collected"
521
+ );
470
522
  const map = new Map();
471
523
  for (const identifier of items) {
472
524
  map.set(identifier, content.content.get(identifier));
@@ -496,7 +548,7 @@ class Pack {
496
548
  const content = this.content[i];
497
549
  if (content !== undefined) {
498
550
  write(content.items);
499
- writeSeparate(content.getLazyContentItems(), { name: `${i}` });
551
+ content.writeLazy(lazy => writeSeparate(lazy, { name: `${i}` }));
500
552
  } else {
501
553
  write(undefined); // undefined marks an empty content slot
502
554
  }
@@ -669,6 +721,25 @@ makeSerializable(
669
721
  );
670
722
 
671
723
  class PackContent {
724
+ /*
725
+ This class can be in these states:
726
+ | this.lazy | this.content | this.outdated | state
727
+ A1 | undefined | Map | false | fresh content
728
+ A2 | undefined | Map | true | (will not happen)
729
+ B1 | lazy () => {} | undefined | false | not deserialized
730
+ B2 | lazy () => {} | undefined | true | not deserialized, but some items has been removed
731
+ C1 | lazy* () => {} | Map | false | deserialized
732
+ C2 | lazy* () => {} | Map | true | deserialized, and some items has been removed
733
+
734
+ this.used is a subset of this.items.
735
+ this.items is a subset of this.content.keys() resp. this.lazy().map.keys()
736
+ When this.outdated === false, this.items === this.content.keys() resp. this.lazy().map.keys()
737
+ When this.outdated === true, this.items should be used to recreated this.lazy/this.content.
738
+ When this.lazy and this.content is set, they contain the same data.
739
+ this.get must only be called with a valid item from this.items.
740
+ In state C this.lazy is unMemoized
741
+ */
742
+
672
743
  /**
673
744
  * @param {Set<string>} items keys
674
745
  * @param {Set<string>} usedItems used keys
@@ -678,7 +749,7 @@ class PackContent {
678
749
  */
679
750
  constructor(items, usedItems, dataOrFn, logger, lazyName) {
680
751
  this.items = items;
681
- /** @type {function(): Promise<PackContentItems> | PackContentItems } */
752
+ /** @type {function(): Promise<PackContentItems> | PackContentItems} */
682
753
  this.lazy = typeof dataOrFn === "function" ? dataOrFn : undefined;
683
754
  /** @type {Map<string, any>} */
684
755
  this.content = typeof dataOrFn === "function" ? undefined : dataOrFn.map;
@@ -693,6 +764,8 @@ class PackContent {
693
764
  if (this.content) {
694
765
  return this.content.get(identifier);
695
766
  }
767
+
768
+ // We are in state B
696
769
  const { lazyName } = this;
697
770
  let timeMessage;
698
771
  if (lazyName) {
@@ -715,6 +788,7 @@ class PackContent {
715
788
  if (timeMessage) {
716
789
  this.logger.timeEnd(timeMessage);
717
790
  }
791
+ // Move to state C
718
792
  this.content = map;
719
793
  this.lazy = SerializerMiddleware.unMemoizeLazy(this.lazy);
720
794
  return map.get(identifier);
@@ -724,6 +798,7 @@ class PackContent {
724
798
  if (timeMessage) {
725
799
  this.logger.timeEnd(timeMessage);
726
800
  }
801
+ // Move to state C
727
802
  this.content = map;
728
803
  this.lazy = SerializerMiddleware.unMemoizeLazy(this.lazy);
729
804
  return map.get(identifier);
@@ -731,10 +806,13 @@ class PackContent {
731
806
  }
732
807
 
733
808
  /**
809
+ * @param {string} reason explanation why unpack is necessary
734
810
  * @returns {void | Promise} maybe a promise if lazy
735
811
  */
736
- unpack() {
812
+ unpack(reason) {
737
813
  if (this.content) return;
814
+
815
+ // Move from state B to C
738
816
  if (this.lazy) {
739
817
  const { lazyName } = this;
740
818
  let timeMessage;
@@ -744,6 +822,11 @@ class PackContent {
744
822
  timeMessage = `unpack cache content ${lazyName} (${formatSize(
745
823
  this.getSize()
746
824
  )})`;
825
+ this.logger.log(
826
+ `starting to unpack cache content ${lazyName} (${formatSize(
827
+ this.getSize()
828
+ )}) because ${reason}`
829
+ );
747
830
  this.logger.time(timeMessage);
748
831
  }
749
832
  const value = this.lazy();
@@ -782,48 +865,93 @@ class PackContent {
782
865
  }
783
866
 
784
867
  /**
785
- * @returns {function(): PackContentItems | Promise<PackContentItems>} lazy content items
868
+ * @template T
869
+ * @param {function(any): function(): Promise<PackContentItems> | PackContentItems} write write function
870
+ * @returns {void}
786
871
  */
787
- getLazyContentItems() {
788
- if (!this.outdated && this.lazy) return this.lazy;
872
+ writeLazy(write) {
873
+ if (!this.outdated && this.lazy) {
874
+ // State B1 or C1
875
+ // this.lazy is still the valid deserialized version
876
+ write(this.lazy);
877
+ return;
878
+ }
789
879
  if (!this.outdated && this.content) {
880
+ // State A1
790
881
  const map = new Map(this.content);
791
- return (this.lazy = memoize(() => new PackContentItems(map)));
882
+ // Move to state C1
883
+ this.lazy = SerializerMiddleware.unMemoizeLazy(
884
+ write(() => new PackContentItems(map))
885
+ );
886
+ return;
792
887
  }
793
- this.outdated = false;
794
888
  if (this.content) {
795
- return (this.lazy = memoize(() => {
796
- /** @type {Map<string, any>} */
797
- const map = new Map();
798
- for (const item of this.items) {
799
- map.set(item, this.content.get(item));
800
- }
801
- return new PackContentItems(map);
802
- }));
889
+ // State A2 or C2
890
+ /** @type {Map<string, any>} */
891
+ const map = new Map();
892
+ for (const item of this.items) {
893
+ map.set(item, this.content.get(item));
894
+ }
895
+ // Move to state C1
896
+ this.outdated = false;
897
+ this.content = map;
898
+ this.lazy = SerializerMiddleware.unMemoizeLazy(
899
+ write(() => new PackContentItems(map))
900
+ );
901
+ return;
803
902
  }
804
- const lazy = this.lazy;
805
- return (this.lazy = () => {
806
- const value = lazy();
807
- if (value instanceof Promise) {
808
- return value.then(data => {
903
+ // State B2
904
+ const { lazyName } = this;
905
+ let timeMessage;
906
+ if (lazyName) {
907
+ // only log once
908
+ this.lazyName = undefined;
909
+ timeMessage = `unpack cache content ${lazyName} (${formatSize(
910
+ this.getSize()
911
+ )})`;
912
+ this.logger.log(
913
+ `starting to unpack cache content ${lazyName} (${formatSize(
914
+ this.getSize()
915
+ )}) because it's outdated and need to be serialized`
916
+ );
917
+ this.logger.time(timeMessage);
918
+ }
919
+ const value = this.lazy();
920
+ this.outdated = false;
921
+ if (value instanceof Promise) {
922
+ // Move to state B1
923
+ this.lazy = write(() =>
924
+ value.then(data => {
925
+ if (timeMessage) {
926
+ this.logger.timeEnd(timeMessage);
927
+ }
809
928
  const oldMap = data.map;
810
929
  /** @type {Map<string, any>} */
811
930
  const map = new Map();
812
931
  for (const item of this.items) {
813
932
  map.set(item, oldMap.get(item));
814
933
  }
934
+ // Move to state C1 (or maybe C2)
935
+ this.content = map;
936
+ this.lazy = SerializerMiddleware.unMemoizeLazy(this.lazy);
937
+
815
938
  return new PackContentItems(map);
816
- });
817
- } else {
818
- const oldMap = value.map;
819
- /** @type {Map<string, any>} */
820
- const map = new Map();
821
- for (const item of this.items) {
822
- map.set(item, oldMap.get(item));
823
- }
824
- return new PackContentItems(map);
939
+ })
940
+ );
941
+ } else {
942
+ // Move to state C1
943
+ if (timeMessage) {
944
+ this.logger.timeEnd(timeMessage);
825
945
  }
826
- });
946
+ const oldMap = value.map;
947
+ /** @type {Map<string, any>} */
948
+ const map = new Map();
949
+ for (const item of this.items) {
950
+ map.set(item, oldMap.get(item));
951
+ }
952
+ this.content = map;
953
+ this.lazy = write(() => new PackContentItems(map));
954
+ }
827
955
  }
828
956
  }
829
957
 
@@ -867,7 +995,8 @@ class PackFileCacheStrategy {
867
995
  this.fileSystemInfo = new FileSystemInfo(fs, {
868
996
  managedPaths: snapshot.managedPaths,
869
997
  immutablePaths: snapshot.immutablePaths,
870
- logger: logger.getChildLogger("webpack.FileSystemInfo")
998
+ logger: logger.getChildLogger("webpack.FileSystemInfo"),
999
+ hashFunction: compiler.options.output.hashFunction
871
1000
  });
872
1001
  this.compiler = compiler;
873
1002
  this.context = context;
@@ -1110,10 +1239,11 @@ class PackFileCacheStrategy {
1110
1239
  const packPromise = this.packPromise;
1111
1240
  if (packPromise === undefined) return Promise.resolve();
1112
1241
  const reportProgress = ProgressPlugin.getReporter(this.compiler);
1113
- this.packPromise = undefined;
1114
1242
  return (this.storePromise = packPromise
1115
1243
  .then(pack => {
1244
+ pack.stopCapturingRequests();
1116
1245
  if (!pack.invalid) return;
1246
+ this.packPromise = undefined;
1117
1247
  this.logger.log(`Storing pack...`);
1118
1248
  let promise;
1119
1249
  const newBuildDependencies = new Set();
@@ -8,6 +8,7 @@
8
8
  const createHash = require("../util/createHash");
9
9
 
10
10
  /** @typedef {import("../util/Hash")} Hash */
11
+ /** @typedef {typeof import("../util/Hash")} HashConstructor */
11
12
 
12
13
  /**
13
14
  * @typedef {Object} HashableObject
@@ -17,10 +18,12 @@ const createHash = require("../util/createHash");
17
18
  class LazyHashedEtag {
18
19
  /**
19
20
  * @param {HashableObject} obj object with updateHash method
21
+ * @param {string | HashConstructor} hashFunction the hash function to use
20
22
  */
21
- constructor(obj) {
23
+ constructor(obj, hashFunction = "md4") {
22
24
  this._obj = obj;
23
25
  this._hash = undefined;
26
+ this._hashFunction = hashFunction;
24
27
  }
25
28
 
26
29
  /**
@@ -28,7 +31,7 @@ class LazyHashedEtag {
28
31
  */
29
32
  toString() {
30
33
  if (this._hash === undefined) {
31
- const hash = createHash("md4");
34
+ const hash = createHash(this._hashFunction);
32
35
  this._obj.updateHash(hash);
33
36
  this._hash = /** @type {string} */ (hash.digest("base64"));
34
37
  }
@@ -36,18 +39,42 @@ class LazyHashedEtag {
36
39
  }
37
40
  }
38
41
 
39
- /** @type {WeakMap<HashableObject, LazyHashedEtag>} */
40
- const map = new WeakMap();
42
+ /** @type {Map<string | HashConstructor, WeakMap<HashableObject, LazyHashedEtag>>} */
43
+ const mapStrings = new Map();
44
+
45
+ /** @type {WeakMap<HashConstructor, WeakMap<HashableObject, LazyHashedEtag>>} */
46
+ const mapObjects = new WeakMap();
41
47
 
42
48
  /**
43
49
  * @param {HashableObject} obj object with updateHash method
50
+ * @param {string | HashConstructor} hashFunction the hash function to use
44
51
  * @returns {LazyHashedEtag} etag
45
52
  */
46
- const getter = obj => {
47
- const hash = map.get(obj);
53
+ const getter = (obj, hashFunction = "md4") => {
54
+ let innerMap;
55
+ if (typeof hashFunction === "string") {
56
+ innerMap = mapStrings.get(hashFunction);
57
+ if (innerMap === undefined) {
58
+ const newHash = new LazyHashedEtag(obj, hashFunction);
59
+ innerMap = new WeakMap();
60
+ innerMap.set(obj, newHash);
61
+ mapStrings.set(hashFunction, innerMap);
62
+ return newHash;
63
+ }
64
+ } else {
65
+ innerMap = mapObjects.get(hashFunction);
66
+ if (innerMap === undefined) {
67
+ const newHash = new LazyHashedEtag(obj, hashFunction);
68
+ innerMap = new WeakMap();
69
+ innerMap.set(obj, newHash);
70
+ mapObjects.set(hashFunction, innerMap);
71
+ return newHash;
72
+ }
73
+ }
74
+ const hash = innerMap.get(obj);
48
75
  if (hash !== undefined) return hash;
49
- const newHash = new LazyHashedEtag(obj);
50
- map.set(obj, newHash);
76
+ const newHash = new LazyHashedEtag(obj, hashFunction);
77
+ innerMap.set(obj, newHash);
51
78
  return newHash;
52
79
  };
53
80
 
@@ -159,20 +159,21 @@ const applyWebpackOptionsDefaults = options => {
159
159
  D(options, "recordsInputPath", false);
160
160
  D(options, "recordsOutputPath", false);
161
161
 
162
+ applyExperimentsDefaults(options.experiments, { production, development });
163
+
162
164
  F(options, "cache", () =>
163
165
  development ? { type: /** @type {"memory"} */ ("memory") } : false
164
166
  );
165
167
  applyCacheDefaults(options.cache, {
166
168
  name: name || "default",
167
169
  mode: mode || "production",
168
- development
170
+ development,
171
+ cacheUnaffected: options.experiments.cacheUnaffected
169
172
  });
170
173
  const cache = !!options.cache;
171
174
 
172
175
  applySnapshotDefaults(options.snapshot, { production });
173
176
 
174
- applyExperimentsDefaults(options.experiments, { production, development });
175
-
176
177
  applyModuleDefaults(options.module, {
177
178
  cache,
178
179
  syncWebAssembly: options.experiments.syncWebAssembly,
@@ -190,7 +191,8 @@ const applyWebpackOptionsDefaults = options => {
190
191
  outputModule: options.experiments.outputModule,
191
192
  development,
192
193
  entry: options.entry,
193
- module: options.module
194
+ module: options.module,
195
+ futureDefaults: options.experiments.futureDefaults
194
196
  });
195
197
 
196
198
  applyExternalsPresetsDefaults(options.externalsPresets, {
@@ -211,7 +213,10 @@ const applyWebpackOptionsDefaults = options => {
211
213
  : "var";
212
214
  });
213
215
 
214
- applyNodeDefaults(options.node, { targetProperties });
216
+ applyNodeDefaults(options.node, {
217
+ futureDefaults: options.experiments.futureDefaults,
218
+ targetProperties
219
+ });
215
220
 
216
221
  F(options, "performance", () =>
217
222
  production &&
@@ -259,10 +264,11 @@ const applyExperimentsDefaults = (experiments, { production, development }) => {
259
264
  D(experiments, "asyncWebAssembly", false);
260
265
  D(experiments, "outputModule", false);
261
266
  D(experiments, "asset", false);
262
- D(experiments, "executeModule", false);
263
267
  D(experiments, "layers", false);
264
268
  D(experiments, "lazyCompilation", false);
265
269
  D(experiments, "buildHttp", false);
270
+ D(experiments, "futureDefaults", false);
271
+ D(experiments, "cacheUnaffected", experiments.futureDefaults);
266
272
 
267
273
  if (typeof experiments.buildHttp === "object") {
268
274
  D(experiments.buildHttp, "frozen", production);
@@ -276,9 +282,13 @@ const applyExperimentsDefaults = (experiments, { production, development }) => {
276
282
  * @param {string} options.name name
277
283
  * @param {string} options.mode mode
278
284
  * @param {boolean} options.development is development mode
285
+ * @param {boolean} options.cacheUnaffected the cacheUnaffected experiment is enabled
279
286
  * @returns {void}
280
287
  */
281
- const applyCacheDefaults = (cache, { name, mode, development }) => {
288
+ const applyCacheDefaults = (
289
+ cache,
290
+ { name, mode, development, cacheUnaffected }
291
+ ) => {
282
292
  if (cache === false) return;
283
293
  switch (cache.type) {
284
294
  case "filesystem":
@@ -322,12 +332,14 @@ const applyCacheDefaults = (cache, { name, mode, development }) => {
322
332
  D(cache, "maxMemoryGenerations", development ? 5 : Infinity);
323
333
  D(cache, "maxAge", 1000 * 60 * 60 * 24 * 60); // 1 month
324
334
  D(cache, "allowCollectingMemory", development);
335
+ D(cache, "memoryCacheUnaffected", development && cacheUnaffected);
325
336
  D(cache.buildDependencies, "defaultWebpack", [
326
337
  path.resolve(__dirname, "..") + path.sep
327
338
  ]);
328
339
  break;
329
340
  case "memory":
330
341
  D(cache, "maxGenerations", Infinity);
342
+ D(cache, "cacheUnaffected", development && cacheUnaffected);
331
343
  break;
332
344
  }
333
345
  };
@@ -577,6 +589,7 @@ const applyModuleDefaults = (
577
589
  * @param {boolean} options.development is development mode
578
590
  * @param {Entry} options.entry entry option
579
591
  * @param {ModuleOptions} options.module module option
592
+ * @param {boolean} options.futureDefaults is future defaults enabled
580
593
  * @returns {void}
581
594
  */
582
595
  const applyOutputDefaults = (
@@ -588,7 +601,8 @@ const applyOutputDefaults = (
588
601
  outputModule,
589
602
  development,
590
603
  entry,
591
- module
604
+ module,
605
+ futureDefaults
592
606
  }
593
607
  ) => {
594
608
  /**
@@ -785,7 +799,7 @@ const applyOutputDefaults = (
785
799
  : ""
786
800
  );
787
801
  D(output, "chunkLoadTimeout", 120000);
788
- D(output, "hashFunction", "md4");
802
+ D(output, "hashFunction", futureDefaults ? "xxhash64" : "md4");
789
803
  D(output, "hashDigest", "hex");
790
804
  D(output, "hashDigestLength", 20);
791
805
  D(output, "strictModuleExceptionHandling", false);
@@ -944,21 +958,26 @@ const applyLoaderDefaults = (loader, { targetProperties }) => {
944
958
  * @param {WebpackNode} node options
945
959
  * @param {Object} options options
946
960
  * @param {TargetProperties | false} options.targetProperties target properties
961
+ * @param {boolean} options.futureDefaults is future defaults enabled
947
962
  * @returns {void}
948
963
  */
949
- const applyNodeDefaults = (node, { targetProperties }) => {
964
+ const applyNodeDefaults = (node, { futureDefaults, targetProperties }) => {
950
965
  if (node === false) return;
966
+
951
967
  F(node, "global", () => {
952
968
  if (targetProperties && targetProperties.global) return false;
953
- return true;
969
+ // TODO webpack 6 should always default to false
970
+ return futureDefaults ? "warn" : true;
954
971
  });
955
972
  F(node, "__filename", () => {
956
973
  if (targetProperties && targetProperties.node) return "eval-only";
957
- return "mock";
974
+ // TODO webpack 6 should always default to false
975
+ return futureDefaults ? "warn-mock" : "mock";
958
976
  });
959
977
  F(node, "__dirname", () => {
960
978
  if (targetProperties && targetProperties.node) return "eval-only";
961
- return "mock";
979
+ // TODO webpack 6 should always default to false
980
+ return futureDefaults ? "warn-mock" : "mock";
962
981
  });
963
982
  };
964
983
 
@@ -27,6 +27,7 @@ class CachedConstDependency extends NullDependency {
27
27
  this.expression = expression;
28
28
  this.range = range;
29
29
  this.identifier = identifier;
30
+ this._hashUpdate = undefined;
30
31
  }
31
32
 
32
33
  /**
@@ -36,9 +37,9 @@ class CachedConstDependency extends NullDependency {
36
37
  * @returns {void}
37
38
  */
38
39
  updateHash(hash, context) {
39
- hash.update(this.identifier + "");
40
- hash.update(this.range + "");
41
- hash.update(this.expression + "");
40
+ if (this._hashUpdate === undefined)
41
+ this._hashUpdate = "" + this.identifier + this.range + this.expression;
42
+ hash.update(this._hashUpdate);
42
43
  }
43
44
 
44
45
  serialize(context) {