webpack 5.108.4 → 5.109.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.
Files changed (186) hide show
  1. package/lib/APIPlugin.js +48 -29
  2. package/lib/CacheFacade.js +8 -0
  3. package/lib/ChunkGroup.js +1 -0
  4. package/lib/CompatibilityPlugin.js +31 -29
  5. package/lib/Compilation.js +49 -4
  6. package/lib/ConstPlugin.js +11 -11
  7. package/lib/ContextModule.js +239 -6
  8. package/lib/ContextModuleFactory.js +139 -14
  9. package/lib/DefinePlugin.js +396 -101
  10. package/lib/Entrypoint.js +1 -1
  11. package/lib/ExportsInfoApiPlugin.js +2 -2
  12. package/lib/ExternalModule.js +107 -5
  13. package/lib/ExternalModuleFactoryPlugin.js +20 -1
  14. package/lib/FileSystemInfo.js +130 -74
  15. package/lib/HotModuleReplacementPlugin.js +18 -15
  16. package/lib/Module.js +3 -0
  17. package/lib/ModuleFilenameHelpers.js +2 -2
  18. package/lib/ModuleTypeConstants.js +8 -1
  19. package/lib/MultiCompiler.js +13 -2
  20. package/lib/MultiWatching.js +1 -0
  21. package/lib/NodeStuffPlugin.js +51 -33
  22. package/lib/NormalModule.js +169 -401
  23. package/lib/NormalModuleFactory.js +76 -2
  24. package/lib/ProgressPlugin.js +211 -119
  25. package/lib/ProvidePlugin.js +2 -2
  26. package/lib/RuntimeGlobals.js +47 -0
  27. package/lib/RuntimePlugin.js +33 -0
  28. package/lib/RuntimeTemplate.js +304 -16
  29. package/lib/UseStrictPlugin.js +1 -1
  30. package/lib/WebpackIsIncludedPlugin.js +1 -1
  31. package/lib/WebpackOptionsApply.js +24 -19
  32. package/lib/asset/AssetGenerator.js +110 -28
  33. package/lib/asset/AssetModulesPlugin.js +92 -2
  34. package/lib/asset/WebManifestGenerator.js +164 -0
  35. package/lib/asset/WebManifestParser.js +130 -0
  36. package/lib/async-modules/AwaitDependenciesInitFragment.js +14 -4
  37. package/lib/async-modules/isGeneratorLowered.js +26 -0
  38. package/lib/cache/PackFileCacheStrategy.js +9 -3
  39. package/lib/config/browserslistTargetHandler.js +40 -0
  40. package/lib/config/defaults.js +219 -29
  41. package/lib/config/normalization.js +26 -0
  42. package/lib/config/target.js +9 -1
  43. package/lib/css/CssGenerator.js +40 -31
  44. package/lib/css/CssLoadingRuntimeModule.js +5 -1
  45. package/lib/css/CssModulesPlugin.js +13 -0
  46. package/lib/css/CssParser.js +594 -263
  47. package/lib/css/syntax.js +875 -462
  48. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +6 -6
  49. package/lib/dependencies/AMDPlugin.js +2 -2
  50. package/lib/dependencies/AMDRequireDependenciesBlockParserPlugin.js +13 -13
  51. package/lib/dependencies/CommonJsDependencyHelpers.js +39 -0
  52. package/lib/dependencies/CommonJsExportsDependency.js +47 -2
  53. package/lib/dependencies/CommonJsExportsParserPlugin.js +10 -10
  54. package/lib/dependencies/CommonJsImportsParserPlugin.js +18 -18
  55. package/lib/dependencies/CommonJsPlugin.js +2 -2
  56. package/lib/dependencies/CommonJsRequireDependency.js +26 -1
  57. package/lib/dependencies/CommonJsSelfReferenceDependency.js +32 -1
  58. package/lib/dependencies/ContextDependencyHelpers.js +3 -3
  59. package/lib/dependencies/CreateRequireParserPlugin.js +6 -6
  60. package/lib/dependencies/CssIcssExportDependency.js +162 -71
  61. package/lib/dependencies/CssUrlDependency.js +35 -4
  62. package/lib/dependencies/ExternalModuleInitFragmentDependency.js +2 -2
  63. package/lib/dependencies/HarmonyCompatibilityDependency.js +32 -14
  64. package/lib/dependencies/HarmonyDetectionParserPlugin.js +43 -13
  65. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +7 -19
  66. package/lib/dependencies/HarmonyImportDependency.js +12 -1
  67. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +11 -11
  68. package/lib/dependencies/HarmonyModulesPlugin.js +6 -0
  69. package/lib/dependencies/HarmonyTopLevelThisParserPlugin.js +1 -1
  70. package/lib/dependencies/HtmlEntryDependency.js +797 -172
  71. package/lib/dependencies/HtmlSourceDependency.js +26 -0
  72. package/lib/dependencies/ImportDependency.js +43 -1
  73. package/lib/dependencies/ImportMetaContextDependencyParserPlugin.js +31 -18
  74. package/lib/dependencies/ImportMetaContextPlugin.js +38 -7
  75. package/lib/dependencies/ImportMetaGlobDependency.js +81 -0
  76. package/lib/dependencies/ImportMetaGlobDependencyParserPlugin.js +78 -0
  77. package/lib/dependencies/ImportMetaGlobHelpers.js +660 -0
  78. package/lib/dependencies/ImportMetaPlugin.js +532 -180
  79. package/lib/dependencies/ImportMetaResolveDependency.js +90 -0
  80. package/lib/dependencies/ImportParserPlugin.js +80 -17
  81. package/lib/dependencies/ImportPhase.js +10 -8
  82. package/lib/dependencies/LoaderPlugin.js +5 -1
  83. package/lib/dependencies/RequireContextDependencyParserPlugin.js +1 -1
  84. package/lib/dependencies/RequireEnsureDependenciesBlockParserPlugin.js +3 -6
  85. package/lib/dependencies/RequireIncludeDependencyParserPlugin.js +4 -11
  86. package/lib/dependencies/SystemPlugin.js +2 -4
  87. package/lib/dependencies/TopLevelAwaitDependency.js +93 -0
  88. package/lib/dependencies/URLDependency.js +141 -21
  89. package/lib/dependencies/{WorkerPlugin.js → WorkerAndWorkletPlugin.js} +324 -112
  90. package/lib/dependencies/WorkerDependency.js +86 -18
  91. package/lib/dependencies/WorkletDependency.js +278 -0
  92. package/lib/dll/DelegatedModuleFactoryPlugin.js +19 -0
  93. package/lib/errors/EnvironmentNotSupportAsyncWarning.js +1 -1
  94. package/lib/errors/LoaderLoadingError.js +20 -0
  95. package/lib/errors/ModuleParseError.js +39 -22
  96. package/lib/errors/NodeStuffInWebError.js +1 -1
  97. package/lib/esm/ModuleChunkFormatPlugin.js +47 -14
  98. package/lib/esm/ModuleChunkLoadingPlugin.js +8 -1
  99. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +29 -1
  100. package/lib/hmr/lazyCompilationBackend.js +32 -8
  101. package/lib/html/HtmlGenerator.js +887 -15
  102. package/lib/html/HtmlModule.js +2 -2
  103. package/lib/html/HtmlModulesPlugin.js +610 -166
  104. package/lib/html/HtmlParser.js +603 -247
  105. package/lib/html/favicon.svg +1 -0
  106. package/lib/html/syntax.js +1264 -661
  107. package/lib/ids/IdHelpers.js +1 -1
  108. package/lib/index.js +6 -0
  109. package/lib/javascript/ArrayPushCallbackChunkFormatPlugin.js +4 -5
  110. package/lib/javascript/BasicEvaluatedExpression.js +366 -48
  111. package/lib/javascript/JavascriptGenerator.js +197 -49
  112. package/lib/javascript/JavascriptModulesPlugin.js +178 -24
  113. package/lib/javascript/JavascriptParser.js +701 -355
  114. package/lib/javascript/JavascriptParserHelpers.js +3 -6
  115. package/lib/javascript/syntax.js +4380 -0
  116. package/lib/library/ModuleLibraryPlugin.js +38 -1
  117. package/lib/loaders/LoaderRunner.js +714 -0
  118. package/lib/loaders/loadLoader.js +100 -0
  119. package/lib/node/ReadFileCompileAsyncWasmPlugin.js +19 -0
  120. package/lib/node/ReadFileCompileWasmPlugin.js +14 -0
  121. package/lib/optimize/ConcatenatedModule.js +120 -16
  122. package/lib/optimize/FlagIncludedChunksPlugin.js +13 -3
  123. package/lib/optimize/InnerGraphPlugin.js +50 -30
  124. package/lib/optimize/ModuleConcatenationPlugin.js +69 -3
  125. package/lib/optimize/SideEffectsFlagPlugin.js +86 -43
  126. package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +15 -0
  127. package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +24 -13
  128. package/lib/prefetch/ResourceHintPlugin.js +663 -0
  129. package/lib/prefetch/ResourceHintRuntimeModule.js +149 -0
  130. package/lib/prefetch/StartupAssetHintRuntimeModule.js +210 -0
  131. package/lib/prefetch/parseResourceHintOptions.js +103 -0
  132. package/lib/rules/RuleSetCompiler.js +114 -0
  133. package/lib/runtime/AsyncModuleGeneratorRuntimeModule.js +56 -0
  134. package/lib/runtime/AsyncModuleRuntimeModule.js +24 -8
  135. package/lib/runtime/AutoPublicPathRuntimeModule.js +7 -1
  136. package/lib/runtime/CommonJsWrapRuntimeModule.js +37 -0
  137. package/lib/runtime/GetWorkletBootstrapRuntimeModule.js +59 -0
  138. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +204 -8
  139. package/lib/runtime/SetAnonymousDefaultNameRuntimeModule.js +4 -1
  140. package/lib/schemes/HttpUriPlugin.js +40 -1
  141. package/lib/schemes/VirtualUrlPlugin.js +1 -2
  142. package/lib/serialization/FileMiddleware.js +29 -3
  143. package/lib/stats/DefaultStatsFactoryPlugin.js +32 -3
  144. package/lib/stats/DefaultStatsPresetPlugin.js +2 -0
  145. package/lib/stats/DefaultStatsPrinterPlugin.js +12 -2
  146. package/lib/stats/StatsFactory.js +15 -8
  147. package/lib/url/URLParserPlugin.js +66 -13
  148. package/lib/util/AsyncQueue.js +122 -72
  149. package/lib/util/SetHelpers.js +1 -1
  150. package/lib/util/StackedMap.js +122 -48
  151. package/lib/util/binarySearchBounds.js +2 -2
  152. package/lib/util/concatenate.js +40 -14
  153. package/lib/util/createHooksRegistry.js +13 -5
  154. package/lib/util/dataURL.js +2 -2
  155. package/lib/util/deterministicGrouping.js +7 -5
  156. package/lib/util/formatSize.js +6 -2
  157. package/lib/util/globUtils.js +710 -0
  158. package/lib/util/identifier.js +23 -6
  159. package/lib/util/implicitTypeLoaderFallback.js +62 -0
  160. package/lib/util/internalSerializables.js +88 -71
  161. package/lib/util/magicComment.js +121 -25
  162. package/lib/util/numberHash.js +2 -2
  163. package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +24 -18
  164. package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +33 -22
  165. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +79 -16
  166. package/lib/web/FetchCompileAsyncWasmPlugin.js +19 -0
  167. package/lib/web/FetchCompileWasmPlugin.js +14 -0
  168. package/lib/web/JsonpChunkLoadingRuntimeModule.js +2 -0
  169. package/lib/webpack.js +65 -0
  170. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +3 -0
  171. package/module.d.ts +21 -0
  172. package/package.json +13 -12
  173. package/schemas/WebpackOptions.check.js +1 -1
  174. package/schemas/WebpackOptions.json +759 -36
  175. package/schemas/plugins/HtmlParserOptions.check.js +1 -1
  176. package/schemas/plugins/ProgressPlugin.check.js +1 -1
  177. package/schemas/plugins/ProgressPlugin.json +17 -1
  178. package/schemas/plugins/container/ContainerReferencePlugin.check.js +1 -1
  179. package/schemas/plugins/container/ContainerReferencePlugin.json +1 -0
  180. package/schemas/plugins/container/ExternalsType.check.js +1 -1
  181. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  182. package/schemas/plugins/container/ModuleFederationPlugin.json +1 -0
  183. package/schemas/plugins/css/CssAutoOrModuleParserOptions.check.js +1 -1
  184. package/schemas/plugins/css/CssModuleParserOptions.check.js +1 -1
  185. package/schemas/plugins/css/CssParserOptions.check.js +1 -1
  186. package/types.d.ts +1213 -96
@@ -12,6 +12,9 @@ const Module = require("../Module");
12
12
  const ModuleGraph = require("../ModuleGraph");
13
13
  const { JAVASCRIPT_TYPE } = require("../ModuleSourceTypeConstants");
14
14
  const { STAGE_DEFAULT } = require("../OptimizationStages");
15
+ const CommonJsSelfReferenceDependency = require("../dependencies/CommonJsSelfReferenceDependency");
16
+ const HarmonyImportDependency = require("../dependencies/HarmonyImportDependency");
17
+ const { ImportPhaseUtils } = require("../dependencies/ImportPhase");
15
18
  const { compareModulesByIdentifier } = require("../util/comparators");
16
19
  const {
17
20
  filterRuntime,
@@ -26,6 +29,7 @@ const ConcatenatedModule = require("./ConcatenatedModule");
26
29
  /** @typedef {import("../Compilation")} Compilation */
27
30
  /** @typedef {import("../Compiler")} Compiler */
28
31
  /** @typedef {import("../Module").BuildInfo} BuildInfo */
32
+ /** @typedef {import("../Module").BuildMeta} BuildMeta */
29
33
  /** @typedef {import("../RequestShortener")} RequestShortener */
30
34
  /** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
31
35
 
@@ -176,9 +180,16 @@ class ModuleConcatenationPlugin {
176
180
  const relevantModules = [];
177
181
  /** @type {Set<Module>} */
178
182
  const possibleInners = new Set();
183
+ const concatenateModules =
184
+ compilation.options.optimization.concatenateModules;
179
185
  const context = {
180
186
  chunkGraph,
181
- moduleGraph
187
+ moduleGraph,
188
+ // commonjs concatenation defaults to on; { commonjs: false } opts out
189
+ concatenateCommonJsModules:
190
+ typeof concatenateModules === "object"
191
+ ? concatenateModules.commonjs !== false
192
+ : concatenateModules === true
182
193
  };
183
194
  const deferEnabled = compilation.options.experiments.deferImport;
184
195
  logger.time("select relevant modules");
@@ -197,7 +208,6 @@ class ModuleConcatenationPlugin {
197
208
  setBailoutReason(module, "Module is async");
198
209
  continue;
199
210
  }
200
-
201
211
  // Must be in strict mode
202
212
  if (!(/** @type {BuildInfo} */ (module.buildInfo).strict)) {
203
213
  setBailoutReason(module, "Module is not in strict mode");
@@ -255,6 +265,16 @@ class ModuleConcatenationPlugin {
255
265
  canBeRoot = false;
256
266
  }
257
267
 
268
+ // A concatenated CommonJS module relies on the root's ESM export
269
+ // rendering, so it can only be an inner module
270
+ if (
271
+ module.type.startsWith("javascript/") &&
272
+ /** @type {BuildMeta} */
273
+ (module.buildMeta).exportsType !== "namespace"
274
+ ) {
275
+ canBeRoot = false;
276
+ }
277
+
258
278
  // Module must not be an entry point
259
279
  if (chunkGraph.isEntryModule(module)) {
260
280
  setInnerBailoutReason(module, "Module is an entry point");
@@ -561,6 +581,26 @@ class ModuleConcatenationPlugin {
561
581
  });
562
582
  }
563
583
 
584
+ /**
585
+ * Checks whether the module `import defer`s a module already in the config.
586
+ * @param {ModuleGraph} moduleGraph the module graph
587
+ * @param {Module} module the candidate module
588
+ * @param {ConcatConfiguration} config the concat configuration
589
+ * @returns {boolean} true when a deferred import targets a module in the config
590
+ */
591
+ _defersModuleIn(moduleGraph, module, config) {
592
+ for (const dep of module.dependencies) {
593
+ if (
594
+ dep instanceof HarmonyImportDependency &&
595
+ ImportPhaseUtils.isDefer(dep.phase)
596
+ ) {
597
+ const target = moduleGraph.getModule(dep);
598
+ if (target && config.has(target)) return true;
599
+ }
600
+ }
601
+ return false;
602
+ }
603
+
564
604
  /**
565
605
  * Returns the imported modules.
566
606
  * @param {Compilation} compilation the compilation
@@ -652,6 +692,26 @@ class ModuleConcatenationPlugin {
652
692
  return module;
653
693
  }
654
694
 
695
+ // A deferred import must stay a concatenation boundary: concatenating a
696
+ // module with a module it `import defer`s (a cycle) would erase the
697
+ // deferred namespace's lazy-evaluation and exotic-object semantics.
698
+ if (
699
+ compilation.options.experiments.deferImport &&
700
+ this._defersModuleIn(compilation.moduleGraph, module, config)
701
+ ) {
702
+ /**
703
+ * @param {RequestShortener} requestShortener request shortener
704
+ * @returns {string} problem description
705
+ */
706
+ const problem = (requestShortener) =>
707
+ `Module ${module.readableIdentifier(
708
+ requestShortener
709
+ )} imports a module in this configuration via import defer`;
710
+ statistics.incorrectDependency++;
711
+ failureCache.set(module, problem); // cache failures for performance
712
+ return problem;
713
+ }
714
+
655
715
  // Module must be in the correct chunks
656
716
  const missingChunks = config.rootChunks.filter(
657
717
  (chunk) => !chunkGraph.isModuleInChunk(module, chunk)
@@ -792,7 +852,13 @@ class ModuleConcatenationPlugin {
792
852
  const selected = connections.filter(
793
853
  (connection) =>
794
854
  !connection.dependency ||
795
- !Dependency.canConcatenate(connection.dependency)
855
+ (!Dependency.canConcatenate(connection.dependency) &&
856
+ // exports self-references of a concatenated CommonJS module
857
+ // are rewritten in place, so they don't block concatenation
858
+ !(
859
+ originModule === module &&
860
+ connection.dependency instanceof CommonJsSelfReferenceDependency
861
+ ))
796
862
  );
797
863
  if (selected.length > 0) {
798
864
  nonHarmonyConnections.set(originModule, connections);
@@ -13,7 +13,9 @@ const {
13
13
  } = require("../ModuleTypeConstants");
14
14
  const { STAGE_DEFAULT } = require("../OptimizationStages");
15
15
  const HarmonyExportImportedSpecifierDependency = require("../dependencies/HarmonyExportImportedSpecifierDependency");
16
+ const HarmonyImportDependency = require("../dependencies/HarmonyImportDependency");
16
17
  const HarmonyImportSpecifierDependency = require("../dependencies/HarmonyImportSpecifierDependency");
18
+ const { ImportPhaseUtils } = require("../dependencies/ImportPhase");
17
19
  const formatLocation = require("../util/formatLocation");
18
20
  const { CompilerHintNotationRegExp } = require("../util/magicComment");
19
21
 
@@ -48,6 +50,20 @@ const { CompilerHintNotationRegExp } = require("../util/magicComment");
48
50
 
49
51
  /** @typedef {Map<string, RegExp>} CacheItem */
50
52
 
53
+ /**
54
+ * Whether a resolved re-export target is reached through an `import defer` edge.
55
+ * Such edges must not be collapsed by the side-effect-free barrel optimization:
56
+ * the source module has to keep being reached through the barrel's cached
57
+ * deferred namespace so deferred-namespace identity and evaluation semantics are
58
+ * preserved.
59
+ * @param {ModuleGraphConnection | undefined} connection the target connection
60
+ * @returns {boolean} true when the target connection is a deferred import
61
+ */
62
+ const isDeferredTargetConnection = (connection) =>
63
+ connection !== undefined &&
64
+ connection.dependency instanceof HarmonyImportDependency &&
65
+ ImportPhaseUtils.isDefer(connection.dependency.phase);
66
+
51
67
  /** @type {WeakMap<Compiler, CacheItem>} */
52
68
  const globToRegexpCache = new WeakMap();
53
69
 
@@ -305,13 +321,14 @@ class SideEffectsFlagPlugin {
305
321
  /** @type {BuildMeta} */
306
322
  (parser.state.module.buildMeta).sideEffectFree = true;
307
323
  } else {
308
- const { loc, type } = sideEffectsStatement;
324
+ const type = sideEffectsStatement.type;
325
+ const loc = parser.getLocation(sideEffectsStatement);
309
326
  moduleGraph
310
327
  .getOptimizationBailout(parser.state.module)
311
328
  .push(
312
329
  () =>
313
330
  `Statement (${type}) with side effects in source code at ${formatLocation(
314
- /** @type {DependencyLocation} */ (loc)
331
+ loc
315
332
  )}`
316
333
  );
317
334
  }
@@ -354,32 +371,34 @@ class SideEffectsFlagPlugin {
354
371
  // 2. export function foo
355
372
  // 3. export default function foo
356
373
  // 4. export default function / export default () => {} (anonymous)
357
- parser.hooks.preStatement.tap(PLUGIN_NAME, (statement) => {
358
- if (parser.scope.topLevelScope !== true) return;
359
- if (statement.type !== "FunctionDeclaration") {
360
- return;
361
- }
362
- const name = statement.id ? statement.id.name : "default";
363
- if (
364
- pureFunctionsFromOption &&
365
- pureFunctionsFromOption.has(name)
366
- ) {
367
- markPure(name);
368
- return;
369
- }
370
- const commentsStart = parser.prevStatement
371
- ? /** @type {Range} */ (parser.prevStatement.range)[1]
372
- : 0;
373
- if (
374
- hasNoSideEffectsNotation(
375
- parser,
376
- commentsStart,
377
- /** @type {Range} */ (statement.range)[0]
378
- )
379
- ) {
380
- markPure(name);
381
- }
382
- });
374
+ parser.hooks.preStatementByType
375
+ .for("FunctionDeclaration")
376
+ .tap(PLUGIN_NAME, (statement) => {
377
+ if (parser.scope.topLevelScope !== true) return;
378
+ if (statement.type !== "FunctionDeclaration") {
379
+ return;
380
+ }
381
+ const name = statement.id ? statement.id.name : "default";
382
+ if (
383
+ pureFunctionsFromOption &&
384
+ pureFunctionsFromOption.has(name)
385
+ ) {
386
+ markPure(name);
387
+ return;
388
+ }
389
+ const commentsStart = parser.prevStatement
390
+ ? /** @type {Range} */ (parser.prevStatement.range)[1]
391
+ : 0;
392
+ if (
393
+ hasNoSideEffectsNotation(
394
+ parser,
395
+ commentsStart,
396
+ /** @type {Range} */ (statement.range)[0]
397
+ )
398
+ ) {
399
+ markPure(name);
400
+ }
401
+ });
383
402
 
384
403
  // Detect on variable declarations with function init
385
404
  parser.hooks.preDeclarator.tap(PLUGIN_NAME, (decl, statement) => {
@@ -421,21 +440,23 @@ class SideEffectsFlagPlugin {
421
440
  });
422
441
 
423
442
  if (pureFunctionsFromOption) {
424
- parser.hooks.blockPreStatement.tap(PLUGIN_NAME, (statement) => {
425
- if (parser.scope.topLevelScope !== true) return;
426
- if (
427
- statement.type === "ExportDefaultDeclaration" &&
428
- pureFunctionsFromOption.has("default")
429
- ) {
430
- const decl = statement.declaration;
443
+ parser.hooks.blockPreStatementByType
444
+ .for("ExportDefaultDeclaration")
445
+ .tap(PLUGIN_NAME, (statement) => {
446
+ if (parser.scope.topLevelScope !== true) return;
431
447
  if (
432
- decl.type === "ArrowFunctionExpression" ||
433
- decl.type === "FunctionExpression"
448
+ statement.type === "ExportDefaultDeclaration" &&
449
+ pureFunctionsFromOption.has("default")
434
450
  ) {
435
- markPure("default");
451
+ const decl = statement.declaration;
452
+ if (
453
+ decl.type === "ArrowFunctionExpression" ||
454
+ decl.type === "FunctionExpression"
455
+ ) {
456
+ markPure("default");
457
+ }
436
458
  }
437
- }
438
- });
459
+ });
439
460
  }
440
461
 
441
462
  parser.hooks.isPure
@@ -500,6 +521,11 @@ class SideEffectsFlagPlugin {
500
521
  /** @type {Set<Module>} */
501
522
  const optimizedModules = new Set();
502
523
 
524
+ // Only defer builds must protect deferred re-export barrels;
525
+ // skip the per-target check entirely otherwise.
526
+ const deferEnabled =
527
+ compilation.options.experiments.deferImport === true;
528
+
503
529
  // Re-export resolution is idempotent within a pass, so cache it
504
530
  // per export info: a shared barrel imported by many modules
505
531
  // resolves each name once instead of once per consumer.
@@ -581,13 +607,18 @@ class SideEffectsFlagPlugin {
581
607
 
582
608
  exportInfo.moveTarget(
583
609
  moduleGraph,
584
- ({ module }) =>
585
- module.getSideEffectsConnectionState(
610
+ (candidate) =>
611
+ candidate.module.getSideEffectsConnectionState(
586
612
  moduleGraph
587
613
  ) === false &&
614
+ // Keep a deferred re-export's barrel (see below).
615
+ (!deferEnabled ||
616
+ !isDeferredTargetConnection(
617
+ candidate.connection
618
+ )) &&
588
619
  (Boolean(dep.name) ||
589
620
  hasSingleStarReexport(
590
- /** @type {Module} */ (module)
621
+ /** @type {Module} */ (candidate.module)
591
622
  )),
592
623
  ({
593
624
  module: newModule,
@@ -639,6 +670,18 @@ class SideEffectsFlagPlugin {
639
670
  }
640
671
  if (!target) continue;
641
672
 
673
+ // A deferred re-export must keep its side-effect-free
674
+ // barrel: collapsing it here would turn the cached
675
+ // deferred namespace (`.z`) into an eager import of the
676
+ // source module, breaking deferred-namespace identity
677
+ // and evaluation semantics.
678
+ if (
679
+ deferEnabled &&
680
+ isDeferredTargetConnection(target.connection)
681
+ ) {
682
+ continue;
683
+ }
684
+
642
685
  moduleGraph.updateModule(dep, target.module);
643
686
  moduleGraph.updateParent(
644
687
  dep,
@@ -66,6 +66,21 @@ class ChunkPrefetchPreloadPlugin {
66
66
  new ChunkPreloadTriggerRuntimeModule(chunkMap.preload)
67
67
  );
68
68
  }
69
+ if (chunkMap.cssPreload) {
70
+ // CSS-only preload (`parser.javascript.dynamicImportCssPreload`):
71
+ // reuse `preloadChunk` — with no JS `preload` order the JS
72
+ // handler is never registered, so only the CSS `.s` handler
73
+ // fires (`<link rel="preload" as="style">`).
74
+ set.add(RuntimeGlobals.preloadChunk);
75
+ set.add(RuntimeGlobals.preloadChunkHandlers);
76
+ compilation.addRuntimeModule(
77
+ chunk,
78
+ new ChunkPreloadTriggerRuntimeModule(
79
+ chunkMap.cssPreload,
80
+ "cssPreload"
81
+ )
82
+ );
83
+ }
69
84
  }
70
85
  );
71
86
  compilation.hooks.runtimeRequirementInTree
@@ -14,11 +14,14 @@ const Template = require("../Template");
14
14
  class ChunkPreloadTriggerRuntimeModule extends RuntimeModule {
15
15
  /**
16
16
  * @param {ChunkChildIdsByOrdersMap} chunkMap map from chunk to chunks
17
+ * @param {string=} handlerKey the `ensureChunkHandlers` key to install under (default `"preload"`); `"cssPreload"` preloads only the CSS handler so it stays CSS-only even when the build also registers a JS preload handler
17
18
  */
18
- constructor(chunkMap) {
19
- super("chunk preload trigger", RuntimeModule.STAGE_TRIGGER);
19
+ constructor(chunkMap, handlerKey = "preload") {
20
+ super(`chunk ${handlerKey} trigger`, RuntimeModule.STAGE_TRIGGER);
20
21
  /** @type {ChunkChildIdsByOrdersMap} */
21
22
  this.chunkMap = chunkMap;
23
+ /** @type {string} */
24
+ this.handlerKey = handlerKey;
22
25
  }
23
26
 
24
27
  /**
@@ -26,20 +29,28 @@ class ChunkPreloadTriggerRuntimeModule extends RuntimeModule {
26
29
  * @returns {string | null} runtime code
27
30
  */
28
31
  generate() {
29
- const { chunkMap } = this;
32
+ const { chunkMap, handlerKey } = this;
30
33
  const compilation = /** @type {Compilation} */ (this.compilation);
31
34
  const { runtimeTemplate } = compilation;
32
- const body = [
33
- "var chunks = chunkToChildrenMap[chunkId];",
34
- `Array.isArray(chunks) && chunks.map(${RuntimeGlobals.preloadChunk});`
35
- ];
35
+ // `cssPreload` calls only the CSS preload handler (`preloadChunkHandlers.s`)
36
+ // so it stays CSS-only regardless of a JS preload handler registered
37
+ // elsewhere; plain `preload` fans out to every handler via `preloadChunk`.
38
+ const body =
39
+ handlerKey === "cssPreload"
40
+ ? [
41
+ `var handler = ${RuntimeGlobals.preloadChunkHandlers}.s;`,
42
+ "var chunks = chunkToChildrenMap[chunkId];",
43
+ "if (handler && Array.isArray(chunks)) chunks.forEach(handler);"
44
+ ]
45
+ : [
46
+ "var chunks = chunkToChildrenMap[chunkId];",
47
+ `Array.isArray(chunks) && chunks.map(${RuntimeGlobals.preloadChunk});`
48
+ ];
36
49
  return Template.asString([
37
- Template.asString([
38
- `var chunkToChildrenMap = ${JSON.stringify(chunkMap, null, "\t")};`,
39
- `${
40
- RuntimeGlobals.ensureChunkHandlers
41
- }.preload = ${runtimeTemplate.basicFunction("chunkId", body)};`
42
- ])
50
+ `var chunkToChildrenMap = ${JSON.stringify(chunkMap, null, "\t")};`,
51
+ `${
52
+ RuntimeGlobals.ensureChunkHandlers
53
+ }.${handlerKey} = ${runtimeTemplate.basicFunction("chunkId", body)};`
43
54
  ]);
44
55
  }
45
56
  }