webpack 5.108.4 → 5.109.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. package/bin/webpack.js +12 -0
  2. package/lib/APIPlugin.js +48 -29
  3. package/lib/CacheFacade.js +8 -0
  4. package/lib/ChunkGraph.js +17 -15
  5. package/lib/ChunkGroup.js +1 -0
  6. package/lib/CompatibilityPlugin.js +62 -29
  7. package/lib/Compilation.js +58 -6
  8. package/lib/ConstPlugin.js +11 -11
  9. package/lib/ContextModule.js +239 -6
  10. package/lib/ContextModuleFactory.js +139 -14
  11. package/lib/DefinePlugin.js +433 -112
  12. package/lib/Entrypoint.js +1 -1
  13. package/lib/ExportsInfo.js +22 -5
  14. package/lib/ExportsInfoApiPlugin.js +2 -2
  15. package/lib/ExternalModule.js +107 -5
  16. package/lib/ExternalModuleFactoryPlugin.js +20 -1
  17. package/lib/FileSystemInfo.js +256 -100
  18. package/lib/FlagDependencyUsagePlugin.js +33 -12
  19. package/lib/HotModuleReplacementPlugin.js +18 -15
  20. package/lib/InitFragment.js +20 -32
  21. package/lib/Module.js +3 -0
  22. package/lib/ModuleFilenameHelpers.js +2 -2
  23. package/lib/ModuleTypeConstants.js +8 -1
  24. package/lib/MultiCompiler.js +13 -2
  25. package/lib/MultiWatching.js +1 -0
  26. package/lib/NodeStuffPlugin.js +51 -33
  27. package/lib/NormalModule.js +175 -401
  28. package/lib/NormalModuleFactory.js +76 -2
  29. package/lib/ProgressPlugin.js +211 -119
  30. package/lib/ProvidePlugin.js +2 -2
  31. package/lib/RuntimeGlobals.js +47 -0
  32. package/lib/RuntimePlugin.js +67 -107
  33. package/lib/RuntimeTemplate.js +304 -16
  34. package/lib/Template.js +23 -3
  35. package/lib/UseStrictPlugin.js +1 -1
  36. package/lib/WebpackIsIncludedPlugin.js +1 -1
  37. package/lib/WebpackOptionsApply.js +24 -19
  38. package/lib/asset/AssetGenerator.js +110 -28
  39. package/lib/asset/AssetModulesPlugin.js +92 -2
  40. package/lib/asset/WebManifestGenerator.js +164 -0
  41. package/lib/asset/WebManifestParser.js +130 -0
  42. package/lib/async-modules/AwaitDependenciesInitFragment.js +14 -4
  43. package/lib/async-modules/isGeneratorLowered.js +26 -0
  44. package/lib/cache/PackFileCacheStrategy.js +9 -3
  45. package/lib/config/browserslistTargetHandler.js +40 -0
  46. package/lib/config/defaults.js +219 -29
  47. package/lib/config/normalization.js +26 -0
  48. package/lib/config/target.js +9 -1
  49. package/lib/container/HoistContainerReferencesPlugin.js +47 -55
  50. package/lib/css/CssGenerator.js +40 -31
  51. package/lib/css/CssLoadingRuntimeModule.js +5 -1
  52. package/lib/css/CssModulesPlugin.js +13 -0
  53. package/lib/css/CssParser.js +729 -313
  54. package/lib/css/syntax.js +1371 -861
  55. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +6 -6
  56. package/lib/dependencies/AMDPlugin.js +2 -2
  57. package/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +13 -13
  58. package/lib/dependencies/CommonJsDependencyHelpers.js +39 -0
  59. package/lib/dependencies/CommonJsExportRequireDependency.js +19 -0
  60. package/lib/dependencies/CommonJsExportsDependency.js +47 -2
  61. package/lib/dependencies/CommonJsExportsParserPlugin.js +10 -10
  62. package/lib/dependencies/CommonJsImportsParserPlugin.js +18 -18
  63. package/lib/dependencies/CommonJsPlugin.js +2 -2
  64. package/lib/dependencies/CommonJsRequireDependency.js +26 -1
  65. package/lib/dependencies/CommonJsSelfReferenceDependency.js +32 -1
  66. package/lib/dependencies/ContextDependencyHelpers.js +3 -3
  67. package/lib/dependencies/CreateRequireParserPlugin.js +6 -6
  68. package/lib/dependencies/CssIcssExportDependency.js +162 -71
  69. package/lib/dependencies/CssUrlDependency.js +35 -4
  70. package/lib/dependencies/ExternalModuleInitFragmentDependency.js +2 -2
  71. package/lib/dependencies/HarmonyCompatibilityDependency.js +32 -14
  72. package/lib/dependencies/HarmonyDetectionParserPlugin.js +43 -13
  73. package/lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js +2 -1
  74. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +7 -19
  75. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +17 -9
  76. package/lib/dependencies/HarmonyImportDependency.js +13 -2
  77. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +11 -11
  78. package/lib/dependencies/HarmonyImportSpecifierDependency.js +10 -7
  79. package/lib/dependencies/HarmonyModulesPlugin.js +6 -0
  80. package/lib/dependencies/HarmonyTopLevelThisParserPlugin.js +1 -1
  81. package/lib/dependencies/HtmlEntryDependency.js +797 -172
  82. package/lib/dependencies/HtmlSourceDependency.js +26 -0
  83. package/lib/dependencies/ImportDependency.js +43 -1
  84. package/lib/dependencies/ImportMetaContextDependencyParserPlugin.js +31 -18
  85. package/lib/dependencies/ImportMetaContextPlugin.js +38 -7
  86. package/lib/dependencies/ImportMetaGlobDependency.js +81 -0
  87. package/lib/dependencies/ImportMetaGlobDependencyParserPlugin.js +78 -0
  88. package/lib/dependencies/ImportMetaGlobHelpers.js +660 -0
  89. package/lib/dependencies/ImportMetaPlugin.js +532 -180
  90. package/lib/dependencies/ImportMetaResolveDependency.js +90 -0
  91. package/lib/dependencies/ImportParserPlugin.js +80 -17
  92. package/lib/dependencies/ImportPhase.js +10 -8
  93. package/lib/dependencies/LoaderPlugin.js +5 -1
  94. package/lib/dependencies/RequireContextDependencyParserPlugin.js +1 -1
  95. package/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js +3 -6
  96. package/lib/dependencies/RequireIncludeDependencyParserPlugin.js +4 -11
  97. package/lib/dependencies/SystemPlugin.js +2 -4
  98. package/lib/dependencies/TopLevelAwaitDependency.js +93 -0
  99. package/lib/dependencies/URLDependency.js +141 -21
  100. package/lib/dependencies/{WorkerPlugin.js → WorkerAndWorkletPlugin.js} +324 -112
  101. package/lib/dependencies/WorkerDependency.js +86 -18
  102. package/lib/dependencies/WorkletDependency.js +278 -0
  103. package/lib/dll/DelegatedModuleFactoryPlugin.js +19 -0
  104. package/lib/errors/EnvironmentNotSupportAsyncWarning.js +1 -1
  105. package/lib/errors/LoaderLoadingError.js +20 -0
  106. package/lib/errors/ModuleParseError.js +39 -22
  107. package/lib/errors/NodeStuffInWebError.js +1 -1
  108. package/lib/esm/ModuleChunkFormatPlugin.js +47 -14
  109. package/lib/esm/ModuleChunkLoadingPlugin.js +8 -1
  110. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +29 -1
  111. package/lib/hmr/lazyCompilationBackend.js +51 -12
  112. package/lib/html/HtmlGenerator.js +907 -15
  113. package/lib/html/HtmlModule.js +2 -2
  114. package/lib/html/HtmlModulesPlugin.js +610 -166
  115. package/lib/html/HtmlParser.js +603 -247
  116. package/lib/html/favicon.svg +1 -0
  117. package/lib/html/syntax.js +3451 -2762
  118. package/lib/ids/IdHelpers.js +25 -11
  119. package/lib/index.js +6 -0
  120. package/lib/javascript/ArrayPushCallbackChunkFormatPlugin.js +4 -5
  121. package/lib/javascript/BasicEvaluatedExpression.js +366 -48
  122. package/lib/javascript/JavascriptGenerator.js +197 -49
  123. package/lib/javascript/JavascriptModulesPlugin.js +178 -24
  124. package/lib/javascript/JavascriptParser.js +704 -355
  125. package/lib/javascript/JavascriptParserHelpers.js +3 -6
  126. package/lib/javascript/syntax.js +5037 -0
  127. package/lib/library/ModuleLibraryPlugin.js +38 -1
  128. package/lib/loaders/LoaderRunner.js +714 -0
  129. package/lib/loaders/loadLoader.js +100 -0
  130. package/lib/node/ReadFileCompileAsyncWasmPlugin.js +29 -2
  131. package/lib/node/ReadFileCompileWasmPlugin.js +24 -2
  132. package/lib/optimize/AggressiveMergingPlugin.js +19 -15
  133. package/lib/optimize/ConcatenatedModule.js +139 -31
  134. package/lib/optimize/FlagIncludedChunksPlugin.js +13 -3
  135. package/lib/optimize/InnerGraphPlugin.js +50 -30
  136. package/lib/optimize/ModuleConcatenationPlugin.js +139 -24
  137. package/lib/optimize/SideEffectsFlagPlugin.js +86 -43
  138. package/lib/optimize/SplitChunksPlugin.js +146 -44
  139. package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +15 -0
  140. package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +24 -13
  141. package/lib/prefetch/ResourceHintPlugin.js +687 -0
  142. package/lib/prefetch/ResourceHintRuntimeModule.js +149 -0
  143. package/lib/prefetch/StartupAssetHintRuntimeModule.js +210 -0
  144. package/lib/prefetch/parseResourceHintOptions.js +103 -0
  145. package/lib/rules/RuleSetCompiler.js +114 -0
  146. package/lib/runtime/AsyncModuleGeneratorRuntimeModule.js +56 -0
  147. package/lib/runtime/AsyncModuleRuntimeModule.js +24 -8
  148. package/lib/runtime/AutoPublicPathRuntimeModule.js +7 -1
  149. package/lib/runtime/CommonJsWrapRuntimeModule.js +37 -0
  150. package/lib/runtime/GetWorkletBootstrapRuntimeModule.js +59 -0
  151. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +204 -8
  152. package/lib/runtime/SetAnonymousDefaultNameRuntimeModule.js +4 -1
  153. package/lib/schemes/HttpUriPlugin.js +40 -1
  154. package/lib/schemes/VirtualUrlPlugin.js +1 -2
  155. package/lib/serialization/BinaryMiddleware.js +270 -938
  156. package/lib/serialization/FileMiddleware.js +29 -3
  157. package/lib/stats/DefaultStatsFactoryPlugin.js +229 -194
  158. package/lib/stats/DefaultStatsPresetPlugin.js +2 -0
  159. package/lib/stats/DefaultStatsPrinterPlugin.js +36 -168
  160. package/lib/stats/StatsFactory.js +46 -17
  161. package/lib/url/URLParserPlugin.js +66 -13
  162. package/lib/util/AsyncQueue.js +122 -72
  163. package/lib/util/SetHelpers.js +1 -1
  164. package/lib/util/StackedMap.js +122 -48
  165. package/lib/util/binarySearchBounds.js +2 -2
  166. package/lib/util/concatenate.js +40 -14
  167. package/lib/util/createHooksRegistry.js +13 -5
  168. package/lib/util/dataURL.js +2 -2
  169. package/lib/util/deterministicGrouping.js +7 -5
  170. package/lib/util/formatSize.js +6 -2
  171. package/lib/util/globUtils.js +710 -0
  172. package/lib/util/identifier.js +23 -6
  173. package/lib/util/implicitTypeLoaderFallback.js +62 -0
  174. package/lib/util/internalSerializables.js +88 -71
  175. package/lib/util/magicComment.js +121 -25
  176. package/lib/util/numberHash.js +2 -2
  177. package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +24 -18
  178. package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +33 -22
  179. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +79 -16
  180. package/lib/web/FetchCompileAsyncWasmPlugin.js +19 -0
  181. package/lib/web/FetchCompileWasmPlugin.js +14 -0
  182. package/lib/web/JsonpChunkLoadingRuntimeModule.js +2 -0
  183. package/lib/webpack.js +65 -0
  184. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +3 -0
  185. package/module.d.ts +21 -0
  186. package/package.json +12 -11
  187. package/schemas/WebpackOptions.check.js +1 -1
  188. package/schemas/WebpackOptions.json +759 -36
  189. package/schemas/plugins/HtmlParserOptions.check.js +1 -1
  190. package/schemas/plugins/ProgressPlugin.check.js +1 -1
  191. package/schemas/plugins/ProgressPlugin.json +17 -1
  192. package/schemas/plugins/container/ContainerReferencePlugin.check.js +1 -1
  193. package/schemas/plugins/container/ContainerReferencePlugin.json +1 -0
  194. package/schemas/plugins/container/ExternalsType.check.js +1 -1
  195. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  196. package/schemas/plugins/container/ModuleFederationPlugin.json +1 -0
  197. package/schemas/plugins/css/CssAutoOrModuleParserOptions.check.js +1 -1
  198. package/schemas/plugins/css/CssModuleParserOptions.check.js +1 -1
  199. package/schemas/plugins/css/CssParserOptions.check.js +1 -1
  200. package/types.d.ts +1212 -99
@@ -13,7 +13,12 @@ const {
13
13
  // eslint-disable-next-line n/no-unsupported-features/node-builtins
14
14
  createBrotliDecompress,
15
15
  createGunzip,
16
- createGzip
16
+ createGzip,
17
+ // zstd is only available on Node.js >= 22.15; guarded at use sites
18
+ // eslint-disable-next-line n/no-unsupported-features/node-builtins
19
+ createZstdCompress,
20
+ // eslint-disable-next-line n/no-unsupported-features/node-builtins
21
+ createZstdDecompress
17
22
  } = require("zlib");
18
23
  const { DEFAULTS } = require("../config/defaults");
19
24
  const createHash = require("../util/createHash");
@@ -378,9 +383,13 @@ const deserialize = async (middleware, name, readFile) => {
378
383
  );
379
384
  result.push(lazy);
380
385
  } else {
386
+ // A section may start exactly at a content-buffer boundary; advance
387
+ // first, then read from the fresh buffer (don't fall through to the
388
+ // `while` below, which would skip it).
381
389
  if (contentPosition === contentItemLength) {
382
390
  nextContent();
383
- } else if (contentPosition !== 0) {
391
+ }
392
+ if (contentPosition !== 0) {
384
393
  if (length <= contentItemLength - contentPosition) {
385
394
  result.push(
386
395
  Buffer.from(
@@ -490,7 +499,7 @@ class FileMiddleware extends SerializerMiddleware {
490
499
  */
491
500
  (resolve, reject) => {
492
501
  let stream = this.fs.createWriteStream(`${file}_`);
493
- /** @type {undefined | import("zlib").Gzip | import("zlib").BrotliCompress} */
502
+ /** @type {undefined | import("zlib").Gzip | import("zlib").BrotliCompress | import("zlib").ZstdCompress} */
494
503
  let compression;
495
504
  if (file.endsWith(".gz")) {
496
505
  compression = createGzip({
@@ -507,6 +516,17 @@ class FileMiddleware extends SerializerMiddleware {
507
516
  [zConstants.BROTLI_PARAM_SIZE_HINT]: size
508
517
  }
509
518
  });
519
+ } else if (file.endsWith(".zst")) {
520
+ // eslint-disable-next-line n/no-unsupported-features/node-builtins
521
+ const levelParam = zConstants.ZSTD_c_compressionLevel;
522
+ // default level 3; some runtimes (e.g. Deno) don't expose ZSTD_CLEVEL_DEFAULT
523
+ // eslint-disable-next-line n/no-unsupported-features/node-builtins
524
+ const defaultLevel = zConstants.ZSTD_CLEVEL_DEFAULT;
525
+ const level = defaultLevel === undefined ? 3 : defaultLevel;
526
+ compression = createZstdCompress({
527
+ chunkSize: COMPRESSION_CHUNK_SIZE,
528
+ params: { [levelParam]: level }
529
+ });
510
530
  }
511
531
  if (compression) {
512
532
  pipeline(compression, stream, reject);
@@ -666,6 +686,10 @@ class FileMiddleware extends SerializerMiddleware {
666
686
  decompression = createBrotliDecompress({
667
687
  chunkSize: DECOMPRESSION_CHUNK_SIZE
668
688
  });
689
+ } else if (file.endsWith(".zst")) {
690
+ decompression = createZstdDecompress({
691
+ chunkSize: DECOMPRESSION_CHUNK_SIZE
692
+ });
669
693
  }
670
694
  if (decompression) {
671
695
  /** @typedef {(value: Buffer[] | PromiseLike<Buffer[]>) => void} NewResolve */
@@ -785,3 +809,5 @@ class FileMiddleware extends SerializerMiddleware {
785
809
  }
786
810
 
787
811
  module.exports = FileMiddleware;
812
+ // Exposed for testing the content-buffer boundary handling in `deserialize`.
813
+ module.exports._deserialize = deserialize;
@@ -47,6 +47,7 @@ const { makePathsRelative, parseResource } = require("../util/identifier");
47
47
  /** @typedef {import("../Module")} Module */
48
48
  /** @typedef {import("../Module").NameForCondition} NameForCondition */
49
49
  /** @typedef {import("../Module").BuildInfo} BuildInfo */
50
+ /** @typedef {import("../ModuleGraph")} ModuleGraph */
50
51
  /** @typedef {import("../ModuleGraphConnection")} ModuleGraphConnection */
51
52
  /** @typedef {import("../ModuleProfile")} ModuleProfile */
52
53
  /** @typedef {import("../errors/WebpackError")} WebpackError */
@@ -176,6 +177,7 @@ const { makePathsRelative, parseResource } = require("../util/identifier");
176
177
  * @property {number=} size
177
178
  * @property {Record<string, number>=} sizes
178
179
  * @property {boolean=} cacheable
180
+ * @property {string[]=} notCacheableReasons
179
181
  * @property {boolean=} built
180
182
  * @property {boolean=} codeGenerated
181
183
  * @property {boolean=} buildTimeExecuted
@@ -833,22 +835,24 @@ const SIMPLE_EXTRACTORS = {
833
835
  }
834
836
 
835
837
  object.assetsByChunkName = {};
836
- for (const [file, chunks] of [
837
- ...compilationFileToChunks,
838
- ...compilationAuxiliaryFileToChunks
838
+ for (const fileToChunks of [
839
+ compilationFileToChunks,
840
+ compilationAuxiliaryFileToChunks
839
841
  ]) {
840
- for (const chunk of chunks) {
841
- const name = chunk.name;
842
- if (!name) continue;
843
- if (
844
- !Object.prototype.hasOwnProperty.call(
845
- object.assetsByChunkName,
846
- name
847
- )
848
- ) {
849
- object.assetsByChunkName[name] = [];
842
+ for (const [file, chunks] of fileToChunks) {
843
+ for (const chunk of chunks) {
844
+ const name = chunk.name;
845
+ if (!name) continue;
846
+ if (
847
+ !Object.prototype.hasOwnProperty.call(
848
+ object.assetsByChunkName,
849
+ name
850
+ )
851
+ ) {
852
+ object.assetsByChunkName[name] = [];
853
+ }
854
+ object.assetsByChunkName[name].push(file);
850
855
  }
851
- object.assetsByChunkName[name].push(file);
852
856
  }
853
857
  }
854
858
 
@@ -1244,6 +1248,25 @@ const SIMPLE_EXTRACTORS = {
1244
1248
  },
1245
1249
  performance: (object, { chunkGroup }) => {
1246
1250
  object.isOverSizeLimit = SizeLimitsPlugin.isOverSizeLimit(chunkGroup);
1251
+ },
1252
+ chunkGroupResourceHints: (
1253
+ object,
1254
+ { name, chunkGroup },
1255
+ { compilation }
1256
+ ) => {
1257
+ // SSR frameworks consume this to inject the initial-chunk +
1258
+ // URL-asset `<link>` tags into their server-rendered HTML without
1259
+ // having to walk the chunk graph themselves. Only entrypoints
1260
+ // carry hints; split-chunk / async chunk groups are skipped.
1261
+ if (!compilation.entrypoints.get(name)) return;
1262
+
1263
+ const ResourceHintPlugin = require("../prefetch/ResourceHintPlugin");
1264
+
1265
+ const hints =
1266
+ ResourceHintPlugin.getCompilationResolver(
1267
+ compilation
1268
+ ).getEntrypointHints(name);
1269
+ if (hints.length > 0) object.resourceHints = hints;
1247
1270
  }
1248
1271
  },
1249
1272
  module: {
@@ -1259,19 +1282,16 @@ const SIMPLE_EXTRACTORS = {
1259
1282
  for (const sourceType of module.getSourceTypes()) {
1260
1283
  sizes[sourceType] = module.size(sourceType);
1261
1284
  }
1262
- /** @type {KnownStatsModule} */
1263
- const statsModule = {
1264
- type: "module",
1265
- moduleType: module.type,
1266
- layer: module.layer,
1267
- size: module.size(),
1268
- sizes,
1269
- built,
1270
- codeGenerated,
1271
- buildTimeExecuted,
1272
- cached: !built && !codeGenerated
1273
- };
1274
- Object.assign(object, statsModule);
1285
+ // assign fields directly to avoid an intermediate object + copy per module
1286
+ object.type = "module";
1287
+ object.moduleType = module.type;
1288
+ object.layer = module.layer;
1289
+ object.size = module.size();
1290
+ object.sizes = sizes;
1291
+ object.built = built;
1292
+ object.codeGenerated = codeGenerated;
1293
+ object.buildTimeExecuted = buildTimeExecuted;
1294
+ object.cached = !built && !codeGenerated;
1275
1295
  if (built || codeGenerated || options.cachedModules) {
1276
1296
  Object.assign(
1277
1297
  object,
@@ -1300,36 +1320,43 @@ const SIMPLE_EXTRACTORS = {
1300
1320
  const warnings = module.getWarnings();
1301
1321
  const warningsCount =
1302
1322
  warnings !== undefined ? countIterable(warnings) : 0;
1303
- /** @type {KnownStatsModule} */
1304
- const statsModule = {
1305
- identifier: module.identifier(),
1306
- name: module.readableIdentifier(requestShortener),
1307
- nameForCondition: module.nameForCondition(),
1308
- index: /** @type {number} */ (moduleGraph.getPreOrderIndex(module)),
1309
- preOrderIndex: /** @type {number} */ (
1310
- moduleGraph.getPreOrderIndex(module)
1311
- ),
1312
- index2: /** @type {number} */ (moduleGraph.getPostOrderIndex(module)),
1313
- postOrderIndex: /** @type {number} */ (
1314
- moduleGraph.getPostOrderIndex(module)
1315
- ),
1316
- cacheable: /** @type {BuildInfo} */ (module.buildInfo).cacheable,
1317
- optional: module.isOptional(moduleGraph),
1318
- orphan:
1319
- !type.endsWith("module.modules[].module$visible") &&
1320
- compilation.chunkGraph.getNumberOfModuleChunks(module) === 0,
1321
- dependent: rootModules ? !rootModules.has(module) : undefined,
1322
- issuer: issuer && issuer.identifier(),
1323
- issuerName: issuer && issuer.readableIdentifier(requestShortener),
1324
- issuerPath:
1325
- issuer &&
1326
- /** @type {StatsModuleIssuer[] | undefined} */
1327
- (factory.create(`${type.slice(0, -8)}.issuerPath`, path, context)),
1328
- failed: errorsCount > 0,
1329
- errors: errorsCount,
1330
- warnings: warningsCount
1331
- };
1332
- Object.assign(object, statsModule);
1323
+ const { cacheable, notCacheableReasons } = /** @type {BuildInfo} */ (
1324
+ module.buildInfo
1325
+ );
1326
+ const preOrderIndex = /** @type {number} */ (
1327
+ moduleGraph.getPreOrderIndex(module)
1328
+ );
1329
+ const postOrderIndex = /** @type {number} */ (
1330
+ moduleGraph.getPostOrderIndex(module)
1331
+ );
1332
+ // assign fields directly to avoid an intermediate object + copy per module
1333
+ object.identifier = module.identifier();
1334
+ object.name = module.readableIdentifier(requestShortener);
1335
+ object.nameForCondition = module.nameForCondition();
1336
+ object.index = preOrderIndex;
1337
+ object.preOrderIndex = preOrderIndex;
1338
+ object.index2 = postOrderIndex;
1339
+ object.postOrderIndex = postOrderIndex;
1340
+ object.cacheable = cacheable;
1341
+ object.notCacheableReasons =
1342
+ notCacheableReasons &&
1343
+ notCacheableReasons.map(
1344
+ (request) => /** @type {string} */ (requestShortener.shorten(request))
1345
+ );
1346
+ object.optional = module.isOptional(moduleGraph);
1347
+ object.orphan =
1348
+ !type.endsWith("module.modules[].module$visible") &&
1349
+ compilation.chunkGraph.getNumberOfModuleChunks(module) === 0;
1350
+ object.dependent = rootModules ? !rootModules.has(module) : undefined;
1351
+ object.issuer = issuer && issuer.identifier();
1352
+ object.issuerName = issuer && issuer.readableIdentifier(requestShortener);
1353
+ object.issuerPath =
1354
+ issuer &&
1355
+ /** @type {StatsModuleIssuer[] | undefined} */
1356
+ (factory.create(`${type.slice(0, -8)}.issuerPath`, path, context));
1357
+ object.failed = errorsCount > 0;
1358
+ object.errors = errorsCount;
1359
+ object.warnings = warningsCount;
1333
1360
  if (profile) {
1334
1361
  object.profile = factory.create(
1335
1362
  `${type.slice(0, -8)}.profile`,
@@ -1441,27 +1468,24 @@ const SIMPLE_EXTRACTORS = {
1441
1468
  },
1442
1469
  profile: {
1443
1470
  _: (object, profile) => {
1444
- /** @type {KnownStatsProfile} */
1445
- const statsProfile = {
1446
- total:
1447
- profile.factory +
1448
- profile.restoring +
1449
- profile.integration +
1450
- profile.building +
1451
- profile.storing,
1452
- resolving: profile.factory,
1453
- restoring: profile.restoring,
1454
- building: profile.building,
1455
- integration: profile.integration,
1456
- storing: profile.storing,
1457
- additionalResolving: profile.additionalFactories,
1458
- additionalIntegration: profile.additionalIntegration,
1459
- // TODO remove this in webpack 6
1460
- factory: profile.factory,
1461
- // TODO remove this in webpack 6
1462
- dependencies: profile.additionalFactories
1463
- };
1464
- Object.assign(object, statsProfile);
1471
+ // assign fields directly to avoid an intermediate object + copy
1472
+ object.total =
1473
+ profile.factory +
1474
+ profile.restoring +
1475
+ profile.integration +
1476
+ profile.building +
1477
+ profile.storing;
1478
+ object.resolving = profile.factory;
1479
+ object.restoring = profile.restoring;
1480
+ object.building = profile.building;
1481
+ object.integration = profile.integration;
1482
+ object.storing = profile.storing;
1483
+ object.additionalResolving = profile.additionalFactories;
1484
+ object.additionalIntegration = profile.additionalIntegration;
1485
+ // TODO remove this in webpack 6
1486
+ object.factory = profile.factory;
1487
+ // TODO remove this in webpack 6
1488
+ object.dependencies = profile.additionalFactories;
1465
1489
  }
1466
1490
  },
1467
1491
  moduleIssuer: {
@@ -1470,12 +1494,9 @@ const SIMPLE_EXTRACTORS = {
1470
1494
  const compilation = /** @type {Compilation} */ (context.compilation);
1471
1495
  const { moduleGraph } = compilation;
1472
1496
  const profile = moduleGraph.getProfile(module);
1473
- /** @type {Partial<KnownStatsModuleIssuer>} */
1474
- const statsModuleIssuer = {
1475
- identifier: module.identifier(),
1476
- name: module.readableIdentifier(requestShortener)
1477
- };
1478
- Object.assign(object, statsModuleIssuer);
1497
+ // assign fields directly to avoid an intermediate object + copy per issuer
1498
+ object.identifier = module.identifier();
1499
+ object.name = module.readableIdentifier(requestShortener);
1479
1500
  if (profile) {
1480
1501
  object.profile = factory.create(`${type}.profile`, profile, context);
1481
1502
  }
@@ -1489,31 +1510,26 @@ const SIMPLE_EXTRACTORS = {
1489
1510
  const dep = reason.dependency;
1490
1511
  const moduleDep =
1491
1512
  dep && dep instanceof ModuleDependency ? dep : undefined;
1492
- /** @type {KnownStatsModuleReason} */
1493
- const statsModuleReason = {
1494
- moduleIdentifier: reason.originModule
1495
- ? reason.originModule.identifier()
1496
- : null,
1497
- module: reason.originModule
1498
- ? reason.originModule.readableIdentifier(requestShortener)
1499
- : null,
1500
- moduleName: reason.originModule
1501
- ? reason.originModule.readableIdentifier(requestShortener)
1502
- : null,
1503
- resolvedModuleIdentifier: reason.resolvedOriginModule
1504
- ? reason.resolvedOriginModule.identifier()
1505
- : null,
1506
- resolvedModule: reason.resolvedOriginModule
1507
- ? reason.resolvedOriginModule.readableIdentifier(requestShortener)
1508
- : null,
1509
- type: reason.dependency ? reason.dependency.type : null,
1510
- active: reason.isActive(runtime),
1511
- explanation: reason.explanation,
1512
- userRequest: (moduleDep && moduleDep.userRequest) || null
1513
- };
1514
- Object.assign(object, statsModuleReason);
1515
- if (reason.dependency) {
1516
- const locInfo = formatLocation(reason.dependency.loc);
1513
+ const { originModule, resolvedOriginModule } = reason;
1514
+ const originName = originModule
1515
+ ? originModule.readableIdentifier(requestShortener)
1516
+ : null;
1517
+ // assign fields directly to avoid an intermediate object + copy per reason
1518
+ object.moduleIdentifier = originModule ? originModule.identifier() : null;
1519
+ object.module = originName;
1520
+ object.moduleName = originName;
1521
+ object.resolvedModuleIdentifier = resolvedOriginModule
1522
+ ? resolvedOriginModule.identifier()
1523
+ : null;
1524
+ object.resolvedModule = resolvedOriginModule
1525
+ ? resolvedOriginModule.readableIdentifier(requestShortener)
1526
+ : null;
1527
+ object.type = dep ? dep.type : null;
1528
+ object.active = reason.isActive(runtime);
1529
+ object.explanation = reason.explanation;
1530
+ object.userRequest = (moduleDep && moduleDep.userRequest) || null;
1531
+ if (dep) {
1532
+ const locInfo = formatLocation(dep.loc);
1517
1533
  if (locInfo) {
1518
1534
  object.loc = locInfo;
1519
1535
  }
@@ -1532,29 +1548,26 @@ const SIMPLE_EXTRACTORS = {
1532
1548
  _: (object, chunk, { makePathsRelative, compilation: { chunkGraph } }) => {
1533
1549
  const childIdByOrder = chunk.getChildIdsByOrders(chunkGraph);
1534
1550
 
1535
- /** @type {KnownStatsChunk} */
1536
- const statsChunk = {
1537
- rendered: chunk.rendered,
1538
- initial: chunk.canBeInitial(),
1539
- entry: chunk.hasRuntime(),
1540
- recorded: AggressiveSplittingPlugin.wasChunkRecorded(chunk),
1541
- reason: chunk.chunkReason,
1542
- size: chunkGraph.getChunkModulesSize(chunk),
1543
- sizes: chunkGraph.getChunkModulesSizes(chunk),
1544
- names: chunk.name ? [chunk.name] : [],
1545
- idHints: [...chunk.idNameHints],
1546
- runtime:
1547
- chunk.runtime === undefined
1548
- ? undefined
1549
- : typeof chunk.runtime === "string"
1550
- ? [makePathsRelative(chunk.runtime)]
1551
- : Array.from(chunk.runtime.sort(), makePathsRelative),
1552
- files: [...chunk.files],
1553
- auxiliaryFiles: [...chunk.auxiliaryFiles].sort(compareIds),
1554
- hash: /** @type {string} */ (chunk.renderedHash),
1555
- childrenByOrder: childIdByOrder
1556
- };
1557
- Object.assign(object, statsChunk);
1551
+ // assign fields directly to avoid an intermediate object + copy per chunk
1552
+ object.rendered = chunk.rendered;
1553
+ object.initial = chunk.canBeInitial();
1554
+ object.entry = chunk.hasRuntime();
1555
+ object.recorded = AggressiveSplittingPlugin.wasChunkRecorded(chunk);
1556
+ object.reason = chunk.chunkReason;
1557
+ object.size = chunkGraph.getChunkModulesSize(chunk);
1558
+ object.sizes = chunkGraph.getChunkModulesSizes(chunk);
1559
+ object.names = chunk.name ? [chunk.name] : [];
1560
+ object.idHints = [...chunk.idNameHints];
1561
+ object.runtime =
1562
+ chunk.runtime === undefined
1563
+ ? undefined
1564
+ : typeof chunk.runtime === "string"
1565
+ ? [makePathsRelative(chunk.runtime)]
1566
+ : Array.from(chunk.runtime.sort(), makePathsRelative);
1567
+ object.files = [...chunk.files];
1568
+ object.auxiliaryFiles = [...chunk.auxiliaryFiles].sort(compareIds);
1569
+ object.hash = /** @type {string} */ (chunk.renderedHash);
1570
+ object.childrenByOrder = childIdByOrder;
1558
1571
  },
1559
1572
  ids: (object, chunk) => {
1560
1573
  object.id = /** @type {ChunkId} */ (chunk.id);
@@ -1631,17 +1644,16 @@ const SIMPLE_EXTRACTORS = {
1631
1644
  },
1632
1645
  chunkOrigin: {
1633
1646
  _: (object, origin, context, { requestShortener }) => {
1634
- /** @type {KnownStatsChunkOrigin} */
1635
- const statsChunkOrigin = {
1636
- module: origin.module ? origin.module.identifier() : "",
1637
- moduleIdentifier: origin.module ? origin.module.identifier() : "",
1638
- moduleName: origin.module
1639
- ? origin.module.readableIdentifier(requestShortener)
1640
- : "",
1641
- loc: formatLocation(origin.loc),
1642
- request: origin.request
1643
- };
1644
- Object.assign(object, statsChunkOrigin);
1647
+ const originModule = origin.module;
1648
+ const identifier = originModule ? originModule.identifier() : "";
1649
+ // assign fields directly to avoid an intermediate object + copy per origin
1650
+ object.module = identifier;
1651
+ object.moduleIdentifier = identifier;
1652
+ object.moduleName = originModule
1653
+ ? originModule.readableIdentifier(requestShortener)
1654
+ : "";
1655
+ object.loc = formatLocation(origin.loc);
1656
+ object.request = origin.request;
1645
1657
  },
1646
1658
  ids: (object, origin, { compilation: { chunkGraph } }) => {
1647
1659
  object.moduleId = origin.module
@@ -1662,13 +1674,16 @@ const SIMPLE_EXTRACTORS = {
1662
1674
  object.originName = origin.readableIdentifier(requestShortener);
1663
1675
  object.moduleIdentifier = module.identifier();
1664
1676
  object.moduleName = module.readableIdentifier(requestShortener);
1665
- const dependencies = [...moduleGraph.getIncomingConnections(module)]
1666
- .filter((c) => c.resolvedOriginModule === origin && c.dependency)
1667
- .map((c) => c.dependency);
1677
+ /** @type {Set<Dependency>} */
1678
+ const dependencies = new Set();
1679
+ for (const c of moduleGraph.getIncomingConnections(module)) {
1680
+ if (c.resolvedOriginModule === origin && c.dependency) {
1681
+ dependencies.add(c.dependency);
1682
+ }
1683
+ }
1668
1684
  object.dependencies = factory.create(
1669
1685
  `${type}.dependencies`,
1670
- /** @type {Dependency[]} */
1671
- ([...new Set(dependencies)]),
1686
+ [...dependencies],
1672
1687
  context
1673
1688
  );
1674
1689
  },
@@ -1720,17 +1735,50 @@ const FILTER_RESULTS = {
1720
1735
  }
1721
1736
  };
1722
1737
 
1738
+ // module sort selectors close over moduleGraph, so cache the built comparators per
1739
+ // moduleGraph (stable per compilation) instead of rebuilding them on every sort
1740
+ /** @type {WeakMap<ModuleGraph, Comparator<Module>[]>} */
1741
+ const modulesSorterCache = new WeakMap();
1742
+
1723
1743
  /** @type {Record<string, (comparators: Comparator<Module>[], context: StatsFactoryContext) => void>} */
1724
1744
  const MODULES_SORTER = {
1725
1745
  _: (comparators, { compilation: { moduleGraph } }) => {
1726
- comparators.push(
1727
- compareSelect((m) => moduleGraph.getDepth(m), compareNumbers),
1728
- compareSelect((m) => moduleGraph.getPreOrderIndex(m), compareNumbers),
1729
- compareSelect((m) => m.identifier(), compareIds)
1730
- );
1746
+ let cached = modulesSorterCache.get(moduleGraph);
1747
+ if (cached === undefined) {
1748
+ cached = [
1749
+ compareSelect((m) => moduleGraph.getDepth(m), compareNumbers),
1750
+ compareSelect((m) => moduleGraph.getPreOrderIndex(m), compareNumbers),
1751
+ compareSelect((m) => m.identifier(), compareIds)
1752
+ ];
1753
+ modulesSorterCache.set(moduleGraph, cached);
1754
+ }
1755
+ comparators.push(...cached);
1731
1756
  }
1732
1757
  };
1733
1758
 
1759
+ // reason comparators use only pure selectors, so build them once instead of per
1760
+ // module.reasons sort (which runs once per module and otherwise thrashes the caches)
1761
+ /** @type {Comparator<ModuleGraphConnection>[]} */
1762
+ const MODULE_REASONS_COMPARATORS = [
1763
+ compareSelect((x) => x.originModule, compareModulesByIdentifier),
1764
+ compareSelect((x) => x.resolvedOriginModule, compareModulesByIdentifier),
1765
+ compareSelect(
1766
+ (x) => x.dependency,
1767
+ concatComparators(
1768
+ compareSelect(
1769
+ /**
1770
+ * Handles the callback for this hook.
1771
+ * @param {Dependency} x dependency
1772
+ * @returns {DependencyLocation} location
1773
+ */
1774
+ (x) => x.loc,
1775
+ compareLocations
1776
+ ),
1777
+ compareSelect((x) => x.type, compareIds)
1778
+ )
1779
+ )
1780
+ ];
1781
+
1734
1782
  /**
1735
1783
  * @type {{
1736
1784
  * "compilation.chunks": Record<string, (comparators: Comparator<Chunk>[], context: StatsFactoryContext, options: NormalizedStatsOptions) => void>,
@@ -1753,30 +1801,8 @@ const SORTERS = {
1753
1801
  "chunk.modules": MODULES_SORTER,
1754
1802
  "module.modules": MODULES_SORTER,
1755
1803
  "module.reasons": {
1756
- _: (comparators, _context) => {
1757
- comparators.push(
1758
- compareSelect((x) => x.originModule, compareModulesByIdentifier)
1759
- );
1760
- comparators.push(
1761
- compareSelect((x) => x.resolvedOriginModule, compareModulesByIdentifier)
1762
- );
1763
- comparators.push(
1764
- compareSelect(
1765
- (x) => x.dependency,
1766
- concatComparators(
1767
- compareSelect(
1768
- /**
1769
- * Handles the callback for this hook.
1770
- * @param {Dependency} x dependency
1771
- * @returns {DependencyLocation} location
1772
- */
1773
- (x) => x.loc,
1774
- compareLocations
1775
- ),
1776
- compareSelect((x) => x.type, compareIds)
1777
- )
1778
- )
1779
- );
1804
+ _: (comparators) => {
1805
+ comparators.push(...MODULE_REASONS_COMPARATORS);
1780
1806
  }
1781
1807
  },
1782
1808
  "chunk.origins": {
@@ -2050,7 +2076,7 @@ const errorsSpaceLimit = (errors, max) => {
2050
2076
  for (; i < errors.length; i++) {
2051
2077
  const error = errors[i];
2052
2078
  if (typeof error === "string" || !error.details) result.push(error);
2053
- result.push({ ...error, details: "" });
2079
+ else result.push({ ...error, details: "" });
2054
2080
  }
2055
2081
  break;
2056
2082
  } else if (fullLength === max) {
@@ -2059,7 +2085,7 @@ const errorsSpaceLimit = (errors, max) => {
2059
2085
  for (; i < errors.length; i++) {
2060
2086
  const error = errors[i];
2061
2087
  if (typeof error === "string" || !error.details) result.push(error);
2062
- result.push({ ...error, details: "" });
2088
+ else result.push({ ...error, details: "" });
2063
2089
  }
2064
2090
  break;
2065
2091
  }
@@ -2559,6 +2585,17 @@ const sortOrderRegular = (field) => {
2559
2585
  return true;
2560
2586
  };
2561
2587
 
2588
+ /**
2589
+ * Returns zero.
2590
+ * @param {EXPECTED_ANY} a first
2591
+ * @param {EXPECTED_ANY} b second
2592
+ * @returns {-1 | 0 | 1} zero
2593
+ */
2594
+ const noSort = (a, b) => 0;
2595
+
2596
+ /** @type {Map<string, (a: EXPECTED_ANY, b: EXPECTED_ANY) => 0 | 1 | -1>} */
2597
+ const sortByFieldCache = new Map();
2598
+
2562
2599
  /**
2563
2600
  * Returns comparators.
2564
2601
  * @template T
@@ -2566,29 +2603,24 @@ const sortOrderRegular = (field) => {
2566
2603
  * @returns {(a: T, b: T) => 0 | 1 | -1} comparators
2567
2604
  */
2568
2605
  const sortByField = (field) => {
2569
- if (!field) {
2570
- /**
2571
- * Returns zero.
2572
- * @param {T} a first
2573
- * @param {T} b second
2574
- * @returns {-1 | 0 | 1} zero
2575
- */
2576
- const noSort = (a, b) => 0;
2577
- return noSort;
2578
- }
2606
+ if (!field) return noSort;
2607
+
2608
+ // memoize per field: the comparator (and its selector) is pure, so building it
2609
+ // once keeps compareSelect's cache warm instead of allocating a new entry per sort
2610
+ let sortFn = sortByFieldCache.get(field);
2611
+ if (sortFn !== undefined) return sortFn;
2579
2612
 
2580
2613
  const fieldKey = normalizeFieldKey(field);
2581
2614
 
2582
- let sortFn = compareSelect((m) => m[fieldKey], compareIds);
2615
+ sortFn = compareSelect((m) => m[fieldKey], compareIds);
2583
2616
 
2584
2617
  // if a field is prefixed with a "!" the sort is reversed!
2585
- const sortIsRegular = sortOrderRegular(field);
2586
-
2587
- if (!sortIsRegular) {
2618
+ if (!sortOrderRegular(field)) {
2588
2619
  const oldSortFn = sortFn;
2589
2620
  sortFn = (a, b) => oldSortFn(b, a);
2590
2621
  }
2591
2622
 
2623
+ sortByFieldCache.set(field, sortFn);
2592
2624
  return sortFn;
2593
2625
  };
2594
2626
 
@@ -2600,13 +2632,16 @@ const sortByField = (field) => {
2600
2632
  * }} AssetSorters
2601
2633
  */
2602
2634
 
2635
+ /** @type {Comparator<Asset>} */
2636
+ const compareAssetsByName = compareSelect((asset) => asset.name, compareIds);
2637
+
2603
2638
  /** @type {AssetSorters} */
2604
2639
  const ASSET_SORTERS = {
2605
2640
  assetsSort: (comparators, context, { assetsSort }) => {
2606
2641
  comparators.push(sortByField(assetsSort));
2607
2642
  },
2608
2643
  _: (comparators) => {
2609
- comparators.push(compareSelect((a) => a.name, compareIds));
2644
+ comparators.push(compareAssetsByName);
2610
2645
  }
2611
2646
  };
2612
2647
 
@@ -41,6 +41,7 @@ const NAMED_PRESETS = {
41
41
  relatedAssets: true,
42
42
  entrypoints: true,
43
43
  chunkGroups: true,
44
+ chunkGroupResourceHints: true,
44
45
  ids: true,
45
46
  modules: false,
46
47
  chunks: true,
@@ -210,6 +211,7 @@ const DEFAULTS = {
210
211
  chunkGroups: OFF_FOR_TO_STRING,
211
212
  chunkGroupAuxiliary: OFF_FOR_TO_STRING,
212
213
  chunkGroupChildren: OFF_FOR_TO_STRING,
214
+ chunkGroupResourceHints: OFF_FOR_TO_STRING,
213
215
  chunkGroupMaxAssets: (o, { forToString }) => (forToString ? 5 : Infinity),
214
216
  chunks: OFF_FOR_TO_STRING,
215
217
  chunkRelations: OFF_FOR_TO_STRING,