webpack 5.66.0 → 5.67.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 (72) hide show
  1. package/README.md +1 -1
  2. package/lib/Cache.js +1 -1
  3. package/lib/CacheFacade.js +2 -2
  4. package/lib/CleanPlugin.js +1 -1
  5. package/lib/Compilation.js +12 -9
  6. package/lib/Compiler.js +57 -3
  7. package/lib/ContextModule.js +21 -17
  8. package/lib/DelegatedModule.js +1 -1
  9. package/lib/DependencyTemplates.js +1 -1
  10. package/lib/DllModule.js +1 -1
  11. package/lib/EvalDevToolModulePlugin.js +16 -1
  12. package/lib/EvalSourceMapDevToolPlugin.js +18 -1
  13. package/lib/ExternalModule.js +1 -1
  14. package/lib/ExternalModuleFactoryPlugin.js +1 -1
  15. package/lib/FileSystemInfo.js +29 -25
  16. package/lib/HookWebpackError.js +1 -1
  17. package/lib/Module.js +1 -1
  18. package/lib/MultiCompiler.js +1 -1
  19. package/lib/MultiWatching.js +1 -1
  20. package/lib/NormalModule.js +6 -4
  21. package/lib/RawModule.js +1 -1
  22. package/lib/RuntimeGlobals.js +18 -0
  23. package/lib/RuntimeModule.js +1 -1
  24. package/lib/RuntimePlugin.js +28 -3
  25. package/lib/RuntimeTemplate.js +1 -1
  26. package/lib/Watching.js +1 -1
  27. package/lib/WebpackOptionsApply.js +1 -1
  28. package/lib/asset/AssetGenerator.js +62 -24
  29. package/lib/asset/AssetModulesPlugin.js +3 -0
  30. package/lib/asset/RawDataUrlModule.js +8 -5
  31. package/lib/cache/ResolverCachePlugin.js +1 -1
  32. package/lib/cli.js +44 -3
  33. package/lib/config/defaults.js +22 -5
  34. package/lib/config/normalization.js +5 -0
  35. package/lib/container/ContainerEntryModule.js +4 -2
  36. package/lib/container/FallbackModule.js +4 -4
  37. package/lib/container/RemoteModule.js +4 -2
  38. package/lib/css/CssExportsGenerator.js +139 -0
  39. package/lib/css/CssGenerator.js +3 -0
  40. package/lib/css/CssLoadingRuntimeModule.js +139 -85
  41. package/lib/css/CssModulesPlugin.js +20 -3
  42. package/lib/debug/ProfilingPlugin.js +12 -10
  43. package/lib/dependencies/CreateScriptUrlDependency.js +12 -0
  44. package/lib/dependencies/LoaderPlugin.js +2 -2
  45. package/lib/hmr/LazyCompilationPlugin.js +45 -21
  46. package/lib/hmr/lazyCompilationBackend.js +1 -1
  47. package/lib/ids/DeterministicModuleIdsPlugin.js +55 -35
  48. package/lib/ids/HashedModuleIdsPlugin.js +9 -12
  49. package/lib/ids/IdHelpers.js +24 -10
  50. package/lib/ids/NamedModuleIdsPlugin.js +6 -9
  51. package/lib/ids/NaturalModuleIdsPlugin.js +10 -13
  52. package/lib/ids/OccurrenceModuleIdsPlugin.js +13 -10
  53. package/lib/ids/SyncModuleIdsPlugin.js +140 -0
  54. package/lib/index.js +5 -0
  55. package/lib/optimize/ConcatenatedModule.js +1 -1
  56. package/lib/runtime/CreateScriptRuntimeModule.js +36 -0
  57. package/lib/runtime/CreateScriptUrlRuntimeModule.js +9 -34
  58. package/lib/runtime/GetTrustedTypesPolicyRuntimeModule.js +76 -0
  59. package/lib/schemes/HttpUriPlugin.js +8 -8
  60. package/lib/sharing/ConsumeSharedModule.js +4 -2
  61. package/lib/sharing/ProvideSharedModule.js +4 -2
  62. package/lib/sharing/utils.js +1 -1
  63. package/lib/stats/DefaultStatsFactoryPlugin.js +112 -67
  64. package/lib/stats/DefaultStatsPrinterPlugin.js +88 -23
  65. package/lib/util/AsyncQueue.js +1 -1
  66. package/lib/webworker/ImportScriptsChunkLoadingPlugin.js +3 -11
  67. package/package.json +3 -10
  68. package/schemas/WebpackOptions.check.js +1 -1
  69. package/schemas/WebpackOptions.json +43 -6
  70. package/schemas/plugins/asset/AssetGeneratorOptions.check.js +1 -1
  71. package/schemas/plugins/asset/AssetResourceGeneratorOptions.check.js +1 -1
  72. package/types.d.ts +163 -42
@@ -67,12 +67,14 @@ class RemoteModule extends Module {
67
67
  * @returns {string | null} an identifier for library inclusion
68
68
  */
69
69
  libIdent(options) {
70
- return `webpack/container/remote/${this.request}`;
70
+ return `${this.layer ? `(${this.layer})/` : ""}webpack/container/remote/${
71
+ this.request
72
+ }`;
71
73
  }
72
74
 
73
75
  /**
74
76
  * @param {NeedBuildContext} context context info
75
- * @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
76
78
  * @returns {void}
77
79
  */
78
80
  needBuild(context, callback) {
@@ -0,0 +1,139 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Sergey Melyukov @smelukov
4
+ */
5
+
6
+ "use strict";
7
+
8
+ const { ReplaceSource, RawSource, ConcatSource } = require("webpack-sources");
9
+ const { UsageState } = require("../ExportsInfo");
10
+ const Generator = require("../Generator");
11
+ const RuntimeGlobals = require("../RuntimeGlobals");
12
+ const Template = require("../Template");
13
+
14
+ /** @typedef {import("webpack-sources").Source} Source */
15
+ /** @typedef {import("../Dependency")} Dependency */
16
+ /** @typedef {import("../Generator").GenerateContext} GenerateContext */
17
+ /** @typedef {import("../Generator").UpdateHashContext} UpdateHashContext */
18
+ /** @typedef {import("../Module").ConcatenationBailoutReasonContext} ConcatenationBailoutReasonContext */
19
+ /** @typedef {import("../NormalModule")} NormalModule */
20
+ /** @typedef {import("../util/Hash")} Hash */
21
+
22
+ const TYPES = new Set(["javascript"]);
23
+
24
+ class CssExportsGenerator extends Generator {
25
+ constructor() {
26
+ super();
27
+ }
28
+
29
+ // TODO add getConcatenationBailoutReason to allow concatenation
30
+ // but how to make it have a module id
31
+
32
+ /**
33
+ * @param {NormalModule} module module for which the code should be generated
34
+ * @param {GenerateContext} generateContext context for generate
35
+ * @returns {Source} generated code
36
+ */
37
+ generate(module, generateContext) {
38
+ const source = new ReplaceSource(new RawSource(""));
39
+ const initFragments = [];
40
+ const cssExports = new Map();
41
+
42
+ generateContext.runtimeRequirements.add(RuntimeGlobals.module);
43
+
44
+ const runtimeRequirements = new Set();
45
+
46
+ const templateContext = {
47
+ runtimeTemplate: generateContext.runtimeTemplate,
48
+ dependencyTemplates: generateContext.dependencyTemplates,
49
+ moduleGraph: generateContext.moduleGraph,
50
+ chunkGraph: generateContext.chunkGraph,
51
+ module,
52
+ runtime: generateContext.runtime,
53
+ runtimeRequirements: runtimeRequirements,
54
+ concatenationScope: generateContext.concatenationScope,
55
+ codeGenerationResults: generateContext.codeGenerationResults,
56
+ initFragments,
57
+ cssExports
58
+ };
59
+
60
+ const handleDependency = dependency => {
61
+ const constructor = /** @type {new (...args: any[]) => Dependency} */ (
62
+ dependency.constructor
63
+ );
64
+ const template = generateContext.dependencyTemplates.get(constructor);
65
+ if (!template) {
66
+ throw new Error(
67
+ "No template for dependency: " + dependency.constructor.name
68
+ );
69
+ }
70
+
71
+ template.apply(dependency, source, templateContext);
72
+ };
73
+ module.dependencies.forEach(handleDependency);
74
+
75
+ if (generateContext.concatenationScope) {
76
+ const source = new ConcatSource();
77
+ const usedIdentifiers = new Set();
78
+ for (const [k, v] of cssExports) {
79
+ let identifier = Template.toIdentifier(k);
80
+ let i = 0;
81
+ while (usedIdentifiers.has(identifier)) {
82
+ identifier = Template.toIdentifier(k + i);
83
+ }
84
+ usedIdentifiers.add(identifier);
85
+ generateContext.concatenationScope.registerExport(k, identifier);
86
+ source.add(
87
+ `${
88
+ generateContext.runtimeTemplate.supportsConst ? "const" : "var"
89
+ } ${identifier} = ${JSON.stringify(v)};\n`
90
+ );
91
+ }
92
+ return source;
93
+ } else {
94
+ const otherUsed =
95
+ generateContext.moduleGraph
96
+ .getExportsInfo(module)
97
+ .otherExportsInfo.getUsed(generateContext.runtime) !==
98
+ UsageState.Unused;
99
+ if (otherUsed) {
100
+ generateContext.runtimeRequirements.add(
101
+ RuntimeGlobals.makeNamespaceObject
102
+ );
103
+ }
104
+ return new RawSource(
105
+ `${otherUsed ? `${RuntimeGlobals.makeNamespaceObject}(` : ""}${
106
+ module.moduleArgument
107
+ }.exports = {\n${Array.from(
108
+ cssExports,
109
+ ([k, v]) => `\t${JSON.stringify(k)}: ${JSON.stringify(v)}`
110
+ ).join(",\n")}\n}${otherUsed ? ")" : ""};`
111
+ );
112
+ }
113
+ }
114
+
115
+ /**
116
+ * @param {NormalModule} module fresh module
117
+ * @returns {Set<string>} available types (do not mutate)
118
+ */
119
+ getTypes(module) {
120
+ return TYPES;
121
+ }
122
+
123
+ /**
124
+ * @param {NormalModule} module the module
125
+ * @param {string=} type source type
126
+ * @returns {number} estimate size of the module
127
+ */
128
+ getSize(module, type) {
129
+ return 42;
130
+ }
131
+
132
+ /**
133
+ * @param {Hash} hash hash that will be modified
134
+ * @param {UpdateHashContext} updateHashContext context for updating hash
135
+ */
136
+ updateHash(hash, { module }) {}
137
+ }
138
+
139
+ module.exports = CssExportsGenerator;
@@ -8,6 +8,7 @@
8
8
  const { ReplaceSource } = require("webpack-sources");
9
9
  const Generator = require("../Generator");
10
10
  const InitFragment = require("../InitFragment");
11
+ const RuntimeGlobals = require("../RuntimeGlobals");
11
12
 
12
13
  /** @typedef {import("webpack-sources").Source} Source */
13
14
  /** @typedef {import("../Dependency")} Dependency */
@@ -34,6 +35,8 @@ class CssGenerator extends Generator {
34
35
  const initFragments = [];
35
36
  const cssExports = new Map();
36
37
 
38
+ generateContext.runtimeRequirements.add(RuntimeGlobals.hasCssModules);
39
+
37
40
  const templateContext = {
38
41
  runtimeTemplate: generateContext.runtimeTemplate,
39
42
  dependencyTemplates: generateContext.dependencyTemplates,
@@ -79,14 +79,6 @@ class CssLoadingRuntimeModule extends RuntimeModule {
79
79
  const withHmr = _runtimeRequirements.has(
80
80
  RuntimeGlobals.hmrDownloadUpdateHandlers
81
81
  );
82
-
83
- if (!withLoading && !withHmr) {
84
- return null;
85
- }
86
-
87
- const { createStylesheet } =
88
- CssLoadingRuntimeModule.getCompilationHooks(compilation);
89
-
90
82
  const initialChunkIdsWithCss = new Set();
91
83
  const initialChunkIdsWithoutCss = new Set();
92
84
  for (const c of chunk.getAllInitialChunks()) {
@@ -96,6 +88,13 @@ class CssLoadingRuntimeModule extends RuntimeModule {
96
88
  ).add(c.id);
97
89
  }
98
90
 
91
+ if (!withLoading && !withHmr && initialChunkIdsWithCss.size === 0) {
92
+ return null;
93
+ }
94
+
95
+ const { createStylesheet } =
96
+ CssLoadingRuntimeModule.getCompilationHooks(compilation);
97
+
99
98
  const stateExpression = withHmr
100
99
  ? `${RuntimeGlobals.hmrRuntimeStatePrefix}_css`
101
100
  : undefined;
@@ -107,7 +106,6 @@ class CssLoadingRuntimeModule extends RuntimeModule {
107
106
  : "",
108
107
  "link.setAttribute(loadingAttribute, 1);",
109
108
  'link.rel = "stylesheet";',
110
- withHmr ? 'if(hmr) link.media = "print and screen";' : "",
111
109
  "link.href = url;",
112
110
  crossOriginLoading
113
111
  ? Template.asString([
@@ -138,64 +136,74 @@ class CssLoadingRuntimeModule extends RuntimeModule {
138
136
  runtimeTemplate.outputOptions.uniqueName
139
137
  )};`
140
138
  : "// data-webpack is not used as build has no uniqueName",
141
- `var loadCssChunkData = ${runtimeTemplate.basicFunction("chunkId, link", [
142
- 'var data, token = "", token2, exports = {}, exportsWithId = [], exportsWithDashes = [], i = 0, cc = 1;',
143
- "try { if(!link) link = loadStylesheet(chunkId); data = link.sheet.cssRules; data = data[data.length - 1].style; } catch(e) { data = getComputedStyle(document.head); }",
144
- `data = data.getPropertyValue(${
145
- uniqueName
146
- ? runtimeTemplate.concatenation(
147
- "--webpack-",
148
- { expr: "uniqueName" },
149
- "-",
150
- { expr: "chunkId" }
151
- )
152
- : runtimeTemplate.concatenation("--webpack-", { expr: "chunkId" })
153
- });`,
154
- "if(!data) return;",
155
- "for(; cc; i++) {",
156
- Template.indent([
157
- "cc = data.charCodeAt(i);",
158
- `if(cc == ${cc("(")}) { token2 = token; token = ""; }`,
159
- `else if(cc == ${cc(
160
- ")"
161
- )}) { exports[token2.replace(/^_/, "")] = token.replace(/^_/, ""); token = ""; }`,
162
- `else if(cc == ${cc("/")} || cc == ${cc(
163
- "%"
164
- )}) { token = token.replace(/^_/, ""); exports[token] = token; exportsWithId.push(token); if(cc == ${cc(
165
- "%"
166
- )}) exportsWithDashes.push(token); token = ""; }`,
167
- `else if(!cc || cc == ${cc(
168
- ","
169
- )}) { token = token.replace(/^_/, ""); exportsWithId.forEach(${runtimeTemplate.expressionFunction(
170
- `exports[x] = ${
171
- uniqueName
172
- ? runtimeTemplate.concatenation(
173
- { expr: "uniqueName" },
174
- "-",
175
- { expr: "token" },
176
- "-",
177
- { expr: "exports[x]" }
178
- )
179
- : runtimeTemplate.concatenation({ expr: "token" }, "-", {
180
- expr: "exports[x]"
181
- })
182
- }`,
183
- "x"
184
- )}); exportsWithDashes.forEach(${runtimeTemplate.expressionFunction(
185
- `exports[x] = "--" + exports[x]`,
186
- "x"
187
- )}); ${RuntimeGlobals.makeNamespaceObject}(exports); ${
188
- RuntimeGlobals.moduleFactories
189
- }[token] = (${runtimeTemplate.basicFunction(
190
- "exports, module",
191
- `module.exports = exports;`
192
- )}).bind(null, exports); token = ""; exports = {}; exportsWithId.length = 0; }`,
193
- `else if(cc == ${cc("\\")}) { token += data[++i] }`,
194
- `else { token += data[i]; }`
195
- ]),
196
- "}",
197
- "installedChunks[chunkId] = 0;"
198
- ])}`,
139
+ `var loadCssChunkData = ${runtimeTemplate.basicFunction(
140
+ "target, link, chunkId",
141
+ [
142
+ `var data, token = "", token2, exports = {}, exportsWithId = [], exportsWithDashes = [], ${
143
+ withHmr ? "moduleIds = [], " : ""
144
+ }i = 0, cc = 1;`,
145
+ "try { if(!link) link = loadStylesheet(chunkId); data = link.sheet.cssRules; data = data[data.length - 1].style; } catch(e) { data = getComputedStyle(document.head); }",
146
+ `data = data.getPropertyValue(${
147
+ uniqueName
148
+ ? runtimeTemplate.concatenation(
149
+ "--webpack-",
150
+ { expr: "uniqueName" },
151
+ "-",
152
+ { expr: "chunkId" }
153
+ )
154
+ : runtimeTemplate.concatenation("--webpack-", { expr: "chunkId" })
155
+ });`,
156
+ "if(!data) return [];",
157
+ "for(; cc; i++) {",
158
+ Template.indent([
159
+ "cc = data.charCodeAt(i);",
160
+ `if(cc == ${cc("(")}) { token2 = token; token = ""; }`,
161
+ `else if(cc == ${cc(
162
+ ")"
163
+ )}) { exports[token2.replace(/^_/, "")] = token.replace(/^_/, ""); token = ""; }`,
164
+ `else if(cc == ${cc("/")} || cc == ${cc(
165
+ "%"
166
+ )}) { token = token.replace(/^_/, ""); exports[token] = token; exportsWithId.push(token); if(cc == ${cc(
167
+ "%"
168
+ )}) exportsWithDashes.push(token); token = ""; }`,
169
+ `else if(!cc || cc == ${cc(
170
+ ","
171
+ )}) { token = token.replace(/^_/, ""); exportsWithId.forEach(${runtimeTemplate.expressionFunction(
172
+ `exports[x] = ${
173
+ uniqueName
174
+ ? runtimeTemplate.concatenation(
175
+ { expr: "uniqueName" },
176
+ "-",
177
+ { expr: "token" },
178
+ "-",
179
+ { expr: "exports[x]" }
180
+ )
181
+ : runtimeTemplate.concatenation({ expr: "token" }, "-", {
182
+ expr: "exports[x]"
183
+ })
184
+ }`,
185
+ "x"
186
+ )}); exportsWithDashes.forEach(${runtimeTemplate.expressionFunction(
187
+ `exports[x] = "--" + exports[x]`,
188
+ "x"
189
+ )}); ${
190
+ RuntimeGlobals.makeNamespaceObject
191
+ }(exports); target[token] = (${runtimeTemplate.basicFunction(
192
+ "exports, module",
193
+ `module.exports = exports;`
194
+ )}).bind(null, exports); ${
195
+ withHmr ? "moduleIds.push(token); " : ""
196
+ }token = ""; exports = {}; exportsWithId.length = 0; }`,
197
+ `else if(cc == ${cc("\\")}) { token += data[++i] }`,
198
+ `else { token += data[i]; }`
199
+ ]),
200
+ "}",
201
+ `${
202
+ withHmr ? `if(target == ${RuntimeGlobals.moduleFactories}) ` : ""
203
+ }installedChunks[chunkId] = 0;`,
204
+ withHmr ? "return moduleIds;" : ""
205
+ ]
206
+ )}`,
199
207
  'var loadingAttribute = "data-webpack-loading";',
200
208
  `var loadStylesheet = ${runtimeTemplate.basicFunction(
201
209
  "chunkId, url, done" + (withHmr ? ", hmr" : ""),
@@ -206,14 +214,18 @@ class CssLoadingRuntimeModule extends RuntimeModule {
206
214
  "for(var i = 0; i < links.length; i++) {",
207
215
  Template.indent([
208
216
  "var l = links[i];",
209
- `if(l.getAttribute("href") == url${
217
+ `if(l.rel == "stylesheet" && (${
218
+ withHmr
219
+ ? 'l.href.startsWith(url) || l.getAttribute("href").startsWith(url)'
220
+ : 'l.href == url || l.getAttribute("href") == url'
221
+ }${
210
222
  uniqueName
211
223
  ? ' || l.getAttribute("data-webpack") == uniqueName + ":" + key'
212
224
  : ""
213
- }) { link = l; break; }`
225
+ })) { link = l; break; }`
214
226
  ]),
215
227
  "}",
216
- "if(!url) return link;",
228
+ "if(!done) return link;",
217
229
  withHmr ? "}" : "",
218
230
  "if(!link) {",
219
231
  Template.indent([
@@ -239,18 +251,24 @@ class CssLoadingRuntimeModule extends RuntimeModule {
239
251
  "link.onload = onLinkComplete.bind(null, link.onload);"
240
252
  ]),
241
253
  "} else onLinkComplete(undefined, { type: 'load', target: link });", // We assume any existing stylesheet is render blocking
254
+ withHmr ? "hmr ? document.head.insertBefore(link, hmr) :" : "",
242
255
  "needAttach && document.head.appendChild(link);",
243
256
  "return link;"
244
257
  ]
245
258
  )};`,
246
- initialChunkIdsWithCss.size > 5
259
+ initialChunkIdsWithCss.size > 2
247
260
  ? `${JSON.stringify(
248
261
  Array.from(initialChunkIdsWithCss)
249
- )}.forEach(loadCssChunkData);`
262
+ )}.forEach(loadCssChunkData.bind(null, ${
263
+ RuntimeGlobals.moduleFactories
264
+ }, 0));`
250
265
  : initialChunkIdsWithCss.size > 0
251
266
  ? `${Array.from(
252
267
  initialChunkIdsWithCss,
253
- id => `loadCssChunkData(${JSON.stringify(id)});`
268
+ id =>
269
+ `loadCssChunkData(${
270
+ RuntimeGlobals.moduleFactories
271
+ }, 0, ${JSON.stringify(id)});`
254
272
  ).join("")}`
255
273
  : "// no initial css",
256
274
  "",
@@ -308,7 +326,7 @@ class CssLoadingRuntimeModule extends RuntimeModule {
308
326
  ]),
309
327
  "} else {",
310
328
  Template.indent([
311
- "loadCssChunkData(chunkId, link);",
329
+ `loadCssChunkData(${RuntimeGlobals.moduleFactories}, link, chunkId);`,
312
330
  "installedChunkData[0]();"
313
331
  ]),
314
332
  "}"
@@ -336,17 +354,41 @@ class CssLoadingRuntimeModule extends RuntimeModule {
336
354
  "var oldTags = [];",
337
355
  "var newTags = [];",
338
356
  `var applyHandler = ${runtimeTemplate.basicFunction("options", [
339
- `return { dispose: ${runtimeTemplate.basicFunction("", [
357
+ `return { dispose: ${runtimeTemplate.basicFunction(
358
+ "",
359
+ []
360
+ )}, apply: ${runtimeTemplate.basicFunction("", [
361
+ "var moduleIds = [];",
362
+ `newTags.forEach(${runtimeTemplate.expressionFunction(
363
+ "info[1].sheet.disabled = false",
364
+ "info"
365
+ )});`,
340
366
  "while(oldTags.length) {",
341
367
  Template.indent([
342
368
  "var oldTag = oldTags.pop();",
343
369
  "if(oldTag.parentNode) oldTag.parentNode.removeChild(oldTag);"
344
370
  ]),
345
- "}"
346
- ])}, apply: ${runtimeTemplate.basicFunction("", [
347
- 'while(newTags.length) { var info = newTags.pop(); info[1].media = "all"; loadCssChunkData(info[0], info[1]); }'
371
+ "}",
372
+ "while(newTags.length) {",
373
+ Template.indent([
374
+ `var info = newTags.pop();`,
375
+ `var chunkModuleIds = loadCssChunkData(${RuntimeGlobals.moduleFactories}, info[1], info[0]);`,
376
+ `chunkModuleIds.forEach(${runtimeTemplate.expressionFunction(
377
+ "moduleIds.push(id)",
378
+ "id"
379
+ )});`
380
+ ]),
381
+ "}",
382
+ "return moduleIds;"
348
383
  ])} };`
349
384
  ])}`,
385
+ `var cssTextKey = ${runtimeTemplate.returningFunction(
386
+ `Array.from(link.sheet.cssRules, ${runtimeTemplate.returningFunction(
387
+ "r.cssText",
388
+ "r"
389
+ )}).join()`,
390
+ "link"
391
+ )}`,
350
392
  `${
351
393
  RuntimeGlobals.hmrDownloadUpdateHandlers
352
394
  }.css = ${runtimeTemplate.basicFunction(
@@ -354,14 +396,14 @@ class CssLoadingRuntimeModule extends RuntimeModule {
354
396
  [
355
397
  "applyHandlers.push(applyHandler);",
356
398
  `chunkIds.forEach(${runtimeTemplate.basicFunction("chunkId", [
357
- "var oldTag = loadStylesheet(chunkId);",
358
- "if(!oldTag) return;",
359
399
  `var filename = ${RuntimeGlobals.getChunkCssFilename}(chunkId);`,
360
400
  `var url = ${RuntimeGlobals.publicPath} + filename;`,
401
+ "var oldTag = loadStylesheet(chunkId, url);",
402
+ "if(!oldTag) return;",
361
403
  `promises.push(new Promise(${runtimeTemplate.basicFunction(
362
404
  "resolve, reject",
363
405
  [
364
- `var link = loadStylesheet(chunkId, url, ${runtimeTemplate.basicFunction(
406
+ `var link = loadStylesheet(chunkId, url + (url.indexOf("?") < 0 ? "?" : "&") + "hmr=" + Date.now(), ${runtimeTemplate.basicFunction(
365
407
  "event",
366
408
  [
367
409
  'if(event.type !== "load") {',
@@ -374,11 +416,23 @@ class CssLoadingRuntimeModule extends RuntimeModule {
374
416
  "error.request = realSrc;",
375
417
  "reject(error);"
376
418
  ]),
377
- "} else resolve();"
419
+ "} else {",
420
+ Template.indent([
421
+ "try { if(cssTextKey(oldTag) == cssTextKey(link)) { if(link.parentNode) link.parentNode.removeChild(link); return resolve(); } } catch(e) {}",
422
+ "var factories = {};",
423
+ "loadCssChunkData(factories, link, chunkId);",
424
+ `Object.keys(factories).forEach(${runtimeTemplate.expressionFunction(
425
+ "updatedModulesList.push(id)",
426
+ "id"
427
+ )})`,
428
+ "link.sheet.disabled = true;",
429
+ "oldTags.push(oldTag);",
430
+ "newTags.push([chunkId, link]);",
431
+ "resolve();"
432
+ ]),
433
+ "}"
378
434
  ]
379
- )}, true);`,
380
- "oldTags.push(oldTag);",
381
- "newTags.push([chunkId, link]);"
435
+ )}, oldTag);`
382
436
  ]
383
437
  )}));`
384
438
  ])});`
@@ -19,10 +19,12 @@ const { compareModulesByIdentifier } = require("../util/comparators");
19
19
  const createSchemaValidation = require("../util/create-schema-validation");
20
20
  const createHash = require("../util/createHash");
21
21
  const memoize = require("../util/memoize");
22
+ const CssExportsGenerator = require("./CssExportsGenerator");
22
23
  const CssGenerator = require("./CssGenerator");
23
24
  const CssParser = require("./CssParser");
24
25
 
25
26
  /** @typedef {import("webpack-sources").Source} Source */
27
+ /** @typedef {import("../../declarations/WebpackOptions").CssExperimentOptions} CssExperimentOptions */
26
28
  /** @typedef {import("../Chunk")} Chunk */
27
29
  /** @typedef {import("../Compiler")} Compiler */
28
30
  /** @typedef {import("../Module")} Module */
@@ -70,6 +72,12 @@ const escapeCss = (str, omitOptionalUnderscore) => {
70
72
  const plugin = "CssModulesPlugin";
71
73
 
72
74
  class CssModulesPlugin {
75
+ /**
76
+ * @param {CssExperimentOptions} options options
77
+ */
78
+ constructor({ exportsOnly = false }) {
79
+ this._exportsOnly = exportsOnly;
80
+ }
73
81
  /**
74
82
  * Apply the plugin
75
83
  * @param {Compiler} compiler the compiler instance
@@ -143,19 +151,25 @@ class CssModulesPlugin {
143
151
  .for("css")
144
152
  .tap(plugin, generatorOptions => {
145
153
  validateGeneratorOptions(generatorOptions);
146
- return new CssGenerator();
154
+ return this._exportsOnly
155
+ ? new CssExportsGenerator()
156
+ : new CssGenerator();
147
157
  });
148
158
  normalModuleFactory.hooks.createGenerator
149
159
  .for("css/global")
150
160
  .tap(plugin, generatorOptions => {
151
161
  validateGeneratorOptions(generatorOptions);
152
- return new CssGenerator();
162
+ return this._exportsOnly
163
+ ? new CssExportsGenerator()
164
+ : new CssGenerator();
153
165
  });
154
166
  normalModuleFactory.hooks.createGenerator
155
167
  .for("css/module")
156
168
  .tap(plugin, generatorOptions => {
157
169
  validateGeneratorOptions(generatorOptions);
158
- return new CssGenerator();
170
+ return this._exportsOnly
171
+ ? new CssExportsGenerator()
172
+ : new CssGenerator();
159
173
  });
160
174
  const orderedCssModulesPerChunk = new WeakMap();
161
175
  compilation.hooks.afterCodeGeneration.tap("CssModulesPlugin", () => {
@@ -238,6 +252,9 @@ class CssModulesPlugin {
238
252
  const CssLoadingRuntimeModule = getCssLoadingRuntimeModule();
239
253
  compilation.addRuntimeModule(chunk, new CssLoadingRuntimeModule(set));
240
254
  };
255
+ compilation.hooks.runtimeRequirementInTree
256
+ .for(RuntimeGlobals.hasCssModules)
257
+ .tap(plugin, handler);
241
258
  compilation.hooks.runtimeRequirementInTree
242
259
  .for(RuntimeGlobals.ensureChunkHandlers)
243
260
  .tap(plugin, handler);
@@ -123,9 +123,7 @@ class Profiler {
123
123
  * @returns {Trace} The trace object
124
124
  */
125
125
  const createTrace = (fs, outputPath) => {
126
- const trace = new Tracer({
127
- noStream: true
128
- });
126
+ const trace = new Tracer();
129
127
  const profiler = new Profiler(inspector);
130
128
  if (/\/|\\/.test(outputPath)) {
131
129
  const dirPath = dirname(fs, outputPath);
@@ -173,6 +171,7 @@ const createTrace = (fs, outputPath) => {
173
171
  counter,
174
172
  profiler,
175
173
  end: callback => {
174
+ trace.push("]");
176
175
  // Wait until the write stream finishes.
177
176
  fsStream.on("close", () => {
178
177
  callback();
@@ -242,10 +241,10 @@ class ProfilingPlugin {
242
241
  stage: Infinity
243
242
  },
244
243
  (stats, callback) => {
244
+ if (compiler.watchMode) return callback();
245
245
  tracer.profiler.stopProfiling().then(parsedResults => {
246
246
  if (parsedResults === undefined) {
247
247
  tracer.profiler.destroy();
248
- tracer.trace.flush();
249
248
  tracer.end(callback);
250
249
  return;
251
250
  }
@@ -293,7 +292,6 @@ class ProfilingPlugin {
293
292
  });
294
293
 
295
294
  tracer.profiler.destroy();
296
- tracer.trace.flush();
297
295
  tracer.end(callback);
298
296
  });
299
297
  }
@@ -346,11 +344,15 @@ const interceptAllJavascriptModulesPluginHooks = (compilation, tracer) => {
346
344
 
347
345
  const makeInterceptorFor = (instance, tracer) => hookName => ({
348
346
  register: ({ name, type, context, fn }) => {
349
- const newFn = makeNewProfiledTapFn(hookName, tracer, {
350
- name,
351
- type,
352
- fn
353
- });
347
+ const newFn =
348
+ // Don't tap our own hooks to ensure stream can close cleanly
349
+ name === pluginName
350
+ ? fn
351
+ : makeNewProfiledTapFn(hookName, tracer, {
352
+ name,
353
+ type,
354
+ fn
355
+ });
354
356
  return {
355
357
  name,
356
358
  type,
@@ -25,6 +25,18 @@ class CreateScriptUrlDependency extends NullDependency {
25
25
  get type() {
26
26
  return "create script url";
27
27
  }
28
+
29
+ serialize(context) {
30
+ const { write } = context;
31
+ write(this.range);
32
+ super.serialize(context);
33
+ }
34
+
35
+ deserialize(context) {
36
+ const { read } = context;
37
+ this.range = read();
38
+ super.deserialize(context);
39
+ }
28
40
  }
29
41
 
30
42
  CreateScriptUrlDependency.Template = class CreateScriptUrlDependencyTemplate extends (
@@ -16,7 +16,7 @@ const LoaderImportDependency = require("./LoaderImportDependency");
16
16
 
17
17
  /**
18
18
  * @callback LoadModuleCallback
19
- * @param {Error=} err error object
19
+ * @param {(Error | null)=} err error object
20
20
  * @param {string | Buffer=} source source code
21
21
  * @param {object=} map source map
22
22
  * @param {Module=} module loaded module if successful
@@ -24,7 +24,7 @@ const LoaderImportDependency = require("./LoaderImportDependency");
24
24
 
25
25
  /**
26
26
  * @callback ImportModuleCallback
27
- * @param {Error=} err error object
27
+ * @param {(Error | null)=} err error object
28
28
  * @param {any=} exports exports of the evaluated module
29
29
  */
30
30