webpack 5.27.2 → 5.31.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.

@@ -15,6 +15,7 @@ const { makePathsRelative } = require("../util/identifier");
15
15
 
16
16
  /** @typedef {import("webpack-sources").Source} Source */
17
17
  /** @typedef {import("../../declarations/WebpackOptions").AssetGeneratorOptions} AssetGeneratorOptions */
18
+ /** @typedef {import("../../declarations/WebpackOptions").RawPublicPath} RawPublicPath */
18
19
  /** @typedef {import("../Compilation")} Compilation */
19
20
  /** @typedef {import("../Compiler")} Compiler */
20
21
  /** @typedef {import("../Generator").GenerateContext} GenerateContext */
@@ -24,6 +25,55 @@ const { makePathsRelative } = require("../util/identifier");
24
25
  /** @typedef {import("../RuntimeTemplate")} RuntimeTemplate */
25
26
  /** @typedef {import("../util/Hash")} Hash */
26
27
 
28
+ const mergeMaybeArrays = (a, b) => {
29
+ const set = new Set();
30
+ if (Array.isArray(a)) for (const item of a) set.add(item);
31
+ else set.add(a);
32
+ if (Array.isArray(b)) for (const item of b) set.add(item);
33
+ else set.add(b);
34
+ return Array.from(set);
35
+ };
36
+
37
+ const mergeAssetInfo = (a, b) => {
38
+ const result = { ...a, ...b };
39
+ for (const key of Object.keys(a)) {
40
+ if (key in b) {
41
+ if (a[key] === b[key]) continue;
42
+ switch (key) {
43
+ case "fullhash":
44
+ case "chunkhash":
45
+ case "modulehash":
46
+ case "contenthash":
47
+ result[key] = mergeMaybeArrays(a[key], b[key]);
48
+ break;
49
+ case "immutable":
50
+ case "development":
51
+ case "hotModuleReplacement":
52
+ case "javascriptModule ":
53
+ result[key] = a[key] || b[key];
54
+ break;
55
+ case "related":
56
+ result[key] = mergeRelatedInfo(a[key], b[key]);
57
+ break;
58
+ default:
59
+ throw new Error(`Can't handle conflicting asset info for ${key}`);
60
+ }
61
+ }
62
+ }
63
+ return result;
64
+ };
65
+
66
+ const mergeRelatedInfo = (a, b) => {
67
+ const result = { ...a, ...b };
68
+ for (const key of Object.keys(a)) {
69
+ if (key in b) {
70
+ if (a[key] === b[key]) continue;
71
+ result[key] = mergeMaybeArrays(a[key], b[key]);
72
+ }
73
+ }
74
+ return result;
75
+ };
76
+
27
77
  const JS_TYPES = new Set(["javascript"]);
28
78
  const JS_AND_ASSET_TYPES = new Set(["javascript", "asset"]);
29
79
 
@@ -31,12 +81,14 @@ class AssetGenerator extends Generator {
31
81
  /**
32
82
  * @param {AssetGeneratorOptions["dataUrl"]=} dataUrlOptions the options for the data url
33
83
  * @param {string=} filename override for output.assetModuleFilename
84
+ * @param {RawPublicPath=} publicPath override for output.assetModulePublicPath
34
85
  * @param {boolean=} emit generate output asset
35
86
  */
36
- constructor(dataUrlOptions, filename, emit) {
87
+ constructor(dataUrlOptions, filename, publicPath, emit) {
37
88
  super();
38
89
  this.dataUrlOptions = dataUrlOptions;
39
90
  this.filename = filename;
91
+ this.publicPath = publicPath;
40
92
  this.emit = emit;
41
93
  }
42
94
 
@@ -131,9 +183,9 @@ class AssetGenerator extends Generator {
131
183
  module.matchResource || module.resource,
132
184
  runtimeTemplate.compilation.compiler.root
133
185
  ).replace(/^\.\//, "");
134
- const {
186
+ let {
135
187
  path: filename,
136
- info
188
+ info: assetInfo
137
189
  } = runtimeTemplate.compilation.getAssetPathWithInfo(
138
190
  assetModuleFilename,
139
191
  {
@@ -144,11 +196,33 @@ class AssetGenerator extends Generator {
144
196
  contentHash
145
197
  }
146
198
  );
147
- module.buildInfo.filename = filename;
148
- module.buildInfo.assetInfo = {
199
+ let publicPath;
200
+ if (this.publicPath) {
201
+ const {
202
+ path,
203
+ info
204
+ } = runtimeTemplate.compilation.getAssetPathWithInfo(
205
+ this.publicPath,
206
+ {
207
+ module,
208
+ runtime,
209
+ filename: sourceFilename,
210
+ chunkGraph,
211
+ contentHash
212
+ }
213
+ );
214
+ publicPath = JSON.stringify(path);
215
+ assetInfo = mergeAssetInfo(assetInfo, info);
216
+ } else {
217
+ publicPath = RuntimeGlobals.publicPath;
218
+ runtimeRequirements.add(RuntimeGlobals.publicPath); // add __webpack_require__.p
219
+ }
220
+ assetInfo = {
149
221
  sourceFilename,
150
- ...info
222
+ ...assetInfo
151
223
  };
224
+ module.buildInfo.filename = filename;
225
+ module.buildInfo.assetInfo = assetInfo;
152
226
  if (getData) {
153
227
  // Due to code generation caching module.buildInfo.XXX can't used to store such information
154
228
  // It need to be stored in the code generation results instead, where it's cached too
@@ -156,15 +230,13 @@ class AssetGenerator extends Generator {
156
230
  const data = getData();
157
231
  data.set("fullContentHash", fullHash);
158
232
  data.set("filename", filename);
159
- data.set("assetInfo", info);
233
+ data.set("assetInfo", assetInfo);
160
234
  }
161
235
 
162
- runtimeRequirements.add(RuntimeGlobals.publicPath); // add __webpack_require__.p
163
-
164
236
  return new RawSource(
165
- `${RuntimeGlobals.module}.exports = ${
166
- RuntimeGlobals.publicPath
167
- } + ${JSON.stringify(filename)};`
237
+ `${
238
+ RuntimeGlobals.module
239
+ }.exports = ${publicPath} + ${JSON.stringify(filename)};`
168
240
  );
169
241
  }
170
242
  }
@@ -118,8 +118,10 @@ class AssetModulesPlugin {
118
118
  }
119
119
 
120
120
  let filename = undefined;
121
+ let publicPath = undefined;
121
122
  if (type !== "asset/inline") {
122
123
  filename = generatorOptions.filename;
124
+ publicPath = generatorOptions.publicPath;
123
125
  }
124
126
 
125
127
  const AssetGenerator = getAssetGenerator();
@@ -127,6 +129,7 @@ class AssetModulesPlugin {
127
129
  return new AssetGenerator(
128
130
  dataUrl,
129
131
  filename,
132
+ publicPath,
130
133
  generatorOptions.emit !== false
131
134
  );
132
135
  });
@@ -30,7 +30,7 @@ class IdleFileCachePlugin {
30
30
  * @returns {void}
31
31
  */
32
32
  apply(compiler) {
33
- const strategy = this.strategy;
33
+ let strategy = this.strategy;
34
34
  const idleTimeout = this.idleTimeout;
35
35
  const idleTimeoutForInitialStore = Math.min(
36
36
  idleTimeout,
@@ -54,20 +54,27 @@ class IdleFileCachePlugin {
54
54
  compiler.cache.hooks.get.tapPromise(
55
55
  { name: "IdleFileCachePlugin", stage: Cache.STAGE_DISK },
56
56
  (identifier, etag, gotHandlers) => {
57
- return strategy.restore(identifier, etag).then(cacheEntry => {
58
- if (cacheEntry === undefined) {
59
- gotHandlers.push((result, callback) => {
60
- if (result !== undefined) {
61
- pendingIdleTasks.set(identifier, () =>
62
- strategy.store(identifier, etag, result)
63
- );
64
- }
65
- callback();
66
- });
67
- } else {
68
- return cacheEntry;
69
- }
70
- });
57
+ const restore = () =>
58
+ strategy.restore(identifier, etag).then(cacheEntry => {
59
+ if (cacheEntry === undefined) {
60
+ gotHandlers.push((result, callback) => {
61
+ if (result !== undefined) {
62
+ pendingIdleTasks.set(identifier, () =>
63
+ strategy.store(identifier, etag, result)
64
+ );
65
+ }
66
+ callback();
67
+ });
68
+ } else {
69
+ return cacheEntry;
70
+ }
71
+ });
72
+ const pendingTask = pendingIdleTasks.get(identifier);
73
+ if (pendingTask !== undefined) {
74
+ pendingIdleTasks.delete(identifier);
75
+ return pendingTask().then(restore);
76
+ }
77
+ return restore();
71
78
  }
72
79
  );
73
80
 
@@ -101,7 +108,10 @@ class IdleFileCachePlugin {
101
108
  reportProgress(1, `stored`);
102
109
  });
103
110
  }
104
- return currentIdlePromise;
111
+ return currentIdlePromise.then(() => {
112
+ // Reset strategy
113
+ if (strategy.clear) strategy.clear();
114
+ });
105
115
  }
106
116
  );
107
117
 
@@ -46,6 +46,12 @@ class MemoryCachePlugin {
46
46
  });
47
47
  }
48
48
  );
49
+ compiler.cache.hooks.shutdown.tap(
50
+ { name: "MemoryCachePlugin", stage: Cache.STAGE_MEMORY },
51
+ () => {
52
+ cache.clear();
53
+ }
54
+ );
49
55
  }
50
56
  }
51
57
  module.exports = MemoryCachePlugin;
@@ -0,0 +1,129 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Tobias Koppers @sokra
4
+ */
5
+
6
+ "use strict";
7
+
8
+ const Cache = require("../Cache");
9
+
10
+ /** @typedef {import("webpack-sources").Source} Source */
11
+ /** @typedef {import("../Cache").Etag} Etag */
12
+ /** @typedef {import("../Compiler")} Compiler */
13
+ /** @typedef {import("../Module")} Module */
14
+
15
+ class MemoryWithGcCachePlugin {
16
+ constructor({ maxGenerations }) {
17
+ this._maxGenerations = maxGenerations;
18
+ }
19
+ /**
20
+ * Apply the plugin
21
+ * @param {Compiler} compiler the compiler instance
22
+ * @returns {void}
23
+ */
24
+ apply(compiler) {
25
+ const maxGenerations = this._maxGenerations;
26
+ /** @type {Map<string, { etag: Etag | null, data: any }>} */
27
+ const cache = new Map();
28
+ /** @type {Map<string, { entry: { etag: Etag | null, data: any }, until: number }>} */
29
+ const oldCache = new Map();
30
+ let generation = 0;
31
+ let cachePosition = 0;
32
+ const logger = compiler.getInfrastructureLogger("MemoryWithGcCachePlugin");
33
+ compiler.hooks.afterDone.tap("MemoryWithGcCachePlugin", () => {
34
+ generation++;
35
+ let clearedEntries = 0;
36
+ let lastClearedIdentifier;
37
+ for (const [identifier, entry] of oldCache) {
38
+ if (entry.until > generation) break;
39
+
40
+ oldCache.delete(identifier);
41
+ if (cache.get(identifier) === undefined) {
42
+ cache.delete(identifier);
43
+ clearedEntries++;
44
+ lastClearedIdentifier = identifier;
45
+ }
46
+ }
47
+ if (clearedEntries > 0 || oldCache.size > 0) {
48
+ logger.log(
49
+ `${cache.size - oldCache.size} active entries, ${
50
+ oldCache.size
51
+ } recently unused cached entries${
52
+ clearedEntries > 0
53
+ ? `, ${clearedEntries} old unused cache entries removed e. g. ${lastClearedIdentifier}`
54
+ : ""
55
+ }`
56
+ );
57
+ }
58
+ let i = (cache.size / maxGenerations) | 0;
59
+ let j = cachePosition >= cache.size ? 0 : cachePosition;
60
+ cachePosition = j + i;
61
+ for (const [identifier, entry] of cache) {
62
+ if (j !== 0) {
63
+ j--;
64
+ continue;
65
+ }
66
+ if (entry !== undefined) {
67
+ // We don't delete the cache entry, but set it to undefined instead
68
+ // This reserves the location in the data table and avoids rehashing
69
+ // when constantly adding and removing entries.
70
+ // It will be deleted when removed from oldCache.
71
+ cache.set(identifier, undefined);
72
+ oldCache.delete(identifier);
73
+ oldCache.set(identifier, {
74
+ entry,
75
+ until: generation + maxGenerations
76
+ });
77
+ if (i-- === 0) break;
78
+ }
79
+ }
80
+ });
81
+ compiler.cache.hooks.store.tap(
82
+ { name: "MemoryWithGcCachePlugin", stage: Cache.STAGE_MEMORY },
83
+ (identifier, etag, data) => {
84
+ cache.set(identifier, { etag, data });
85
+ }
86
+ );
87
+ compiler.cache.hooks.get.tap(
88
+ { name: "MemoryWithGcCachePlugin", stage: Cache.STAGE_MEMORY },
89
+ (identifier, etag, gotHandlers) => {
90
+ const cacheEntry = cache.get(identifier);
91
+ if (cacheEntry === null) {
92
+ return null;
93
+ } else if (cacheEntry !== undefined) {
94
+ return cacheEntry.etag === etag ? cacheEntry.data : null;
95
+ }
96
+ const oldCacheEntry = oldCache.get(identifier);
97
+ if (oldCacheEntry !== undefined) {
98
+ const cacheEntry = oldCacheEntry.entry;
99
+ if (cacheEntry === null) {
100
+ oldCache.delete(identifier);
101
+ cache.set(identifier, cacheEntry);
102
+ return null;
103
+ } else {
104
+ if (cacheEntry.etag !== etag) return null;
105
+ oldCache.delete(identifier);
106
+ cache.set(identifier, cacheEntry);
107
+ return cacheEntry.data;
108
+ }
109
+ }
110
+ gotHandlers.push((result, callback) => {
111
+ if (result === undefined) {
112
+ cache.set(identifier, null);
113
+ } else {
114
+ cache.set(identifier, { etag, data: result });
115
+ }
116
+ return callback();
117
+ });
118
+ }
119
+ );
120
+ compiler.cache.hooks.shutdown.tap(
121
+ { name: "MemoryWithGcCachePlugin", stage: Cache.STAGE_MEMORY },
122
+ () => {
123
+ cache.clear();
124
+ oldCache.clear();
125
+ }
126
+ );
127
+ }
128
+ }
129
+ module.exports = MemoryWithGcCachePlugin;
@@ -29,7 +29,7 @@ class PackContainer {
29
29
  * @param {string} version version identifier
30
30
  * @param {Snapshot} buildSnapshot snapshot of all build dependencies
31
31
  * @param {Set<string>} buildDependencies list of all unresolved build dependencies captured
32
- * @param {Map<string, string>} resolveResults result of the resolved build dependencies
32
+ * @param {Map<string, string | false>} resolveResults result of the resolved build dependencies
33
33
  * @param {Snapshot} resolveBuildDependenciesSnapshot snapshot of the dependencies of the build dependencies resolving
34
34
  */
35
35
  constructor(
@@ -75,7 +75,6 @@ makeSerializable(
75
75
 
76
76
  const MIN_CONTENT_SIZE = 1024 * 1024; // 1 MB
77
77
  const CONTENT_COUNT_TO_MERGE = 10;
78
- const MAX_AGE = 1000 * 60 * 60 * 24 * 60; // 1 month
79
78
  const MAX_ITEMS_IN_FRESH_PACK = 50000;
80
79
 
81
80
  class PackItemInfo {
@@ -94,7 +93,7 @@ class PackItemInfo {
94
93
  }
95
94
 
96
95
  class Pack {
97
- constructor(logger) {
96
+ constructor(logger, maxAge) {
98
97
  /** @type {Map<string, PackItemInfo>} */
99
98
  this.itemInfo = new Map();
100
99
  /** @type {string[]} */
@@ -105,6 +104,7 @@ class Pack {
105
104
  this.content = [];
106
105
  this.invalid = false;
107
106
  this.logger = logger;
107
+ this.maxAge = maxAge;
108
108
  }
109
109
 
110
110
  /**
@@ -167,6 +167,21 @@ class Pack {
167
167
  }
168
168
  }
169
169
 
170
+ getContentStats() {
171
+ let count = 0;
172
+ let size = 0;
173
+ for (const content of this.content) {
174
+ if (content !== undefined) {
175
+ count++;
176
+ const s = content.getSize();
177
+ if (s > 0) {
178
+ size += s;
179
+ }
180
+ }
181
+ }
182
+ return { count, size };
183
+ }
184
+
170
185
  /**
171
186
  * @returns {number} new location of data entries
172
187
  */
@@ -182,7 +197,7 @@ class Pack {
182
197
  const now = Date.now();
183
198
  for (const identifier of items) {
184
199
  const info = this.itemInfo.get(identifier);
185
- if (now - info.lastAccess > MAX_AGE) {
200
+ if (now - info.lastAccess > this.maxAge) {
186
201
  this.itemInfo.delete(identifier);
187
202
  items.delete(identifier);
188
203
  usedItems.delete(identifier);
@@ -194,9 +209,10 @@ class Pack {
194
209
  }
195
210
  if (count > 0) {
196
211
  this.logger.log(
197
- "Garbage Collected %d old items at pack %d e. g. %s",
212
+ "Garbage Collected %d old items at pack %d (%d items remaining) e. g. %s",
198
213
  count,
199
214
  newLoc,
215
+ items.size,
200
216
  lastGC
201
217
  );
202
218
  }
@@ -426,10 +442,45 @@ class Pack {
426
442
  }
427
443
  }
428
444
 
445
+ /**
446
+ * Find the content with the oldest item and run GC on that.
447
+ * Only runs for one content to avoid large invalidation.
448
+ */
449
+ _gcOldestContent() {
450
+ /** @type {PackItemInfo} */
451
+ let oldest = undefined;
452
+ for (const info of this.itemInfo.values()) {
453
+ if (oldest === undefined || info.lastAccess < oldest.lastAccess) {
454
+ oldest = info;
455
+ }
456
+ }
457
+ if (Date.now() - oldest.lastAccess > this.maxAge) {
458
+ const loc = oldest.location;
459
+ if (loc < 0) return;
460
+ const content = this.content[loc];
461
+ const items = new Set(content.items);
462
+ const usedItems = new Set(content.used);
463
+ this._gcAndUpdateLocation(items, usedItems, loc);
464
+
465
+ this.content[loc] =
466
+ items.size > 0
467
+ ? new PackContent(items, usedItems, async () => {
468
+ await content.unpack();
469
+ const map = new Map();
470
+ for (const identifier of items) {
471
+ map.set(identifier, content.content.get(identifier));
472
+ }
473
+ return new PackContentItems(map);
474
+ })
475
+ : undefined;
476
+ }
477
+ }
478
+
429
479
  serialize({ write, writeSeparate }) {
430
480
  this._persistFreshContent();
431
481
  this._optimizeSmallContent();
432
482
  this._optimizeUnusedContent();
483
+ this._gcOldestContent();
433
484
  for (const identifier of this.itemInfo.keys()) {
434
485
  write(identifier);
435
486
  }
@@ -727,6 +778,7 @@ class PackFileCacheStrategy {
727
778
  * @param {string} options.version version identifier
728
779
  * @param {Logger} options.logger a logger
729
780
  * @param {SnapshotOptions} options.snapshot options regarding snapshotting
781
+ * @param {number} options.maxAge max age of cache items
730
782
  */
731
783
  constructor({
732
784
  compiler,
@@ -735,7 +787,8 @@ class PackFileCacheStrategy {
735
787
  cacheLocation,
736
788
  version,
737
789
  logger,
738
- snapshot
790
+ snapshot,
791
+ maxAge
739
792
  }) {
740
793
  this.fileSerializer = createFileSerializer(fs);
741
794
  this.fileSystemInfo = new FileSystemInfo(fs, {
@@ -748,6 +801,7 @@ class PackFileCacheStrategy {
748
801
  this.cacheLocation = cacheLocation;
749
802
  this.version = version;
750
803
  this.logger = logger;
804
+ this.maxAge = maxAge;
751
805
  this.snapshot = snapshot;
752
806
  /** @type {Set<string>} */
753
807
  this.buildDependencies = new Set();
@@ -755,12 +809,20 @@ class PackFileCacheStrategy {
755
809
  this.newBuildDependencies = new LazySet();
756
810
  /** @type {Snapshot} */
757
811
  this.resolveBuildDependenciesSnapshot = undefined;
758
- /** @type {Map<string, string>} */
812
+ /** @type {Map<string, string | false>} */
759
813
  this.resolveResults = undefined;
760
814
  /** @type {Snapshot} */
761
815
  this.buildSnapshot = undefined;
762
816
  /** @type {Promise<Pack>} */
763
817
  this.packPromise = this._openPack();
818
+ this.storePromise = Promise.resolve();
819
+ }
820
+
821
+ _getPack() {
822
+ if (this.packPromise === undefined) {
823
+ this.packPromise = this.storePromise.then(() => this._openPack());
824
+ }
825
+ return this.packPromise;
764
826
  }
765
827
 
766
828
  /**
@@ -776,7 +838,7 @@ class PackFileCacheStrategy {
776
838
  let newBuildDependencies;
777
839
  /** @type {Snapshot} */
778
840
  let resolveBuildDependenciesSnapshot;
779
- /** @type {Map<string, string>} */
841
+ /** @type {Map<string, string | false>} */
780
842
  let resolveResults;
781
843
  logger.time("restore cache container");
782
844
  return this.fileSerializer
@@ -899,6 +961,7 @@ class PackFileCacheStrategy {
899
961
  })
900
962
  .then(pack => {
901
963
  if (pack) {
964
+ pack.maxAge = this.maxAge;
902
965
  this.buildSnapshot = buildSnapshot;
903
966
  if (buildDependencies) this.buildDependencies = buildDependencies;
904
967
  if (newBuildDependencies)
@@ -907,14 +970,14 @@ class PackFileCacheStrategy {
907
970
  this.resolveBuildDependenciesSnapshot = resolveBuildDependenciesSnapshot;
908
971
  return pack;
909
972
  }
910
- return new Pack(logger);
973
+ return new Pack(logger, this.maxAge);
911
974
  })
912
975
  .catch(err => {
913
976
  this.logger.warn(
914
977
  `Restoring pack from ${cacheLocation}.pack failed: ${err}`
915
978
  );
916
979
  this.logger.debug(err.stack);
917
- return new Pack(logger);
980
+ return new Pack(logger, this.maxAge);
918
981
  });
919
982
  }
920
983
 
@@ -925,7 +988,7 @@ class PackFileCacheStrategy {
925
988
  * @returns {Promise<void>} promise
926
989
  */
927
990
  store(identifier, etag, data) {
928
- return this.packPromise.then(pack => {
991
+ return this._getPack().then(pack => {
929
992
  pack.set(identifier, etag === null ? null : etag.toString(), data);
930
993
  });
931
994
  }
@@ -936,7 +999,7 @@ class PackFileCacheStrategy {
936
999
  * @returns {Promise<any>} promise to the cached content
937
1000
  */
938
1001
  restore(identifier, etag) {
939
- return this.packPromise
1002
+ return this._getPack()
940
1003
  .then(pack =>
941
1004
  pack.get(identifier, etag === null ? null : etag.toString())
942
1005
  )
@@ -955,8 +1018,11 @@ class PackFileCacheStrategy {
955
1018
  }
956
1019
 
957
1020
  afterAllStored() {
1021
+ const packPromise = this.packPromise;
1022
+ if (packPromise === undefined) return Promise.resolve();
958
1023
  const reportProgress = ProgressPlugin.getReporter(this.compiler);
959
- return this.packPromise
1024
+ this.packPromise = undefined;
1025
+ return (this.storePromise = packPromise
960
1026
  .then(pack => {
961
1027
  if (!pack.invalid) return;
962
1028
  this.logger.log(`Storing pack...`);
@@ -1100,7 +1166,13 @@ class PackFileCacheStrategy {
1100
1166
  }
1101
1167
  this.newBuildDependencies.clear();
1102
1168
  this.logger.timeEnd(`store pack`);
1103
- this.logger.log(`Stored pack`);
1169
+ const stats = pack.getContentStats();
1170
+ this.logger.log(
1171
+ "Stored pack (%d items, %d files, %d MiB)",
1172
+ pack.itemInfo.size,
1173
+ stats.count,
1174
+ Math.round(stats.size / 1024 / 1024)
1175
+ );
1104
1176
  })
1105
1177
  .catch(err => {
1106
1178
  this.logger.timeEnd(`store pack`);
@@ -1112,7 +1184,17 @@ class PackFileCacheStrategy {
1112
1184
  .catch(err => {
1113
1185
  this.logger.warn(`Caching failed for pack: ${err}`);
1114
1186
  this.logger.debug(err.stack);
1115
- });
1187
+ }));
1188
+ }
1189
+
1190
+ clear() {
1191
+ this.fileSystemInfo.clear();
1192
+ this.buildDependencies.clear();
1193
+ this.newBuildDependencies.clear();
1194
+ this.resolveBuildDependenciesSnapshot = undefined;
1195
+ this.resolveResults = undefined;
1196
+ this.buildSnapshot = undefined;
1197
+ this.packPromise = undefined;
1116
1198
  }
1117
1199
  }
1118
1200
 
@@ -117,6 +117,7 @@ const A = (obj, prop, factory) => {
117
117
  */
118
118
  const applyWebpackOptionsBaseDefaults = options => {
119
119
  F(options, "context", () => process.cwd());
120
+ applyInfrastructureLoggingDefaults(options.infrastructureLogging);
120
121
  };
121
122
 
122
123
  /**
@@ -163,7 +164,8 @@ const applyWebpackOptionsDefaults = options => {
163
164
  );
164
165
  applyCacheDefaults(options.cache, {
165
166
  name: name || "default",
166
- mode: mode || "production"
167
+ mode: mode || "production",
168
+ development
167
169
  });
168
170
  const cache = !!options.cache;
169
171
 
@@ -234,8 +236,6 @@ const applyWebpackOptionsDefaults = options => {
234
236
  getResolveLoaderDefaults({ cache }),
235
237
  options.resolveLoader
236
238
  );
237
-
238
- applyInfrastructureLoggingDefaults(options.infrastructureLogging);
239
239
  };
240
240
 
241
241
  /**
@@ -254,9 +254,10 @@ const applyExperimentsDefaults = experiments => {
254
254
  * @param {Object} options options
255
255
  * @param {string} options.name name
256
256
  * @param {string} options.mode mode
257
+ * @param {boolean} options.development is development mode
257
258
  * @returns {void}
258
259
  */
259
- const applyCacheDefaults = (cache, { name, mode }) => {
260
+ const applyCacheDefaults = (cache, { name, mode, development }) => {
260
261
  if (cache === false) return;
261
262
  switch (cache.type) {
262
263
  case "filesystem":
@@ -294,10 +295,15 @@ const applyCacheDefaults = (cache, { name, mode }) => {
294
295
  D(cache, "store", "pack");
295
296
  D(cache, "idleTimeout", 60000);
296
297
  D(cache, "idleTimeoutForInitialStore", 0);
298
+ D(cache, "maxMemoryGenerations", development ? 10 : Infinity);
299
+ D(cache, "maxAge", 1000 * 60 * 60 * 24 * 60); // 1 month
297
300
  D(cache.buildDependencies, "defaultWebpack", [
298
301
  path.resolve(__dirname, "..") + path.sep
299
302
  ]);
300
303
  break;
304
+ case "memory":
305
+ D(cache, "maxGenerations", Infinity);
306
+ break;
301
307
  }
302
308
  };
303
309
 
@@ -1070,8 +1076,14 @@ const getResolveLoaderDefaults = ({ cache }) => {
1070
1076
  * @returns {void}
1071
1077
  */
1072
1078
  const applyInfrastructureLoggingDefaults = infrastructureLogging => {
1079
+ F(infrastructureLogging, "stream", () => process.stderr);
1080
+ const tty =
1081
+ /** @type {any} */ (infrastructureLogging.stream).isTTY &&
1082
+ process.env.TERM !== "dumb";
1073
1083
  D(infrastructureLogging, "level", "info");
1074
1084
  D(infrastructureLogging, "debug", false);
1085
+ D(infrastructureLogging, "colors", tty);
1086
+ D(infrastructureLogging, "appendOnly", !tty);
1075
1087
  };
1076
1088
 
1077
1089
  exports.applyWebpackOptionsBaseDefaults = applyWebpackOptionsBaseDefaults;