webpack 5.59.0 → 5.71.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 (209) hide show
  1. package/README.md +1 -7
  2. package/hot/lazy-compilation-node.js +3 -1
  3. package/hot/poll.js +1 -1
  4. package/hot/signal.js +1 -1
  5. package/lib/APIPlugin.js +33 -0
  6. package/lib/BannerPlugin.js +10 -4
  7. package/lib/Cache.js +1 -1
  8. package/lib/CacheFacade.js +4 -11
  9. package/lib/Chunk.js +6 -3
  10. package/lib/ChunkGraph.js +1 -2
  11. package/lib/ChunkGroup.js +1 -1
  12. package/lib/CleanPlugin.js +81 -20
  13. package/lib/Compilation.js +179 -91
  14. package/lib/Compiler.js +86 -17
  15. package/lib/ConstPlugin.js +2 -2
  16. package/lib/ContextModule.js +142 -51
  17. package/lib/ContextModuleFactory.js +65 -25
  18. package/lib/DelegatedModule.js +1 -1
  19. package/lib/DelegatedModuleFactoryPlugin.js +1 -1
  20. package/lib/Dependency.js +17 -0
  21. package/lib/DependencyTemplate.js +9 -0
  22. package/lib/DependencyTemplates.js +1 -1
  23. package/lib/DllModule.js +1 -1
  24. package/lib/EntryOptionPlugin.js +2 -0
  25. package/lib/ErrorHelpers.js +2 -2
  26. package/lib/EvalDevToolModulePlugin.js +16 -1
  27. package/lib/EvalSourceMapDevToolPlugin.js +18 -1
  28. package/lib/ExportsInfo.js +4 -4
  29. package/lib/ExternalModule.js +94 -54
  30. package/lib/ExternalModuleFactoryPlugin.js +5 -5
  31. package/lib/FileSystemInfo.js +89 -44
  32. package/lib/Generator.js +3 -0
  33. package/lib/HookWebpackError.js +1 -1
  34. package/lib/HotModuleReplacementPlugin.js +3 -1
  35. package/lib/LoaderOptionsPlugin.js +1 -1
  36. package/lib/Module.js +27 -4
  37. package/lib/ModuleFilenameHelpers.js +8 -4
  38. package/lib/ModuleHashingError.js +29 -0
  39. package/lib/MultiCompiler.js +1 -1
  40. package/lib/MultiWatching.js +1 -1
  41. package/lib/NodeStuffPlugin.js +10 -0
  42. package/lib/NormalModule.js +41 -26
  43. package/lib/NormalModuleFactory.js +42 -37
  44. package/lib/ProgressPlugin.js +4 -5
  45. package/lib/RawModule.js +1 -1
  46. package/lib/RuntimeGlobals.js +29 -1
  47. package/lib/RuntimeModule.js +1 -1
  48. package/lib/RuntimePlugin.js +77 -1
  49. package/lib/RuntimeTemplate.js +114 -2
  50. package/lib/Template.js +2 -1
  51. package/lib/TemplatedPathPlugin.js +48 -23
  52. package/lib/WatchIgnorePlugin.js +19 -7
  53. package/lib/Watching.js +33 -19
  54. package/lib/WebpackOptionsApply.js +57 -11
  55. package/lib/asset/AssetGenerator.js +193 -63
  56. package/lib/asset/AssetModulesPlugin.js +3 -0
  57. package/lib/asset/RawDataUrlModule.js +148 -0
  58. package/lib/async-modules/AwaitDependenciesInitFragment.js +4 -4
  59. package/lib/buildChunkGraph.js +36 -6
  60. package/lib/cache/PackFileCacheStrategy.js +7 -4
  61. package/lib/cache/ResolverCachePlugin.js +90 -29
  62. package/lib/cli.js +44 -3
  63. package/lib/config/browserslistTargetHandler.js +41 -6
  64. package/lib/config/defaults.js +115 -19
  65. package/lib/config/normalization.js +9 -0
  66. package/lib/config/target.js +10 -0
  67. package/lib/container/ContainerEntryModule.js +8 -5
  68. package/lib/container/FallbackModule.js +4 -4
  69. package/lib/container/RemoteModule.js +4 -2
  70. package/lib/css/CssExportsGenerator.js +139 -0
  71. package/lib/css/CssGenerator.js +109 -0
  72. package/lib/css/CssLoadingRuntimeModule.js +440 -0
  73. package/lib/css/CssModulesPlugin.js +462 -0
  74. package/lib/css/CssParser.js +618 -0
  75. package/lib/css/walkCssTokens.js +659 -0
  76. package/lib/debug/ProfilingPlugin.js +24 -21
  77. package/lib/dependencies/AMDRequireDependency.js +6 -6
  78. package/lib/dependencies/CommonJsExportsParserPlugin.js +1 -2
  79. package/lib/dependencies/CommonJsFullRequireDependency.js +5 -1
  80. package/lib/dependencies/CommonJsImportsParserPlugin.js +5 -3
  81. package/lib/dependencies/CommonJsRequireContextDependency.js +5 -1
  82. package/lib/dependencies/ContextDependency.js +1 -0
  83. package/lib/dependencies/ContextDependencyHelpers.js +3 -3
  84. package/lib/dependencies/ContextDependencyTemplateAsRequireCall.js +4 -1
  85. package/lib/dependencies/ContextElementDependency.js +41 -3
  86. package/lib/dependencies/CreateScriptUrlDependency.js +12 -0
  87. package/lib/dependencies/CssExportDependency.js +85 -0
  88. package/lib/dependencies/CssImportDependency.js +75 -0
  89. package/lib/dependencies/CssLocalIdentifierDependency.js +119 -0
  90. package/lib/dependencies/CssSelfLocalIdentifierDependency.js +101 -0
  91. package/lib/dependencies/CssUrlDependency.js +132 -0
  92. package/lib/dependencies/ExportsInfoDependency.js +6 -0
  93. package/lib/dependencies/HarmonyAcceptImportDependency.js +5 -3
  94. package/lib/dependencies/HarmonyCompatibilityDependency.js +5 -5
  95. package/lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js +95 -0
  96. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +12 -3
  97. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +25 -17
  98. package/lib/dependencies/HarmonyExportInitFragment.js +4 -1
  99. package/lib/dependencies/HarmonyImportDependency.js +23 -0
  100. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +142 -45
  101. package/lib/dependencies/HarmonyImportSpecifierDependency.js +46 -22
  102. package/lib/dependencies/HarmonyModulesPlugin.js +10 -0
  103. package/lib/dependencies/ImportContextDependency.js +0 -2
  104. package/lib/dependencies/ImportMetaContextDependency.js +35 -0
  105. package/lib/dependencies/ImportMetaContextDependencyParserPlugin.js +252 -0
  106. package/lib/dependencies/ImportMetaContextPlugin.js +59 -0
  107. package/lib/dependencies/ImportMetaPlugin.js +22 -3
  108. package/lib/dependencies/LoaderPlugin.js +4 -2
  109. package/lib/dependencies/RequireContextDependency.js +0 -16
  110. package/lib/dependencies/RequireEnsureDependency.js +2 -2
  111. package/lib/dependencies/URLDependency.js +3 -8
  112. package/lib/dependencies/URLPlugin.js +1 -1
  113. package/lib/esm/ModuleChunkFormatPlugin.js +74 -49
  114. package/lib/esm/ModuleChunkLoadingPlugin.js +3 -1
  115. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +25 -9
  116. package/lib/hmr/HotModuleReplacement.runtime.js +29 -14
  117. package/lib/hmr/JavascriptHotModuleReplacement.runtime.js +4 -3
  118. package/lib/hmr/LazyCompilationPlugin.js +54 -26
  119. package/lib/hmr/lazyCompilationBackend.js +51 -12
  120. package/lib/ids/DeterministicModuleIdsPlugin.js +55 -35
  121. package/lib/ids/HashedModuleIdsPlugin.js +11 -14
  122. package/lib/ids/IdHelpers.js +25 -11
  123. package/lib/ids/NamedModuleIdsPlugin.js +6 -9
  124. package/lib/ids/NaturalModuleIdsPlugin.js +10 -13
  125. package/lib/ids/OccurrenceModuleIdsPlugin.js +13 -10
  126. package/lib/ids/SyncModuleIdsPlugin.js +140 -0
  127. package/lib/index.js +13 -0
  128. package/lib/javascript/ArrayPushCallbackChunkFormatPlugin.js +2 -2
  129. package/lib/javascript/BasicEvaluatedExpression.js +5 -2
  130. package/lib/javascript/ChunkHelpers.js +33 -0
  131. package/lib/javascript/JavascriptGenerator.js +1 -0
  132. package/lib/javascript/JavascriptModulesPlugin.js +27 -2
  133. package/lib/javascript/JavascriptParser.js +82 -48
  134. package/lib/javascript/StartupHelpers.js +7 -30
  135. package/lib/library/AssignLibraryPlugin.js +39 -15
  136. package/lib/library/EnableLibraryPlugin.js +11 -0
  137. package/lib/library/UmdLibraryPlugin.js +5 -3
  138. package/lib/node/NodeTargetPlugin.js +3 -0
  139. package/lib/node/NodeWatchFileSystem.js +85 -31
  140. package/lib/node/ReadFileChunkLoadingRuntimeModule.js +23 -8
  141. package/lib/node/RequireChunkLoadingRuntimeModule.js +24 -9
  142. package/lib/optimize/ConcatenatedModule.js +21 -9
  143. package/lib/optimize/ModuleConcatenationPlugin.js +5 -2
  144. package/lib/optimize/SplitChunksPlugin.js +8 -1
  145. package/lib/runtime/AsyncModuleRuntimeModule.js +27 -17
  146. package/lib/runtime/BaseUriRuntimeModule.js +31 -0
  147. package/lib/runtime/CreateScriptRuntimeModule.js +36 -0
  148. package/lib/runtime/CreateScriptUrlRuntimeModule.js +9 -34
  149. package/lib/runtime/GetTrustedTypesPolicyRuntimeModule.js +76 -0
  150. package/lib/schemes/HttpUriPlugin.js +77 -14
  151. package/lib/serialization/FileMiddleware.js +44 -9
  152. package/lib/sharing/ConsumeSharedModule.js +8 -2
  153. package/lib/sharing/ConsumeSharedRuntimeModule.js +26 -5
  154. package/lib/sharing/ProvideSharedModule.js +4 -2
  155. package/lib/sharing/ShareRuntimeModule.js +1 -1
  156. package/lib/sharing/utils.js +1 -1
  157. package/lib/stats/DefaultStatsFactoryPlugin.js +113 -68
  158. package/lib/stats/DefaultStatsPrinterPlugin.js +89 -24
  159. package/lib/util/ArrayHelpers.js +30 -0
  160. package/lib/util/AsyncQueue.js +1 -1
  161. package/lib/util/compileBooleanMatcher.js +1 -1
  162. package/lib/util/create-schema-validation.js +9 -2
  163. package/lib/util/createHash.js +12 -0
  164. package/lib/util/deprecation.js +10 -2
  165. package/lib/util/deterministicGrouping.js +1 -1
  166. package/lib/util/extractUrlAndGlobal.js +3 -0
  167. package/lib/util/fs.js +11 -0
  168. package/lib/util/hash/BatchedHash.js +7 -4
  169. package/lib/util/hash/md4.js +20 -0
  170. package/lib/util/hash/wasm-hash.js +163 -0
  171. package/lib/util/hash/xxhash64.js +5 -139
  172. package/lib/util/identifier.js +65 -44
  173. package/lib/util/internalSerializables.js +15 -0
  174. package/lib/util/nonNumericOnlyHash.js +22 -0
  175. package/lib/util/semver.js +17 -10
  176. package/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js +9 -3
  177. package/lib/web/JsonpChunkLoadingRuntimeModule.js +20 -9
  178. package/lib/webpack.js +10 -3
  179. package/lib/webworker/ImportScriptsChunkLoadingPlugin.js +3 -11
  180. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +33 -22
  181. package/module.d.ts +215 -0
  182. package/package.json +23 -28
  183. package/schemas/WebpackOptions.check.js +1 -1
  184. package/schemas/WebpackOptions.json +254 -29
  185. package/schemas/plugins/DllReferencePlugin.check.js +1 -1
  186. package/schemas/plugins/HashedModuleIdsPlugin.check.js +1 -1
  187. package/schemas/plugins/ProgressPlugin.check.js +1 -1
  188. package/schemas/plugins/asset/AssetGeneratorOptions.check.js +1 -1
  189. package/schemas/plugins/asset/AssetParserOptions.check.js +1 -1
  190. package/schemas/plugins/asset/AssetResourceGeneratorOptions.check.js +1 -1
  191. package/schemas/plugins/container/ContainerPlugin.check.js +1 -1
  192. package/schemas/plugins/container/ContainerPlugin.json +2 -1
  193. package/schemas/plugins/container/ContainerReferencePlugin.check.js +1 -1
  194. package/schemas/plugins/container/ContainerReferencePlugin.json +1 -0
  195. package/schemas/plugins/container/ExternalsType.check.js +1 -1
  196. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  197. package/schemas/plugins/container/ModuleFederationPlugin.json +3 -1
  198. package/schemas/plugins/css/CssGeneratorOptions.check.d.ts +7 -0
  199. package/schemas/plugins/css/CssGeneratorOptions.check.js +6 -0
  200. package/schemas/plugins/css/CssGeneratorOptions.json +3 -0
  201. package/schemas/plugins/css/CssParserOptions.check.d.ts +7 -0
  202. package/schemas/plugins/css/CssParserOptions.check.js +6 -0
  203. package/schemas/plugins/css/CssParserOptions.json +3 -0
  204. package/schemas/plugins/optimize/AggressiveSplittingPlugin.check.js +1 -1
  205. package/schemas/plugins/optimize/LimitChunkCountPlugin.check.js +1 -1
  206. package/schemas/plugins/optimize/MinChunkSizePlugin.check.js +1 -1
  207. package/schemas/plugins/schemes/HttpUriPlugin.check.js +1 -1
  208. package/schemas/plugins/schemes/HttpUriPlugin.json +4 -0
  209. package/types.d.ts +628 -179
@@ -28,7 +28,8 @@ module.exports = function () {
28
28
  var currentStatus = "idle";
29
29
 
30
30
  // while downloading
31
- var blockingPromises;
31
+ var blockingPromises = 0;
32
+ var blockingPromisesWaiting = [];
32
33
 
33
34
  // The update info
34
35
  var currentUpdateApplyHandlers;
@@ -218,17 +219,28 @@ module.exports = function () {
218
219
  return Promise.all(results);
219
220
  }
220
221
 
222
+ function unblock() {
223
+ if (--blockingPromises === 0) {
224
+ setStatus("ready").then(function () {
225
+ if (blockingPromises === 0) {
226
+ var list = blockingPromisesWaiting;
227
+ blockingPromisesWaiting = [];
228
+ for (var i = 0; i < list.length; i++) {
229
+ list[i]();
230
+ }
231
+ }
232
+ });
233
+ }
234
+ }
235
+
221
236
  function trackBlockingPromise(promise) {
222
237
  switch (currentStatus) {
223
238
  case "ready":
224
239
  setStatus("prepare");
225
- blockingPromises.push(promise);
226
- waitForBlockingPromises(function () {
227
- return setStatus("ready");
228
- });
229
- return promise;
240
+ /* fallthrough */
230
241
  case "prepare":
231
- blockingPromises.push(promise);
242
+ blockingPromises++;
243
+ promise.then(unblock, unblock);
232
244
  return promise;
233
245
  default:
234
246
  return promise;
@@ -236,11 +248,11 @@ module.exports = function () {
236
248
  }
237
249
 
238
250
  function waitForBlockingPromises(fn) {
239
- if (blockingPromises.length === 0) return fn();
240
- var blocker = blockingPromises;
241
- blockingPromises = [];
242
- return Promise.all(blocker).then(function () {
243
- return waitForBlockingPromises(fn);
251
+ if (blockingPromises === 0) return fn();
252
+ return new Promise(function (resolve) {
253
+ blockingPromisesWaiting.push(function () {
254
+ resolve(fn());
255
+ });
244
256
  });
245
257
  }
246
258
 
@@ -261,7 +273,6 @@ module.exports = function () {
261
273
 
262
274
  return setStatus("prepare").then(function () {
263
275
  var updatedModules = [];
264
- blockingPromises = [];
265
276
  currentUpdateApplyHandlers = [];
266
277
 
267
278
  return Promise.all(
@@ -298,7 +309,11 @@ module.exports = function () {
298
309
  function hotApply(options) {
299
310
  if (currentStatus !== "ready") {
300
311
  return Promise.resolve().then(function () {
301
- throw new Error("apply() is only allowed in ready status");
312
+ throw new Error(
313
+ "apply() is only allowed in ready status (state: " +
314
+ currentStatus +
315
+ ")"
316
+ );
302
317
  });
303
318
  }
304
319
  return internalApply(options);
@@ -443,15 +443,16 @@ module.exports = function () {
443
443
  ) {
444
444
  promises.push($loadUpdateChunk$(chunkId, updatedModulesList));
445
445
  currentUpdateChunks[chunkId] = true;
446
+ } else {
447
+ currentUpdateChunks[chunkId] = false;
446
448
  }
447
449
  });
448
450
  if ($ensureChunkHandlers$) {
449
451
  $ensureChunkHandlers$.$key$Hmr = function (chunkId, promises) {
450
452
  if (
451
453
  currentUpdateChunks &&
452
- !$hasOwnProperty$(currentUpdateChunks, chunkId) &&
453
- $hasOwnProperty$($installedChunks$, chunkId) &&
454
- $installedChunks$[chunkId] !== undefined
454
+ $hasOwnProperty$(currentUpdateChunks, chunkId) &&
455
+ !currentUpdateChunks[chunkId]
455
456
  ) {
456
457
  promises.push($loadUpdateChunk$(chunkId));
457
458
  currentUpdateChunks[chunkId] = true;
@@ -29,10 +29,17 @@ const { registerNotSerializable } = require("../util/serialization");
29
29
  /** @typedef {import("../RequestShortener")} RequestShortener */
30
30
  /** @typedef {import("../ResolverFactory").ResolverWithOptions} ResolverWithOptions */
31
31
  /** @typedef {import("../WebpackError")} WebpackError */
32
+ /** @typedef {import("../dependencies/HarmonyImportDependency")} HarmonyImportDependency */
32
33
  /** @typedef {import("../util/Hash")} Hash */
33
34
  /** @typedef {import("../util/fs").InputFileSystem} InputFileSystem */
34
35
 
35
- const IGNORED_DEPENDENCY_TYPES = new Set([
36
+ /**
37
+ * @typedef {Object} BackendApi
38
+ * @property {function(Error=): void} dispose
39
+ * @property {function(Module): { client: string, data: string, active: boolean }} module
40
+ */
41
+
42
+ const HMR_DEPENDENCY_TYPES = new Set([
36
43
  "import.meta.webpackHot.accept",
37
44
  "import.meta.webpackHot.decline",
38
45
  "module.hot.accept",
@@ -140,7 +147,7 @@ class LazyCompilationProxyModule extends Module {
140
147
 
141
148
  /**
142
149
  * @param {NeedBuildContext} context context info
143
- * @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
150
+ * @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
144
151
  * @returns {void}
145
152
  */
146
153
  needBuild(context, callback) {
@@ -303,15 +310,13 @@ class LazyCompilationDependencyFactory extends ModuleFactory {
303
310
  class LazyCompilationPlugin {
304
311
  /**
305
312
  * @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
313
+ * @param {(function(Compiler, function(Error?, BackendApi?): void): void) | function(Compiler): Promise<BackendApi>} options.backend the backend
308
314
  * @param {boolean} options.entries true, when entries are lazy compiled
309
315
  * @param {boolean} options.imports true, when import() modules are lazy compiled
310
316
  * @param {RegExp | string | (function(Module): boolean)} options.test additional filter for lazy compiled entrypoint modules
311
317
  */
312
- constructor({ backend, client, entries, imports, test }) {
318
+ constructor({ backend, entries, imports, test }) {
313
319
  this.backend = backend;
314
- this.client = client;
315
320
  this.entries = entries;
316
321
  this.imports = imports;
317
322
  this.test = test;
@@ -327,7 +332,7 @@ class LazyCompilationPlugin {
327
332
  "LazyCompilationPlugin",
328
333
  (params, callback) => {
329
334
  if (backend !== undefined) return callback();
330
- const promise = this.backend(compiler, this.client, (err, result) => {
335
+ const promise = this.backend(compiler, (err, result) => {
331
336
  if (err) return callback(err);
332
337
  backend = result;
333
338
  callback();
@@ -347,32 +352,55 @@ class LazyCompilationPlugin {
347
352
  "LazyCompilationPlugin",
348
353
  (originalModule, createData, resolveData) => {
349
354
  if (
350
- resolveData.dependencies.every(
355
+ resolveData.dependencies.every(dep =>
356
+ HMR_DEPENDENCY_TYPES.has(dep.type)
357
+ )
358
+ ) {
359
+ // for HMR only resolving, try to determine if the HMR accept/decline refers to
360
+ // an import() or not
361
+ const hmrDep = resolveData.dependencies[0];
362
+ const originModule =
363
+ compilation.moduleGraph.getParentModule(hmrDep);
364
+ const isReferringToDynamicImport = originModule.blocks.some(
365
+ block =>
366
+ block.dependencies.some(
367
+ dep =>
368
+ dep.type === "import()" &&
369
+ /** @type {HarmonyImportDependency} */ (dep).request ===
370
+ hmrDep.request
371
+ )
372
+ );
373
+ if (!isReferringToDynamicImport) return;
374
+ } else if (
375
+ !resolveData.dependencies.every(
351
376
  dep =>
352
- IGNORED_DEPENDENCY_TYPES.has(dep.type) ||
377
+ HMR_DEPENDENCY_TYPES.has(dep.type) ||
353
378
  (this.imports &&
354
379
  (dep.type === "import()" ||
355
380
  dep.type === "import() context element")) ||
356
381
  (this.entries && dep.type === "entry")
357
- ) &&
358
- !/webpack[/\\]hot[/\\]|webpack-dev-server[/\\]client/.test(
382
+ )
383
+ )
384
+ return;
385
+ if (
386
+ /webpack[/\\]hot[/\\]|webpack-dev-server[/\\]client|webpack-hot-middleware[/\\]client/.test(
359
387
  resolveData.request
360
- ) &&
361
- checkTest(this.test, originalModule)
362
- ) {
363
- const moduleInfo = backend.module(originalModule);
364
- if (!moduleInfo) return;
365
- const { client, data, active } = moduleInfo;
388
+ ) ||
389
+ !checkTest(this.test, originalModule)
390
+ )
391
+ return;
392
+ const moduleInfo = backend.module(originalModule);
393
+ if (!moduleInfo) return;
394
+ const { client, data, active } = moduleInfo;
366
395
 
367
- return new LazyCompilationProxyModule(
368
- compiler.context,
369
- originalModule,
370
- resolveData.request,
371
- client,
372
- data,
373
- active
374
- );
375
- }
396
+ return new LazyCompilationProxyModule(
397
+ compiler.context,
398
+ originalModule,
399
+ resolveData.request,
400
+ client,
401
+ data,
402
+ active
403
+ );
376
404
  }
377
405
  );
378
406
  compilation.dependencyFactories.set(
@@ -5,21 +5,51 @@
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
- * @param {function(Error?, any?): void} callback callback
16
+ * @param {function((Error | null)=, 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 => {
45
+ let listen = options.listen;
46
+ if (typeof listen === "object" && !("port" in listen))
47
+ listen = { ...listen, port: undefined };
48
+ server.listen(listen);
49
+ };
50
+
51
+ const protocol = options.protocol || (isHttps ? "https" : "http");
52
+
23
53
  const requestListener = (req, res) => {
24
54
  const keys = req.url.slice(prefix.length).split("@");
25
55
  req.socket.on("close", () => {
@@ -38,7 +68,9 @@ module.exports = (compiler, client, callback) => {
38
68
  req.socket.setNoDelay(true);
39
69
  res.writeHead(200, {
40
70
  "content-type": "text/event-stream",
41
- "Access-Control-Allow-Origin": "*"
71
+ "Access-Control-Allow-Origin": "*",
72
+ "Access-Control-Allow-Methods": "*",
73
+ "Access-Control-Allow-Headers": "*"
42
74
  });
43
75
  res.write("\n");
44
76
  let moduleActivated = false;
@@ -52,7 +84,10 @@ module.exports = (compiler, client, callback) => {
52
84
  }
53
85
  if (moduleActivated && compiler.watching) compiler.watching.invalidate();
54
86
  };
55
- const server = http.createServer(requestListener);
87
+
88
+ const server = /** @type {import("net").Server} */ (createServer());
89
+ server.on("request", requestListener);
90
+
56
91
  let isClosing = false;
57
92
  /** @type {Set<import("net").Socket>} */
58
93
  const sockets = new Set();
@@ -63,16 +98,19 @@ module.exports = (compiler, client, callback) => {
63
98
  });
64
99
  if (isClosing) socket.destroy();
65
100
  });
66
- server.listen(err => {
101
+ server.on("clientError", e => {
102
+ if (e.message !== "Server is disposing") logger.warn(e);
103
+ });
104
+ server.on("listening", err => {
67
105
  if (err) return callback(err);
68
106
  const addr = server.address();
69
107
  if (typeof addr === "string") throw new Error("addr must not be a string");
70
108
  const urlBase =
71
109
  addr.address === "::" || addr.address === "0.0.0.0"
72
- ? `http://localhost:${addr.port}`
110
+ ? `${protocol}://localhost:${addr.port}`
73
111
  : addr.family === "IPv6"
74
- ? `http://[${addr.address}]:${addr.port}`
75
- : `http://${addr.address}:${addr.port}`;
112
+ ? `${protocol}://[${addr.address}]:${addr.port}`
113
+ : `${protocol}://${addr.address}:${addr.port}`;
76
114
  logger.log(
77
115
  `Server-Sent-Events server for lazy compilation open at ${urlBase}.`
78
116
  );
@@ -94,11 +132,12 @@ module.exports = (compiler, client, callback) => {
94
132
  ).replace(/%(2F|3A|24|26|2B|2C|3B|3D|3A)/g, decodeURIComponent)}`;
95
133
  const active = activeModules.get(key) > 0;
96
134
  return {
97
- client: `${client}?${encodeURIComponent(urlBase + prefix)}`,
135
+ client: `${options.client}?${encodeURIComponent(urlBase + prefix)}`,
98
136
  data: key,
99
137
  active
100
138
  };
101
139
  }
102
140
  });
103
141
  });
142
+ listen(server);
104
143
  };
@@ -9,7 +9,7 @@ const {
9
9
  compareModulesByPreOrderIndexOrIdentifier
10
10
  } = require("../util/comparators");
11
11
  const {
12
- getUsedModuleIds,
12
+ getUsedModuleIdsAndModules,
13
13
  getFullModuleName,
14
14
  assignDeterministicIds
15
15
  } = require("./IdHelpers");
@@ -18,8 +18,17 @@ const {
18
18
  /** @typedef {import("../Module")} Module */
19
19
 
20
20
  class DeterministicModuleIdsPlugin {
21
- constructor(options) {
22
- this.options = options || {};
21
+ /**
22
+ * @param {Object} options options
23
+ * @param {string=} options.context context relative to which module identifiers are computed
24
+ * @param {function(Module): boolean=} options.test selector function for modules
25
+ * @param {number=} options.maxLength maximum id length in digits (used as starting point)
26
+ * @param {number=} options.salt hash salt for ids
27
+ * @param {boolean=} options.fixedLength do not increase the maxLength to find an optimal id space size
28
+ * @param {boolean=} options.failOnConflict throw an error when id conflicts occur (instead of rehashing)
29
+ */
30
+ constructor(options = {}) {
31
+ this.options = options;
23
32
  }
24
33
 
25
34
  /**
@@ -31,40 +40,51 @@ class DeterministicModuleIdsPlugin {
31
40
  compiler.hooks.compilation.tap(
32
41
  "DeterministicModuleIdsPlugin",
33
42
  compilation => {
34
- compilation.hooks.moduleIds.tap(
35
- "DeterministicModuleIdsPlugin",
36
- modules => {
37
- const chunkGraph = compilation.chunkGraph;
38
- const context = this.options.context
39
- ? this.options.context
40
- : compiler.context;
41
- const maxLength = this.options.maxLength || 3;
43
+ compilation.hooks.moduleIds.tap("DeterministicModuleIdsPlugin", () => {
44
+ const chunkGraph = compilation.chunkGraph;
45
+ const context = this.options.context
46
+ ? this.options.context
47
+ : compiler.context;
48
+ const maxLength = this.options.maxLength || 3;
49
+ const failOnConflict = this.options.failOnConflict || false;
50
+ const fixedLength = this.options.fixedLength || false;
51
+ const salt = this.options.salt || 0;
52
+ let conflicts = 0;
42
53
 
43
- const usedIds = getUsedModuleIds(compilation);
44
- assignDeterministicIds(
45
- Array.from(modules).filter(module => {
46
- if (!module.needId) return false;
47
- if (chunkGraph.getNumberOfModuleChunks(module) === 0)
48
- return false;
49
- return chunkGraph.getModuleId(module) === null;
50
- }),
51
- module => getFullModuleName(module, context, compiler.root),
52
- compareModulesByPreOrderIndexOrIdentifier(
53
- compilation.moduleGraph
54
- ),
55
- (module, id) => {
56
- const size = usedIds.size;
57
- usedIds.add(`${id}`);
58
- if (size === usedIds.size) return false;
59
- chunkGraph.setModuleId(module, id);
60
- return true;
61
- },
62
- [Math.pow(10, maxLength)],
63
- 10,
64
- usedIds.size
54
+ const [usedIds, modules] = getUsedModuleIdsAndModules(
55
+ compilation,
56
+ this.options.test
57
+ );
58
+ assignDeterministicIds(
59
+ modules,
60
+ module => getFullModuleName(module, context, compiler.root),
61
+ failOnConflict
62
+ ? () => 0
63
+ : compareModulesByPreOrderIndexOrIdentifier(
64
+ compilation.moduleGraph
65
+ ),
66
+ (module, id) => {
67
+ const size = usedIds.size;
68
+ usedIds.add(`${id}`);
69
+ if (size === usedIds.size) {
70
+ conflicts++;
71
+ return false;
72
+ }
73
+ chunkGraph.setModuleId(module, id);
74
+ return true;
75
+ },
76
+ [Math.pow(10, maxLength)],
77
+ fixedLength ? 0 : 10,
78
+ usedIds.size,
79
+ salt
80
+ );
81
+ if (failOnConflict && conflicts)
82
+ throw new Error(
83
+ `Assigning deterministic module ids has lead to ${conflicts} conflict${
84
+ conflicts > 1 ? "s" : ""
85
+ }.\nIncrease the 'maxLength' to increase the id space and make conflicts less likely (recommended when there are many conflicts or application is expected to grow), or add an 'salt' number to try another hash starting value in the same id space (recommended when there is only a single conflict).`
65
86
  );
66
- }
67
- );
87
+ });
68
88
  }
69
89
  );
70
90
  }
@@ -10,7 +10,10 @@ const {
10
10
  } = require("../util/comparators");
11
11
  const createSchemaValidation = require("../util/create-schema-validation");
12
12
  const createHash = require("../util/createHash");
13
- const { getUsedModuleIds, getFullModuleName } = require("./IdHelpers");
13
+ const {
14
+ getUsedModuleIdsAndModules,
15
+ getFullModuleName
16
+ } = require("./IdHelpers");
14
17
 
15
18
  /** @typedef {import("../../declarations/plugins/HashedModuleIdsPlugin").HashedModuleIdsPluginOptions} HashedModuleIdsPluginOptions */
16
19
 
@@ -43,22 +46,16 @@ class HashedModuleIdsPlugin {
43
46
  apply(compiler) {
44
47
  const options = this.options;
45
48
  compiler.hooks.compilation.tap("HashedModuleIdsPlugin", compilation => {
46
- compilation.hooks.moduleIds.tap("HashedModuleIdsPlugin", modules => {
49
+ compilation.hooks.moduleIds.tap("HashedModuleIdsPlugin", () => {
47
50
  const chunkGraph = compilation.chunkGraph;
48
51
  const context = this.options.context
49
52
  ? this.options.context
50
53
  : compiler.context;
51
54
 
52
- const usedIds = getUsedModuleIds(compilation);
53
- const modulesInNaturalOrder = Array.from(modules)
54
- .filter(m => {
55
- if (!m.needId) return false;
56
- if (chunkGraph.getNumberOfModuleChunks(m) === 0) return false;
57
- return chunkGraph.getModuleId(module) === null;
58
- })
59
- .sort(
60
- compareModulesByPreOrderIndexOrIdentifier(compilation.moduleGraph)
61
- );
55
+ const [usedIds, modules] = getUsedModuleIdsAndModules(compilation);
56
+ const modulesInNaturalOrder = modules.sort(
57
+ compareModulesByPreOrderIndexOrIdentifier(compilation.moduleGraph)
58
+ );
62
59
  for (const module of modulesInNaturalOrder) {
63
60
  const ident = getFullModuleName(module, context, compiler.root);
64
61
  const hash = createHash(options.hashFunction);
@@ -67,8 +64,8 @@ class HashedModuleIdsPlugin {
67
64
  hash.digest(options.hashDigest)
68
65
  );
69
66
  let len = options.hashDigestLength;
70
- while (usedIds.has(hashId.substr(0, len))) len++;
71
- const moduleId = hashId.substr(0, len);
67
+ while (usedIds.has(hashId.slice(0, len))) len++;
68
+ const moduleId = hashId.slice(0, len);
72
69
  chunkGraph.setModuleId(module, moduleId);
73
70
  usedIds.add(moduleId);
74
71
  }
@@ -25,7 +25,7 @@ const getHash = (str, len, hashFunction) => {
25
25
  const hash = createHash(hashFunction);
26
26
  hash.update(str);
27
27
  const digest = /** @type {string} */ (hash.digest("hex"));
28
- return digest.substr(0, len);
28
+ return digest.slice(0, len);
29
29
  };
30
30
 
31
31
  /**
@@ -234,11 +234,14 @@ const addToMapOfItems = (map, key, value) => {
234
234
 
235
235
  /**
236
236
  * @param {Compilation} compilation the compilation
237
- * @returns {Set<string>} used module ids as strings
237
+ * @param {function(Module): boolean=} filter filter modules
238
+ * @returns {[Set<string>, Module[]]} used module ids as strings and modules without id matching the filter
238
239
  */
239
- const getUsedModuleIds = compilation => {
240
+ const getUsedModuleIdsAndModules = (compilation, filter) => {
240
241
  const chunkGraph = compilation.chunkGraph;
241
242
 
243
+ const modules = [];
244
+
242
245
  /** @type {Set<string>} */
243
246
  const usedIds = new Set();
244
247
  if (compilation.usedModuleIds) {
@@ -248,15 +251,23 @@ const getUsedModuleIds = compilation => {
248
251
  }
249
252
 
250
253
  for (const module of compilation.modules) {
254
+ if (!module.needId) continue;
251
255
  const moduleId = chunkGraph.getModuleId(module);
252
256
  if (moduleId !== null) {
253
257
  usedIds.add(moduleId + "");
258
+ } else {
259
+ if (
260
+ (!filter || filter(module)) &&
261
+ chunkGraph.getNumberOfModuleChunks(module) !== 0
262
+ ) {
263
+ modules.push(module);
264
+ }
254
265
  }
255
266
  }
256
267
 
257
- return usedIds;
268
+ return [usedIds, modules];
258
269
  };
259
- exports.getUsedModuleIds = getUsedModuleIds;
270
+ exports.getUsedModuleIdsAndModules = getUsedModuleIdsAndModules;
260
271
 
261
272
  /**
262
273
  * @param {Compilation} compilation the compilation
@@ -359,6 +370,7 @@ exports.assignNames = assignNames;
359
370
  * @param {number[]} ranges usable ranges for ids
360
371
  * @param {number} expandFactor factor to create more ranges
361
372
  * @param {number} extraSpace extra space to allocate, i. e. when some ids are already used
373
+ * @param {number} salt salting number to initialize hashing
362
374
  * @returns {void}
363
375
  */
364
376
  const assignDeterministicIds = (
@@ -368,7 +380,8 @@ const assignDeterministicIds = (
368
380
  assignId,
369
381
  ranges = [10],
370
382
  expandFactor = 10,
371
- extraSpace = 0
383
+ extraSpace = 0,
384
+ salt = 0
372
385
  ) => {
373
386
  items.sort(comparator);
374
387
 
@@ -384,15 +397,17 @@ const assignDeterministicIds = (
384
397
  i++;
385
398
  if (i < ranges.length) {
386
399
  range = Math.min(ranges[i], Number.MAX_SAFE_INTEGER);
387
- } else {
400
+ } else if (expandFactor) {
388
401
  range = Math.min(range * expandFactor, Number.MAX_SAFE_INTEGER);
402
+ } else {
403
+ break;
389
404
  }
390
405
  }
391
406
 
392
407
  for (const item of items) {
393
408
  const ident = getName(item);
394
409
  let id;
395
- let i = 0;
410
+ let i = salt;
396
411
  do {
397
412
  id = numberHash(ident + i++, range);
398
413
  } while (!assignId(item, id));
@@ -401,15 +416,14 @@ const assignDeterministicIds = (
401
416
  exports.assignDeterministicIds = assignDeterministicIds;
402
417
 
403
418
  /**
419
+ * @param {Set<string>} usedIds used ids
404
420
  * @param {Iterable<Module>} modules the modules
405
421
  * @param {Compilation} compilation the compilation
406
422
  * @returns {void}
407
423
  */
408
- const assignAscendingModuleIds = (modules, compilation) => {
424
+ const assignAscendingModuleIds = (usedIds, modules, compilation) => {
409
425
  const chunkGraph = compilation.chunkGraph;
410
426
 
411
- const usedIds = getUsedModuleIds(compilation);
412
-
413
427
  let nextId = 0;
414
428
  let assignId;
415
429
  if (usedIds.size > 0) {
@@ -10,7 +10,7 @@ const {
10
10
  getShortModuleName,
11
11
  getLongModuleName,
12
12
  assignNames,
13
- getUsedModuleIds,
13
+ getUsedModuleIdsAndModules,
14
14
  assignAscendingModuleIds
15
15
  } = require("./IdHelpers");
16
16
 
@@ -31,27 +31,24 @@ class NamedModuleIdsPlugin {
31
31
  const { root } = compiler;
32
32
  compiler.hooks.compilation.tap("NamedModuleIdsPlugin", compilation => {
33
33
  const { hashFunction } = compilation.outputOptions;
34
- compilation.hooks.moduleIds.tap("NamedModuleIdsPlugin", modules => {
34
+ compilation.hooks.moduleIds.tap("NamedModuleIdsPlugin", () => {
35
35
  const chunkGraph = compilation.chunkGraph;
36
36
  const context = this.options.context
37
37
  ? this.options.context
38
38
  : compiler.context;
39
39
 
40
+ const [usedIds, modules] = getUsedModuleIdsAndModules(compilation);
40
41
  const unnamedModules = assignNames(
41
- Array.from(modules).filter(module => {
42
- if (!module.needId) return false;
43
- if (chunkGraph.getNumberOfModuleChunks(module) === 0) return false;
44
- return chunkGraph.getModuleId(module) === null;
45
- }),
42
+ modules,
46
43
  m => getShortModuleName(m, context, root),
47
44
  (m, shortName) =>
48
45
  getLongModuleName(shortName, m, context, hashFunction, root),
49
46
  compareModulesByIdentifier,
50
- getUsedModuleIds(compilation),
47
+ usedIds,
51
48
  (m, name) => chunkGraph.setModuleId(m, name)
52
49
  );
53
50
  if (unnamedModules.length > 0) {
54
- assignAscendingModuleIds(unnamedModules, compilation);
51
+ assignAscendingModuleIds(usedIds, unnamedModules, compilation);
55
52
  }
56
53
  });
57
54
  });