webpack 5.110.3 → 5.111.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 (208) hide show
  1. package/README.md +5 -0
  2. package/lib/APIPlugin.js +23 -7
  3. package/lib/AutomaticPrefetchPlugin.js +1 -1
  4. package/lib/Cache.js +8 -3
  5. package/lib/CacheFacade.js +1 -1
  6. package/lib/CircularModulesPlugin.js +157 -55
  7. package/lib/CleanPlugin.js +2 -2
  8. package/lib/Compilation.js +320 -302
  9. package/lib/Compiler.js +209 -46
  10. package/lib/ContextModule.js +17 -81
  11. package/lib/ContextModuleFactory.js +1 -1
  12. package/lib/CopyPlugin.js +1054 -0
  13. package/lib/DefinePlugin.js +24 -8
  14. package/lib/ExternalModule.js +41 -14
  15. package/lib/FileSystemInfo.js +17 -14
  16. package/lib/FlagDependencyExportsPlugin.js +45 -21
  17. package/lib/HotModuleReplacementPlugin.js +53 -7
  18. package/lib/JavascriptMetaInfoPlugin.js +5 -3
  19. package/lib/MainTemplate.js +5 -1
  20. package/lib/Module.js +16 -7
  21. package/lib/MultiCompiler.js +1 -1
  22. package/lib/MultiWatching.js +1 -1
  23. package/lib/NormalModule.js +45 -12
  24. package/lib/NormalModuleFactory.js +1 -1
  25. package/lib/RuntimeGlobals.js +21 -7
  26. package/lib/RuntimeModule.js +28 -12
  27. package/lib/RuntimePlugin.js +30 -3
  28. package/lib/RuntimeTemplate.js +780 -475
  29. package/lib/SourceMapDevToolPlugin.js +1 -1
  30. package/lib/Watching.js +9 -0
  31. package/lib/WebpackOptionsApply.js +84 -91
  32. package/lib/asset/AssetGenerator.js +25 -8
  33. package/lib/asset/AssetModule.js +3 -0
  34. package/lib/asset/WebManifestParser.js +7 -5
  35. package/lib/cache/AddBuildDependenciesPlugin.js +33 -4
  36. package/lib/cache/IdleFileCachePlugin.js +2 -2
  37. package/lib/cache/PackFileCacheStrategy.js +14 -1
  38. package/lib/config/browserslistTargetHandler.js +19 -0
  39. package/lib/config/defaults.js +86 -50
  40. package/lib/config/normalization.js +82 -12
  41. package/lib/config/target.js +10 -0
  42. package/lib/container/ContainerReferencePlugin.js +6 -0
  43. package/lib/container/RemoteRuntimeModule.js +9 -0
  44. package/lib/container/declaredRemotes.js +39 -0
  45. package/lib/css/CssGenerator.js +8 -0
  46. package/lib/css/CssInjectStyleRuntimeModule.js +9 -0
  47. package/lib/css/CssLoadingRuntimeModule.js +94 -36
  48. package/lib/css/CssModule.js +1 -1
  49. package/lib/css/CssModulesPlugin.js +7 -6
  50. package/lib/css/CssParser.js +144 -11
  51. package/lib/css/CssServerStylesRuntimeModule.js +9 -0
  52. package/lib/css/cssMinify.js +11 -3
  53. package/lib/css/data.js +2814 -678
  54. package/lib/css/syntax.js +4082 -248
  55. package/lib/debug/ProfilingPlugin.js +4 -0
  56. package/lib/dependencies/AMDDefineDependencyParserPlugin.js +6 -3
  57. package/lib/dependencies/AMDRuntimeModules.js +18 -0
  58. package/lib/dependencies/CommonJsExportRequireDependency.js +3 -1
  59. package/lib/dependencies/CommonJsExportsParserPlugin.js +12 -13
  60. package/lib/dependencies/CommonJsImportsParserPlugin.js +1 -0
  61. package/lib/dependencies/CommonJsPlugin.js +19 -3
  62. package/lib/dependencies/CommonJsRequireDependency.js +14 -5
  63. package/lib/dependencies/CssIcssExportDependency.js +7 -1
  64. package/lib/dependencies/HarmonyCompatibilityDependency.js +58 -4
  65. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +8 -3
  66. package/lib/dependencies/HarmonyExportExpressionDependency.js +44 -29
  67. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +71 -13
  68. package/lib/dependencies/HarmonyExportInitFragment.js +99 -19
  69. package/lib/dependencies/HarmonyExportSpecifierDependency.js +18 -30
  70. package/lib/dependencies/HarmonyImportBareSideEffectDependency.js +59 -0
  71. package/lib/dependencies/HarmonyImportDependency.js +6 -1
  72. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +8 -1
  73. package/lib/dependencies/HarmonyImportSpecifierDependency.js +24 -1
  74. package/lib/dependencies/HarmonyModulesPlugin.js +20 -0
  75. package/lib/dependencies/HtmlEntryDependency.js +50 -0
  76. package/lib/dependencies/ImportMetaMainDependency.js +104 -0
  77. package/lib/dependencies/ImportMetaPlugin.js +59 -15
  78. package/lib/dependencies/SystemRuntimeModule.js +9 -0
  79. package/lib/dependencies/WorkerDependency.js +1 -2
  80. package/lib/dependencies/WorkletDependency.js +1 -2
  81. package/lib/dll/DelegatedModule.js +18 -1
  82. package/lib/dll/DllReferencePlugin.js +11 -8
  83. package/lib/dll/LibManifestPlugin.js +1 -1
  84. package/lib/errors/AnalyzableBailoutsWarning.js +41 -0
  85. package/lib/errors/DuplicateModulesWarning.js +12 -7
  86. package/lib/errors/EmptyCopyPatternWarning.js +26 -0
  87. package/lib/errors/ExternalStarReexportError.js +44 -0
  88. package/lib/errors/MissingSourceMapsWarning.js +36 -0
  89. package/lib/errors/ModuleParseError.js +2 -1
  90. package/lib/errors/UnusedAssetsWarning.js +36 -0
  91. package/lib/errors/UnusedFederationWarning.js +35 -0
  92. package/lib/errors/UnusedModulesWarning.js +38 -0
  93. package/lib/esm/ExportWebpackRequireRuntimeModule.js +9 -0
  94. package/lib/esm/ModuleChunkFormatPlugin.js +28 -3
  95. package/lib/esm/ModuleChunkLoadingPlugin.js +30 -11
  96. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +92 -60
  97. package/lib/hmr/HotModuleReplacement.runtime.js +8 -2
  98. package/lib/hmr/HotModuleReplacementRuntimeModule.js +9 -0
  99. package/lib/html/HtmlGenerator.js +11 -5
  100. package/lib/html/HtmlModulesPlugin.js +331 -62
  101. package/lib/html/HtmlParser.js +13 -6
  102. package/lib/html/builtinEmbeddedRenderer.js +107 -0
  103. package/lib/html/data.js +121 -7
  104. package/lib/html/htmlMinify.js +84 -113
  105. package/lib/html/syntax.js +763 -426
  106. package/lib/ids/HashedModuleIdsPlugin.js +2 -1
  107. package/lib/index.js +3 -0
  108. package/lib/javascript/JavascriptModule.js +1 -0
  109. package/lib/javascript/JavascriptModulesPlugin.js +52 -24
  110. package/lib/javascript/JavascriptParser.js +1255 -728
  111. package/lib/javascript/StartupHelpers.js +27 -3
  112. package/lib/javascript/data.js +172 -0
  113. package/lib/javascript/grammar.js +5546 -0
  114. package/lib/javascript/parser.js +1494 -0
  115. package/lib/javascript/regexp.js +1762 -0
  116. package/lib/javascript/regexpData.js +51 -0
  117. package/lib/javascript/syntax.js +8696 -5225
  118. package/lib/library/ModuleLibraryPlugin.js +116 -5
  119. package/lib/node/ReadFileChunkLoadingRuntimeModule.js +22 -0
  120. package/lib/node/RequireChunkLoadingRuntimeModule.js +22 -0
  121. package/lib/optimize/ConcatenatedModule.js +97 -20
  122. package/lib/optimize/ConstExportsPlugin.js +50 -39
  123. package/lib/optimize/InlineExports.js +20 -123
  124. package/lib/optimize/MangleExportsPlugin.js +10 -0
  125. package/lib/optimize/ModuleConcatenationPlugin.js +24 -1
  126. package/lib/optimize/RealContentHashPlugin.js +68 -9
  127. package/lib/optimize/SideEffectsFlagPlugin.js +17 -9
  128. package/lib/performance/AnalyzableBailoutsPlugin.js +115 -0
  129. package/lib/performance/CacheEffectivenessPlugin.js +4 -3
  130. package/lib/performance/DuplicateModulesPlugin.js +57 -13
  131. package/lib/performance/EvalUsagePlugin.js +5 -2
  132. package/lib/performance/MissingSourceMapsPlugin.js +115 -0
  133. package/lib/performance/PureAnnotationsPlugin.js +6 -3
  134. package/lib/performance/TopLevelThisPlugin.js +5 -4
  135. package/lib/performance/UnusedAssetsPlugin.js +109 -0
  136. package/lib/performance/UnusedFederationPlugin.js +147 -0
  137. package/lib/performance/UnusedModulesPlugin.js +141 -0
  138. package/lib/performance/UnusedReexportsPlugin.js +1 -55
  139. package/lib/performance/isOnlyReexported.js +65 -0
  140. package/lib/prefetch/ChunkPrefetchFunctionRuntimeModule.js +25 -5
  141. package/lib/prefetch/ChunkPrefetchPreloadPlugin.js +2 -0
  142. package/lib/prefetch/ChunkPrefetchStartupRuntimeModule.js +9 -0
  143. package/lib/prefetch/ChunkPrefetchTriggerRuntimeModule.js +9 -0
  144. package/lib/prefetch/ChunkPreloadTriggerRuntimeModule.js +9 -0
  145. package/lib/prefetch/ResourceHintPlugin.js +1 -2
  146. package/lib/prefetch/ResourceHintRuntimeModule.js +9 -0
  147. package/lib/prefetch/StartupAssetHintRuntimeModule.js +9 -0
  148. package/lib/rules/RuleSetCompiler.js +211 -4
  149. package/lib/runtime/AsyncModuleRuntimeModule.js +100 -66
  150. package/lib/runtime/AutoPublicPathRuntimeModule.js +9 -0
  151. package/lib/runtime/BaseUriRuntimeModule.js +9 -0
  152. package/lib/runtime/ChunkNameRuntimeModule.js +9 -0
  153. package/lib/runtime/EnsureChunkRuntimeModule.js +35 -16
  154. package/lib/runtime/GetChunkFilenameRuntimeModule.js +9 -0
  155. package/lib/runtime/GetFullHashRuntimeModule.js +9 -0
  156. package/lib/runtime/GetMainFilenameRuntimeModule.js +9 -0
  157. package/lib/runtime/GetWorkletBootstrapRuntimeModule.js +9 -0
  158. package/lib/runtime/GlobalRuntimeModule.js +9 -0
  159. package/lib/runtime/HasOwnPropertyRuntimeModule.js +9 -0
  160. package/lib/runtime/HelperRuntimeModule.js +10 -0
  161. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +330 -219
  162. package/lib/runtime/NonceRuntimeModule.js +9 -0
  163. package/lib/runtime/OnChunksLoadedRuntimeModule.js +67 -20
  164. package/lib/runtime/PublicPathRuntimeModule.js +9 -0
  165. package/lib/runtime/RuntimeIdRuntimeModule.js +9 -0
  166. package/lib/runtime/SpecNamespaceObjectRuntimeModule.js +90 -0
  167. package/lib/runtime/StartupChunkDependenciesRuntimeModule.js +9 -0
  168. package/lib/runtime/StartupEntrypointRuntimeModule.js +9 -0
  169. package/lib/runtime/SystemContextRuntimeModule.js +9 -0
  170. package/lib/runtime/ToBinaryRuntimeModule.js +9 -0
  171. package/lib/serialization/ObjectMiddleware.js +138 -106
  172. package/lib/sharing/ConsumeSharedPlugin.js +12 -0
  173. package/lib/sharing/ConsumeSharedRuntimeModule.js +11 -0
  174. package/lib/sharing/ShareRuntimeModule.js +9 -0
  175. package/lib/sharing/declaredShared.js +47 -0
  176. package/lib/stats/DefaultStatsFactoryPlugin.js +3 -1
  177. package/lib/stats/DefaultStatsPrinterPlugin.js +3 -0
  178. package/lib/util/SourceProcessor.js +76 -69
  179. package/lib/util/async.js +292 -0
  180. package/lib/util/buildDiagnostics.js +69 -0
  181. package/lib/util/fs.js +27 -1
  182. package/lib/util/handlerKeys.js +40 -0
  183. package/lib/util/identifier.js +20 -0
  184. package/lib/util/internalSerializables.js +4 -0
  185. package/lib/util/registerExternalSerializer.js +6 -45
  186. package/lib/wasm-async/AsyncWasmCompileRuntimeModule.js +9 -0
  187. package/lib/wasm-async/AsyncWasmLoadingRuntimeModule.js +9 -0
  188. package/lib/wasm-sync/WasmChunkLoadingRuntimeModule.js +9 -0
  189. package/lib/web/JsonpChunkLoadingRuntimeModule.js +36 -0
  190. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +19 -0
  191. package/package.json +22 -16
  192. package/schemas/WebpackOptions.check.js +1 -1
  193. package/schemas/WebpackOptions.json +379 -66
  194. package/schemas/plugins/LoaderOptionsPlugin.check.js +1 -1
  195. package/schemas/plugins/ManifestPlugin.check.js +1 -1
  196. package/schemas/plugins/SourceMapDevToolPlugin.check.js +1 -1
  197. package/schemas/plugins/asset/AssetGeneratorOptions.check.js +1 -1
  198. package/schemas/plugins/asset/AssetResourceGeneratorOptions.check.js +1 -1
  199. package/schemas/plugins/container/ContainerPlugin.check.js +1 -1
  200. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  201. package/schemas/plugins/debug/ProfilingPlugin.check.js +1 -1
  202. package/schemas/plugins/dll/DllReferencePlugin.check.js +1 -1
  203. package/schemas/plugins/ids/HashedModuleIdsPlugin.check.js +1 -1
  204. package/schemas/plugins/schemes/HttpUriPlugin.check.js +1 -1
  205. package/types.d.ts +1414 -314
  206. package/lib/dependencies/ExportBindingInitFragment.js +0 -191
  207. package/lib/errors/EntrypointOverlapWarning.js +0 -45
  208. package/lib/performance/EntrypointOverlapPlugin.js +0 -122
@@ -0,0 +1,38 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Alexander Akait @alexander-akait
4
+ */
5
+
6
+ "use strict";
7
+
8
+ const WebpackError = require("./WebpackError");
9
+
10
+ /**
11
+ * @typedef {object} UnusedModuleDetails
12
+ * @property {string} name the module, by request
13
+ * @property {number} size the bytes it adds to the bundle
14
+ * @property {string} statement the statement that kept it, as `type at location`
15
+ */
16
+
17
+ class UnusedModulesWarning extends WebpackError {
18
+ /**
19
+ * Creates an instance of UnusedModulesWarning.
20
+ * @param {UnusedModuleDetails[]} modules the modules nothing uses
21
+ * @param {number} total how many such modules there are
22
+ * @param {number} size the bytes they add between them
23
+ */
24
+ constructor(modules, total, size) {
25
+ const list = modules
26
+ .map((it) => `\n ${it.name} (${it.size} bytes) — ${it.statement}`)
27
+ .join("");
28
+
29
+ super(
30
+ `unused modules: ${total} ${total === 1 ? "module is" : "modules are"} bundled although nothing uses what they export, costing ${size} bytes:${list}\nEach is kept only by the statement named above, which runs for its effect rather than for anything the importer reads. Move that effect to where it is wanted, or drop the import — 'sideEffects' in the package's package.json says so for a whole package at once.\nFor more info visit https://webpack.js.org/guides/tree-shaking/#mark-the-file-as-side-effect-free`
31
+ );
32
+
33
+ /** @type {string} */
34
+ this.name = "UnusedModulesWarning";
35
+ }
36
+ }
37
+
38
+ module.exports = UnusedModulesWarning;
@@ -22,6 +22,15 @@ class ExportWebpackRequireRuntimeModule extends RuntimeModule {
22
22
  return false;
23
23
  }
24
24
 
25
+ /**
26
+ * The `[handlerMap, key]` pairs this module installs onto a chunk handler map
27
+ * such as `__webpack_require__.f`, or `null` where it cannot name them.
28
+ * @returns {[string, string][] | null} installed chunk handlers (do not mutate)
29
+ */
30
+ getInstalledChunkHandlers() {
31
+ return RuntimeModule.NO_CHUNK_HANDLERS;
32
+ }
33
+
25
34
  /**
26
35
  * Generates runtime code for this runtime module.
27
36
  * @returns {string | null} runtime code
@@ -19,7 +19,10 @@ const {
19
19
  getChunkFilenameTemplate,
20
20
  getCompilationHooks
21
21
  } = require("../javascript/JavascriptModulesPlugin");
22
- const { entryModuleIdExpression } = require("../javascript/StartupHelpers");
22
+ const {
23
+ entryModuleIdExpression,
24
+ renderAwaitedEntries
25
+ } = require("../javascript/StartupHelpers");
23
26
  const { getUndoPath } = require("../util/identifier");
24
27
 
25
28
  /** @import { Source } from "webpack-sources" */
@@ -186,7 +189,8 @@ class ModuleChunkFormatPlugin {
186
189
  }
187
190
  );
188
191
  hooks.renderChunk.tap(PLUGIN_NAME, (modules, renderContext) => {
189
- const { chunk, chunkGraph, runtimeTemplate } = renderContext;
192
+ const { chunk, chunkGraph, moduleGraph, runtimeTemplate } =
193
+ renderContext;
190
194
  const hotUpdateChunk = chunk instanceof HotUpdateChunk ? chunk : null;
191
195
  const source = new ConcatSource();
192
196
  const cst = runtimeTemplate.renderConst();
@@ -239,6 +243,17 @@ class ModuleChunkFormatPlugin {
239
243
  );
240
244
  }
241
245
 
246
+ const entryOptions = chunk.getEntryOptions();
247
+ const library =
248
+ entryOptions && entryOptions.library !== undefined
249
+ ? entryOptions.library
250
+ : runtimeTemplate.outputOptions.library;
251
+ // A module library awaits the entry itself, in `ModuleLibraryPlugin`.
252
+ const canAwaitEntry =
253
+ runtimeTemplate.supportsTopLevelAwait() &&
254
+ !(library !== undefined && library.type === "module");
255
+ /** @type {string[]} */
256
+ const awaitedEntries = [];
242
257
  /** @type {Set<Chunk>} */
243
258
  const loadedChunks = new Set();
244
259
  let ownInstalled = false;
@@ -296,13 +311,23 @@ class ModuleChunkFormatPlugin {
296
311
  startupSource.add(inlinedEntrySource);
297
312
  startupSource.add("\n");
298
313
  } else {
314
+ // An async entry nobody awaits settles after the bundle did,
315
+ // which orphans its rejection.
316
+ const awaitEntry = canAwaitEntry && moduleGraph.isAsync(module);
317
+ const target = final
318
+ ? RuntimeGlobals.exports
319
+ : `${RuntimeGlobals.exports}_${i}`;
299
320
  startupSource.add(
300
321
  `${
301
- final ? `var ${RuntimeGlobals.exports} = ` : ""
322
+ final || awaitEntry ? `var ${target} = ` : ""
302
323
  }__webpack_exec__(${JSON.stringify(moduleId)});\n`
303
324
  );
325
+ if (awaitEntry) awaitedEntries.push(target);
304
326
  }
305
327
  }
328
+ for (const line of renderAwaitedEntries(awaitedEntries)) {
329
+ startupSource.add(`${line}\n`);
330
+ }
306
331
 
307
332
  entrySource.add(
308
333
  hooks.renderStartup.call(
@@ -78,7 +78,6 @@ class ModuleChunkLoadingPlugin {
78
78
  RuntimeGlobals.ensureChunkHandlers,
79
79
  RuntimeGlobals.baseURI,
80
80
  RuntimeGlobals.externalInstallChunk,
81
- RuntimeGlobals.analyzableChunkImport,
82
81
  RuntimeGlobals.onChunksLoaded,
83
82
  RuntimeGlobals.hmrDownloadUpdateHandlers,
84
83
  RuntimeGlobals.hmrDownloadManifest
@@ -90,7 +89,6 @@ class ModuleChunkLoadingPlugin {
90
89
  for (const requirement of [
91
90
  RuntimeGlobals.ensureChunkHandlers,
92
91
  RuntimeGlobals.externalInstallChunk,
93
- RuntimeGlobals.analyzableChunkImport,
94
92
  RuntimeGlobals.hmrDownloadUpdateHandlers
95
93
  ]) {
96
94
  compilation.hooks.runtimeRequirementInTree
@@ -120,23 +118,44 @@ class ModuleChunkLoadingPlugin {
120
118
  if (!isEnabledForChunk(chunk)) return;
121
119
  // A baked url carries where the chunk is, so neither is read for it.
122
120
  // Asked as the runtime module asks, so the two always agree.
123
- const baked = compilation.runtimeTemplate.analyzableChunkScriptUrls(
124
- chunk,
125
- chunkGraph,
126
- set
127
- );
128
- if (baked !== null && baked.complete) return;
121
+ if (
122
+ compilation.runtimeTemplate.analyzableChunkScriptUrls(
123
+ chunk,
124
+ chunkGraph,
125
+ set
126
+ ) !== null
127
+ ) {
128
+ return;
129
+ }
129
130
  set.add(RuntimeGlobals.publicPath);
130
131
  set.add(RuntimeGlobals.getChunkScriptFilename);
131
132
  });
132
133
  }
133
134
 
134
135
  // Keyed on `ensureChunk`, not on the handler map: only the runtime chunk loader
135
- // builds a URL from a chunk id, and an analyzable `import()` carries its own.
136
+ // builds a URL from a chunk id, and a baked specifier carries its own.
136
137
  compilation.hooks.runtimeRequirementInTree
137
138
  .for(RuntimeGlobals.ensureChunk)
138
- .tap(PLUGIN_NAME, (chunk, set) => {
139
- if (!isEnabledForChunk(chunk)) return;
139
+ .tap(PLUGIN_NAME, (chunk, set, { chunkGraph }) => {
140
+ if (!isEnabledForChunk(chunk)) {
141
+ compilation.runtimeTemplate.reportChunkImportBailout(
142
+ chunk,
143
+ chunkGraph
144
+ );
145
+ return;
146
+ }
147
+
148
+ // Asked as the runtime module asks, so the two always agree on whether
149
+ // a chunk id is ever turned into a url here.
150
+ const { runtimeTemplate } = compilation;
151
+ if (
152
+ runtimeTemplate.analyzableChunkImports(chunk, chunkGraph, set) !==
153
+ null &&
154
+ !set.has(RuntimeGlobals.hmrDownloadUpdateHandlers) &&
155
+ !runtimeTemplate.chunkImportsNeedRuntimeUrl(chunk, chunkGraph)
156
+ ) {
157
+ return;
158
+ }
140
159
 
141
160
  if (compilation.outputOptions.publicPath !== "auto") {
142
161
  set.add(RuntimeGlobals.publicPath);
@@ -17,6 +17,7 @@ const { getInitialChunkIds } = require("../javascript/StartupHelpers");
17
17
  const { renderBaseUri } = require("../runtime/baseUri");
18
18
  const compileBooleanMatcher = require("../util/compileBooleanMatcher");
19
19
  const createHooksRegistry = require("../util/createHooksRegistry");
20
+ const { RESOLVABLE_SPECIFIER_REGEXP } = require("../util/identifier");
20
21
  const memoize = require("../util/memoize");
21
22
 
22
23
  const getAPIPlugin = memoize(() => require("../APIPlugin"));
@@ -53,6 +54,54 @@ class ModuleChunkLoadingRuntimeModule extends RuntimeModule {
53
54
  this._runtimeRequirements = runtimeRequirements;
54
55
  }
55
56
 
57
+ /**
58
+ * The `[handlerMap, key]` pairs this module installs onto a chunk handler map
59
+ * such as `__webpack_require__.f`, or `null` where it cannot name them.
60
+ * @returns {[string, string][] | null} installed chunk handlers (do not mutate)
61
+ */
62
+ getInstalledChunkHandlers() {
63
+ const compilation = /** @type {Compilation} */ (this.compilation);
64
+ const chunkGraph = /** @type {ChunkGraph} */ (this.chunkGraph);
65
+ const chunk = /** @type {Chunk} */ (this.chunk);
66
+ const runtimeRequirements = this._runtimeRequirements;
67
+ const withHmr = runtimeRequirements.has(
68
+ RuntimeGlobals.hmrDownloadUpdateHandlers
69
+ );
70
+ const withHint =
71
+ compilation.outputOptions.environment.document ||
72
+ compilation.runtimeTemplate.isNeutralPlatform();
73
+ /** @type {[string, string][]} */
74
+ const handlers = [];
75
+ if (
76
+ runtimeRequirements.has(RuntimeGlobals.ensureChunkHandlers) &&
77
+ (runtimeRequirements.has(RuntimeGlobals.ensureChunk) || withHmr)
78
+ ) {
79
+ handlers.push([RuntimeGlobals.ensureChunkHandlers, "j"]);
80
+ }
81
+ // The hot update flow installs this one onto the same map while it runs.
82
+ if (withHmr) {
83
+ handlers.push([RuntimeGlobals.ensureChunkHandlers, "moduleHmr"]);
84
+ }
85
+ if (
86
+ withHint &&
87
+ runtimeRequirements.has(RuntimeGlobals.prefetchChunkHandlers) &&
88
+ chunk.hasChildByOrder(chunkGraph, "prefetch", true, chunkHasJs)
89
+ ) {
90
+ handlers.push([RuntimeGlobals.prefetchChunkHandlers, "j"]);
91
+ }
92
+ if (
93
+ withHint &&
94
+ runtimeRequirements.has(RuntimeGlobals.preloadChunkHandlers) &&
95
+ chunk.hasChildByOrder(chunkGraph, "preload", true, chunkHasJs)
96
+ ) {
97
+ handlers.push([RuntimeGlobals.preloadChunkHandlers, "j"]);
98
+ }
99
+ if (runtimeRequirements.has(RuntimeGlobals.onChunksLoaded)) {
100
+ handlers.push([RuntimeGlobals.onChunksLoaded, "j"]);
101
+ }
102
+ return handlers;
103
+ }
104
+
56
105
  /**
57
106
  * Returns generated code.
58
107
  * @private
@@ -96,9 +145,6 @@ class ModuleChunkLoadingRuntimeModule extends RuntimeModule {
96
145
  const withExternalInstallChunk = this._runtimeRequirements.has(
97
146
  RuntimeGlobals.externalInstallChunk
98
147
  );
99
- const withAnalyzableImport = this._runtimeRequirements.has(
100
- RuntimeGlobals.analyzableChunkImport
101
- );
102
148
  const withLoading = this._runtimeRequirements.has(
103
149
  RuntimeGlobals.ensureChunkHandlers
104
150
  );
@@ -111,8 +157,8 @@ class ModuleChunkLoadingRuntimeModule extends RuntimeModule {
111
157
  const withHmrManifest = this._runtimeRequirements.has(
112
158
  RuntimeGlobals.hmrDownloadManifest
113
159
  );
114
- // `.f.j` serves `ensureChunk`: an analyzable import dispatches every handler but
115
- // this one. HMR's force-load knows only a chunk id, so it needs the loader too.
160
+ // `.f.j` serves `ensureChunk`. HMR's force-load knows only a chunk id, so it
161
+ // needs the loader too.
116
162
  const withJsLoading =
117
163
  withLoading &&
118
164
  (this._runtimeRequirements.has(RuntimeGlobals.ensureChunk) || withHmr);
@@ -129,7 +175,7 @@ class ModuleChunkLoadingRuntimeModule extends RuntimeModule {
129
175
  chunk.hasChildByOrder(chunkGraph, "preload", true, chunkHasJs);
130
176
  // Under module output each hinted chunk is a known file, so the urls are written
131
177
  // out and read by id rather than built from the chunk id at runtime.
132
- const bakedChunkUrls =
178
+ const chunkUrls =
133
179
  withPrefetch || withPreload
134
180
  ? runtimeTemplate.analyzableChunkScriptUrls(
135
181
  chunk,
@@ -138,12 +184,16 @@ class ModuleChunkLoadingRuntimeModule extends RuntimeModule {
138
184
  this
139
185
  )
140
186
  : null;
141
- // A hint is best-effort, so an id an incomplete map lacks is not worth a per-id
142
- // fallback — only a complete map replaces the runtime name lookup.
143
- const chunkUrls =
144
- bakedChunkUrls !== null && bakedChunkUrls.complete
145
- ? bakedChunkUrls.urls
146
- : null;
187
+ // Under module output every chunk the loader reaches is a known file, so it
188
+ // imports a literal specifier read by id instead of a url built from that id.
189
+ const chunkImports = withJsLoading
190
+ ? runtimeTemplate.analyzableChunkImports(
191
+ chunk,
192
+ chunkGraph,
193
+ this._runtimeRequirements,
194
+ this
195
+ )
196
+ : null;
147
197
  const conditionMap = chunkGraph.getChunkConditionMap(chunk, chunkHasJs);
148
198
  const hasJsMatcher = compileBooleanMatcher(conditionMap);
149
199
  const initialChunkIds = getInitialChunkIds(chunk, chunkGraph, chunkHasJs);
@@ -158,7 +208,7 @@ class ModuleChunkLoadingRuntimeModule extends RuntimeModule {
158
208
  publicPath === "auto"
159
209
  ? JSON.stringify(rootOutputDir)
160
210
  : typeof publicPath === "string" &&
161
- !/^(?:\.{0,2}\/|[a-zA-Z][\w+.-]*:)/.test(publicPath) &&
211
+ !RESOLVABLE_SPECIFIER_REGEXP.test(publicPath) &&
162
212
  !getAPIPlugin().usesRuntimePublicPathOverride(compilation)
163
213
  ? `"./" + ${RuntimeGlobals.publicPath}`
164
214
  : RuntimeGlobals.publicPath;
@@ -179,7 +229,6 @@ class ModuleChunkLoadingRuntimeModule extends RuntimeModule {
179
229
  const withInstalledChunks =
180
230
  withLoading ||
181
231
  withExternalInstallChunk ||
182
- withAnalyzableImport ||
183
232
  withOnChunkLoad ||
184
233
  withHmr ||
185
234
  withPrefetch ||
@@ -194,6 +243,19 @@ class ModuleChunkLoadingRuntimeModule extends RuntimeModule {
194
243
  chunkUrls === null
195
244
  ? `${RuntimeGlobals.publicPath} + ${RuntimeGlobals.getChunkScriptFilename}(${id})`
196
245
  : `chunkUrls[${id}]()`;
246
+ const runtimeImport = `${importFunctionName}(${chunkImportBase} + ${RuntimeGlobals.getChunkScriptFilename}(chunkId))`;
247
+ // A hot update can force-load an id this build never saw, and a chunk with a
248
+ // runtime of its own is never named, so only those keep the url form.
249
+ const withRuntimeUrl =
250
+ chunkImports === null ||
251
+ withHmr ||
252
+ runtimeTemplate.chunkImportsNeedRuntimeUrl(chunk, chunkGraph);
253
+ const chunkImport =
254
+ chunkImports === null
255
+ ? runtimeImport
256
+ : withRuntimeUrl
257
+ ? `(${RuntimeGlobals.hasOwnProperty}(chunkImports, chunkId) ? chunkImports[chunkId]() : ${runtimeImport})`
258
+ : "chunkImports[chunkId]()";
197
259
  return Template.asString([
198
260
  withBaseURI
199
261
  ? this._generateBaseUri(chunk, rootOutputDir)
@@ -211,6 +273,20 @@ class ModuleChunkLoadingRuntimeModule extends RuntimeModule {
211
273
  ""
212
274
  ]
213
275
  : []),
276
+ ...(chunkImports
277
+ ? [
278
+ `${cst} chunkImports = {\n${Template.indent(
279
+ Array.from(
280
+ chunkImports,
281
+ ([id, specifier]) =>
282
+ `${JSON.stringify(String(id))}: ${runtimeTemplate.returningFunction(
283
+ `${importFunctionName}(${specifier})`
284
+ )}`
285
+ ).join(",\n")
286
+ )}\n};`,
287
+ ""
288
+ ]
289
+ : []),
214
290
  withInstalledChunks
215
291
  ? Template.asString([
216
292
  "// object to store loaded and loading chunks",
@@ -227,7 +303,7 @@ class ModuleChunkLoadingRuntimeModule extends RuntimeModule {
227
303
  ])
228
304
  : "// no installed chunks",
229
305
  "",
230
- withLoading || withExternalInstallChunk || withAnalyzableImport
306
+ withLoading || withExternalInstallChunk
231
307
  ? `${cst} installChunk = ${runtimeTemplate.basicFunction("data", [
232
308
  runtimeTemplate.destructureObject(
233
309
  [
@@ -286,9 +362,7 @@ class ModuleChunkLoadingRuntimeModule extends RuntimeModule {
286
362
  : `if(${hasJsMatcher("chunkId")}) {`,
287
363
  Template.indent([
288
364
  "// setup Promise in chunk cache",
289
- `${lt} promise = ${importFunctionName}(${chunkImportBase} + ${
290
- RuntimeGlobals.getChunkScriptFilename
291
- }(chunkId)).then(installChunk, ${runtimeTemplate.basicFunction(
365
+ `${lt} promise = ${chunkImport}.then(installChunk, ${runtimeTemplate.basicFunction(
292
366
  "e",
293
367
  [
294
368
  "if(installedChunks[chunkId] !== 0) installedChunks[chunkId] = undefined;",
@@ -428,48 +502,6 @@ class ModuleChunkLoadingRuntimeModule extends RuntimeModule {
428
502
  ])
429
503
  : "// no external install chunk",
430
504
  "",
431
- withAnalyzableImport
432
- ? `${
433
- RuntimeGlobals.analyzableChunkImport
434
- } = ${runtimeTemplate.basicFunction("chunkId, importFn", [
435
- // `ensureChunk` with its `.j` half replaced by a literal `import()` a foreign
436
- // bundler can follow. The remaining handlers still run, so a chunk's css and
437
- // its prefetch/preload children are not lost by taking this path.
438
- `${lt} promises = [];`,
439
- `${lt} installedChunkData = ${RuntimeGlobals.hasOwnProperty}(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;`,
440
- 'if(installedChunkData !== 0) { // 0 means "already installed".',
441
- Template.indent([
442
- '// a Promise means "currently loading".',
443
- "if(installedChunkData) {",
444
- Template.indent(["promises.push(installedChunkData[1]);"]),
445
- "} else {",
446
- Template.indent([
447
- `${lt} promise = importFn().then(installChunk, ${runtimeTemplate.basicFunction(
448
- "e",
449
- [
450
- "if(installedChunks[chunkId] !== 0) installedChunks[chunkId] = undefined;",
451
- "throw e;"
452
- ]
453
- )});`,
454
- `promise = Promise.race([promise, new Promise(${runtimeTemplate.expressionFunction(
455
- "installedChunkData = installedChunks[chunkId] = [resolve]",
456
- "resolve"
457
- )})]);`,
458
- "promises.push((installedChunkData[1] = promise));"
459
- ]),
460
- "}"
461
- ]),
462
- "}",
463
- withLoading
464
- ? `Object.keys(${fn}).forEach(${runtimeTemplate.basicFunction(
465
- "key",
466
- [`if(key !== "j") ${fn}[key](chunkId, promises);`]
467
- )});`
468
- : "// no other chunk loading handlers",
469
- "return Promise.all(promises);"
470
- ])};`
471
- : "// no analyzable chunk import",
472
- "",
473
505
  withOnChunkLoad
474
506
  ? `${
475
507
  RuntimeGlobals.onChunksLoaded
@@ -26,14 +26,20 @@
26
26
 
27
27
  /** @typedef {(options: ApplyOptions) => ApplyResult} ApplyHandler */
28
28
  /** @typedef {(moduleId: ModuleId, applyHandlers: ApplyHandler[]) => void} InvalidateModuleHandler */
29
- /** @typedef {(chunkIds: ModuleId[], removedChunks: ModuleId[], removedModules: ModuleId[], promises: Promise<unknown>[], applyHandlers: ApplyHandler[], updatedModulesList: ModuleId[], css: ModuleId[] | undefined, forceLoadChunks: ModuleId[] | undefined) => void} DownloadUpdateHandler */
29
+ /**
30
+ * @typedef {object} CssUpdateManifest
31
+ * @property {ModuleId[]} r updated chunk ids that no longer have a stylesheet
32
+ * @property {Record<string, string>=} n the stylesheet name of each updated chunk whose name moved with its content
33
+ */
34
+
35
+ /** @typedef {(chunkIds: ModuleId[], removedChunks: ModuleId[], removedModules: ModuleId[], promises: Promise<unknown>[], applyHandlers: ApplyHandler[], updatedModulesList: ModuleId[], css: CssUpdateManifest | undefined, forceLoadChunks: ModuleId[] | undefined) => void} DownloadUpdateHandler */
30
36
 
31
37
  /**
32
38
  * @typedef {object} HMRManifest
33
39
  * @property {ModuleId[]} c updated chunk ids
34
40
  * @property {ModuleId[]} r removed chunk ids
35
41
  * @property {ModuleId[]} m removed module ids
36
- * @property {ModuleId[]=} css updated css chunk ids
42
+ * @property {CssUpdateManifest=} css what the stylesheet loader needs to know about the update
37
43
  * @property {ModuleId[]=} f chunk ids to force-load
38
44
  */
39
45
 
@@ -16,6 +16,15 @@ class HotModuleReplacementRuntimeModule extends RuntimeModule {
16
16
  super("hot module replacement", RuntimeModule.STAGE_BASIC);
17
17
  }
18
18
 
19
+ /**
20
+ * The `[handlerMap, key]` pairs this module installs onto a chunk handler map
21
+ * such as `__webpack_require__.f`, or `null` where it cannot name them.
22
+ * @returns {[string, string][] | null} installed chunk handlers (do not mutate)
23
+ */
24
+ getInstalledChunkHandlers() {
25
+ return RuntimeModule.NO_CHUNK_HANDLERS;
26
+ }
27
+
19
28
  /**
20
29
  * Generates runtime code for this runtime module.
21
30
  * @returns {string | null} runtime code
@@ -9,6 +9,7 @@ const ConcatenationScope = require("../ConcatenationScope");
9
9
  const Generator = require("../Generator");
10
10
  const {
11
11
  HTML_TYPE,
12
+ HTML_TYPES,
12
13
  JAVASCRIPT_TYPE,
13
14
  JAVASCRIPT_TYPES
14
15
  } = require("../ModuleSourceTypeConstants");
@@ -1047,13 +1048,16 @@ class HtmlGenerator extends Generator {
1047
1048
  * Creates an instance of HtmlGenerator.
1048
1049
  * @param {HtmlGeneratorOptions=} options generator options
1049
1050
  * @param {ModuleGraph=} moduleGraph the module graph; used to detect when an HTML module is reached as a compilation entry so `extract` can default to `true` for it
1051
+ * @param {((module: NormalModule) => boolean)=} isPageOnly tells whether the module's only output is its emitted page, so it exposes no JavaScript
1050
1052
  */
1051
- constructor(options, moduleGraph) {
1053
+ constructor(options, moduleGraph, isPageOnly) {
1052
1054
  super();
1053
1055
  /** @type {HtmlGeneratorOptions} */
1054
1056
  this.options = options || {};
1055
1057
  /** @type {ModuleGraph | undefined} */
1056
1058
  this._moduleGraph = moduleGraph;
1059
+ /** @type {((module: NormalModule) => boolean) | undefined} */
1060
+ this._isPageOnly = isPageOnly;
1057
1061
  // Raw dependency-template render (before `[webpack/auto]` resolution),
1058
1062
  // shared between the JS and HTML type passes of a single
1059
1063
  // `codeGeneration()` call. Keyed by that call's `runtimeRequirements`
@@ -1134,6 +1138,9 @@ class HtmlGenerator extends Generator {
1134
1138
  */
1135
1139
  getTypes(module) {
1136
1140
  if (this._shouldExposeHtmlType(module)) {
1141
+ // A page nothing else reads has no JavaScript side: that chunk would
1142
+ // only re-export the markup already emitted as the `.html` asset.
1143
+ if (this._isPageOnly && this._isPageOnly(module)) return HTML_TYPES;
1137
1144
  return JAVASCRIPT_AND_HTML_TYPES;
1138
1145
  }
1139
1146
  return JAVASCRIPT_TYPES;
@@ -1143,10 +1150,9 @@ class HtmlGenerator extends Generator {
1143
1150
  * @returns {boolean} whether getTypes() depends on the module's incoming connections
1144
1151
  */
1145
1152
  getTypesDependOnIncomingConnections() {
1146
- // A fixed extract (`true` / `false` / `"inline"`) gives a stable type set;
1147
- // only the unset default reads `_isEntryModule` (incoming connections).
1148
- const { extract } = this.options;
1149
- return extract !== true && extract !== false && extract !== "inline";
1153
+ // Every page that can expose the html type reads incoming connections —
1154
+ // for the `extract` default, and for the page-only JavaScript drop.
1155
+ return this.options.extract !== false;
1150
1156
  }
1151
1157
 
1152
1158
  /**