webpack 5.58.1 → 5.60.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.

@@ -19,6 +19,7 @@ const {
19
19
  /** @typedef {import("../../declarations/WebpackOptions").EntryDescription} EntryDescription */
20
20
  /** @typedef {import("../../declarations/WebpackOptions").EntryNormalized} Entry */
21
21
  /** @typedef {import("../../declarations/WebpackOptions").Experiments} Experiments */
22
+ /** @typedef {import("../../declarations/WebpackOptions").ExperimentsNormalized} ExperimentsNormalized */
22
23
  /** @typedef {import("../../declarations/WebpackOptions").ExternalsPresets} ExternalsPresets */
23
24
  /** @typedef {import("../../declarations/WebpackOptions").ExternalsType} ExternalsType */
24
25
  /** @typedef {import("../../declarations/WebpackOptions").InfrastructureLogging} InfrastructureLogging */
@@ -161,6 +162,8 @@ const applyWebpackOptionsDefaults = options => {
161
162
 
162
163
  applyExperimentsDefaults(options.experiments, { production, development });
163
164
 
165
+ const futureDefaults = options.experiments.futureDefaults;
166
+
164
167
  F(options, "cache", () =>
165
168
  development ? { type: /** @type {"memory"} */ ("memory") } : false
166
169
  );
@@ -172,7 +175,10 @@ const applyWebpackOptionsDefaults = options => {
172
175
  });
173
176
  const cache = !!options.cache;
174
177
 
175
- applySnapshotDefaults(options.snapshot, { production });
178
+ applySnapshotDefaults(options.snapshot, {
179
+ production,
180
+ futureDefaults
181
+ });
176
182
 
177
183
  applyModuleDefaults(options.module, {
178
184
  cache,
@@ -192,7 +198,7 @@ const applyWebpackOptionsDefaults = options => {
192
198
  development,
193
199
  entry: options.entry,
194
200
  module: options.module,
195
- futureDefaults: options.experiments.futureDefaults
201
+ futureDefaults
196
202
  });
197
203
 
198
204
  applyExternalsPresetsDefaults(options.externalsPresets, {
@@ -252,7 +258,7 @@ const applyWebpackOptionsDefaults = options => {
252
258
  };
253
259
 
254
260
  /**
255
- * @param {Experiments} experiments options
261
+ * @param {ExperimentsNormalized} experiments options
256
262
  * @param {Object} options options
257
263
  * @param {boolean} options.production is production
258
264
  * @param {boolean} options.development is development mode
@@ -265,14 +271,14 @@ const applyExperimentsDefaults = (experiments, { production, development }) => {
265
271
  D(experiments, "outputModule", false);
266
272
  D(experiments, "asset", false);
267
273
  D(experiments, "layers", false);
268
- D(experiments, "lazyCompilation", false);
269
- D(experiments, "buildHttp", false);
274
+ D(experiments, "lazyCompilation", undefined);
275
+ D(experiments, "buildHttp", undefined);
270
276
  D(experiments, "futureDefaults", false);
271
277
  D(experiments, "cacheUnaffected", experiments.futureDefaults);
272
278
 
273
279
  if (typeof experiments.buildHttp === "object") {
274
280
  D(experiments.buildHttp, "frozen", production);
275
- D(experiments.buildHttp, "upgrade", development);
281
+ D(experiments.buildHttp, "upgrade", false);
276
282
  }
277
283
  };
278
284
 
@@ -348,49 +354,65 @@ const applyCacheDefaults = (
348
354
  * @param {SnapshotOptions} snapshot options
349
355
  * @param {Object} options options
350
356
  * @param {boolean} options.production is production
357
+ * @param {boolean} options.futureDefaults is future defaults enabled
351
358
  * @returns {void}
352
359
  */
353
- const applySnapshotDefaults = (snapshot, { production }) => {
354
- A(snapshot, "managedPaths", () => {
355
- if (process.versions.pnp === "3") {
356
- const match =
357
- /^(.+?)[\\/]cache[\\/]watchpack-npm-[^\\/]+\.zip[\\/]node_modules[\\/]/.exec(
358
- require.resolve("watchpack")
359
- );
360
- if (match) {
361
- return [path.resolve(match[1], "unplugged")];
362
- }
363
- } else {
364
- const match = /^(.+?[\\/]node_modules)[\\/]/.exec(
365
- // eslint-disable-next-line node/no-extraneous-require
366
- require.resolve("watchpack")
367
- );
368
- if (match) {
369
- return [match[1]];
370
- }
371
- }
372
- return [];
373
- });
374
- A(snapshot, "immutablePaths", () => {
375
- if (process.versions.pnp === "1") {
376
- const match =
377
- /^(.+?[\\/]v4)[\\/]npm-watchpack-[^\\/]+-[\da-f]{40}[\\/]node_modules[\\/]/.exec(
360
+ const applySnapshotDefaults = (snapshot, { production, futureDefaults }) => {
361
+ if (futureDefaults) {
362
+ F(snapshot, "managedPaths", () =>
363
+ process.versions.pnp === "3"
364
+ ? [
365
+ /^(.+?(?:[\\/]\.yarn[\\/]unplugged[\\/][^\\/]+)?[\\/]node_modules[\\/])/
366
+ ]
367
+ : [/^(.+?[\\/]node_modules[\\/])/]
368
+ );
369
+ F(snapshot, "immutablePaths", () =>
370
+ process.versions.pnp === "3"
371
+ ? [/^(.+?[\\/]cache[\\/][^\\/]+\.zip[\\/]node_modules[\\/])/]
372
+ : []
373
+ );
374
+ } else {
375
+ A(snapshot, "managedPaths", () => {
376
+ if (process.versions.pnp === "3") {
377
+ const match =
378
+ /^(.+?)[\\/]cache[\\/]watchpack-npm-[^\\/]+\.zip[\\/]node_modules[\\/]/.exec(
379
+ require.resolve("watchpack")
380
+ );
381
+ if (match) {
382
+ return [path.resolve(match[1], "unplugged")];
383
+ }
384
+ } else {
385
+ const match = /^(.+?[\\/]node_modules)[\\/]/.exec(
386
+ // eslint-disable-next-line node/no-extraneous-require
378
387
  require.resolve("watchpack")
379
388
  );
380
- if (match) {
381
- return [match[1]];
389
+ if (match) {
390
+ return [match[1]];
391
+ }
382
392
  }
383
- } else if (process.versions.pnp === "3") {
384
- const match =
385
- /^(.+?)[\\/]watchpack-npm-[^\\/]+\.zip[\\/]node_modules[\\/]/.exec(
386
- require.resolve("watchpack")
387
- );
388
- if (match) {
389
- return [match[1]];
393
+ return [];
394
+ });
395
+ A(snapshot, "immutablePaths", () => {
396
+ if (process.versions.pnp === "1") {
397
+ const match =
398
+ /^(.+?[\\/]v4)[\\/]npm-watchpack-[^\\/]+-[\da-f]{40}[\\/]node_modules[\\/]/.exec(
399
+ require.resolve("watchpack")
400
+ );
401
+ if (match) {
402
+ return [match[1]];
403
+ }
404
+ } else if (process.versions.pnp === "3") {
405
+ const match =
406
+ /^(.+?)[\\/]watchpack-npm-[^\\/]+\.zip[\\/]node_modules[\\/]/.exec(
407
+ require.resolve("watchpack")
408
+ );
409
+ if (match) {
410
+ return [match[1]];
411
+ }
390
412
  }
391
- }
392
- return [];
393
- });
413
+ return [];
414
+ });
415
+ }
394
416
  F(snapshot, "resolveBuildDependencies", () => ({
395
417
  timestamp: true,
396
418
  hash: true
@@ -174,7 +174,12 @@ const getNormalizedWebpackOptions = config => {
174
174
  experiments: nestedConfig(config.experiments, experiments => ({
175
175
  ...experiments,
176
176
  buildHttp: optionalNestedConfig(experiments.buildHttp, options =>
177
- options === true ? {} : options
177
+ Array.isArray(options) ? { allowedUris: options } : options
178
+ ),
179
+ lazyCompilation: optionalNestedConfig(
180
+ experiments.lazyCompilation,
181
+ options =>
182
+ options === true ? {} : options === false ? undefined : options
178
183
  )
179
184
  })),
180
185
  externals: config.externals,
@@ -32,6 +32,12 @@ const { registerNotSerializable } = require("../util/serialization");
32
32
  /** @typedef {import("../util/Hash")} Hash */
33
33
  /** @typedef {import("../util/fs").InputFileSystem} InputFileSystem */
34
34
 
35
+ /**
36
+ * @typedef {Object} BackendApi
37
+ * @property {function(Error=): void} dispose
38
+ * @property {function(Module): { client: string, data: string, active: boolean }} module
39
+ */
40
+
35
41
  const IGNORED_DEPENDENCY_TYPES = new Set([
36
42
  "import.meta.webpackHot.accept",
37
43
  "import.meta.webpackHot.decline",
@@ -303,15 +309,13 @@ class LazyCompilationDependencyFactory extends ModuleFactory {
303
309
  class LazyCompilationPlugin {
304
310
  /**
305
311
  * @param {Object} options options
306
- * @param {(function(Compiler, string, function(Error?, any?): void): void) | function(Compiler, string): Promise<any>} options.backend the backend
307
- * @param {string} options.client the client reference
312
+ * @param {(function(Compiler, function(Error?, BackendApi?): void): void) | function(Compiler): Promise<BackendApi>} options.backend the backend
308
313
  * @param {boolean} options.entries true, when entries are lazy compiled
309
314
  * @param {boolean} options.imports true, when import() modules are lazy compiled
310
315
  * @param {RegExp | string | (function(Module): boolean)} options.test additional filter for lazy compiled entrypoint modules
311
316
  */
312
- constructor({ backend, client, entries, imports, test }) {
317
+ constructor({ backend, entries, imports, test }) {
313
318
  this.backend = backend;
314
- this.client = client;
315
319
  this.entries = entries;
316
320
  this.imports = imports;
317
321
  this.test = test;
@@ -327,7 +331,7 @@ class LazyCompilationPlugin {
327
331
  "LazyCompilationPlugin",
328
332
  (params, callback) => {
329
333
  if (backend !== undefined) return callback();
330
- const promise = this.backend(compiler, this.client, (err, result) => {
334
+ const promise = this.backend(compiler, (err, result) => {
331
335
  if (err) return callback(err);
332
336
  backend = result;
333
337
  callback();
@@ -5,21 +5,46 @@
5
5
 
6
6
  "use strict";
7
7
 
8
- const http = require("http");
9
-
8
+ /** @typedef {import("http").ServerOptions} HttpServerOptions */
9
+ /** @typedef {import("https").ServerOptions} HttpsServerOptions */
10
+ /** @typedef {import("../../declarations/WebpackOptions").LazyCompilationDefaultBackendOptions} LazyCompilationDefaultBackendOptions */
10
11
  /** @typedef {import("../Compiler")} Compiler */
11
12
 
12
13
  /**
14
+ * @callback BackendHandler
13
15
  * @param {Compiler} compiler compiler
14
- * @param {string} client client reference
15
16
  * @param {function(Error?, any?): void} callback callback
16
17
  * @returns {void}
17
18
  */
18
- module.exports = (compiler, client, callback) => {
19
+
20
+ /**
21
+ * @param {Omit<LazyCompilationDefaultBackendOptions, "client"> & { client: NonNullable<LazyCompilationDefaultBackendOptions["client"]>}} options additional options for the backend
22
+ * @returns {BackendHandler} backend
23
+ */
24
+ module.exports = options => (compiler, callback) => {
19
25
  const logger = compiler.getInfrastructureLogger("LazyCompilationBackend");
20
26
  const activeModules = new Map();
21
27
  const prefix = "/lazy-compilation-using-";
22
28
 
29
+ const isHttps =
30
+ options.protocol === "https" ||
31
+ (typeof options.server === "object" &&
32
+ ("key" in options.server || "pfx" in options.server));
33
+
34
+ const createServer =
35
+ typeof options.server === "function"
36
+ ? options.server
37
+ : (() => {
38
+ const http = isHttps ? require("https") : require("http");
39
+ return http.createServer.bind(http, options.server);
40
+ })();
41
+ const listen =
42
+ typeof options.listen === "function"
43
+ ? options.listen
44
+ : server => server.listen(options.listen);
45
+
46
+ const protocol = options.protocol || (isHttps ? "https" : "http");
47
+
23
48
  const requestListener = (req, res) => {
24
49
  const keys = req.url.slice(prefix.length).split("@");
25
50
  req.socket.on("close", () => {
@@ -52,7 +77,10 @@ module.exports = (compiler, client, callback) => {
52
77
  }
53
78
  if (moduleActivated && compiler.watching) compiler.watching.invalidate();
54
79
  };
55
- const server = http.createServer(requestListener);
80
+
81
+ const server = /** @type {import("net").Server} */ (createServer());
82
+ server.on("request", requestListener);
83
+
56
84
  let isClosing = false;
57
85
  /** @type {Set<import("net").Socket>} */
58
86
  const sockets = new Set();
@@ -63,16 +91,19 @@ module.exports = (compiler, client, callback) => {
63
91
  });
64
92
  if (isClosing) socket.destroy();
65
93
  });
66
- server.listen(err => {
94
+ server.on("clientError", e => {
95
+ if (e.message !== "Server is disposing") logger.warn(e);
96
+ });
97
+ server.on("listening", err => {
67
98
  if (err) return callback(err);
68
99
  const addr = server.address();
69
100
  if (typeof addr === "string") throw new Error("addr must not be a string");
70
101
  const urlBase =
71
102
  addr.address === "::" || addr.address === "0.0.0.0"
72
- ? `http://localhost:${addr.port}`
103
+ ? `${protocol}://localhost:${addr.port}`
73
104
  : addr.family === "IPv6"
74
- ? `http://[${addr.address}]:${addr.port}`
75
- : `http://${addr.address}:${addr.port}`;
105
+ ? `${protocol}://[${addr.address}]:${addr.port}`
106
+ : `${protocol}://${addr.address}:${addr.port}`;
76
107
  logger.log(
77
108
  `Server-Sent-Events server for lazy compilation open at ${urlBase}.`
78
109
  );
@@ -94,11 +125,12 @@ module.exports = (compiler, client, callback) => {
94
125
  ).replace(/%(2F|3A|24|26|2B|2C|3B|3D|3A)/g, decodeURIComponent)}`;
95
126
  const active = activeModules.get(key) > 0;
96
127
  return {
97
- client: `${client}?${encodeURIComponent(urlBase + prefix)}`,
128
+ client: `${options.client}?${encodeURIComponent(urlBase + prefix)}`,
98
129
  data: key,
99
130
  active
100
131
  };
101
132
  }
102
133
  });
103
134
  });
135
+ listen(server);
104
136
  };
@@ -564,7 +564,7 @@ const getFinalName = (
564
564
  ? `(0,${reference})`
565
565
  : asiSafe === false
566
566
  ? `;(0,${reference})`
567
- : `Object(${reference})`;
567
+ : `/*#__PURE__*/Object(${reference})`;
568
568
  }
569
569
  return reference;
570
570
  }
@@ -59,6 +59,7 @@ const MinMaxSizeWarning = require("./MinMaxSizeWarning");
59
59
  * @property {ChunkFilterFunction=} chunksFilter
60
60
  * @property {boolean=} enforce
61
61
  * @property {SplitChunksSizes} minSize
62
+ * @property {SplitChunksSizes} minSizeReduction
62
63
  * @property {SplitChunksSizes} minRemainingSize
63
64
  * @property {SplitChunksSizes} enforceSizeThreshold
64
65
  * @property {SplitChunksSizes} maxAsyncSize
@@ -80,6 +81,7 @@ const MinMaxSizeWarning = require("./MinMaxSizeWarning");
80
81
  * @property {GetName=} getName
81
82
  * @property {ChunkFilterFunction=} chunksFilter
82
83
  * @property {SplitChunksSizes} minSize
84
+ * @property {SplitChunksSizes} minSizeReduction
83
85
  * @property {SplitChunksSizes} minRemainingSize
84
86
  * @property {SplitChunksSizes} enforceSizeThreshold
85
87
  * @property {SplitChunksSizes} maxAsyncSize
@@ -132,6 +134,7 @@ const MinMaxSizeWarning = require("./MinMaxSizeWarning");
132
134
  * @property {ChunkFilterFunction} chunksFilter
133
135
  * @property {string[]} defaultSizeTypes
134
136
  * @property {SplitChunksSizes} minSize
137
+ * @property {SplitChunksSizes} minSizeReduction
135
138
  * @property {SplitChunksSizes} minRemainingSize
136
139
  * @property {SplitChunksSizes} enforceSizeThreshold
137
140
  * @property {SplitChunksSizes} maxInitialSize
@@ -336,6 +339,21 @@ const checkMinSize = (sizes, minSize) => {
336
339
  return true;
337
340
  };
338
341
 
342
+ /**
343
+ * @param {SplitChunksSizes} sizes the sizes
344
+ * @param {SplitChunksSizes} minSizeReduction the min sizes
345
+ * @param {number} chunkCount number of chunks
346
+ * @returns {boolean} true if there are sizes and all existing sizes are at least `minSizeReduction`
347
+ */
348
+ const checkMinSizeReduction = (sizes, minSizeReduction, chunkCount) => {
349
+ for (const key of Object.keys(minSizeReduction)) {
350
+ const size = sizes[key];
351
+ if (size === undefined || size === 0) continue;
352
+ if (size * chunkCount < minSizeReduction[key]) return false;
353
+ }
354
+ return true;
355
+ };
356
+
339
357
  /**
340
358
  * @param {SplitChunksSizes} sizes the sizes
341
359
  * @param {SplitChunksSizes} minSize the min sizes
@@ -548,6 +566,10 @@ const checkModuleLayer = (test, module) => {
548
566
  */
549
567
  const createCacheGroupSource = (options, key, defaultSizeTypes) => {
550
568
  const minSize = normalizeSizes(options.minSize, defaultSizeTypes);
569
+ const minSizeReduction = normalizeSizes(
570
+ options.minSizeReduction,
571
+ defaultSizeTypes
572
+ );
551
573
  const maxSize = normalizeSizes(options.maxSize, defaultSizeTypes);
552
574
  return {
553
575
  key,
@@ -556,6 +578,7 @@ const createCacheGroupSource = (options, key, defaultSizeTypes) => {
556
578
  chunksFilter: normalizeChunksFilter(options.chunks),
557
579
  enforce: options.enforce,
558
580
  minSize,
581
+ minSizeReduction,
559
582
  minRemainingSize: mergeSizes(
560
583
  normalizeSizes(options.minRemainingSize, defaultSizeTypes),
561
584
  minSize
@@ -594,6 +617,10 @@ module.exports = class SplitChunksPlugin {
594
617
  ];
595
618
  const fallbackCacheGroup = options.fallbackCacheGroup || {};
596
619
  const minSize = normalizeSizes(options.minSize, defaultSizeTypes);
620
+ const minSizeReduction = normalizeSizes(
621
+ options.minSizeReduction,
622
+ defaultSizeTypes
623
+ );
597
624
  const maxSize = normalizeSizes(options.maxSize, defaultSizeTypes);
598
625
 
599
626
  /** @type {SplitChunksOptions} */
@@ -601,6 +628,7 @@ module.exports = class SplitChunksPlugin {
601
628
  chunksFilter: normalizeChunksFilter(options.chunks || "all"),
602
629
  defaultSizeTypes,
603
630
  minSize,
631
+ minSizeReduction,
604
632
  minRemainingSize: mergeSizes(
605
633
  normalizeSizes(options.minRemainingSize, defaultSizeTypes),
606
634
  minSize
@@ -668,6 +696,10 @@ module.exports = class SplitChunksPlugin {
668
696
  cacheGroupSource.minSize,
669
697
  cacheGroupSource.enforce ? undefined : this.options.minSize
670
698
  );
699
+ const minSizeReduction = mergeSizes(
700
+ cacheGroupSource.minSizeReduction,
701
+ cacheGroupSource.enforce ? undefined : this.options.minSizeReduction
702
+ );
671
703
  const minRemainingSize = mergeSizes(
672
704
  cacheGroupSource.minRemainingSize,
673
705
  cacheGroupSource.enforce ? undefined : this.options.minRemainingSize
@@ -681,6 +713,7 @@ module.exports = class SplitChunksPlugin {
681
713
  priority: cacheGroupSource.priority || 0,
682
714
  chunksFilter: cacheGroupSource.chunksFilter || this.options.chunksFilter,
683
715
  minSize,
716
+ minSizeReduction,
684
717
  minRemainingSize,
685
718
  enforceSizeThreshold,
686
719
  maxAsyncSize: mergeSizes(
@@ -774,9 +807,13 @@ module.exports = class SplitChunksPlugin {
774
807
  const chunkIndexMap = new Map();
775
808
  const ZERO = BigInt("0");
776
809
  const ONE = BigInt("1");
777
- let index = ONE;
810
+ const START = ONE << BigInt("31");
811
+ let index = START;
778
812
  for (const chunk of chunks) {
779
- chunkIndexMap.set(chunk, index);
813
+ chunkIndexMap.set(
814
+ chunk,
815
+ index | BigInt((Math.random() * 0x7fffffff) | 0)
816
+ );
780
817
  index = index << ONE;
781
818
  }
782
819
  /**
@@ -793,7 +830,8 @@ module.exports = class SplitChunksPlugin {
793
830
  let key =
794
831
  chunkIndexMap.get(first) | chunkIndexMap.get(result.value);
795
832
  while (!(result = iterator.next()).done) {
796
- key = key | chunkIndexMap.get(result.value);
833
+ const raw = chunkIndexMap.get(result.value);
834
+ key = key ^ raw;
797
835
  }
798
836
  return key;
799
837
  };
@@ -1239,6 +1277,14 @@ module.exports = class SplitChunksPlugin {
1239
1277
  for (const [key, info] of chunksInfoMap) {
1240
1278
  if (removeMinSizeViolatingModules(info)) {
1241
1279
  chunksInfoMap.delete(key);
1280
+ } else if (
1281
+ !checkMinSizeReduction(
1282
+ info.sizes,
1283
+ info.cacheGroup.minSizeReduction,
1284
+ info.chunks.size
1285
+ )
1286
+ ) {
1287
+ chunksInfoMap.delete(key);
1242
1288
  }
1243
1289
  }
1244
1290
 
@@ -1526,7 +1572,14 @@ module.exports = class SplitChunksPlugin {
1526
1572
  chunksInfoMap.delete(key);
1527
1573
  continue;
1528
1574
  }
1529
- if (removeMinSizeViolatingModules(info)) {
1575
+ if (
1576
+ removeMinSizeViolatingModules(info) ||
1577
+ !checkMinSizeReduction(
1578
+ info.sizes,
1579
+ info.cacheGroup.minSizeReduction,
1580
+ info.chunks.size
1581
+ )
1582
+ ) {
1530
1583
  chunksInfoMap.delete(key);
1531
1584
  continue;
1532
1585
  }