webpack 5.102.1 → 5.103.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (118) hide show
  1. package/README.md +121 -134
  2. package/lib/CompatibilityPlugin.js +25 -2
  3. package/lib/Compilation.js +25 -2
  4. package/lib/ConcatenationScope.js +0 -15
  5. package/lib/CssModule.js +6 -1
  6. package/lib/DefinePlugin.js +11 -11
  7. package/lib/Dependency.js +8 -1
  8. package/lib/DependencyTemplate.js +1 -0
  9. package/lib/DotenvPlugin.js +457 -0
  10. package/lib/EnvironmentPlugin.js +19 -16
  11. package/lib/EvalSourceMapDevToolPlugin.js +16 -0
  12. package/lib/ExportsInfo.js +6 -2
  13. package/lib/ExternalModule.js +20 -28
  14. package/lib/ExternalModuleFactoryPlugin.js +10 -8
  15. package/lib/ExternalsPlugin.js +2 -1
  16. package/lib/ManifestPlugin.js +235 -0
  17. package/lib/Module.js +3 -0
  18. package/lib/ModuleGraph.js +2 -1
  19. package/lib/ModuleSourceTypesConstants.js +0 -6
  20. package/lib/MultiCompiler.js +1 -1
  21. package/lib/NodeStuffPlugin.js +419 -121
  22. package/lib/NormalModule.js +17 -16
  23. package/lib/RuntimeGlobals.js +22 -4
  24. package/lib/RuntimePlugin.js +27 -6
  25. package/lib/RuntimeTemplate.js +115 -56
  26. package/lib/SourceMapDevToolPlugin.js +20 -0
  27. package/lib/WebpackOptionsApply.js +33 -9
  28. package/lib/asset/AssetBytesGenerator.js +1 -1
  29. package/lib/asset/AssetGenerator.js +1 -2
  30. package/lib/asset/AssetSourceGenerator.js +1 -1
  31. package/lib/config/browserslistTargetHandler.js +5 -0
  32. package/lib/config/defaults.js +98 -18
  33. package/lib/config/normalization.js +2 -1
  34. package/lib/config/target.js +6 -0
  35. package/lib/css/CssGenerator.js +283 -57
  36. package/lib/css/CssLoadingRuntimeModule.js +2 -0
  37. package/lib/css/CssMergeStyleSheetsRuntimeModule.js +56 -0
  38. package/lib/css/CssModulesPlugin.js +84 -34
  39. package/lib/css/CssParser.js +1174 -667
  40. package/lib/css/walkCssTokens.js +97 -0
  41. package/lib/dependencies/CommonJsImportsParserPlugin.js +0 -9
  42. package/lib/dependencies/CommonJsPlugin.js +12 -0
  43. package/lib/dependencies/CssIcssExportDependency.js +247 -8
  44. package/lib/dependencies/CssIcssFromIdentifierDependency.js +124 -0
  45. package/lib/dependencies/CssIcssGlobalIdentifierDependency.js +48 -0
  46. package/lib/dependencies/CssIcssImportDependency.js +60 -54
  47. package/lib/dependencies/CssIcssLocalIdentifierDependency.js +61 -0
  48. package/lib/dependencies/{CssSelfLocalIdentifierDependency.js → CssIcssSelfLocalIdentifierDependency.js} +88 -10
  49. package/lib/dependencies/CssIcssSymbolDependency.js +31 -29
  50. package/lib/dependencies/CssImportDependency.js +15 -5
  51. package/lib/dependencies/ExternalModuleInitFragment.js +1 -1
  52. package/lib/dependencies/ExternalModuleInitFragmentDependency.js +95 -0
  53. package/lib/dependencies/HarmonyAcceptDependency.js +6 -1
  54. package/lib/dependencies/HarmonyAcceptImportDependency.js +2 -1
  55. package/lib/dependencies/HarmonyEvaluatedImportSpecifierDependency.js +12 -1
  56. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +32 -21
  57. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +12 -8
  58. package/lib/dependencies/HarmonyImportDependency.js +23 -27
  59. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +28 -69
  60. package/lib/dependencies/HarmonyImportSideEffectDependency.js +4 -3
  61. package/lib/dependencies/HarmonyImportSpecifierDependency.js +10 -8
  62. package/lib/dependencies/ImportDependency.js +8 -2
  63. package/lib/dependencies/ImportEagerDependency.js +6 -3
  64. package/lib/dependencies/ImportMetaPlugin.js +97 -9
  65. package/lib/dependencies/ImportParserPlugin.js +19 -21
  66. package/lib/dependencies/ImportPhase.js +121 -0
  67. package/lib/dependencies/ImportWeakDependency.js +6 -3
  68. package/lib/dependencies/ModuleDependency.js +5 -1
  69. package/lib/dependencies/ModuleHotAcceptDependency.js +1 -1
  70. package/lib/esm/ExportWebpackRequireRuntimeModule.js +1 -8
  71. package/lib/hmr/LazyCompilationPlugin.js +1 -0
  72. package/lib/ids/IdHelpers.js +4 -1
  73. package/lib/index.js +6 -0
  74. package/lib/javascript/ChunkHelpers.js +16 -5
  75. package/lib/javascript/JavascriptGenerator.js +101 -101
  76. package/lib/javascript/JavascriptModulesPlugin.js +23 -13
  77. package/lib/javascript/JavascriptParser.js +142 -38
  78. package/lib/json/JsonParser.js +7 -1
  79. package/lib/library/ModuleLibraryPlugin.js +0 -10
  80. package/lib/library/SystemLibraryPlugin.js +4 -0
  81. package/lib/library/UmdLibraryPlugin.js +1 -1
  82. package/lib/node/NodeTargetPlugin.js +9 -1
  83. package/lib/node/ReadFileCompileWasmPlugin.js +0 -2
  84. package/lib/optimize/ConcatenatedModule.js +161 -135
  85. package/lib/runtime/AsyncModuleRuntimeModule.js +28 -18
  86. package/lib/runtime/AutoPublicPathRuntimeModule.js +8 -3
  87. package/lib/runtime/MakeDeferredNamespaceObjectRuntime.js +89 -55
  88. package/lib/util/comparators.js +4 -3
  89. package/lib/util/internalSerializables.js +4 -4
  90. package/lib/util/jsonParseEvenBetterErrors.js +10 -0
  91. package/lib/wasm/EnableWasmLoadingPlugin.js +10 -4
  92. package/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js +8 -5
  93. package/lib/wasm-sync/WebAssemblyJavascriptGenerator.js +8 -4
  94. package/lib/web/FetchCompileWasmPlugin.js +0 -2
  95. package/lib/webpack.js +85 -82
  96. package/module.d.ts +5 -0
  97. package/package.json +16 -14
  98. package/schemas/WebpackOptions.check.js +1 -1
  99. package/schemas/WebpackOptions.json +109 -27
  100. package/schemas/plugins/ManifestPlugin.check.d.ts +7 -0
  101. package/schemas/plugins/ManifestPlugin.check.js +6 -0
  102. package/schemas/plugins/ManifestPlugin.json +98 -0
  103. package/schemas/plugins/SourceMapDevToolPlugin.check.js +1 -1
  104. package/schemas/plugins/SourceMapDevToolPlugin.json +16 -3
  105. package/schemas/plugins/container/ContainerReferencePlugin.check.js +1 -1
  106. package/schemas/plugins/container/ContainerReferencePlugin.json +4 -1
  107. package/schemas/plugins/container/ExternalsType.check.js +1 -1
  108. package/schemas/plugins/container/ModuleFederationPlugin.check.js +1 -1
  109. package/schemas/plugins/container/ModuleFederationPlugin.json +4 -1
  110. package/schemas/plugins/css/CssAutoParserOptions.check.js +1 -1
  111. package/schemas/plugins/css/CssGlobalGeneratorOptions.check.js +1 -1
  112. package/schemas/plugins/css/CssGlobalParserOptions.check.js +1 -1
  113. package/schemas/plugins/css/CssModuleGeneratorOptions.check.js +1 -1
  114. package/schemas/plugins/css/CssModuleParserOptions.check.js +1 -1
  115. package/schemas/plugins/css/CssParserOptions.check.js +1 -1
  116. package/schemas/plugins/json/JsonModulesPluginParser.check.js +1 -1
  117. package/types.d.ts +560 -293
  118. package/lib/dependencies/CssLocalIdentifierDependency.js +0 -250
@@ -12,12 +12,14 @@ const InitFragment = require("../InitFragment");
12
12
  const {
13
13
  CSS_TYPE,
14
14
  CSS_TYPES,
15
- JS_AND_CSS_EXPORT_TYPES,
16
15
  JS_AND_CSS_TYPES,
17
- JS_TYPE
16
+ JS_TYPE,
17
+ JS_TYPES
18
18
  } = require("../ModuleSourceTypesConstants");
19
19
  const RuntimeGlobals = require("../RuntimeGlobals");
20
20
  const Template = require("../Template");
21
+ const CssImportDependency = require("../dependencies/CssImportDependency");
22
+ const { getUndoPath } = require("../util/identifier");
21
23
  const memoize = require("../util/memoize");
22
24
 
23
25
  /** @typedef {import("webpack-sources").Source} Source */
@@ -38,8 +40,14 @@ const memoize = require("../util/memoize");
38
40
  /** @typedef {import("../ModuleGraph")} ModuleGraph */
39
41
  /** @typedef {import("../NormalModule")} NormalModule */
40
42
  /** @typedef {import("../util/Hash")} Hash */
43
+ /** @typedef {import("./CssModulesPlugin").ModuleFactoryCacheEntry} ModuleFactoryCacheEntry */
44
+ /** @typedef {import("../CssModule")} CssModule */
45
+ /** @typedef {import("../Compilation")} Compilation */
46
+ /** @typedef {import("../Module").RuntimeRequirements} RuntimeRequirements */
47
+ /** @typedef {import("../../declarations/WebpackOptions").CssParserExportType} CssParserExportType */
41
48
 
42
49
  const getPropertyName = memoize(() => require("../util/propertyName"));
50
+ const getCssModulesPlugin = memoize(() => require("./CssModulesPlugin"));
43
51
 
44
52
  class CssGenerator extends Generator {
45
53
  /**
@@ -50,9 +58,11 @@ class CssGenerator extends Generator {
50
58
  super();
51
59
  this.convention = options.exportsConvention;
52
60
  this.localIdentName = options.localIdentName;
53
- this.exportsOnly = options.exportsOnly;
54
- this.esModule = options.esModule;
61
+ this._exportsOnly = options.exportsOnly;
62
+ this._esModule = options.esModule;
55
63
  this._moduleGraph = moduleGraph;
64
+ /** @type {WeakMap<Source, ModuleFactoryCacheEntry>} */
65
+ this._moduleFactoryCache = new WeakMap();
56
66
  }
57
67
 
58
68
  /**
@@ -61,7 +71,7 @@ class CssGenerator extends Generator {
61
71
  * @returns {string | undefined} reason why this module can't be concatenated, undefined when it can be concatenated
62
72
  */
63
73
  getConcatenationBailoutReason(module, context) {
64
- if (!this.esModule) {
74
+ if (!this._esModule) {
65
75
  return "Module is not an ECMAScript module";
66
76
  }
67
77
 
@@ -69,24 +79,117 @@ class CssGenerator extends Generator {
69
79
  }
70
80
 
71
81
  /**
72
- * @param {NormalModule} module module for which the code should be generated
73
- * @param {GenerateContext} generateContext context for generate
74
- * @returns {Source | null} generated code
82
+ * Generate JavaScript code that requires and concatenates all CSS imports
83
+ * @param {NormalModule} module the module to generate CSS text for
84
+ * @param {GenerateContext} generateContext the generate context
85
+ * @returns {{ expr: string, type: CssParserExportType }[]} JavaScript code that concatenates all imported CSS
75
86
  */
76
- generate(module, generateContext) {
77
- const source =
78
- generateContext.type === "javascript"
79
- ? new ReplaceSource(new RawSource(""))
80
- : new ReplaceSource(/** @type {Source} */ (module.originalSource()));
87
+ _generateImportCode(module, generateContext) {
88
+ const moduleGraph = generateContext.moduleGraph;
89
+ /** @type {{ expr: string, type: CssParserExportType }[]} */
90
+ const parts = [];
91
+
92
+ // Iterate through module.dependencies to maintain source order
93
+ for (const dep of module.dependencies) {
94
+ if (dep instanceof CssImportDependency) {
95
+ /** @type {CssModule} */
96
+ const depModule = /** @type {CssModule} */ (moduleGraph.getModule(dep));
97
+ const importVar = generateContext.runtimeTemplate.moduleExports({
98
+ module: depModule,
99
+ chunkGraph: generateContext.chunkGraph,
100
+ request: /** @type {CssModule} */ (depModule).userRequest,
101
+ weak: false,
102
+ runtimeRequirements: generateContext.runtimeRequirements
103
+ });
104
+
105
+ generateContext.runtimeRequirements.add(
106
+ RuntimeGlobals.compatGetDefaultExport
107
+ );
108
+ parts.push({
109
+ expr: `(${RuntimeGlobals.compatGetDefaultExport}(${importVar})() || "")`,
110
+ type: /** @type {CssParserExportType} */ (
111
+ /** @type {BuildMeta} */ (depModule.buildMeta).exportType
112
+ )
113
+ });
114
+ }
115
+ }
81
116
 
82
- /** @type {InitFragment<GenerateContext>[]} */
83
- const initFragments = [];
84
- /** @type {CssData} */
85
- const cssData = {
86
- esModule: /** @type {boolean} */ (this.esModule),
87
- exports: new Map()
88
- };
117
+ return parts;
118
+ }
119
+
120
+ /**
121
+ * Generate CSS code for the current module
122
+ * @param {NormalModule} module the module to generate CSS code for
123
+ * @param {GenerateContext} generateContext the generate context
124
+ * @returns {string} the CSS code as string
125
+ */
126
+ _generateModuleCode(module, generateContext) {
127
+ const moduleSourceContent = /** @type {Source} */ (
128
+ this.generate(module, {
129
+ ...generateContext,
130
+ type: "css"
131
+ })
132
+ );
133
+
134
+ if (!moduleSourceContent) {
135
+ return "";
136
+ }
137
+
138
+ const compilation = generateContext.runtimeTemplate.compilation;
139
+ const { path: filename } = compilation.getPathWithInfo(
140
+ compilation.outputOptions.cssChunkFilename,
141
+ {
142
+ runtime: generateContext.runtime,
143
+ contentHashType: "css"
144
+ }
145
+ );
146
+ const undoPath = getUndoPath(
147
+ filename,
148
+ compilation.outputOptions.path,
149
+ false
150
+ );
151
+
152
+ const CssModulesPlugin = getCssModulesPlugin();
153
+ const hooks = CssModulesPlugin.getCompilationHooks(compilation);
154
+ const renderedSource = CssModulesPlugin.renderModule(
155
+ /** @type {CssModule} */ (module),
156
+ {
157
+ undoPath,
158
+ moduleSourceContent,
159
+ moduleFactoryCache: this._moduleFactoryCache,
160
+ runtimeTemplate: generateContext.runtimeTemplate
161
+ },
162
+ hooks
163
+ );
164
+
165
+ if (!renderedSource) {
166
+ return "";
167
+ }
168
+
169
+ const content = renderedSource.source();
170
+ return typeof content === "string" ? content : content.toString("utf8");
171
+ }
89
172
 
173
+ /**
174
+ * @param {NormalModule} module the current module
175
+ * @param {Dependency} dependency the dependency to generate
176
+ * @param {InitFragment<GenerateContext>[]} initFragments mutable list of init fragments
177
+ * @param {ReplaceSource} source the current replace source which can be modified
178
+ * @param {GenerateContext & { cssData: CssData }} generateContext the render context
179
+ * @returns {void}
180
+ */
181
+ sourceDependency(module, dependency, initFragments, source, generateContext) {
182
+ const constructor =
183
+ /** @type {DependencyConstructor} */
184
+ (dependency.constructor);
185
+ const template = generateContext.dependencyTemplates.get(constructor);
186
+ if (!template) {
187
+ throw new Error(
188
+ `No template for dependency: ${dependency.constructor.name}`
189
+ );
190
+ }
191
+
192
+ /** @type {DependencyTemplateContext} */
90
193
  /** @type {InitFragment<GenerateContext>[] | undefined} */
91
194
  let chunkInitFragments;
92
195
  /** @type {DependencyTemplateContext} */
@@ -103,7 +206,8 @@ class CssGenerator extends Generator {
103
206
  /** @type {CodeGenerationResults} */
104
207
  (generateContext.codeGenerationResults),
105
208
  initFragments,
106
- cssData,
209
+ cssData: generateContext.cssData,
210
+ type: generateContext.type,
107
211
  get chunkInitFragments() {
108
212
  if (!chunkInitFragments) {
109
213
  const data =
@@ -120,38 +224,149 @@ class CssGenerator extends Generator {
120
224
  }
121
225
  };
122
226
 
123
- /**
124
- * @param {Dependency} dependency dependency
125
- */
126
- const handleDependency = (dependency) => {
127
- const constructor =
128
- /** @type {DependencyConstructor} */
129
- (dependency.constructor);
130
- const template = generateContext.dependencyTemplates.get(constructor);
131
- if (!template) {
132
- throw new Error(
133
- `No template for dependency: ${dependency.constructor.name}`
227
+ template.apply(dependency, source, templateContext);
228
+ }
229
+
230
+ /**
231
+ * @param {NormalModule} module the module to generate
232
+ * @param {InitFragment<GenerateContext>[]} initFragments mutable list of init fragments
233
+ * @param {ReplaceSource} source the current replace source which can be modified
234
+ * @param {GenerateContext & { cssData: CssData }} generateContext the generateContext
235
+ * @returns {void}
236
+ */
237
+ sourceModule(module, initFragments, source, generateContext) {
238
+ for (const dependency of module.dependencies) {
239
+ this.sourceDependency(
240
+ module,
241
+ dependency,
242
+ initFragments,
243
+ source,
244
+ generateContext
245
+ );
246
+ }
247
+
248
+ if (module.presentationalDependencies !== undefined) {
249
+ for (const dependency of module.presentationalDependencies) {
250
+ this.sourceDependency(
251
+ module,
252
+ dependency,
253
+ initFragments,
254
+ source,
255
+ generateContext
134
256
  );
135
257
  }
258
+ }
259
+ }
136
260
 
137
- template.apply(dependency, source, templateContext);
261
+ /**
262
+ * @param {NormalModule} module module for which the code should be generated
263
+ * @param {GenerateContext} generateContext context for generate
264
+ * @returns {Source | null} generated code
265
+ */
266
+ generate(module, generateContext) {
267
+ const exportType = /** @type {BuildMeta} */ (module.buildMeta).exportType;
268
+ const source =
269
+ generateContext.type === "javascript"
270
+ ? exportType === "link"
271
+ ? new ReplaceSource(new RawSource(""))
272
+ : new ReplaceSource(/** @type {Source} */ (module.originalSource()))
273
+ : new ReplaceSource(/** @type {Source} */ (module.originalSource()));
274
+ /** @type {InitFragment<GenerateContext>[]} */
275
+ const initFragments = [];
276
+ /** @type {CssData} */
277
+ const cssData = {
278
+ esModule: /** @type {boolean} */ (this._esModule),
279
+ exports: new Map()
138
280
  };
139
281
 
140
- for (const dependency of module.dependencies) {
141
- handleDependency(dependency);
142
- }
282
+ this.sourceModule(module, initFragments, source, {
283
+ ...generateContext,
284
+ cssData
285
+ });
286
+
287
+ const generateCssText = () => {
288
+ const importCode = this._generateImportCode(module, generateContext);
289
+ const moduleCode = this._generateModuleCode(module, generateContext);
290
+
291
+ if (importCode.length > 0) {
292
+ if (
293
+ exportType === "css-style-sheet" ||
294
+ importCode.some((part) => part.type !== exportType)
295
+ ) {
296
+ generateContext.runtimeRequirements.add(
297
+ RuntimeGlobals.cssMergeStyleSheets
298
+ );
299
+
300
+ return `${RuntimeGlobals.cssMergeStyleSheets}([${[...importCode.map((part) => part.expr), JSON.stringify(moduleCode)].join(", ")}])`;
301
+ }
302
+ return generateContext.runtimeTemplate.concatenation(
303
+ ...importCode,
304
+ moduleCode
305
+ );
306
+ }
307
+ return JSON.stringify(moduleCode);
308
+ };
309
+
310
+ /**
311
+ * @returns {string | null} the default export
312
+ */
313
+ const generateJSDefaultExport = () => {
314
+ switch (exportType) {
315
+ case "text": {
316
+ return generateCssText();
317
+ }
318
+ case "css-style-sheet": {
319
+ const constOrVar = generateContext.runtimeTemplate.renderConst();
320
+ return `(${generateContext.runtimeTemplate.basicFunction("", [
321
+ `${constOrVar} cssText = ${generateCssText()};`,
322
+ `${constOrVar} sheet = new CSSStyleSheet();`,
323
+ "sheet.replaceSync(cssText);",
324
+ "return sheet;"
325
+ ])})()`;
326
+ }
327
+ default:
328
+ return null;
329
+ }
330
+ };
143
331
 
144
332
  switch (generateContext.type) {
145
333
  case "javascript": {
334
+ const isCSSModule = /** @type {BuildMeta} */ (module.buildMeta)
335
+ .isCSSModule;
336
+ const defaultExport = generateJSDefaultExport();
337
+ /**
338
+ * @param {string} name the export name
339
+ * @param {string} value the export value
340
+ * @returns {string} the value to be used in the export
341
+ */
342
+ const stringifyExportValue = (name, value) => {
343
+ if (defaultExport) {
344
+ return name === "default" ? value : JSON.stringify(value);
345
+ }
346
+ return JSON.stringify(value);
347
+ };
348
+
146
349
  /** @type {BuildInfo} */
147
350
  (module.buildInfo).cssData = cssData;
148
351
 
149
- generateContext.runtimeRequirements.add(RuntimeGlobals.module);
352
+ // Required for HMR
353
+ if (module.hot) {
354
+ generateContext.runtimeRequirements.add(RuntimeGlobals.module);
355
+ }
356
+
357
+ if (defaultExport) {
358
+ cssData.exports.set("default", /** @type {string} */ (defaultExport));
359
+ }
360
+
361
+ if (cssData.exports.size === 0 && !isCSSModule) {
362
+ return new RawSource("");
363
+ }
150
364
 
151
365
  if (generateContext.concatenationScope) {
152
366
  const source = new ConcatSource();
153
367
  const usedIdentifiers = new Set();
154
368
  const { RESERVED_IDENTIFIER } = getPropertyName();
369
+
155
370
  for (const [name, v] of cssData.exports) {
156
371
  const usedName = generateContext.moduleGraph
157
372
  .getExportInfo(module, name)
@@ -171,21 +386,14 @@ class CssGenerator extends Generator {
171
386
  usedIdentifiers.add(identifier);
172
387
  generateContext.concatenationScope.registerExport(name, identifier);
173
388
  source.add(
174
- `${generateContext.runtimeTemplate.renderConst()} ${identifier} = ${JSON.stringify(v)};\n`
389
+ `${generateContext.runtimeTemplate.renderConst()} ${identifier} = ${stringifyExportValue(name, v)};\n`
175
390
  );
176
391
  }
177
392
  return source;
178
393
  }
179
394
 
180
- if (
181
- cssData.exports.size === 0 &&
182
- !(/** @type {BuildMeta} */ (module.buildMeta).isCSSModule)
183
- ) {
184
- return new RawSource("");
185
- }
186
-
187
395
  const needNsObj =
188
- this.esModule &&
396
+ this._esModule &&
189
397
  generateContext.moduleGraph
190
398
  .getExportsInfo(module)
191
399
  .otherExportsInfo.getUsed(generateContext.runtime) !==
@@ -197,10 +405,21 @@ class CssGenerator extends Generator {
197
405
  );
198
406
  }
199
407
 
408
+ // Should be after `concatenationScope` to allow module inlining
409
+ generateContext.runtimeRequirements.add(RuntimeGlobals.module);
410
+
411
+ if (!isCSSModule && !needNsObj) {
412
+ return new RawSource(
413
+ `${module.moduleArgument}.exports = ${defaultExport}`
414
+ );
415
+ }
416
+
200
417
  const exports = [];
201
418
 
202
419
  for (const [name, v] of cssData.exports) {
203
- exports.push(`\t${JSON.stringify(name)}: ${JSON.stringify(v)}`);
420
+ exports.push(
421
+ `\t${JSON.stringify(name)}: ${stringifyExportValue(name, v)}`
422
+ );
204
423
  }
205
424
 
206
425
  return new RawSource(
@@ -210,14 +429,10 @@ class CssGenerator extends Generator {
210
429
  );
211
430
  }
212
431
  case "css": {
213
- if (module.presentationalDependencies !== undefined) {
214
- for (const dependency of module.presentationalDependencies) {
215
- handleDependency(dependency);
216
- }
432
+ if (!this._generatesJsOnly(module)) {
433
+ generateContext.runtimeRequirements.add(RuntimeGlobals.hasCssModules);
217
434
  }
218
435
 
219
- generateContext.runtimeRequirements.add(RuntimeGlobals.hasCssModules);
220
-
221
436
  return InitFragment.addToSource(source, initFragments, generateContext);
222
437
  }
223
438
  default:
@@ -251,9 +466,8 @@ class CssGenerator extends Generator {
251
466
  * @returns {SourceTypes} available types (do not mutate)
252
467
  */
253
468
  getTypes(module) {
254
- // TODO, find a better way to prevent the original module from being removed after concatenation, maybe it is a bug
255
- if (this.exportsOnly) {
256
- return JS_AND_CSS_EXPORT_TYPES;
469
+ if (this._generatesJsOnly(module)) {
470
+ return JS_TYPES;
257
471
  }
258
472
  const sourceTypes = new Set();
259
473
  const connections = this._moduleGraph.getIncomingConnections(module);
@@ -318,7 +532,19 @@ class CssGenerator extends Generator {
318
532
  * @param {UpdateHashContext} updateHashContext context for updating hash
319
533
  */
320
534
  updateHash(hash, { module }) {
321
- hash.update(/** @type {boolean} */ (this.esModule).toString());
535
+ hash.update(/** @type {boolean} */ (this._esModule).toString());
536
+ }
537
+
538
+ /**
539
+ * @param {NormalModule} module module
540
+ * @returns {boolean} true if the module only outputs JavaScript
541
+ */
542
+ _generatesJsOnly(module) {
543
+ const exportType = /** @type {BuildMeta} */ (module.buildMeta).exportType;
544
+ return (
545
+ this._exportsOnly ||
546
+ /** @type {boolean} */ (exportType && exportType !== "link")
547
+ );
322
548
  }
323
549
  }
324
550
 
@@ -462,6 +462,8 @@ class CssLoadingRuntimeModule extends RuntimeModule {
462
462
  `var url = ${RuntimeGlobals.publicPath} + filename;`,
463
463
  "var oldTag = loadStylesheet(chunkId, url);",
464
464
  "if(!oldTag) return;",
465
+ "// create error before stack unwound to get useful stacktrace later",
466
+ "var error = new Error();",
465
467
  `promises.push(new Promise(${runtimeTemplate.basicFunction(
466
468
  "resolve, reject",
467
469
  [
@@ -0,0 +1,56 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Natsu @xiaoxiaojx
4
+ */
5
+
6
+ "use strict";
7
+
8
+ const RuntimeGlobals = require("../RuntimeGlobals");
9
+ const RuntimeModule = require("../RuntimeModule");
10
+ const Template = require("../Template");
11
+
12
+ /** @typedef {import("../Chunk")} Chunk */
13
+
14
+ class CssMergeStyleSheetsRuntimeModule extends RuntimeModule {
15
+ constructor() {
16
+ super("css merge stylesheets");
17
+ }
18
+
19
+ /**
20
+ * @returns {string | null} runtime code
21
+ */
22
+ generate() {
23
+ const { runtimeTemplate } = /** @type {import("../Compilation")} */ (
24
+ this.compilation
25
+ );
26
+
27
+ return Template.asString([
28
+ `${RuntimeGlobals.cssMergeStyleSheets} = ${runtimeTemplate.basicFunction(
29
+ "sheets",
30
+ [
31
+ "var sheetsArray = Array.isArray(sheets) ? sheets : [sheets];",
32
+ "var cssTexts = [];",
33
+ "for (var i = 0; i < sheetsArray.length; i++) {",
34
+ Template.indent([
35
+ "var s = sheetsArray[i];",
36
+ "if (!s) continue;",
37
+ "if (typeof s === 'string') {",
38
+ Template.indent("cssTexts.push(s);"),
39
+ "} else if (s.cssRules) {",
40
+ Template.indent([
41
+ "var rules = s.cssRules;",
42
+ "for (var j = 0; j < rules.length; j++) {",
43
+ Template.indent("cssTexts.push(rules[j].cssText);"),
44
+ "}"
45
+ ]),
46
+ "}"
47
+ ]),
48
+ "}",
49
+ "return cssTexts.join('');"
50
+ ]
51
+ )};`
52
+ ]);
53
+ }
54
+ }
55
+
56
+ module.exports = CssMergeStyleSheetsRuntimeModule;