webpack 5.65.0 → 5.69.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of webpack might be problematic. Click here for more details.

Files changed (134) hide show
  1. package/README.md +1 -1
  2. package/lib/APIPlugin.js +33 -0
  3. package/lib/Cache.js +1 -1
  4. package/lib/CacheFacade.js +4 -11
  5. package/lib/Chunk.js +2 -0
  6. package/lib/ChunkGraph.js +1 -2
  7. package/lib/CleanPlugin.js +1 -1
  8. package/lib/Compilation.js +93 -47
  9. package/lib/Compiler.js +57 -3
  10. package/lib/ContextModule.js +100 -41
  11. package/lib/ContextModuleFactory.js +60 -21
  12. package/lib/DelegatedModule.js +1 -1
  13. package/lib/Dependency.js +10 -0
  14. package/lib/DependencyTemplate.js +9 -0
  15. package/lib/DependencyTemplates.js +1 -1
  16. package/lib/DllModule.js +1 -1
  17. package/lib/EvalDevToolModulePlugin.js +16 -1
  18. package/lib/EvalSourceMapDevToolPlugin.js +18 -1
  19. package/lib/ExportsInfo.js +4 -4
  20. package/lib/ExternalModule.js +93 -53
  21. package/lib/ExternalModuleFactoryPlugin.js +1 -1
  22. package/lib/FileSystemInfo.js +29 -25
  23. package/lib/Generator.js +2 -0
  24. package/lib/HookWebpackError.js +1 -1
  25. package/lib/Module.js +25 -4
  26. package/lib/ModuleFilenameHelpers.js +5 -1
  27. package/lib/MultiCompiler.js +1 -1
  28. package/lib/MultiWatching.js +1 -1
  29. package/lib/NormalModule.js +9 -5
  30. package/lib/NormalModuleFactory.js +25 -27
  31. package/lib/ProgressPlugin.js +1 -1
  32. package/lib/RawModule.js +1 -1
  33. package/lib/RuntimeGlobals.js +29 -1
  34. package/lib/RuntimeModule.js +1 -1
  35. package/lib/RuntimePlugin.js +50 -0
  36. package/lib/RuntimeTemplate.js +21 -0
  37. package/lib/Template.js +2 -1
  38. package/lib/TemplatedPathPlugin.js +48 -23
  39. package/lib/Watching.js +2 -2
  40. package/lib/WebpackOptionsApply.js +43 -2
  41. package/lib/asset/AssetGenerator.js +67 -26
  42. package/lib/asset/AssetModulesPlugin.js +3 -0
  43. package/lib/asset/RawDataUrlModule.js +148 -0
  44. package/lib/async-modules/AwaitDependenciesInitFragment.js +4 -4
  45. package/lib/buildChunkGraph.js +1 -1
  46. package/lib/cache/ResolverCachePlugin.js +81 -29
  47. package/lib/cli.js +44 -3
  48. package/lib/config/defaults.js +86 -7
  49. package/lib/config/normalization.js +5 -0
  50. package/lib/container/ContainerEntryModule.js +4 -2
  51. package/lib/container/FallbackModule.js +4 -4
  52. package/lib/container/RemoteModule.js +4 -2
  53. package/lib/css/CssExportsGenerator.js +139 -0
  54. package/lib/css/CssGenerator.js +109 -0
  55. package/lib/css/CssLoadingRuntimeModule.js +440 -0
  56. package/lib/css/CssModulesPlugin.js +462 -0
  57. package/lib/css/CssParser.js +618 -0
  58. package/lib/css/walkCssTokens.js +659 -0
  59. package/lib/debug/ProfilingPlugin.js +15 -14
  60. package/lib/dependencies/ContextElementDependency.js +8 -2
  61. package/lib/dependencies/CreateScriptUrlDependency.js +12 -0
  62. package/lib/dependencies/CssExportDependency.js +85 -0
  63. package/lib/dependencies/CssImportDependency.js +75 -0
  64. package/lib/dependencies/CssLocalIdentifierDependency.js +119 -0
  65. package/lib/dependencies/CssSelfLocalIdentifierDependency.js +101 -0
  66. package/lib/dependencies/CssUrlDependency.js +132 -0
  67. package/lib/dependencies/ExportsInfoDependency.js +6 -0
  68. package/lib/dependencies/HarmonyCompatibilityDependency.js +5 -5
  69. package/lib/dependencies/ImportMetaPlugin.js +22 -3
  70. package/lib/dependencies/LoaderPlugin.js +2 -2
  71. package/lib/dependencies/URLDependency.js +3 -8
  72. package/lib/esm/ModuleChunkLoadingRuntimeModule.js +1 -1
  73. package/lib/hmr/LazyCompilationPlugin.js +45 -21
  74. package/lib/hmr/lazyCompilationBackend.js +4 -2
  75. package/lib/ids/DeterministicModuleIdsPlugin.js +55 -35
  76. package/lib/ids/HashedModuleIdsPlugin.js +9 -12
  77. package/lib/ids/IdHelpers.js +24 -10
  78. package/lib/ids/NamedModuleIdsPlugin.js +6 -9
  79. package/lib/ids/NaturalModuleIdsPlugin.js +10 -13
  80. package/lib/ids/OccurrenceModuleIdsPlugin.js +13 -10
  81. package/lib/ids/SyncModuleIdsPlugin.js +140 -0
  82. package/lib/index.js +10 -0
  83. package/lib/javascript/JavascriptGenerator.js +1 -0
  84. package/lib/javascript/JavascriptModulesPlugin.js +27 -2
  85. package/lib/javascript/StartupHelpers.js +6 -5
  86. package/lib/library/AssignLibraryPlugin.js +34 -5
  87. package/lib/library/EnableLibraryPlugin.js +11 -0
  88. package/lib/node/NodeTargetPlugin.js +1 -0
  89. package/lib/node/ReadFileChunkLoadingRuntimeModule.js +1 -1
  90. package/lib/node/RequireChunkLoadingRuntimeModule.js +1 -1
  91. package/lib/optimize/ConcatenatedModule.js +21 -9
  92. package/lib/runtime/AsyncModuleRuntimeModule.js +25 -15
  93. package/lib/runtime/CreateScriptRuntimeModule.js +36 -0
  94. package/lib/runtime/CreateScriptUrlRuntimeModule.js +9 -34
  95. package/lib/runtime/GetTrustedTypesPolicyRuntimeModule.js +76 -0
  96. package/lib/schemes/HttpUriPlugin.js +32 -11
  97. package/lib/serialization/FileMiddleware.js +44 -9
  98. package/lib/sharing/ConsumeSharedModule.js +4 -2
  99. package/lib/sharing/ProvideSharedModule.js +4 -2
  100. package/lib/sharing/utils.js +1 -1
  101. package/lib/stats/DefaultStatsFactoryPlugin.js +112 -67
  102. package/lib/stats/DefaultStatsPrinterPlugin.js +88 -23
  103. package/lib/util/ArrayHelpers.js +18 -4
  104. package/lib/util/AsyncQueue.js +1 -1
  105. package/lib/util/compileBooleanMatcher.js +1 -1
  106. package/lib/util/deterministicGrouping.js +1 -1
  107. package/lib/util/hash/xxhash64.js +2 -2
  108. package/lib/util/identifier.js +65 -44
  109. package/lib/util/internalSerializables.js +11 -0
  110. package/lib/util/nonNumericOnlyHash.js +22 -0
  111. package/lib/util/semver.js +17 -10
  112. package/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js +9 -3
  113. package/lib/web/JsonpChunkLoadingRuntimeModule.js +2 -2
  114. package/lib/webworker/ImportScriptsChunkLoadingPlugin.js +3 -11
  115. package/lib/webworker/ImportScriptsChunkLoadingRuntimeModule.js +1 -1
  116. package/package.json +16 -23
  117. package/schemas/WebpackOptions.check.js +1 -1
  118. package/schemas/WebpackOptions.json +96 -1
  119. package/schemas/plugins/asset/AssetGeneratorOptions.check.js +1 -1
  120. package/schemas/plugins/asset/AssetResourceGeneratorOptions.check.js +1 -1
  121. package/schemas/plugins/container/ContainerPlugin.check.js +1 -1
  122. package/schemas/plugins/container/ContainerPlugin.json +2 -1
  123. package/schemas/plugins/container/ContainerReferencePlugin.check.js +1 -1
  124. package/schemas/plugins/container/ContainerReferencePlugin.json +1 -0
  125. package/schemas/plugins/container/ExternalsType.check.js +1 -1
  126. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  127. package/schemas/plugins/container/ModuleFederationPlugin.json +3 -1
  128. package/schemas/plugins/css/CssGeneratorOptions.check.d.ts +7 -0
  129. package/schemas/plugins/css/CssGeneratorOptions.check.js +6 -0
  130. package/schemas/plugins/css/CssGeneratorOptions.json +3 -0
  131. package/schemas/plugins/css/CssParserOptions.check.d.ts +7 -0
  132. package/schemas/plugins/css/CssParserOptions.check.js +6 -0
  133. package/schemas/plugins/css/CssParserOptions.json +3 -0
  134. package/types.d.ts +295 -59
@@ -28,7 +28,10 @@ const LazySet = require("./util/LazySet");
28
28
  const { getScheme } = require("./util/URLAbsoluteSpecifier");
29
29
  const { cachedCleverMerge, cachedSetProperty } = require("./util/cleverMerge");
30
30
  const { join } = require("./util/fs");
31
- const { parseResource } = require("./util/identifier");
31
+ const {
32
+ parseResource,
33
+ parseResourceWithoutFragment
34
+ } = require("./util/identifier");
32
35
 
33
36
  /** @typedef {import("../declarations/WebpackOptions").ModuleOptionsNormalized} ModuleOptions */
34
37
  /** @typedef {import("./Generator")} Generator */
@@ -66,6 +69,11 @@ const { parseResource } = require("./util/identifier");
66
69
 
67
70
  /** @typedef {ResourceData & { data: Record<string, any> }} ResourceDataWithData */
68
71
 
72
+ /** @typedef {Object} ParsedLoaderRequest
73
+ * @property {string} loader loader
74
+ * @property {string|undefined} options options
75
+ */
76
+
69
77
  const EMPTY_RESOLVE_OPTIONS = {};
70
78
  const EMPTY_PARSER_OPTIONS = {};
71
79
  const EMPTY_GENERATOR_OPTIONS = {};
@@ -97,27 +105,6 @@ const stringifyLoadersAndResource = (loaders, resource) => {
97
105
  return str + resource;
98
106
  };
99
107
 
100
- /**
101
- * @param {string} resultString resultString
102
- * @returns {{loader: string, options: string|undefined}} parsed loader request
103
- */
104
- const identToLoaderRequest = resultString => {
105
- const idx = resultString.indexOf("?");
106
- if (idx >= 0) {
107
- const loader = resultString.substr(0, idx);
108
- const options = resultString.substr(idx + 1);
109
- return {
110
- loader,
111
- options
112
- };
113
- } else {
114
- return {
115
- loader: resultString,
116
- options: undefined
117
- };
118
- }
119
- };
120
-
121
108
  const needCalls = (times, callback) => {
122
109
  return err => {
123
110
  if (--times === 0) {
@@ -264,6 +251,9 @@ class NormalModuleFactory extends ModuleFactory {
264
251
  const cacheParseResource = parseResource.bindCache(
265
252
  associatedObjectForCache
266
253
  );
254
+ const cachedParseResourceWithoutFragment =
255
+ parseResourceWithoutFragment.bindCache(associatedObjectForCache);
256
+ this._parseResourceWithoutFragment = cachedParseResourceWithoutFragment;
267
257
 
268
258
  this.hooks.factorize.tapAsync(
269
259
  {
@@ -351,7 +341,7 @@ class NormalModuleFactory extends ModuleFactory {
351
341
  let matchResourceData = undefined;
352
342
  /** @type {string} */
353
343
  let unresolvedResource;
354
- /** @type {{loader: string, options: string|undefined}[]} */
344
+ /** @type {ParsedLoaderRequest[]} */
355
345
  let elements;
356
346
  let noPreAutoLoaders = false;
357
347
  let noAutoLoaders = false;
@@ -405,7 +395,13 @@ class NormalModuleFactory extends ModuleFactory {
405
395
  )
406
396
  .split(/!+/);
407
397
  unresolvedResource = rawElements.pop();
408
- elements = rawElements.map(identToLoaderRequest);
398
+ elements = rawElements.map(el => {
399
+ const { path, query } = cachedParseResourceWithoutFragment(el);
400
+ return {
401
+ loader: path,
402
+ options: query ? query.slice(1) : undefined
403
+ };
404
+ });
409
405
  scheme = getScheme(unresolvedResource);
410
406
  } else {
411
407
  unresolvedResource = requestWithoutMatchResource;
@@ -1017,12 +1013,14 @@ If changing the source code is not an option there is also a resolve options cal
1017
1013
  }
1018
1014
  if (err) return callback(err);
1019
1015
 
1020
- const parsedResult = identToLoaderRequest(result);
1016
+ const parsedResult = this._parseResourceWithoutFragment(result);
1021
1017
  const resolved = {
1022
- loader: parsedResult.loader,
1018
+ loader: parsedResult.path,
1023
1019
  options:
1024
1020
  item.options === undefined
1025
- ? parsedResult.options
1021
+ ? parsedResult.query
1022
+ ? parsedResult.query.slice(1)
1023
+ : undefined
1026
1024
  : item.options,
1027
1025
  ident: item.options === undefined ? undefined : item.ident
1028
1026
  };
@@ -96,7 +96,7 @@ const createDefaultHandler = (profile, logger) => {
96
96
  /**
97
97
  * @callback ReportProgress
98
98
  * @param {number} p
99
- * @param {...string[]} [args]
99
+ * @param {...string} [args]
100
100
  * @returns {void}
101
101
  */
102
102
 
package/lib/RawModule.js CHANGED
@@ -74,7 +74,7 @@ class RawModule extends Module {
74
74
 
75
75
  /**
76
76
  * @param {NeedBuildContext} context context info
77
- * @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
77
+ * @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
78
78
  * @returns {void}
79
79
  */
80
80
  needBuild(context, callback) {
@@ -164,10 +164,17 @@ exports.scriptNonce = "__webpack_require__.nc";
164
164
  * function to load a script tag.
165
165
  * Arguments: (url: string, done: (event) => void), key?: string | number, chunkId?: string | number) => void
166
166
  * done function is called when loading has finished or timeout occurred.
167
- * It will attach to existing script tags with data-webpack == key or src == url.
167
+ * It will attach to existing script tags with data-webpack == uniqueName + ":" + key or src == url.
168
168
  */
169
169
  exports.loadScript = "__webpack_require__.l";
170
170
 
171
+ /**
172
+ * function to promote a string to a TrustedScript using webpack's Trusted
173
+ * Types policy
174
+ * Arguments: (script: string) => TrustedScript
175
+ */
176
+ exports.createScript = "__webpack_require__.ts";
177
+
171
178
  /**
172
179
  * function to promote a string to a TrustedScriptURL using webpack's Trusted
173
180
  * Types policy
@@ -175,6 +182,12 @@ exports.loadScript = "__webpack_require__.l";
175
182
  */
176
183
  exports.createScriptUrl = "__webpack_require__.tu";
177
184
 
185
+ /**
186
+ * function to return webpack's Trusted Types policy
187
+ * Arguments: () => TrustedTypePolicy
188
+ */
189
+ exports.getTrustedTypesPolicy = "__webpack_require__.tt";
190
+
178
191
  /**
179
192
  * the chunk name of the chunk with the runtime
180
193
  */
@@ -190,11 +203,26 @@ exports.runtimeId = "__webpack_require__.j";
190
203
  */
191
204
  exports.getChunkScriptFilename = "__webpack_require__.u";
192
205
 
206
+ /**
207
+ * the filename of the css part of the chunk
208
+ */
209
+ exports.getChunkCssFilename = "__webpack_require__.k";
210
+
211
+ /**
212
+ * a flag when a module/chunk/tree has css modules
213
+ */
214
+ exports.hasCssModules = "has css modules";
215
+
193
216
  /**
194
217
  * the filename of the script part of the hot update chunk
195
218
  */
196
219
  exports.getChunkUpdateScriptFilename = "__webpack_require__.hu";
197
220
 
221
+ /**
222
+ * the filename of the css part of the hot update chunk
223
+ */
224
+ exports.getChunkUpdateCssFilename = "__webpack_require__.hk";
225
+
198
226
  /**
199
227
  * startup signal from runtime
200
228
  * This will be called when the runtime chunk has been loaded.
@@ -78,7 +78,7 @@ class RuntimeModule extends Module {
78
78
 
79
79
  /**
80
80
  * @param {NeedBuildContext} context context info
81
- * @param {function(WebpackError=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
81
+ * @param {function((WebpackError | null)=, boolean=): void} callback callback function, returns true, if the module needs a rebuild
82
82
  * @returns {void}
83
83
  */
84
84
  needBuild(context, callback) {
@@ -6,6 +6,7 @@
6
6
  "use strict";
7
7
 
8
8
  const RuntimeGlobals = require("./RuntimeGlobals");
9
+ const { getChunkFilenameTemplate } = require("./css/CssModulesPlugin");
9
10
  const RuntimeRequirementsDependency = require("./dependencies/RuntimeRequirementsDependency");
10
11
  const JavascriptModulesPlugin = require("./javascript/JavascriptModulesPlugin");
11
12
  const AsyncModuleRuntimeModule = require("./runtime/AsyncModuleRuntimeModule");
@@ -13,11 +14,13 @@ const AutoPublicPathRuntimeModule = require("./runtime/AutoPublicPathRuntimeModu
13
14
  const CompatGetDefaultExportRuntimeModule = require("./runtime/CompatGetDefaultExportRuntimeModule");
14
15
  const CompatRuntimeModule = require("./runtime/CompatRuntimeModule");
15
16
  const CreateFakeNamespaceObjectRuntimeModule = require("./runtime/CreateFakeNamespaceObjectRuntimeModule");
17
+ const CreateScriptRuntimeModule = require("./runtime/CreateScriptRuntimeModule");
16
18
  const CreateScriptUrlRuntimeModule = require("./runtime/CreateScriptUrlRuntimeModule");
17
19
  const DefinePropertyGettersRuntimeModule = require("./runtime/DefinePropertyGettersRuntimeModule");
18
20
  const EnsureChunkRuntimeModule = require("./runtime/EnsureChunkRuntimeModule");
19
21
  const GetChunkFilenameRuntimeModule = require("./runtime/GetChunkFilenameRuntimeModule");
20
22
  const GetMainFilenameRuntimeModule = require("./runtime/GetMainFilenameRuntimeModule");
23
+ const GetTrustedTypesPolicyRuntimeModule = require("./runtime/GetTrustedTypesPolicyRuntimeModule");
21
24
  const GlobalRuntimeModule = require("./runtime/GlobalRuntimeModule");
22
25
  const HasOwnPropertyRuntimeModule = require("./runtime/HasOwnPropertyRuntimeModule");
23
26
  const LoadScriptRuntimeModule = require("./runtime/LoadScriptRuntimeModule");
@@ -39,7 +42,9 @@ const GLOBALS_ON_REQUIRE = [
39
42
  RuntimeGlobals.runtimeId,
40
43
  RuntimeGlobals.compatGetDefaultExport,
41
44
  RuntimeGlobals.createFakeNamespaceObject,
45
+ RuntimeGlobals.createScript,
42
46
  RuntimeGlobals.createScriptUrl,
47
+ RuntimeGlobals.getTrustedTypesPolicy,
43
48
  RuntimeGlobals.definePropertyGetters,
44
49
  RuntimeGlobals.ensureChunk,
45
50
  RuntimeGlobals.entryModuleId,
@@ -261,6 +266,30 @@ class RuntimePlugin {
261
266
  );
262
267
  return true;
263
268
  });
269
+ compilation.hooks.runtimeRequirementInTree
270
+ .for(RuntimeGlobals.getChunkCssFilename)
271
+ .tap("RuntimePlugin", (chunk, set) => {
272
+ if (
273
+ typeof compilation.outputOptions.cssChunkFilename === "string" &&
274
+ /\[(full)?hash(:\d+)?\]/.test(
275
+ compilation.outputOptions.cssChunkFilename
276
+ )
277
+ ) {
278
+ set.add(RuntimeGlobals.getFullHash);
279
+ }
280
+ compilation.addRuntimeModule(
281
+ chunk,
282
+ new GetChunkFilenameRuntimeModule(
283
+ "css",
284
+ "css",
285
+ RuntimeGlobals.getChunkCssFilename,
286
+ chunk =>
287
+ getChunkFilenameTemplate(chunk, compilation.outputOptions),
288
+ set.has(RuntimeGlobals.hmrDownloadUpdateHandlers)
289
+ )
290
+ );
291
+ return true;
292
+ });
264
293
  compilation.hooks.runtimeRequirementInTree
265
294
  .for(RuntimeGlobals.getChunkUpdateScriptFilename)
266
295
  .tap("RuntimePlugin", (chunk, set) => {
@@ -339,15 +368,36 @@ class RuntimePlugin {
339
368
  );
340
369
  return true;
341
370
  });
371
+ compilation.hooks.runtimeRequirementInTree
372
+ .for(RuntimeGlobals.createScript)
373
+ .tap("RuntimePlugin", (chunk, set) => {
374
+ if (compilation.outputOptions.trustedTypes) {
375
+ set.add(RuntimeGlobals.getTrustedTypesPolicy);
376
+ }
377
+ compilation.addRuntimeModule(chunk, new CreateScriptRuntimeModule());
378
+ return true;
379
+ });
342
380
  compilation.hooks.runtimeRequirementInTree
343
381
  .for(RuntimeGlobals.createScriptUrl)
344
382
  .tap("RuntimePlugin", (chunk, set) => {
383
+ if (compilation.outputOptions.trustedTypes) {
384
+ set.add(RuntimeGlobals.getTrustedTypesPolicy);
385
+ }
345
386
  compilation.addRuntimeModule(
346
387
  chunk,
347
388
  new CreateScriptUrlRuntimeModule()
348
389
  );
349
390
  return true;
350
391
  });
392
+ compilation.hooks.runtimeRequirementInTree
393
+ .for(RuntimeGlobals.getTrustedTypesPolicy)
394
+ .tap("RuntimePlugin", (chunk, set) => {
395
+ compilation.addRuntimeModule(
396
+ chunk,
397
+ new GetTrustedTypesPolicyRuntimeModule(set)
398
+ );
399
+ return true;
400
+ });
351
401
  compilation.hooks.runtimeRequirementInTree
352
402
  .for(RuntimeGlobals.relativeUrl)
353
403
  .tap("RuntimePlugin", (chunk, set) => {
@@ -16,6 +16,7 @@ const { forEachRuntime, subtractRuntime } = require("./util/runtime");
16
16
  /** @typedef {import("../declarations/WebpackOptions").OutputNormalized} OutputOptions */
17
17
  /** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */
18
18
  /** @typedef {import("./ChunkGraph")} ChunkGraph */
19
+ /** @typedef {import("./CodeGenerationResults")} CodeGenerationResults */
19
20
  /** @typedef {import("./Compilation")} Compilation */
20
21
  /** @typedef {import("./Dependency")} Dependency */
21
22
  /** @typedef {import("./Module")} Module */
@@ -1014,6 +1015,26 @@ class RuntimeTemplate {
1014
1015
  runtimeRequirements.add(RuntimeGlobals.exports);
1015
1016
  return `${RuntimeGlobals.makeNamespaceObject}(${exportsArgument});\n`;
1016
1017
  }
1018
+
1019
+ /**
1020
+ * @param {Object} options options object
1021
+ * @param {Module} options.module the module
1022
+ * @param {string} options.publicPath the public path
1023
+ * @param {RuntimeSpec=} options.runtime runtime
1024
+ * @param {CodeGenerationResults} options.codeGenerationResults the code generation results
1025
+ * @returns {string} the url of the asset
1026
+ */
1027
+ assetUrl({ publicPath, runtime, module, codeGenerationResults }) {
1028
+ if (!module) {
1029
+ return "data:,";
1030
+ }
1031
+ const codeGen = codeGenerationResults.get(module, runtime);
1032
+ const { data } = codeGen;
1033
+ const url = data.get("url");
1034
+ if (url) return url.toString();
1035
+ const filename = data.get("filename");
1036
+ return publicPath + filename;
1037
+ }
1017
1038
  }
1018
1039
 
1019
1040
  module.exports = RuntimeTemplate;
package/lib/Template.js CHANGED
@@ -370,7 +370,8 @@ class Template {
370
370
  dependencyTemplates: renderContext.dependencyTemplates,
371
371
  moduleGraph: renderContext.moduleGraph,
372
372
  runtimeTemplate: renderContext.runtimeTemplate,
373
- runtime: renderContext.chunk.runtime
373
+ runtime: renderContext.chunk.runtime,
374
+ codeGenerationResults
374
375
  });
375
376
  if (!codeGenResult) continue;
376
377
  runtimeSource = codeGenResult.sources.get("runtime");
@@ -5,6 +5,7 @@
5
5
 
6
6
  "use strict";
7
7
 
8
+ const mime = require("mime-types");
8
9
  const { basename, extname } = require("path");
9
10
  const util = require("util");
10
11
  const Chunk = require("./Chunk");
@@ -117,29 +118,53 @@ const replacePathVariables = (path, data, assetInfo) => {
117
118
  // [name] - file
118
119
  // [ext] - .js
119
120
  if (typeof data.filename === "string") {
120
- const { path: file, query, fragment } = parseResource(data.filename);
121
-
122
- const ext = extname(file);
123
- const base = basename(file);
124
- const name = base.slice(0, base.length - ext.length);
125
- const path = file.slice(0, file.length - base.length);
126
-
127
- replacements.set("file", replacer(file));
128
- replacements.set("query", replacer(query, true));
129
- replacements.set("fragment", replacer(fragment, true));
130
- replacements.set("path", replacer(path, true));
131
- replacements.set("base", replacer(base));
132
- replacements.set("name", replacer(name));
133
- replacements.set("ext", replacer(ext, true));
134
- // Legacy
135
- replacements.set(
136
- "filebase",
137
- deprecated(
138
- replacer(base),
139
- "[filebase] is now [base]",
140
- "DEP_WEBPACK_TEMPLATE_PATH_PLUGIN_REPLACE_PATH_VARIABLES_FILENAME"
141
- )
142
- );
121
+ // check that filename is data uri
122
+ let match = data.filename.match(/^data:([^;,]+)/);
123
+ if (match) {
124
+ const ext = mime.extension(match[1]);
125
+ const emptyReplacer = replacer("", true);
126
+
127
+ replacements.set("file", emptyReplacer);
128
+ replacements.set("query", emptyReplacer);
129
+ replacements.set("fragment", emptyReplacer);
130
+ replacements.set("path", emptyReplacer);
131
+ replacements.set("base", emptyReplacer);
132
+ replacements.set("name", emptyReplacer);
133
+ replacements.set("ext", replacer(ext ? `.${ext}` : "", true));
134
+ // Legacy
135
+ replacements.set(
136
+ "filebase",
137
+ deprecated(
138
+ emptyReplacer,
139
+ "[filebase] is now [base]",
140
+ "DEP_WEBPACK_TEMPLATE_PATH_PLUGIN_REPLACE_PATH_VARIABLES_FILENAME"
141
+ )
142
+ );
143
+ } else {
144
+ const { path: file, query, fragment } = parseResource(data.filename);
145
+
146
+ const ext = extname(file);
147
+ const base = basename(file);
148
+ const name = base.slice(0, base.length - ext.length);
149
+ const path = file.slice(0, file.length - base.length);
150
+
151
+ replacements.set("file", replacer(file));
152
+ replacements.set("query", replacer(query, true));
153
+ replacements.set("fragment", replacer(fragment, true));
154
+ replacements.set("path", replacer(path, true));
155
+ replacements.set("base", replacer(base));
156
+ replacements.set("name", replacer(name));
157
+ replacements.set("ext", replacer(ext, true));
158
+ // Legacy
159
+ replacements.set(
160
+ "filebase",
161
+ deprecated(
162
+ replacer(base),
163
+ "[filebase] is now [base]",
164
+ "DEP_WEBPACK_TEMPLATE_PATH_PLUGIN_REPLACE_PATH_VARIABLES_FILENAME"
165
+ )
166
+ );
167
+ }
143
168
  }
144
169
 
145
170
  // Compilation context
package/lib/Watching.js CHANGED
@@ -15,7 +15,7 @@ const Stats = require("./Stats");
15
15
  /**
16
16
  * @template T
17
17
  * @callback Callback
18
- * @param {Error=} err
18
+ * @param {(Error | null)=} err
19
19
  * @param {T=} result
20
20
  */
21
21
 
@@ -49,7 +49,7 @@ class Watching {
49
49
  this.watchOptions = {};
50
50
  }
51
51
  if (typeof this.watchOptions.aggregateTimeout !== "number") {
52
- this.watchOptions.aggregateTimeout = 200;
52
+ this.watchOptions.aggregateTimeout = 20;
53
53
  }
54
54
  this.compiler = compiler;
55
55
  this.running = false;
@@ -118,11 +118,47 @@ class WebpackOptionsApply extends OptionsApply {
118
118
  if (options.externalsPresets.webAsync) {
119
119
  //@ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
120
120
  const ExternalsPlugin = require("./ExternalsPlugin");
121
- new ExternalsPlugin("import", /^(https?:\/\/|std:)/).apply(compiler);
121
+ new ExternalsPlugin(
122
+ "import",
123
+ options.experiments.css
124
+ ? ({ request, dependencyType }, callback) => {
125
+ if (dependencyType === "url") {
126
+ if (/^(\/\/|https?:\/\/)/.test(request))
127
+ return callback(null, `asset ${request}`);
128
+ } else if (dependencyType === "css-import") {
129
+ if (/^(\/\/|https?:\/\/)/.test(request))
130
+ return callback(null, `css-import ${request}`);
131
+ } else if (/^(\/\/|https?:\/\/|std:)/.test(request)) {
132
+ if (/^\.css(\?|$)/.test(request))
133
+ return callback(null, `css-import ${request}`);
134
+ return callback(null, `import ${request}`);
135
+ }
136
+ callback();
137
+ }
138
+ : /^(\/\/|https?:\/\/|std:)/
139
+ ).apply(compiler);
122
140
  } else if (options.externalsPresets.web) {
123
141
  //@ts-expect-error https://github.com/microsoft/TypeScript/issues/41697
124
142
  const ExternalsPlugin = require("./ExternalsPlugin");
125
- new ExternalsPlugin("module", /^(https?:\/\/|std:)/).apply(compiler);
143
+ new ExternalsPlugin(
144
+ "module",
145
+ options.experiments.css
146
+ ? ({ request, dependencyType }, callback) => {
147
+ if (dependencyType === "url") {
148
+ if (/^(\/\/|https?:\/\/)/.test(request))
149
+ return callback(null, `asset ${request}`);
150
+ } else if (dependencyType === "css-import") {
151
+ if (/^(\/\/|https?:\/\/)/.test(request))
152
+ return callback(null, `css-import ${request}`);
153
+ } else if (/^(\/\/|https?:\/\/|std:)/.test(request)) {
154
+ if (/^\.css(\?|$)/.test(request))
155
+ return callback(null, `css-import ${request}`);
156
+ return callback(null, `module ${request}`);
157
+ }
158
+ callback();
159
+ }
160
+ : /^(\/\/|https?:\/\/|std:)/
161
+ ).apply(compiler);
126
162
  }
127
163
 
128
164
  new ChunkPrefetchPreloadPlugin().apply(compiler);
@@ -253,6 +289,11 @@ class WebpackOptionsApply extends OptionsApply {
253
289
  }).apply(compiler);
254
290
  }
255
291
 
292
+ if (options.experiments.css) {
293
+ const CssModulesPlugin = require("./css/CssModulesPlugin");
294
+ new CssModulesPlugin(options.experiments.css).apply(compiler);
295
+ }
296
+
256
297
  if (options.experiments.lazyCompilation) {
257
298
  const LazyCompilationPlugin = require("./hmr/LazyCompilationPlugin");
258
299
  const lazyOptions =
@@ -12,9 +12,11 @@ const Generator = require("../Generator");
12
12
  const RuntimeGlobals = require("../RuntimeGlobals");
13
13
  const createHash = require("../util/createHash");
14
14
  const { makePathsRelative } = require("../util/identifier");
15
+ const nonNumericOnlyHash = require("../util/nonNumericOnlyHash");
15
16
 
16
17
  /** @typedef {import("webpack-sources").Source} Source */
17
18
  /** @typedef {import("../../declarations/WebpackOptions").AssetGeneratorOptions} AssetGeneratorOptions */
19
+ /** @typedef {import("../../declarations/WebpackOptions").AssetModuleOutputPath} AssetModuleOutputPath */
18
20
  /** @typedef {import("../../declarations/WebpackOptions").RawPublicPath} RawPublicPath */
19
21
  /** @typedef {import("../Compilation")} Compilation */
20
22
  /** @typedef {import("../Compiler")} Compiler */
@@ -49,7 +51,7 @@ const mergeAssetInfo = (a, b) => {
49
51
  case "immutable":
50
52
  case "development":
51
53
  case "hotModuleReplacement":
52
- case "javascriptModule ":
54
+ case "javascriptModule":
53
55
  result[key] = a[key] || b[key];
54
56
  break;
55
57
  case "related":
@@ -74,6 +76,41 @@ const mergeRelatedInfo = (a, b) => {
74
76
  return result;
75
77
  };
76
78
 
79
+ const encodeDataUri = (encoding, source) => {
80
+ let encodedContent;
81
+
82
+ switch (encoding) {
83
+ case "base64": {
84
+ encodedContent = source.buffer().toString("base64");
85
+ break;
86
+ }
87
+ case false: {
88
+ const content = source.source();
89
+
90
+ if (typeof content !== "string") {
91
+ encodedContent = content.toString("utf-8");
92
+ }
93
+
94
+ encodedContent = encodeURIComponent(encodedContent).replace(
95
+ /[!'()*]/g,
96
+ character => "%" + character.codePointAt(0).toString(16)
97
+ );
98
+ break;
99
+ }
100
+ default:
101
+ throw new Error(`Unsupported encoding '${encoding}'`);
102
+ }
103
+
104
+ return encodedContent;
105
+ };
106
+
107
+ const decodeDataUriContent = (encoding, content) => {
108
+ const isBase64 = encoding === "base64";
109
+ return isBase64
110
+ ? Buffer.from(content, "base64")
111
+ : Buffer.from(decodeURIComponent(content), "ascii");
112
+ };
113
+
77
114
  const JS_TYPES = new Set(["javascript"]);
78
115
  const JS_AND_ASSET_TYPES = new Set(["javascript", "asset"]);
79
116
 
@@ -82,13 +119,15 @@ class AssetGenerator extends Generator {
82
119
  * @param {AssetGeneratorOptions["dataUrl"]=} dataUrlOptions the options for the data url
83
120
  * @param {string=} filename override for output.assetModuleFilename
84
121
  * @param {RawPublicPath=} publicPath override for output.assetModulePublicPath
122
+ * @param {AssetModuleOutputPath=} outputPath the output path for the emitted file which is not included in the runtime import
85
123
  * @param {boolean=} emit generate output asset
86
124
  */
87
- constructor(dataUrlOptions, filename, publicPath, emit) {
125
+ constructor(dataUrlOptions, filename, publicPath, outputPath, emit) {
88
126
  super();
89
127
  this.dataUrlOptions = dataUrlOptions;
90
128
  this.filename = filename;
91
129
  this.publicPath = publicPath;
130
+ this.outputPath = outputPath;
92
131
  this.emit = emit;
93
132
  }
94
133
 
@@ -158,39 +197,26 @@ class AssetGenerator extends Generator {
158
197
  }
159
198
 
160
199
  let encodedContent;
200
+
161
201
  if (
162
202
  module.resourceResolveData &&
163
- module.resourceResolveData.encoding === encoding
203
+ module.resourceResolveData.encoding === encoding &&
204
+ decodeDataUriContent(
205
+ module.resourceResolveData.encoding,
206
+ module.resourceResolveData.encodedContent
207
+ ).equals(originalSource.buffer())
164
208
  ) {
165
209
  encodedContent = module.resourceResolveData.encodedContent;
166
210
  } else {
167
- switch (encoding) {
168
- case "base64": {
169
- encodedContent = originalSource.buffer().toString("base64");
170
- break;
171
- }
172
- case false: {
173
- const content = originalSource.source();
174
-
175
- if (typeof content !== "string") {
176
- encodedContent = content.toString("utf-8");
177
- }
178
-
179
- encodedContent = encodeURIComponent(encodedContent).replace(
180
- /[!'()*]/g,
181
- character => "%" + character.codePointAt(0).toString(16)
182
- );
183
- break;
184
- }
185
- default:
186
- throw new Error(`Unsupported encoding '${encoding}'`);
187
- }
211
+ encodedContent = encodeDataUri(encoding, originalSource);
188
212
  }
189
213
 
190
214
  encodedSource = `data:${mimeType}${
191
215
  encoding ? `;${encoding}` : ""
192
216
  },${encodedContent}`;
193
217
  }
218
+ const data = getData();
219
+ data.set("url", Buffer.from(encodedSource));
194
220
  return new RawSource(
195
221
  `${RuntimeGlobals.module}.exports = ${JSON.stringify(
196
222
  encodedSource
@@ -207,8 +233,8 @@ class AssetGenerator extends Generator {
207
233
  const fullHash = /** @type {string} */ (
208
234
  hash.digest(runtimeTemplate.outputOptions.hashDigest)
209
235
  );
210
- const contentHash = fullHash.slice(
211
- 0,
236
+ const contentHash = nonNumericOnlyHash(
237
+ fullHash,
212
238
  runtimeTemplate.outputOptions.hashDigestLength
213
239
  );
214
240
  module.buildInfo.fullContentHash = fullHash;
@@ -254,6 +280,21 @@ class AssetGenerator extends Generator {
254
280
  sourceFilename,
255
281
  ...assetInfo
256
282
  };
283
+ if (this.outputPath) {
284
+ const { path: outputPath, info } =
285
+ runtimeTemplate.compilation.getAssetPathWithInfo(
286
+ this.outputPath,
287
+ {
288
+ module,
289
+ runtime,
290
+ filename: sourceFilename,
291
+ chunkGraph,
292
+ contentHash
293
+ }
294
+ );
295
+ assetInfo = mergeAssetInfo(assetInfo, info);
296
+ filename = path.posix.join(outputPath, filename);
297
+ }
257
298
  module.buildInfo.filename = filename;
258
299
  module.buildInfo.assetInfo = assetInfo;
259
300
  if (getData) {