webpack 5.2.1 → 5.4.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.

package/bin/webpack.js CHANGED
@@ -41,6 +41,19 @@ const isInstalled = packageName => {
41
41
  }
42
42
  };
43
43
 
44
+ /**
45
+ * @param {CliOption} cli options
46
+ * @returns {void}
47
+ */
48
+ const runCli = cli => {
49
+ const path = require("path");
50
+ const pkgPath = require.resolve(`${cli.package}/package.json`);
51
+ // eslint-disable-next-line node/no-missing-require
52
+ const pkg = require(pkgPath);
53
+ // eslint-disable-next-line node/no-missing-require
54
+ require(path.resolve(path.dirname(pkgPath), pkg.bin[cli.binName]));
55
+ };
56
+
44
57
  /**
45
58
  * @typedef {Object} CliOption
46
59
  * @property {string} name display name
@@ -116,7 +129,7 @@ if (!cli.installed) {
116
129
 
117
130
  runCommand(packageManager, installOptions.concat(cli.package))
118
131
  .then(() => {
119
- require(cli.package); //eslint-disable-line
132
+ runCli(cli);
120
133
  })
121
134
  .catch(error => {
122
135
  console.error(error);
@@ -124,10 +137,5 @@ if (!cli.installed) {
124
137
  });
125
138
  });
126
139
  } else {
127
- const path = require("path");
128
- const pkgPath = require.resolve(`${cli.package}/package.json`);
129
- // eslint-disable-next-line node/no-missing-require
130
- const pkg = require(pkgPath);
131
- // eslint-disable-next-line node/no-missing-require
132
- require(path.resolve(path.dirname(pkgPath), pkg.bin[cli.binName]));
140
+ runCli(cli);
133
141
  }
package/lib/ChunkGraph.js CHANGED
@@ -200,6 +200,8 @@ class ChunkGraph {
200
200
  this._chunks = new WeakMap();
201
201
  /** @private @type {WeakMap<AsyncDependenciesBlock, ChunkGroup>} */
202
202
  this._blockChunkGroups = new WeakMap();
203
+ /** @private @type {Map<string, string | number>} */
204
+ this._runtimeIds = new Map();
203
205
  /** @type {ModuleGraph} */
204
206
  this.moduleGraph = moduleGraph;
205
207
 
@@ -1144,6 +1146,23 @@ class ChunkGraph {
1144
1146
  cgm.id = id;
1145
1147
  }
1146
1148
 
1149
+ /**
1150
+ * @param {string} runtime runtime
1151
+ * @returns {string | number} the id of the runtime
1152
+ */
1153
+ getRuntimeId(runtime) {
1154
+ return this._runtimeIds.get(runtime);
1155
+ }
1156
+
1157
+ /**
1158
+ * @param {string} runtime runtime
1159
+ * @param {string | number} id the id of the runtime
1160
+ * @returns {void}
1161
+ */
1162
+ setRuntimeId(runtime, id) {
1163
+ this._runtimeIds.set(runtime, id);
1164
+ }
1165
+
1147
1166
  /**
1148
1167
  * @param {Module} module the module
1149
1168
  * @param {RuntimeSpec} runtime the runtime
@@ -1939,6 +1939,8 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
1939
1939
  this.hooks.optimizeChunkIds.call(this.chunks);
1940
1940
  this.hooks.afterOptimizeChunkIds.call(this.chunks);
1941
1941
 
1942
+ this.assignRuntimeIds();
1943
+
1942
1944
  this.sortItemsWithChunkIds();
1943
1945
 
1944
1946
  if (shouldRecord) {
@@ -2556,6 +2558,21 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
2556
2558
  }
2557
2559
  }
2558
2560
 
2561
+ assignRuntimeIds() {
2562
+ const { chunkGraph } = this;
2563
+ const processEntrypoint = ep => {
2564
+ const runtime = ep.options.runtime || ep.name;
2565
+ const chunk = ep.getRuntimeChunk();
2566
+ chunkGraph.setRuntimeId(runtime, chunk.id);
2567
+ };
2568
+ for (const ep of this.entrypoints.values()) {
2569
+ processEntrypoint(ep);
2570
+ }
2571
+ for (const ep of this.asyncEntrypoints) {
2572
+ processEntrypoint(ep);
2573
+ }
2574
+ }
2575
+
2559
2576
  sortItemsWithChunkIds() {
2560
2577
  for (const chunkGroup of this.chunkGroups) {
2561
2578
  chunkGroup.sortItems();
@@ -2592,7 +2609,7 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
2592
2609
 
2593
2610
  createModuleHashes() {
2594
2611
  let statModulesHashed = 0;
2595
- const chunkGraph = this.chunkGraph;
2612
+ const { chunkGraph, runtimeTemplate } = this;
2596
2613
  const { hashFunction, hashDigest, hashDigestLength } = this.outputOptions;
2597
2614
  for (const module of this.modules) {
2598
2615
  for (const runtime of chunkGraph.getModuleRuntimes(module)) {
@@ -2600,7 +2617,8 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
2600
2617
  const moduleHash = createHash(hashFunction);
2601
2618
  module.updateHash(moduleHash, {
2602
2619
  chunkGraph,
2603
- runtime
2620
+ runtime,
2621
+ runtimeTemplate
2604
2622
  });
2605
2623
  const moduleHashDigest = /** @type {string} */ (moduleHash.digest(
2606
2624
  hashDigest
@@ -2623,6 +2641,7 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
2623
2641
  createHash() {
2624
2642
  this.logger.time("hashing: initialize hash");
2625
2643
  const chunkGraph = this.chunkGraph;
2644
+ const runtimeTemplate = this.runtimeTemplate;
2626
2645
  const outputOptions = this.outputOptions;
2627
2646
  const hashFunction = outputOptions.hashFunction;
2628
2647
  const hashDigest = outputOptions.hashDigest;
@@ -2707,7 +2726,8 @@ This prevents using hashes of each other and should be avoided.`
2707
2726
  const moduleHash = createHash(hashFunction);
2708
2727
  module.updateHash(moduleHash, {
2709
2728
  chunkGraph,
2710
- runtime: chunk.runtime
2729
+ runtime: chunk.runtime,
2730
+ runtimeTemplate
2711
2731
  });
2712
2732
  const moduleHashDigest = /** @type {string} */ (moduleHash.digest(
2713
2733
  hashDigest
@@ -2769,7 +2789,8 @@ This prevents using hashes of each other and should be avoided.`
2769
2789
  const moduleHash = createHash(hashFunction);
2770
2790
  module.updateHash(moduleHash, {
2771
2791
  chunkGraph,
2772
- runtime: chunk.runtime
2792
+ runtime: chunk.runtime,
2793
+ runtimeTemplate
2773
2794
  });
2774
2795
  const moduleHashDigest = /** @type {string} */ (moduleHash.digest(
2775
2796
  hashDigest
@@ -39,16 +39,19 @@ const NAMESPACE_OBJECT_EXPORT = "__WEBPACK_NAMESPACE_OBJECT__";
39
39
 
40
40
  class ConcatenationScope {
41
41
  /**
42
- * @param {ModuleInfo[]} modulesWithInfo all module info in order
42
+ * @param {ModuleInfo[] | Map<Module, ModuleInfo>} modulesMap all module info by module
43
43
  * @param {ConcatenatedModuleInfo} currentModule the current module info
44
44
  */
45
- constructor(modulesWithInfo, currentModule) {
45
+ constructor(modulesMap, currentModule) {
46
46
  this._currentModule = currentModule;
47
- this._modulesWithInfo = modulesWithInfo;
48
- this._modulesMap = new Map();
49
- for (const info of modulesWithInfo) {
50
- this._modulesMap.set(info.module, info);
47
+ if (Array.isArray(modulesMap)) {
48
+ const map = new Map();
49
+ for (const info of modulesMap) {
50
+ map.set(info.module, info);
51
+ }
52
+ modulesMap = map;
51
53
  }
54
+ this._modulesMap = modulesMap;
52
55
  }
53
56
 
54
57
  /**
@@ -0,0 +1,109 @@
1
+ /*
2
+ MIT License http://www.opensource.org/licenses/mit-license.php
3
+ Author Tobias Koppers @sokra
4
+ */
5
+
6
+ "use strict";
7
+
8
+ const { ConcatSource, PrefixSource } = require("webpack-sources");
9
+ const InitFragment = require("./InitFragment");
10
+ const Template = require("./Template");
11
+ const { mergeRuntime } = require("./util/runtime");
12
+
13
+ /** @typedef {import("webpack-sources").Source} Source */
14
+ /** @typedef {import("./Generator").GenerateContext} GenerateContext */
15
+ /** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */
16
+
17
+ const wrapInCondition = (condition, source) => {
18
+ if (typeof source === "string") {
19
+ return Template.asString([
20
+ `if (${condition}) {`,
21
+ Template.indent(source),
22
+ "}",
23
+ ""
24
+ ]);
25
+ } else {
26
+ return new ConcatSource(
27
+ `if (${condition}) {\n`,
28
+ new PrefixSource("\t", source),
29
+ "}\n"
30
+ );
31
+ }
32
+ };
33
+
34
+ class ConditionalInitFragment extends InitFragment {
35
+ /**
36
+ * @param {string|Source} content the source code that will be included as initialization code
37
+ * @param {number} stage category of initialization code (contribute to order)
38
+ * @param {number} position position in the category (contribute to order)
39
+ * @param {string} key unique key to avoid emitting the same initialization code twice
40
+ * @param {RuntimeSpec | boolean} runtimeCondition in which runtime this fragment should be executed
41
+ * @param {string|Source=} endContent the source code that will be included at the end of the module
42
+ */
43
+ constructor(
44
+ content,
45
+ stage,
46
+ position,
47
+ key,
48
+ runtimeCondition = true,
49
+ endContent
50
+ ) {
51
+ super(content, stage, position, key, endContent);
52
+ this.runtimeCondition = runtimeCondition;
53
+ }
54
+
55
+ /**
56
+ * @param {GenerateContext} generateContext context for generate
57
+ * @returns {string|Source} the source code that will be included as initialization code
58
+ */
59
+ getContent(generateContext) {
60
+ if (this.runtimeCondition === false || !this.content) return "";
61
+ if (this.runtimeCondition === true) return this.content;
62
+ const expr = generateContext.runtimeTemplate.runtimeConditionExpression({
63
+ chunkGraph: generateContext.chunkGraph,
64
+ runtimeRequirements: generateContext.runtimeRequirements,
65
+ runtime: generateContext.runtime,
66
+ runtimeCondition: this.runtimeCondition
67
+ });
68
+ if (expr === "true") return this.content;
69
+ return wrapInCondition(expr, this.content);
70
+ }
71
+
72
+ /**
73
+ * @param {GenerateContext} generateContext context for generate
74
+ * @returns {string|Source=} the source code that will be included at the end of the module
75
+ */
76
+ getEndContent(generateContext) {
77
+ if (this.runtimeCondition === false || !this.endContent) return "";
78
+ if (this.runtimeCondition === true) return this.endContent;
79
+ const expr = generateContext.runtimeTemplate.runtimeConditionExpression({
80
+ chunkGraph: generateContext.chunkGraph,
81
+ runtimeRequirements: generateContext.runtimeRequirements,
82
+ runtime: generateContext.runtime,
83
+ runtimeCondition: this.runtimeCondition
84
+ });
85
+ if (expr === "true") return this.endContent;
86
+ return wrapInCondition(expr, this.endContent);
87
+ }
88
+
89
+ merge(other) {
90
+ if (this.runtimeCondition === true) return this;
91
+ if (other.runtimeCondition === true) return other;
92
+ if (this.runtimeCondition === false) return other;
93
+ if (other.runtimeCondition === false) return this;
94
+ const runtimeCondition = mergeRuntime(
95
+ this.runtimeCondition,
96
+ other.runtimeCondition
97
+ );
98
+ return new ConditionalInitFragment(
99
+ this.content,
100
+ this.stage,
101
+ this.position,
102
+ this.key,
103
+ runtimeCondition,
104
+ this.endContent
105
+ );
106
+ }
107
+ }
108
+
109
+ module.exports = ConditionalInitFragment;
package/lib/Dependency.js CHANGED
@@ -21,6 +21,7 @@
21
21
  * @typedef {Object} UpdateHashContext
22
22
  * @property {ChunkGraph} chunkGraph
23
23
  * @property {RuntimeSpec} runtime
24
+ * @property {RuntimeTemplate=} runtimeTemplate
24
25
  */
25
26
 
26
27
  /**
package/lib/Module.js CHANGED
@@ -415,19 +415,20 @@ class Module extends DependenciesBlock {
415
415
  getExportsType(moduleGraph, strict) {
416
416
  switch (this.buildMeta && this.buildMeta.exportsType) {
417
417
  case "flagged":
418
- return strict ? "default-only" : "namespace";
418
+ return strict ? "default-with-named" : "namespace";
419
419
  case "namespace":
420
420
  return "namespace";
421
421
  case "default":
422
422
  switch (this.buildMeta.defaultObject) {
423
423
  case "redirect":
424
+ return "default-with-named";
424
425
  case "redirect-warn":
425
426
  return strict ? "default-only" : "default-with-named";
426
427
  default:
427
428
  return "default-only";
428
429
  }
429
430
  case "dynamic": {
430
- if (strict) return "default-only";
431
+ if (strict) return "default-with-named";
431
432
  // Try to figure out value of __esModule by following reexports
432
433
  const handleDefault = () => {
433
434
  switch (this.buildMeta.defaultObject) {
@@ -465,7 +466,7 @@ class Module extends DependenciesBlock {
465
466
  }
466
467
  }
467
468
  default:
468
- return strict ? "default-only" : "dynamic";
469
+ return strict ? "default-with-named" : "dynamic";
469
470
  }
470
471
  }
471
472
 
@@ -281,14 +281,13 @@ class ProgressPlugin {
281
281
  if (modulesCount % 100 === 0) updateThrottled();
282
282
  };
283
283
 
284
+ // only used when showActiveModules is set
284
285
  const moduleBuild = module => {
285
- if (showActiveModules) {
286
- const ident = module.identifier();
287
- if (ident) {
288
- activeModules.add(ident);
289
- lastActiveModule = ident;
290
- update();
291
- }
286
+ const ident = module.identifier();
287
+ if (ident) {
288
+ activeModules.add(ident);
289
+ lastActiveModule = ident;
290
+ update();
292
291
  }
293
292
  };
294
293
 
@@ -346,6 +345,7 @@ class ProgressPlugin {
346
345
  });
347
346
 
348
347
  compiler.hooks.afterCompile.tapPromise("ProgressPlugin", compilation => {
348
+ if (compilation.compiler.isChild()) return Promise.resolve();
349
349
  return cacheGetPromise.then(async oldData => {
350
350
  if (
351
351
  !oldData ||
@@ -380,7 +380,9 @@ class ProgressPlugin {
380
380
  moduleDone
381
381
  );
382
382
 
383
- compilation.hooks.buildModule.tap("ProgressPlugin", moduleBuild);
383
+ if (showActiveModules) {
384
+ compilation.hooks.buildModule.tap("ProgressPlugin", moduleBuild);
385
+ }
384
386
 
385
387
  compilation.hooks.addEntry.tap("ProgressPlugin", entryAdd);
386
388
  compilation.hooks.failedEntry.tap("ProgressPlugin", entryDone);
@@ -173,6 +173,11 @@ exports.loadScript = "__webpack_require__.l";
173
173
  */
174
174
  exports.chunkName = "__webpack_require__.cn";
175
175
 
176
+ /**
177
+ * the runtime id of the current runtime
178
+ */
179
+ exports.runtimeId = "__webpack_require__.j";
180
+
176
181
  /**
177
182
  * the filename of the script part of the chunk
178
183
  */
@@ -21,6 +21,7 @@ const HasOwnPropertyRuntimeModule = require("./runtime/HasOwnPropertyRuntimeModu
21
21
  const LoadScriptRuntimeModule = require("./runtime/LoadScriptRuntimeModule");
22
22
  const MakeNamespaceObjectRuntimeModule = require("./runtime/MakeNamespaceObjectRuntimeModule");
23
23
  const PublicPathRuntimeModule = require("./runtime/PublicPathRuntimeModule");
24
+ const RuntimeIdRuntimeModule = require("./runtime/RuntimeIdRuntimeModule");
24
25
  const SystemContextRuntimeModule = require("./runtime/SystemContextRuntimeModule");
25
26
  const ShareRuntimeModule = require("./sharing/ShareRuntimeModule");
26
27
  const StringXor = require("./util/StringXor");
@@ -31,6 +32,7 @@ const StringXor = require("./util/StringXor");
31
32
 
32
33
  const GLOBALS_ON_REQUIRE = [
33
34
  RuntimeGlobals.chunkName,
35
+ RuntimeGlobals.runtimeId,
34
36
  RuntimeGlobals.compatGetDefaultExport,
35
37
  RuntimeGlobals.createFakeNamespaceObject,
36
38
  RuntimeGlobals.definePropertyGetters,
@@ -156,6 +158,12 @@ class RuntimePlugin {
156
158
  );
157
159
  return true;
158
160
  });
161
+ compilation.hooks.runtimeRequirementInTree
162
+ .for(RuntimeGlobals.runtimeId)
163
+ .tap("RuntimePlugin", chunk => {
164
+ compilation.addRuntimeModule(chunk, new RuntimeIdRuntimeModule());
165
+ return true;
166
+ });
159
167
  compilation.hooks.runtimeRequirementInTree
160
168
  .for(RuntimeGlobals.publicPath)
161
169
  .tap("RuntimePlugin", (chunk, set) => {
@@ -9,7 +9,9 @@ const InitFragment = require("./InitFragment");
9
9
  const RuntimeGlobals = require("./RuntimeGlobals");
10
10
  const Template = require("./Template");
11
11
  const { equals } = require("./util/ArrayHelpers");
12
+ const compileBooleanMatcher = require("./util/compileBooleanMatcher");
12
13
  const propertyAccess = require("./util/propertyAccess");
14
+ const { forEachRuntime, subtractRuntime } = require("./util/runtime");
13
15
 
14
16
  /** @typedef {import("../declarations/WebpackOptions").OutputNormalized} OutputOptions */
15
17
  /** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */
@@ -562,6 +564,39 @@ class RuntimeTemplate {
562
564
  return `${promise || "Promise.resolve()"}${appending}`;
563
565
  }
564
566
 
567
+ /**
568
+ * @param {Object} options options object
569
+ * @param {ChunkGraph} options.chunkGraph the chunk graph
570
+ * @param {RuntimeSpec=} options.runtime runtime for which this code will be generated
571
+ * @param {RuntimeSpec | boolean=} options.runtimeCondition only execute the statement in some runtimes
572
+ * @param {Set<string>} options.runtimeRequirements if set, will be filled with runtime requirements
573
+ * @returns {string} expression
574
+ */
575
+ runtimeConditionExpression({
576
+ chunkGraph,
577
+ runtimeCondition,
578
+ runtime,
579
+ runtimeRequirements
580
+ }) {
581
+ if (runtimeCondition === undefined) return "true";
582
+ if (typeof runtimeCondition === "boolean") return `${runtimeCondition}`;
583
+ /** @type {Set<string>} */
584
+ const positiveRuntimeIds = new Set();
585
+ forEachRuntime(runtimeCondition, runtime =>
586
+ positiveRuntimeIds.add(`${chunkGraph.getRuntimeId(runtime)}`)
587
+ );
588
+ /** @type {Set<string>} */
589
+ const negativeRuntimeIds = new Set();
590
+ forEachRuntime(subtractRuntime(runtime, runtimeCondition), runtime =>
591
+ negativeRuntimeIds.add(`${chunkGraph.getRuntimeId(runtime)}`)
592
+ );
593
+ runtimeRequirements.add(RuntimeGlobals.runtimeId);
594
+ return compileBooleanMatcher.fromLists(
595
+ Array.from(positiveRuntimeIds),
596
+ Array.from(negativeRuntimeIds)
597
+ )(RuntimeGlobals.runtimeId);
598
+ }
599
+
565
600
  /**
566
601
  *
567
602
  * @param {Object} options options object
@@ -572,6 +607,8 @@ class RuntimeTemplate {
572
607
  * @param {string} options.importVar name of the import variable
573
608
  * @param {Module} options.originModule module in which the statement is emitted
574
609
  * @param {boolean=} options.weak true, if this is a weak dependency
610
+ * @param {RuntimeSpec=} options.runtime runtime for which this code will be generated
611
+ * @param {RuntimeSpec | boolean=} options.runtimeCondition only execute the statement in some runtimes
575
612
  * @param {Set<string>} options.runtimeRequirements if set, will be filled with runtime requirements
576
613
  * @returns {[string, string]} the import statement and the compat statement
577
614
  */
@@ -124,7 +124,7 @@ class WebpackOptionsApply extends OptionsApply {
124
124
  }
125
125
  case "module":
126
126
  throw new Error(
127
- "EcmaScript Module CHunk Format is not implemented yet"
127
+ "EcmaScript Module Chunk Format is not implemented yet"
128
128
  );
129
129
  default:
130
130
  throw new Error(
@@ -308,7 +308,9 @@ class WebpackOptionsApply extends OptionsApply {
308
308
  }
309
309
  if (options.optimization.sideEffects) {
310
310
  const SideEffectsFlagPlugin = require("./optimize/SideEffectsFlagPlugin");
311
- new SideEffectsFlagPlugin().apply(compiler);
311
+ new SideEffectsFlagPlugin(
312
+ options.optimization.sideEffects === true
313
+ ).apply(compiler);
312
314
  }
313
315
  if (options.optimization.providedExports) {
314
316
  const FlagDependencyExportsPlugin = require("./FlagDependencyExportsPlugin");