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
@@ -0,0 +1,149 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ */
4
+
5
+ "use strict";
6
+
7
+ const { SyncWaterfallHook } = require("tapable");
8
+ const Compilation = require("../Compilation");
9
+ const RuntimeGlobals = require("../RuntimeGlobals");
10
+ const RuntimeModule = require("../RuntimeModule");
11
+ const Template = require("../Template");
12
+
13
+ /**
14
+ * @typedef {object} ResourceHintRuntimeModulePluginHooks
15
+ * @property {SyncWaterfallHook<[string]>} linkPrefetch
16
+ * @property {SyncWaterfallHook<[string]>} linkPreload
17
+ */
18
+
19
+ /** @type {WeakMap<Compilation, ResourceHintRuntimeModulePluginHooks>} */
20
+ const compilationHooksMap = new WeakMap();
21
+
22
+ /**
23
+ * Maps a request/filename to the value of the `<link>` `as` attribute. Best
24
+ * effort — falls back to `"fetch"` when the type cannot be guessed. Pattern
25
+ * matches against the path part, ignoring any query string suffix.
26
+ * @param {string} request request/filename
27
+ * @returns {string} value for the `as` attribute
28
+ */
29
+ const guessAsAttribute = (request) => {
30
+ if (/\.(png|jpe?g|gif|svg|webp|avif|bmp|ico|tiff?)(\?.*)?$/i.test(request)) {
31
+ return "image";
32
+ }
33
+ if (/\.(woff2?|ttf|otf|eot)(\?.*)?$/i.test(request)) return "font";
34
+ if (/\.css(\?.*)?$/i.test(request)) return "style";
35
+ if (/\.[cm]?jsx?(\?.*)?$/i.test(request)) return "script";
36
+ if (/\.[cm]?tsx?(\?.*)?$/i.test(request)) return "script";
37
+ if (/\.(mp3|wav|flac|aac|m4a|ogg|oga)(\?.*)?$/i.test(request)) return "audio";
38
+ if (/\.(mp4|webm|mkv|mov|m4v|ogv|avi)(\?.*)?$/i.test(request)) return "video";
39
+ if (/\.vtt(\?.*)?$/i.test(request)) return "track";
40
+ return "fetch";
41
+ };
42
+
43
+ class ResourceHintRuntimeModule extends RuntimeModule {
44
+ /**
45
+ * @param {Compilation} compilation the compilation
46
+ * @returns {ResourceHintRuntimeModulePluginHooks} hooks
47
+ */
48
+ static getCompilationHooks(compilation) {
49
+ if (!(compilation instanceof Compilation)) {
50
+ throw new TypeError(
51
+ "The 'compilation' argument must be an instance of Compilation"
52
+ );
53
+ }
54
+ let hooks = compilationHooksMap.get(compilation);
55
+ if (hooks === undefined) {
56
+ hooks = {
57
+ linkPrefetch: new SyncWaterfallHook(["source"]),
58
+ linkPreload: new SyncWaterfallHook(["source"])
59
+ };
60
+ compilationHooksMap.set(compilation, hooks);
61
+ }
62
+ return hooks;
63
+ }
64
+
65
+ /**
66
+ * @param {"prefetch" | "preload"} rel link rel value
67
+ */
68
+ constructor(rel) {
69
+ super(`asset ${rel}`, RuntimeModule.STAGE_ATTACH);
70
+ this._rel = rel;
71
+ }
72
+
73
+ /**
74
+ * Generates runtime code for this runtime module.
75
+ * @returns {string | null} runtime code
76
+ */
77
+ generate() {
78
+ const compilation = /** @type {Compilation} */ (this.compilation);
79
+ const { runtimeTemplate, outputOptions } = compilation;
80
+ const { crossOriginLoading } = outputOptions;
81
+ const isNeutralPlatform = runtimeTemplate.isNeutralPlatform();
82
+ const rel = this._rel;
83
+ const fnName =
84
+ rel === "prefetch"
85
+ ? RuntimeGlobals.prefetchAsset
86
+ : RuntimeGlobals.preloadAsset;
87
+ const hook =
88
+ ResourceHintRuntimeModule.getCompilationHooks(compilation)[
89
+ rel === "prefetch" ? "linkPrefetch" : "linkPreload"
90
+ ];
91
+
92
+ const body = [
93
+ "if (installed[href]) return href;",
94
+ "installed[href] = 1;",
95
+ hook.call(
96
+ Template.asString([
97
+ "var link = document.createElement('link');",
98
+ `link.rel = ${JSON.stringify(rel)};`,
99
+ "link.href = href;",
100
+ "if (as) link.as = as;",
101
+ "if (type) link.type = type;",
102
+ "if (media) link.media = media;",
103
+ "if (fetchPriority) {",
104
+ Template.indent([
105
+ 'link.setAttribute("fetchpriority", fetchPriority);'
106
+ ]),
107
+ "}",
108
+ `if (${RuntimeGlobals.scriptNonce}) {`,
109
+ Template.indent(
110
+ `link.setAttribute("nonce", ${RuntimeGlobals.scriptNonce});`
111
+ ),
112
+ "}",
113
+ crossOriginLoading
114
+ ? crossOriginLoading === "use-credentials"
115
+ ? 'link.crossOrigin = "use-credentials";'
116
+ : Template.asString([
117
+ "if (link.href.indexOf(window.location.origin + '/') !== 0) {",
118
+ Template.indent(
119
+ `link.crossOrigin = ${JSON.stringify(crossOriginLoading)};`
120
+ ),
121
+ "}"
122
+ ])
123
+ : ""
124
+ ])
125
+ ),
126
+ "document.head.appendChild(link);",
127
+ "return href;"
128
+ ];
129
+
130
+ const fnBody = isNeutralPlatform
131
+ ? ["if (typeof document === 'undefined') return href;", ...body]
132
+ : body;
133
+
134
+ // `Object.create(null)` keeps the dedupe map free of inherited
135
+ // properties (`toString`, `__proto__`, …) so any URL string is a
136
+ // safe key.
137
+ return Template.asString([
138
+ "var installed = Object.create(null);",
139
+ `${fnName} = ${runtimeTemplate.basicFunction(
140
+ "href, as, type, media, fetchPriority",
141
+ fnBody
142
+ )};`
143
+ ]);
144
+ }
145
+ }
146
+
147
+ ResourceHintRuntimeModule.guessAsAttribute = guessAsAttribute;
148
+
149
+ module.exports = ResourceHintRuntimeModule;
@@ -0,0 +1,210 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ */
4
+
5
+ "use strict";
6
+
7
+ const RuntimeGlobals = require("../RuntimeGlobals");
8
+ const RuntimeModule = require("../RuntimeModule");
9
+ const Template = require("../Template");
10
+ const CssUrlDependency = require("../dependencies/CssUrlDependency");
11
+ const HtmlSourceDependency = require("../dependencies/HtmlSourceDependency");
12
+ const URLDependency = require("../dependencies/URLDependency");
13
+ const ResourceHintRuntimeModule = require("./ResourceHintRuntimeModule");
14
+
15
+ /** @typedef {import("../Chunk")} Chunk */
16
+ /** @typedef {import("../ChunkGraph")} ChunkGraph */
17
+ /** @typedef {import("../Compilation")} Compilation */
18
+ /** @typedef {import("../Module")} Module */
19
+ /** @typedef {import("../ModuleGraph")} ModuleGraph */
20
+
21
+ /**
22
+ * Fires `<link rel="prefetch">` / `<link rel="preload">` for every asset
23
+ * referenced from this chunk via `new URL(..., import.meta.url)` carrying
24
+ * `webpackPrefetch` / `webpackPreload`, at chunk startup. Runs before any
25
+ * user module evaluates, so by the time user code reaches the
26
+ * corresponding `new URL(...)` (or hands the URL to `<img>`, `fetch`,
27
+ * `new Worker`, etc.), the browser already has the response in flight.
28
+ */
29
+ class StartupAssetHintRuntimeModule extends RuntimeModule {
30
+ constructor() {
31
+ super("startup asset hints", RuntimeModule.STAGE_TRIGGER);
32
+ }
33
+
34
+ /**
35
+ * Generates runtime code for this runtime module.
36
+ * @returns {string | null} runtime code
37
+ */
38
+ generate() {
39
+ const compilation = /** @type {Compilation} */ (this.compilation);
40
+ const chunkGraph = /** @type {ChunkGraph} */ (this.chunkGraph);
41
+ const moduleGraph = /** @type {ModuleGraph} */ (compilation.moduleGraph);
42
+ const runtimeTemplate = compilation.runtimeTemplate;
43
+ const chunk = /** @type {Chunk} */ (this.chunk);
44
+ const runtimeRequirements =
45
+ /** @type {Set<string>} */
46
+ (chunkGraph.getTreeRuntimeRequirements(chunk));
47
+
48
+ // Dedupe per asset module: if the same asset is referenced twice
49
+ // (e.g. CSS rule says `prefetch`, a JS magic comment says
50
+ // `preload`), pick `preload` over `prefetch` and keep the most
51
+ // recently seen explicit attribute overrides. Avoids emitting a
52
+ // duplicate `<link>` and ordering-dependent winners.
53
+ /**
54
+ * @typedef {object} AssetHintEntry
55
+ * @property {import("../Module")} assetModule
56
+ * @property {string} request
57
+ * @property {boolean} preload
58
+ * @property {("low" | "high" | "auto" | undefined)} fetchPriority
59
+ * @property {(string | undefined)} as
60
+ * @property {(string | undefined)} type
61
+ * @property {(string | undefined)} media
62
+ */
63
+ // Per-asset dedupe vs the HTML-head emission by `HtmlEntryDependency`:
64
+ // if the asset is reachable from an HTML entrypoint's chunks, its
65
+ // `<link>` lands in that HTML `<head>` already — skip the runtime
66
+ // hint for that asset so the DOM doesn't carry two tags for one URL.
67
+ // Set is computed once per compilation from the module graph (stable
68
+ // across cache reads), never from a mutable cross-module marker.
69
+ const ResourceHintPlugin = require("./ResourceHintPlugin");
70
+
71
+ // `output.resourceHints: "none"` is a hard off switch — the plugin's
72
+ // runtime-requirements hook already skips adding this module then, so no
73
+ // `"none"` guard is needed here.
74
+ const { isHtmlHinted } =
75
+ ResourceHintPlugin.getCompilationResolver(compilation);
76
+
77
+ /** @type {Map<string, AssetHintEntry>} */
78
+ const perAsset = new Map();
79
+ for (const module of chunkGraph.getChunkModulesIterable(chunk)) {
80
+ const deps =
81
+ /** @type {{ dependencies?: import("../Dependency")[] }} */
82
+ (module).dependencies;
83
+ if (!deps) continue;
84
+ for (const dep of deps) {
85
+ if (
86
+ !(dep instanceof URLDependency) &&
87
+ !(dep instanceof CssUrlDependency) &&
88
+ !(dep instanceof HtmlSourceDependency)
89
+ ) {
90
+ continue;
91
+ }
92
+ if (!dep.prefetch && !dep.preload) continue;
93
+ const assetModule = moduleGraph.getModule(dep);
94
+ if (!assetModule) continue;
95
+ if (isHtmlHinted(assetModule)) continue;
96
+ const key = assetModule.identifier();
97
+ const urlDep =
98
+ /** @type {URLDependency & Partial<CssUrlDependency> & Partial<HtmlSourceDependency>} */
99
+ (dep);
100
+ const existing = perAsset.get(key);
101
+ if (existing) {
102
+ if (dep.preload) existing.preload = true;
103
+ if (dep.fetchPriority) existing.fetchPriority = dep.fetchPriority;
104
+ if (urlDep.asAttribute) existing.as = urlDep.asAttribute;
105
+ if (urlDep.typeAttribute) existing.type = urlDep.typeAttribute;
106
+ if (urlDep.mediaAttribute) existing.media = urlDep.mediaAttribute;
107
+ } else {
108
+ perAsset.set(key, {
109
+ assetModule: /** @type {Module} */ (assetModule),
110
+ request: dep.request,
111
+ preload: Boolean(dep.preload),
112
+ fetchPriority: dep.fetchPriority,
113
+ as: urlDep.asAttribute,
114
+ type: urlDep.typeAttribute,
115
+ media: urlDep.mediaAttribute
116
+ });
117
+ }
118
+ }
119
+ }
120
+ const lines = [];
121
+ for (const entry of perAsset.values()) {
122
+ const fn = entry.preload
123
+ ? RuntimeGlobals.preloadAsset
124
+ : RuntimeGlobals.prefetchAsset;
125
+ // For CSS-only assets (referenced from `url(...)` but never
126
+ // from JS) the module produces no JS source, so
127
+ // `__webpack_require__(id)` would throw at runtime. Use the
128
+ // emitted filename + publicPath directly in that case; asset
129
+ // modules referenced from JS stay on the existing `moduleRaw`
130
+ // path which yields the same URL.
131
+ const hasJsSourceType = entry.assetModule
132
+ .getSourceTypes()
133
+ .has("javascript");
134
+ let hrefExpr;
135
+ if (hasJsSourceType) {
136
+ hrefExpr = runtimeTemplate.moduleRaw({
137
+ chunkGraph,
138
+ module: entry.assetModule,
139
+ request: entry.request,
140
+ runtimeRequirements,
141
+ weak: false
142
+ });
143
+ } else {
144
+ const buildInfo =
145
+ /** @type {{ filename?: string }} */
146
+ (entry.assetModule.buildInfo);
147
+ if (!buildInfo || !buildInfo.filename) continue;
148
+ runtimeRequirements.add(RuntimeGlobals.publicPath);
149
+ hrefExpr = `${RuntimeGlobals.publicPath} + ${JSON.stringify(buildInfo.filename)}`;
150
+ }
151
+ const as =
152
+ entry.as || ResourceHintRuntimeModule.guessAsAttribute(entry.request);
153
+ lines.push(
154
+ `${fn}(${hrefExpr}, ${JSON.stringify(as)}, ${
155
+ entry.type ? JSON.stringify(entry.type) : "undefined"
156
+ }, ${entry.media ? JSON.stringify(entry.media) : "undefined"}, ${
157
+ entry.fetchPriority
158
+ ? JSON.stringify(entry.fetchPriority)
159
+ : "undefined"
160
+ });`
161
+ );
162
+ }
163
+ if (lines.length === 0) return null;
164
+ // `__webpack_nonce__` set inside the entry module is too late — the
165
+ // entry hasn't run yet. Read the nonce off the `<script>` tag that
166
+ // loaded the bundle, so prefetch / preload links match a CSP that
167
+ // demands the same nonce as the script.
168
+ //
169
+ // - For classic script output, `document.currentScript` is the
170
+ // loading `<script>` element while the runtime executes.
171
+ // - For ESM output (`output.module: true`), `document.currentScript`
172
+ // is `null`; locate the loading `<script type="module">` by
173
+ // matching `script.src` against `import.meta.url`.
174
+ const { module: isModule, importMetaName } = compilation.outputOptions;
175
+ const nonceSetup = isModule
176
+ ? [
177
+ "if (typeof document !== 'undefined') {",
178
+ Template.indent([
179
+ `var url = ${importMetaName}.url;`,
180
+ "var scripts = document.getElementsByTagName('script');",
181
+ "for (var i = 0; i < scripts.length; i++) {",
182
+ Template.indent([
183
+ `if (scripts[i].src === url && scripts[i].nonce && !${RuntimeGlobals.scriptNonce}) {`,
184
+ Template.indent([
185
+ `${RuntimeGlobals.scriptNonce} = scripts[i].nonce;`,
186
+ "break;"
187
+ ]),
188
+ "}"
189
+ ]),
190
+ "}"
191
+ ]),
192
+ "}"
193
+ ]
194
+ : [
195
+ "if (typeof document !== 'undefined') {",
196
+ Template.indent([
197
+ "var currentScript = document.currentScript;",
198
+ `if (currentScript && currentScript.nonce && !${RuntimeGlobals.scriptNonce}) {`,
199
+ Template.indent(
200
+ `${RuntimeGlobals.scriptNonce} = currentScript.nonce;`
201
+ ),
202
+ "}"
203
+ ]),
204
+ "}"
205
+ ];
206
+ return Template.asString([...nonceSetup, ...lines]);
207
+ }
208
+ }
209
+
210
+ module.exports = StartupAssetHintRuntimeModule;
@@ -0,0 +1,103 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ */
4
+
5
+ "use strict";
6
+
7
+ const UnsupportedFeatureWarning = require("../errors/UnsupportedFeatureWarning");
8
+
9
+ /** @typedef {import("../Dependency").DependencyLocation} DependencyLocation */
10
+ /** @typedef {import("../NormalModule")} NormalModule */
11
+
12
+ /**
13
+ * @typedef {object} ResourceHintOptions
14
+ * @property {true=} prefetch
15
+ * @property {true=} preload
16
+ * @property {("high" | "low" | "auto")=} fetchPriority
17
+ * @property {string=} as
18
+ * @property {string=} type
19
+ * @property {string=} media
20
+ */
21
+
22
+ /**
23
+ * Reads `webpackPrefetch` / `webpackPreload` / `webpackFetchPriority` /
24
+ * `webpackAs` / `webpackType` / `webpackMedia` from a parsed magic-comment
25
+ * options object. Invalid values emit warnings to the given module.
26
+ * @param {Record<string, EXPECTED_ANY> | null | undefined} importOptions parsed comment options
27
+ * @param {NormalModule} module the module to attach warnings to
28
+ * @param {DependencyLocation} loc location for warnings
29
+ * @returns {ResourceHintOptions} parsed hints (empty when no comments matched)
30
+ */
31
+ const parseResourceHintOptions = (importOptions, module, loc) => {
32
+ /** @type {ResourceHintOptions} */
33
+ const hints = {};
34
+ if (!importOptions) return hints;
35
+
36
+ /**
37
+ * @param {string} message warning text
38
+ * @returns {void}
39
+ */
40
+ const warn = (message) => {
41
+ module.addWarning(new UnsupportedFeatureWarning(message, loc));
42
+ };
43
+
44
+ if (importOptions.webpackPrefetch !== undefined) {
45
+ if (importOptions.webpackPrefetch === true) {
46
+ hints.prefetch = true;
47
+ } else {
48
+ warn(
49
+ `\`webpackPrefetch\` expected true, but received: ${importOptions.webpackPrefetch}.`
50
+ );
51
+ }
52
+ }
53
+ if (importOptions.webpackPreload !== undefined) {
54
+ if (importOptions.webpackPreload === true) {
55
+ hints.preload = true;
56
+ } else {
57
+ warn(
58
+ `\`webpackPreload\` expected true, but received: ${importOptions.webpackPreload}.`
59
+ );
60
+ }
61
+ }
62
+ if (importOptions.webpackFetchPriority !== undefined) {
63
+ const fp = importOptions.webpackFetchPriority;
64
+ if (fp === "high" || fp === "low" || fp === "auto") {
65
+ hints.fetchPriority = fp;
66
+ } else {
67
+ warn(
68
+ `\`webpackFetchPriority\` expected "low", "high" or "auto", but received: ${fp}.`
69
+ );
70
+ }
71
+ }
72
+ if (importOptions.webpackAs !== undefined) {
73
+ if (typeof importOptions.webpackAs === "string") {
74
+ hints.as = importOptions.webpackAs;
75
+ } else {
76
+ warn(
77
+ `\`webpackAs\` expected a string, but received: ${importOptions.webpackAs}.`
78
+ );
79
+ }
80
+ }
81
+ if (importOptions.webpackType !== undefined) {
82
+ if (typeof importOptions.webpackType === "string") {
83
+ hints.type = importOptions.webpackType;
84
+ } else {
85
+ warn(
86
+ `\`webpackType\` expected a string, but received: ${importOptions.webpackType}.`
87
+ );
88
+ }
89
+ }
90
+ if (importOptions.webpackMedia !== undefined) {
91
+ if (typeof importOptions.webpackMedia === "string") {
92
+ hints.media = importOptions.webpackMedia;
93
+ } else {
94
+ warn(
95
+ `\`webpackMedia\` expected a string, but received: ${importOptions.webpackMedia}.`
96
+ );
97
+ }
98
+ }
99
+
100
+ return hints;
101
+ };
102
+
103
+ module.exports = parseResourceHintOptions;
@@ -12,6 +12,7 @@ const { SyncHook } = require("tapable");
12
12
  /** @typedef {import("../../declarations/WebpackOptions").RuleSetUseItem} RuleSetUseItem */
13
13
  /** @typedef {import("../../declarations/WebpackOptions").RuleSetLoaderOptions} RuleSetLoaderOptions */
14
14
  /** @typedef {import("../../declarations/WebpackOptions").RuleSetRule} RuleSetRule */
15
+ /** @typedef {import("../../declarations/WebpackOptions").RuleSetConditionAbsolute} RuleSetConditionAbsolute */
15
16
 
16
17
  /** @typedef {(Falsy | RuleSetRule)[]} RuleSetRules */
17
18
 
@@ -461,6 +462,119 @@ class RuleSetCompiler {
461
462
  `Compiling RuleSet failed: ${message} (at ${path}: ${value})`
462
463
  );
463
464
  }
465
+
466
+ /**
467
+ * Best-effort detection of a user-registered loader (or explicit module type)
468
+ * for a resource, without building the whole rule set. Used to resolve the
469
+ * `experiments.css`/`experiments.html`/`experiments.asyncWebAssembly` "auto"
470
+ * defaults: when the user already handles these files the built-in module type
471
+ * stays off, so enabling it by default is non-breaking.
472
+ *
473
+ * `include`/`exclude` are treated leniently — a matching `test`/`resource`/
474
+ * `include` with a loader counts even when another condition would narrow it —
475
+ * so a loader scoped to e.g. `include: /src/` still keeps the built-in type off
476
+ * and those files are not double-processed. `enforce: "pre"`/`"post"` loaders
477
+ * are ignored: they don't establish the module type (e.g. a stylelint pre-loader
478
+ * must not suppress the built-in css type). A `test` regexp that references the
479
+ * extension (e.g. `/source\.css$/`) also counts even if the sample path itself
480
+ * doesn't match, so a loader scoped to specific filenames is still detected.
481
+ * @param {import("../../declarations/WebpackOptions").RuleSetRules | undefined} rules user `module.rules`
482
+ * @param {string} resource sample resource path (e.g. `"/file.css"`)
483
+ * @param {boolean=} inherited whether an enclosing rule already matched the resource
484
+ * @returns {boolean} whether a rule assigns a loader or module type to the resource
485
+ */
486
+ static hasRuleForResource(rules, resource, inherited = false) {
487
+ if (!rules) return false;
488
+ // `\.css` for `/file.css`, `\.wasm` for `/file.wasm`, …
489
+ const extProbe = `\\.${resource.slice(resource.lastIndexOf(".") + 1)}`;
490
+ for (const rule of rules) {
491
+ if (!rule || typeof rule !== "object") continue;
492
+ const matched =
493
+ inherited ||
494
+ matchesResource(rule.test, resource, extProbe) ||
495
+ matchesResource(rule.resource, resource, extProbe) ||
496
+ matchesResource(rule.include, resource, extProbe);
497
+ const establishesType =
498
+ rule.type !== undefined ||
499
+ ((rule.use !== undefined || rule.loader !== undefined) &&
500
+ rule.enforce === undefined);
501
+ if (matched && establishesType) return true;
502
+ if (
503
+ rule.oneOf &&
504
+ RuleSetCompiler.hasRuleForResource(rule.oneOf, resource, matched)
505
+ ) {
506
+ return true;
507
+ }
508
+ if (
509
+ rule.rules &&
510
+ RuleSetCompiler.hasRuleForResource(rule.rules, resource, matched)
511
+ ) {
512
+ return true;
513
+ }
514
+ }
515
+ return false;
516
+ }
464
517
  }
465
518
 
519
+ // Bare compiler reused to match single conditions via `compileCondition`
520
+ // (no plugins needed); created lazily on first use.
521
+ /** @type {RuleSetCompiler | undefined} */
522
+ let conditionCompiler;
523
+
524
+ /**
525
+ * Matches a single rule condition against a sample string, reusing the ruleset
526
+ * condition logic (string/regexp/function/array/and/or/not).
527
+ * @param {RuleSetConditionAbsolute | undefined} condition condition
528
+ * @param {string} resource sample resource path
529
+ * @returns {boolean} whether the condition matches
530
+ */
531
+ const matchRuleSetCondition = (condition, resource) => {
532
+ if (condition === undefined) return false;
533
+ if (conditionCompiler === undefined) {
534
+ conditionCompiler = new RuleSetCompiler([]);
535
+ }
536
+ try {
537
+ return conditionCompiler
538
+ .compileCondition("ruleSet", condition)
539
+ .fn(resource);
540
+ } catch (_err) {
541
+ return false;
542
+ }
543
+ };
544
+
545
+ /**
546
+ * Whether any regexp in the condition references the extension probe (e.g.
547
+ * `\.css`), i.e. the rule clearly targets that extension even if the generic
548
+ * sample path doesn't match its (possibly filename-scoped) pattern.
549
+ * @param {EXPECTED_ANY} condition condition
550
+ * @param {string} extProbe escaped extension probe (e.g. `"\\.css"`)
551
+ * @returns {boolean} whether a regexp in the condition targets the extension
552
+ */
553
+ const conditionReferencesExtension = (condition, extProbe) => {
554
+ if (condition instanceof RegExp) return condition.source.includes(extProbe);
555
+ if (Array.isArray(condition)) {
556
+ return condition.some((c) => conditionReferencesExtension(c, extProbe));
557
+ }
558
+ if (condition && typeof condition === "object") {
559
+ return (
560
+ conditionReferencesExtension(condition.and, extProbe) ||
561
+ conditionReferencesExtension(condition.or, extProbe)
562
+ );
563
+ }
564
+ return false;
565
+ };
566
+
567
+ /**
568
+ * A condition counts as targeting the resource if it matches the sample path or
569
+ * references the extension via a regexp.
570
+ * @param {RuleSetConditionAbsolute | undefined} condition condition
571
+ * @param {string} resource sample resource path
572
+ * @param {string} extProbe escaped extension probe (e.g. `"\\.css"`)
573
+ * @returns {boolean} whether the condition targets the resource's extension
574
+ */
575
+ const matchesResource = (condition, resource, extProbe) =>
576
+ condition !== undefined &&
577
+ (matchRuleSetCondition(condition, resource) ||
578
+ conditionReferencesExtension(condition, extProbe));
579
+
466
580
  module.exports = RuleSetCompiler;
@@ -0,0 +1,56 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ */
4
+
5
+ "use strict";
6
+
7
+ const RuntimeGlobals = require("../RuntimeGlobals");
8
+ const Template = require("../Template");
9
+ const HelperRuntimeModule = require("./HelperRuntimeModule");
10
+
11
+ /** @typedef {import("../Compilation")} Compilation */
12
+
13
+ class AsyncModuleGeneratorRuntimeModule extends HelperRuntimeModule {
14
+ constructor() {
15
+ super("async module generator");
16
+ }
17
+
18
+ /**
19
+ * Generates runtime code for this runtime module.
20
+ * @returns {string | null} runtime code
21
+ */
22
+ generate() {
23
+ const compilation = /** @type {Compilation} */ (this.compilation);
24
+ const { runtimeTemplate } = compilation;
25
+ const fn = RuntimeGlobals.asyncModuleGenerator;
26
+ const cst = runtimeTemplate.renderConst();
27
+ // Wrap a generator-based async module body so it drives like an `async`
28
+ // function: run the generator and resolve each `yield`ed dependency
29
+ // promise, without emitting `async`/`await`.
30
+ return Template.asString([
31
+ `${fn} = ${runtimeTemplate.returningFunction(
32
+ runtimeTemplate.basicFunction(
33
+ "__webpack_handle_async_dependencies__, __webpack_async_result__",
34
+ [
35
+ `${cst} gen = body(__webpack_handle_async_dependencies__, __webpack_async_result__);`,
36
+ `${cst} step = ${runtimeTemplate.basicFunction("key, arg", [
37
+ `${cst} info = gen[key](arg);`,
38
+ "if (info.done) return;",
39
+ `Promise.resolve(info.value).then(${runtimeTemplate.expressionFunction(
40
+ 'step("next", value)',
41
+ "value"
42
+ )}, ${runtimeTemplate.expressionFunction(
43
+ 'step("throw", err)',
44
+ "err"
45
+ )});`
46
+ ])};`,
47
+ 'step("next");'
48
+ ]
49
+ ),
50
+ "body"
51
+ )};`
52
+ ]);
53
+ }
54
+ }
55
+
56
+ module.exports = AsyncModuleGeneratorRuntimeModule;