webpack 5.1.2 → 5.3.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 (42) hide show
  1. package/lib/ChunkGraph.js +19 -0
  2. package/lib/Compilation.js +37 -9
  3. package/lib/Compiler.js +26 -2
  4. package/lib/ConditionalInitFragment.js +109 -0
  5. package/lib/ContextModule.js +1 -1
  6. package/lib/DelegatedModule.js +1 -1
  7. package/lib/Dependency.js +1 -0
  8. package/lib/ExportsInfo.js +62 -16
  9. package/lib/ExternalModule.js +7 -6
  10. package/lib/FlagDependencyUsagePlugin.js +38 -42
  11. package/lib/Module.js +8 -0
  12. package/lib/NormalModule.js +26 -20
  13. package/lib/RawModule.js +1 -1
  14. package/lib/RuntimeGlobals.js +5 -0
  15. package/lib/RuntimeModule.js +4 -1
  16. package/lib/RuntimePlugin.js +8 -0
  17. package/lib/RuntimeTemplate.js +41 -0
  18. package/lib/SourceMapDevToolModuleOptionsPlugin.js +25 -0
  19. package/lib/SourceMapDevToolPlugin.js +6 -2
  20. package/lib/Template.js +1 -0
  21. package/lib/WebpackOptionsApply.js +3 -1
  22. package/lib/asset/AssetGenerator.js +10 -6
  23. package/lib/buildChunkGraph.js +111 -25
  24. package/lib/config/browserslistTargetHandler.js +4 -2
  25. package/lib/config/defaults.js +1 -1
  26. package/lib/container/ContainerEntryModule.js +4 -2
  27. package/lib/dependencies/HarmonyAcceptDependency.js +33 -5
  28. package/lib/dependencies/HarmonyImportDependency.js +70 -28
  29. package/lib/dependencies/HarmonyImportSpecifierDependency.js +2 -2
  30. package/lib/dependencies/PureExpressionDependency.js +30 -6
  31. package/lib/dependencies/WorkerPlugin.js +8 -3
  32. package/lib/javascript/JavascriptModulesPlugin.js +16 -10
  33. package/lib/optimize/ConcatenatedModule.js +87 -20
  34. package/lib/optimize/ModuleConcatenationPlugin.js +71 -6
  35. package/lib/optimize/SideEffectsFlagPlugin.js +112 -100
  36. package/lib/runtime/RuntimeIdRuntimeModule.js +29 -0
  37. package/lib/stats/DefaultStatsPrinterPlugin.js +17 -1
  38. package/lib/util/compileBooleanMatcher.js +13 -1
  39. package/lib/util/runtime.js +63 -1
  40. package/package.json +7 -7
  41. package/schemas/WebpackOptions.json +13 -2
  42. package/types.d.ts +63 -8
package/lib/Module.js CHANGED
@@ -139,6 +139,12 @@ class Module extends DependenciesBlock {
139
139
  this.resolveOptions = EMPTY_RESOLVE_OPTIONS;
140
140
  /** @type {object | undefined} */
141
141
  this.factoryMeta = undefined;
142
+ // TODO refactor this -> options object filled from Factory
143
+ // TODO webpack 6: use an enum
144
+ /** @type {boolean} */
145
+ this.useSourceMap = false;
146
+ /** @type {boolean} */
147
+ this.useSimpleSourceMap = false;
142
148
 
143
149
  // Info from Build
144
150
  /** @type {WebpackError[] | undefined} */
@@ -910,6 +916,7 @@ class Module extends DependenciesBlock {
910
916
  write(this.resolveOptions);
911
917
  write(this.factoryMeta);
912
918
  write(this.useSourceMap);
919
+ write(this.useSimpleSourceMap);
913
920
  write(
914
921
  this._warnings !== undefined && this._warnings.length === 0
915
922
  ? undefined
@@ -933,6 +940,7 @@ class Module extends DependenciesBlock {
933
940
  this.resolveOptions = read();
934
941
  this.factoryMeta = read();
935
942
  this.useSourceMap = read();
943
+ this.useSimpleSourceMap = read();
936
944
  this._warnings = read();
937
945
  this._errors = read();
938
946
  this.buildMeta = read();
@@ -249,9 +249,6 @@ class NormalModule extends Module {
249
249
  this._lastSuccessfulBuildMeta = {};
250
250
  this._forceBuild = true;
251
251
  this._isEvaluatingSideEffects = false;
252
-
253
- // TODO refactor this -> options object filled from Factory
254
- this.useSourceMap = false;
255
252
  }
256
253
 
257
254
  /**
@@ -327,22 +324,27 @@ class NormalModule extends Module {
327
324
  sourceMap,
328
325
  associatedObjectForCache
329
326
  ) {
330
- if (!sourceMap) {
331
- return new RawSource(content);
332
- }
327
+ if (sourceMap) {
328
+ if (
329
+ typeof sourceMap === "string" &&
330
+ (this.useSourceMap || this.useSimpleSourceMap)
331
+ ) {
332
+ return new OriginalSource(
333
+ content,
334
+ contextifySourceUrl(context, sourceMap, associatedObjectForCache)
335
+ );
336
+ }
333
337
 
334
- if (typeof sourceMap === "string") {
335
- return new OriginalSource(
336
- content,
337
- contextifySourceUrl(context, sourceMap, associatedObjectForCache)
338
- );
338
+ if (this.useSourceMap) {
339
+ return new SourceMapSource(
340
+ content,
341
+ name,
342
+ contextifySourceMap(context, sourceMap, associatedObjectForCache)
343
+ );
344
+ }
339
345
  }
340
346
 
341
- return new SourceMapSource(
342
- content,
343
- name,
344
- contextifySourceMap(context, sourceMap, associatedObjectForCache)
345
- );
347
+ return new RawSource(content);
346
348
  }
347
349
 
348
350
  /**
@@ -545,10 +547,14 @@ class NormalModule extends Module {
545
547
  );
546
548
  }
547
549
 
548
- return new OriginalSource(
549
- content,
550
- contextifySourceUrl(context, identifier, associatedObjectForCache)
551
- );
550
+ if (this.useSourceMap || this.useSimpleSourceMap) {
551
+ return new OriginalSource(
552
+ content,
553
+ contextifySourceUrl(context, identifier, associatedObjectForCache)
554
+ );
555
+ }
556
+
557
+ return new RawSource(content);
552
558
  }
553
559
 
554
560
  /**
package/lib/RawModule.js CHANGED
@@ -99,7 +99,7 @@ class RawModule extends Module {
99
99
  */
100
100
  codeGeneration(context) {
101
101
  const sources = new Map();
102
- if (this.useSourceMap) {
102
+ if (this.useSourceMap || this.useSimpleSourceMap) {
103
103
  sources.set(
104
104
  "javascript",
105
105
  new OriginalSource(this.sourceStr, this.identifier())
@@ -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
  */
@@ -5,6 +5,7 @@
5
5
 
6
6
  "use strict";
7
7
 
8
+ const { RawSource } = require("webpack-sources");
8
9
  const OriginalSource = require("webpack-sources").OriginalSource;
9
10
  const Module = require("./Module");
10
11
 
@@ -132,7 +133,9 @@ class RuntimeModule extends Module {
132
133
  if (generatedCode) {
133
134
  sources.set(
134
135
  "runtime",
135
- new OriginalSource(generatedCode, this.identifier())
136
+ this.useSourceMap || this.useSimpleSourceMap
137
+ ? new OriginalSource(generatedCode, this.identifier())
138
+ : new RawSource(generatedCode)
136
139
  );
137
140
  }
138
141
  return {
@@ -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 */
@@ -63,6 +65,10 @@ class RuntimeTemplate {
63
65
  return this.outputOptions.iife;
64
66
  }
65
67
 
68
+ isModule() {
69
+ return this.outputOptions.module;
70
+ }
71
+
66
72
  supportsConst() {
67
73
  return this.outputOptions.environment.const;
68
74
  }
@@ -558,6 +564,39 @@ class RuntimeTemplate {
558
564
  return `${promise || "Promise.resolve()"}${appending}`;
559
565
  }
560
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
+
561
600
  /**
562
601
  *
563
602
  * @param {Object} options options object
@@ -568,6 +607,8 @@ class RuntimeTemplate {
568
607
  * @param {string} options.importVar name of the import variable
569
608
  * @param {Module} options.originModule module in which the statement is emitted
570
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
571
612
  * @param {Set<string>} options.runtimeRequirements if set, will be filled with runtime requirements
572
613
  * @returns {[string, string]} the import statement and the compat statement
573
614
  */
@@ -5,6 +5,8 @@
5
5
 
6
6
  "use strict";
7
7
 
8
+ const JavascriptModulesPlugin = require("./javascript/JavascriptModulesPlugin");
9
+
8
10
  /** @typedef {import("./Compilation")} Compilation */
9
11
 
10
12
  class SourceMapDevToolModuleOptionsPlugin {
@@ -25,7 +27,30 @@ class SourceMapDevToolModuleOptionsPlugin {
25
27
  module.useSourceMap = true;
26
28
  }
27
29
  );
30
+ compilation.hooks.runtimeModule.tap(
31
+ "SourceMapDevToolModuleOptionsPlugin",
32
+ module => {
33
+ module.useSourceMap = true;
34
+ }
35
+ );
36
+ } else {
37
+ compilation.hooks.buildModule.tap(
38
+ "SourceMapDevToolModuleOptionsPlugin",
39
+ module => {
40
+ module.useSimpleSourceMap = true;
41
+ }
42
+ );
43
+ compilation.hooks.runtimeModule.tap(
44
+ "SourceMapDevToolModuleOptionsPlugin",
45
+ module => {
46
+ module.useSimpleSourceMap = true;
47
+ }
48
+ );
28
49
  }
50
+ JavascriptModulesPlugin.getCompilationHooks(compilation).useSourceMap.tap(
51
+ "SourceMapDevToolModuleOptionsPlugin",
52
+ () => true
53
+ );
29
54
  }
30
55
  }
31
56
 
@@ -19,6 +19,7 @@ const { absolutify } = require("./util/identifier");
19
19
  const schema = require("../schemas/plugins/SourceMapDevToolPlugin.json");
20
20
 
21
21
  /** @typedef {import("source-map").RawSourceMap} SourceMap */
22
+ /** @typedef {import("webpack-sources").MapOptions} MapOptions */
22
23
  /** @typedef {import("webpack-sources").Source} Source */
23
24
  /** @typedef {import("../declarations/plugins/SourceMapDevToolPlugin").SourceMapDevToolPluginOptions} SourceMapDevToolPluginOptions */
24
25
  /** @typedef {import("./Cache").Etag} Etag */
@@ -54,7 +55,7 @@ const quoteMeta = str => {
54
55
  * @param {string} file current compiled file
55
56
  * @param {Source} asset the asset
56
57
  * @param {AssetInfo} assetInfo the asset info
57
- * @param {SourceMapDevToolPluginOptions} options source map options
58
+ * @param {MapOptions} options source map options
58
59
  * @param {Compilation} compilation compilation instance
59
60
  * @param {ItemCacheFacade} cacheItem cache item
60
61
  * @returns {SourceMapTask | undefined} created task instance or `undefined`
@@ -265,7 +266,10 @@ class SourceMapDevToolPlugin {
265
266
  file,
266
267
  asset.source,
267
268
  asset.info,
268
- options,
269
+ {
270
+ module: options.module,
271
+ columns: options.columns
272
+ },
269
273
  compilation,
270
274
  cacheItem
271
275
  );
package/lib/Template.js CHANGED
@@ -59,6 +59,7 @@ const MATCH_PADDED_HYPHENS_REPLACE_REGEX = /^-|-$/g;
59
59
  * @property {function(): Source} render
60
60
  * @property {string | function(PathData, AssetInfo=): string} filenameTemplate
61
61
  * @property {PathData=} pathOptions
62
+ * @property {AssetInfo=} info
62
63
  * @property {string} identifier
63
64
  * @property {string=} hash
64
65
  * @property {boolean=} auxiliary
@@ -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");
@@ -126,22 +126,26 @@ class AssetGenerator extends Generator {
126
126
  runtimeTemplate.outputOptions.hashDigestLength
127
127
  );
128
128
  module.buildInfo.fullContentHash = fullHash;
129
+ const sourceFilename = makePathsRelative(
130
+ this.compilation.compiler.context,
131
+ module.matchResource || module.resource,
132
+ this.compilation.compiler.root
133
+ ).replace(/^\.\//, "");
129
134
  const {
130
135
  path: filename,
131
136
  info
132
137
  } = this.compilation.getAssetPathWithInfo(assetModuleFilename, {
133
138
  module,
134
139
  runtime,
135
- filename: makePathsRelative(
136
- this.compilation.compiler.context,
137
- module.matchResource || module.resource,
138
- this.compilation.compiler.root
139
- ).replace(/^\.\//, ""),
140
+ filename: sourceFilename,
140
141
  chunkGraph,
141
142
  contentHash
142
143
  });
143
144
  module.buildInfo.filename = filename;
144
- module.buildInfo.assetInfo = info;
145
+ module.buildInfo.assetInfo = {
146
+ sourceFilename,
147
+ ...info
148
+ };
145
149
 
146
150
  runtimeRequirements.add(RuntimeGlobals.publicPath); // add __webpack_require__.p
147
151
 
@@ -8,6 +8,7 @@
8
8
  const AsyncDependencyToInitialChunkError = require("./AsyncDependencyToInitialChunkError");
9
9
  const { connectChunkGroupParentAndChild } = require("./GraphHelpers");
10
10
  const ModuleGraphConnection = require("./ModuleGraphConnection");
11
+ const { getEntryRuntime, mergeRuntime } = require("./util/runtime");
11
12
 
12
13
  /** @typedef {import("./AsyncDependenciesBlock")} AsyncDependenciesBlock */
13
14
  /** @typedef {import("./Chunk")} Chunk */
@@ -20,6 +21,7 @@ const ModuleGraphConnection = require("./ModuleGraphConnection");
20
21
  /** @typedef {import("./ModuleGraph")} ModuleGraph */
21
22
  /** @typedef {import("./ModuleGraphConnection").ConnectionState} ConnectionState */
22
23
  /** @typedef {import("./logging/Logger").Logger} Logger */
24
+ /** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */
23
25
 
24
26
  /**
25
27
  * @typedef {Object} QueueItem
@@ -36,10 +38,12 @@ const ModuleGraphConnection = require("./ModuleGraphConnection");
36
38
  /**
37
39
  * @typedef {Object} ChunkGroupInfo
38
40
  * @property {ChunkGroup} chunkGroup the chunk group
41
+ * @property {RuntimeSpec} runtime the runtimes
39
42
  * @property {ModuleSetPlus} minAvailableModules current minimal set of modules available at this point
40
43
  * @property {boolean} minAvailableModulesOwned true, if minAvailableModules is owned and can be modified
41
44
  * @property {ModuleSetPlus[]} availableModulesToBeMerged enqueued updates to the minimal set of available modules
42
45
  * @property {Set<Module>=} skippedItems modules that were skipped because module is already available in parent chunks (need to reconsider when minAvailableModules is shrinking)
46
+ * @property {Set<[Module, ModuleGraphConnection[]]>=} skippedModuleConnections referenced modules that where skipped because they were not active in this runtime
43
47
  * @property {ModuleSetPlus} resultingAvailableModules set of modules available including modules from this chunk group
44
48
  * @property {Set<ChunkGroupInfo>} children set of children chunk groups, that will be revisited when availableModules shrink
45
49
  * @property {Set<ChunkGroupInfo>} availableSources set of chunk groups that are the source for minAvailableModules
@@ -66,21 +70,41 @@ const bySetSize = (a, b) => {
66
70
  return b.size + b.plus.size - a.size - a.plus.size;
67
71
  };
68
72
 
73
+ /**
74
+ *
75
+ * @param {ModuleGraphConnection[]} connections list of connections
76
+ * @param {RuntimeSpec} runtime for which runtime
77
+ * @returns {ConnectionState} connection state
78
+ */
79
+ const getActiveStateOfConnections = (connections, runtime) => {
80
+ let merged = connections[0].getActiveState(runtime);
81
+ if (merged === true) return true;
82
+ for (let i = 1; i < connections.length; i++) {
83
+ const c = connections[i];
84
+ merged = ModuleGraphConnection.addConnectionStates(
85
+ merged,
86
+ c.getActiveState(runtime)
87
+ );
88
+ if (merged === true) return true;
89
+ }
90
+ return merged;
91
+ };
92
+
69
93
  /**
70
94
  * Extracts block to modules mapping from all modules
71
95
  * @param {Compilation} compilation the compilation
72
- * @returns {Map<DependenciesBlock, Map<Module, Exclude<ConnectionState, false>>>} the mapping block to modules
96
+ * @returns {Map<DependenciesBlock, Map<Module, ModuleGraphConnection[]>>} the mapping block to modules
73
97
  */
74
98
  const extractBlockModulesMap = compilation => {
75
99
  const { moduleGraph } = compilation;
76
100
 
77
- /** @type {Map<DependenciesBlock, Map<Module, Exclude<ConnectionState, false>>>} */
101
+ /** @type {Map<DependenciesBlock, Map<Module, ModuleGraphConnection[]>>} */
78
102
  const blockModulesMap = new Map();
79
103
 
80
104
  const blockQueue = new Set();
81
105
 
82
106
  for (const module of compilation.modules) {
83
- /** @type {WeakMap<Dependency, [Module, Exclude<ConnectionState, false>]>} */
107
+ /** @type {WeakMap<Dependency, ModuleGraphConnection>} */
84
108
  let moduleMap;
85
109
 
86
110
  for (const connection of moduleGraph.getOutgoingConnections(module)) {
@@ -101,7 +125,7 @@ const extractBlockModulesMap = compilation => {
101
125
  if (moduleMap === undefined) {
102
126
  moduleMap = new WeakMap();
103
127
  }
104
- moduleMap.set(connection.dependency, [m, state]);
128
+ moduleMap.set(connection.dependency, connection);
105
129
  }
106
130
 
107
131
  blockQueue.clear();
@@ -111,27 +135,19 @@ const extractBlockModulesMap = compilation => {
111
135
 
112
136
  if (moduleMap !== undefined && block.dependencies) {
113
137
  for (const dep of block.dependencies) {
114
- const map = moduleMap.get(dep);
115
- if (map !== undefined) {
116
- const [module, state] = map;
138
+ const connection = moduleMap.get(dep);
139
+ if (connection !== undefined) {
140
+ const { module } = connection;
117
141
  if (modules === undefined) {
118
142
  modules = new Map();
119
143
  blockModulesMap.set(block, modules);
120
144
  }
121
- let merged = state;
122
- if (merged !== true) {
123
- const old = modules.get(module);
124
- if (old !== undefined) {
125
- merged = /** @type {Exclude<ConnectionState, false>} */ (ModuleGraphConnection.addConnectionStates(
126
- old,
127
- merged
128
- ));
129
- if (merged === old) {
130
- continue;
131
- }
132
- }
145
+ const old = modules.get(module);
146
+ if (old !== undefined) {
147
+ old.push(connection);
148
+ } else {
149
+ modules.set(module, [connection]);
133
150
  }
134
- modules.set(module, merged);
135
151
  }
136
152
  }
137
153
  }
@@ -216,9 +232,15 @@ const visitModules = (
216
232
  // Fill queue with entrypoint modules
217
233
  // Create ChunkGroupInfo for entrypoints
218
234
  for (const [chunkGroup, modules] of inputEntrypointsAndModules) {
235
+ const runtime = getEntryRuntime(
236
+ compilation,
237
+ chunkGroup.name,
238
+ chunkGroup.options
239
+ );
219
240
  /** @type {ChunkGroupInfo} */
220
241
  const chunkGroupInfo = {
221
242
  chunkGroup,
243
+ runtime,
222
244
  minAvailableModules: undefined,
223
245
  minAvailableModulesOwned: false,
224
246
  availableModulesToBeMerged: [],
@@ -288,6 +310,8 @@ const visitModules = (
288
310
 
289
311
  logger.timeEnd("visitModules: prepare");
290
312
 
313
+ /** @type {[Module, ModuleGraphConnection[]][]} */
314
+ const skipConnectionBuffer = [];
291
315
  /** @type {Module[]} */
292
316
  const skipBuffer = [];
293
317
  /** @type {QueueItem[]} */
@@ -332,6 +356,7 @@ const visitModules = (
332
356
  entrypoint.index = nextChunkGroupIndex++;
333
357
  cgi = {
334
358
  chunkGroup: entrypoint,
359
+ runtime: entrypoint.options.runtime || entrypoint.name,
335
360
  minAvailableModules: EMPTY_SET,
336
361
  minAvailableModulesOwned: false,
337
362
  availableModulesToBeMerged: [],
@@ -377,6 +402,7 @@ const visitModules = (
377
402
  c.index = nextChunkGroupIndex++;
378
403
  cgi = {
379
404
  chunkGroup: c,
405
+ runtime: chunkGroupInfo.runtime,
380
406
  minAvailableModules: undefined,
381
407
  minAvailableModulesOwned: undefined,
382
408
  availableModulesToBeMerged: [],
@@ -455,17 +481,24 @@ const visitModules = (
455
481
  const blockModules = blockModulesMap.get(block);
456
482
 
457
483
  if (blockModules !== undefined) {
458
- const { minAvailableModules } = chunkGroupInfo;
484
+ const { minAvailableModules, runtime } = chunkGroupInfo;
459
485
  // Buffer items because order need to be reversed to get indices correct
460
486
  // Traverse all referenced modules
461
- for (const [refModule, activeState] of blockModules) {
487
+ for (const entry of blockModules) {
488
+ const [refModule, connections] = entry;
462
489
  if (chunkGraph.isModuleInChunk(refModule, chunk)) {
463
490
  // skip early if already connected
464
491
  continue;
465
492
  }
493
+ const activeState = getActiveStateOfConnections(connections, runtime);
494
+ if (activeState !== true) {
495
+ skipConnectionBuffer.push(entry);
496
+ if (activeState === false) continue;
497
+ }
466
498
  if (
467
- minAvailableModules.has(refModule) ||
468
- minAvailableModules.plus.has(refModule)
499
+ activeState === true &&
500
+ (minAvailableModules.has(refModule) ||
501
+ minAvailableModules.plus.has(refModule))
469
502
  ) {
470
503
  // already in parent chunks, skip it for now
471
504
  skipBuffer.push(refModule);
@@ -483,6 +516,16 @@ const visitModules = (
483
516
  });
484
517
  }
485
518
  // Add buffered items in reverse order
519
+ if (skipConnectionBuffer.length > 0) {
520
+ let { skippedModuleConnections } = chunkGroupInfo;
521
+ if (skippedModuleConnections === undefined) {
522
+ chunkGroupInfo.skippedModuleConnections = skippedModuleConnections = new Set();
523
+ }
524
+ for (let i = skipConnectionBuffer.length - 1; i >= 0; i--) {
525
+ skippedModuleConnections.add(skipConnectionBuffer[i]);
526
+ }
527
+ skipConnectionBuffer.length = 0;
528
+ }
486
529
  if (skipBuffer.length > 0) {
487
530
  let { skippedItems } = chunkGroupInfo;
488
531
  if (skippedItems === undefined) {
@@ -522,7 +565,8 @@ const visitModules = (
522
565
 
523
566
  if (blockModules !== undefined) {
524
567
  // Traverse all referenced modules
525
- for (const [refModule, activeState] of blockModules) {
568
+ for (const [refModule, connections] of blockModules) {
569
+ const activeState = getActiveStateOfConnections(connections, undefined);
526
570
  // enqueue, then add and enter to be in the correct order
527
571
  // this is relevant with circular dependencies
528
572
  queueBuffer.push({
@@ -692,10 +736,18 @@ const visitModules = (
692
736
  chunkGroupInfo
693
737
  );
694
738
 
739
+ const runtime = chunkGroupInfo.runtime;
740
+
695
741
  // 3. Update chunk group info
696
742
  for (const target of targets) {
697
743
  target.availableModulesToBeMerged.push(resultingAvailableModules);
698
744
  chunkGroupsForMerging.add(target);
745
+ const oldRuntime = target.runtime;
746
+ const newRuntime = mergeRuntime(oldRuntime, runtime);
747
+ if (oldRuntime !== newRuntime) {
748
+ target.runtime = newRuntime;
749
+ outdatedChunkGroupInfo.add(target);
750
+ }
699
751
  }
700
752
 
701
753
  statConnectedChunkGroups += targets.size;
@@ -1000,6 +1052,35 @@ const visitModules = (
1000
1052
  }
1001
1053
  }
1002
1054
 
1055
+ // 2. Reconsider skipped connections
1056
+ if (info.skippedModuleConnections !== undefined) {
1057
+ const { minAvailableModules, runtime } = info;
1058
+ for (const entry of info.skippedModuleConnections) {
1059
+ const [module, connections] = entry;
1060
+ const activeState = getActiveStateOfConnections(connections, runtime);
1061
+ if (activeState === false) continue;
1062
+ if (activeState === true) {
1063
+ info.skippedModuleConnections.delete(entry);
1064
+ }
1065
+ if (
1066
+ activeState === true &&
1067
+ (minAvailableModules.has(module) ||
1068
+ minAvailableModules.plus.has(module))
1069
+ ) {
1070
+ info.skippedItems.add(module);
1071
+ continue;
1072
+ }
1073
+ queue.push({
1074
+ action: activeState === true ? ADD_AND_ENTER_MODULE : PROCESS_BLOCK,
1075
+ block: module,
1076
+ module,
1077
+ chunk: info.chunkGroup.chunks[0],
1078
+ chunkGroup: info.chunkGroup,
1079
+ chunkGroupInfo: info
1080
+ });
1081
+ }
1082
+ }
1083
+
1003
1084
  // 2. Reconsider children chunk groups
1004
1085
  if (info.children !== undefined) {
1005
1086
  statChildChunkGroupsReconnected += info.children.size;
@@ -1213,6 +1294,11 @@ const buildChunkGraph = (compilation, inputEntrypointsAndModules) => {
1213
1294
  );
1214
1295
  logger.timeEnd("connectChunkGroups");
1215
1296
 
1297
+ for (const [chunkGroup, chunkGroupInfo] of chunkGroupInfoMap) {
1298
+ for (const chunk of chunkGroup.chunks)
1299
+ chunk.runtime = mergeRuntime(chunk.runtime, chunkGroupInfo.runtime);
1300
+ }
1301
+
1216
1302
  // Cleanup work
1217
1303
 
1218
1304
  logger.time("cleanup");
@@ -119,11 +119,13 @@ const resolve = browsers => {
119
119
  const browserProperty = !anyBrowser ? false : anyNode ? null : true;
120
120
  const nodeProperty = !anyNode ? false : anyBrowser ? null : true;
121
121
  const es6 = browserslistChecker("es6");
122
+ const letConst = browserslistChecker("let");
123
+ const arrowFunctions = browserslistChecker("arrow-functions");
122
124
  const es6DynamicImport = browserslistChecker("es6-module-dynamic-import");
123
125
  const node6 = nodeChecker(6);
124
126
  return {
125
- const: es6 && node6,
126
- arrowFunction: es6 && node6,
127
+ const: letConst && node6,
128
+ arrowFunction: arrowFunctions && node6,
127
129
  forOf: es6 && nodeChecker(5),
128
130
  destructuring: es6 && node6,
129
131
  bigIntLiteral: browserslistChecker("bigint") && nodeChecker(10, 4),
@@ -848,7 +848,7 @@ const applyOptimizationDefaults = (
848
848
  if (development) return "named";
849
849
  return "natural";
850
850
  });
851
- D(optimization, "sideEffects", true);
851
+ F(optimization, "sideEffects", () => (production ? true : "flag"));
852
852
  D(optimization, "providedExports", true);
853
853
  D(optimization, "usedExports", production);
854
854
  D(optimization, "innerGraph", production);