webpack 5.14.0 → 5.18.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 (71) hide show
  1. package/bin/webpack.js +0 -0
  2. package/hot/lazy-compilation-node.js +38 -0
  3. package/hot/lazy-compilation-web.js +74 -0
  4. package/lib/AutomaticPrefetchPlugin.js +14 -7
  5. package/lib/CacheFacade.js +1 -0
  6. package/lib/ChunkGraph.js +132 -19
  7. package/lib/CodeGenerationResults.js +43 -8
  8. package/lib/Compilation.js +253 -149
  9. package/lib/Compiler.js +7 -2
  10. package/lib/ContextModule.js +2 -2
  11. package/lib/Dependency.js +1 -7
  12. package/lib/ExportsInfo.js +23 -5
  13. package/lib/ExternalModuleFactoryPlugin.js +46 -3
  14. package/lib/FileSystemInfo.js +192 -137
  15. package/lib/HotModuleReplacementPlugin.js +76 -29
  16. package/lib/IgnoreErrorModuleFactory.js +39 -0
  17. package/lib/Module.js +2 -3
  18. package/lib/NormalModuleFactory.js +27 -8
  19. package/lib/Template.js +32 -23
  20. package/lib/WebpackIsIncludedPlugin.js +85 -0
  21. package/lib/WebpackOptionsApply.js +27 -5
  22. package/lib/cache/PackFileCacheStrategy.js +5 -1
  23. package/lib/config/defaults.js +18 -18
  24. package/lib/config/normalization.js +44 -9
  25. package/lib/debug/ProfilingPlugin.js +20 -1
  26. package/lib/dependencies/AMDDefineDependency.js +1 -1
  27. package/lib/dependencies/AMDPlugin.js +6 -7
  28. package/lib/dependencies/CommonJsImportsParserPlugin.js +43 -1
  29. package/lib/dependencies/CommonJsPlugin.js +1 -6
  30. package/lib/dependencies/ContextDependencyHelpers.js +3 -2
  31. package/lib/dependencies/ExportsInfoDependency.js +0 -20
  32. package/lib/dependencies/HarmonyExportDependencyParserPlugin.js +1 -2
  33. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +0 -29
  34. package/lib/dependencies/HarmonyImportDependency.js +0 -41
  35. package/lib/dependencies/HarmonyImportDependencyParserPlugin.js +2 -3
  36. package/lib/dependencies/HarmonyImportSpecifierDependency.js +2 -36
  37. package/lib/dependencies/HarmonyModulesPlugin.js +2 -2
  38. package/lib/dependencies/ImportPlugin.js +1 -6
  39. package/lib/dependencies/JsonExportsDependency.js +0 -1
  40. package/lib/dependencies/ModuleDecoratorDependency.js +0 -1
  41. package/lib/dependencies/NullDependency.js +0 -8
  42. package/lib/dependencies/ProvidedDependency.js +0 -1
  43. package/lib/dependencies/StaticExportsDependency.js +0 -12
  44. package/lib/dependencies/SystemPlugin.js +0 -4
  45. package/lib/dependencies/URLDependency.js +45 -3
  46. package/lib/dependencies/URLPlugin.js +33 -7
  47. package/lib/dependencies/WebpackIsIncludedDependency.js +80 -0
  48. package/lib/hmr/LazyCompilationPlugin.js +348 -0
  49. package/lib/hmr/lazyCompilationBackend.js +86 -0
  50. package/lib/javascript/JavascriptModulesPlugin.js +4 -3
  51. package/lib/javascript/JavascriptParser.js +20 -5
  52. package/lib/library/AssignLibraryPlugin.js +13 -4
  53. package/lib/library/EnableLibraryPlugin.js +12 -0
  54. package/lib/optimize/ConcatenatedModule.js +0 -12
  55. package/lib/optimize/InnerGraph.js +32 -0
  56. package/lib/optimize/SplitChunksPlugin.js +4 -1
  57. package/lib/serialization/ObjectMiddleware.js +7 -5
  58. package/lib/sharing/ProvideSharedModule.js +1 -1
  59. package/lib/sharing/ShareRuntimeModule.js +2 -2
  60. package/lib/stats/DefaultStatsPresetPlugin.js +1 -0
  61. package/lib/util/MapHelpers.js +22 -0
  62. package/lib/util/binarySearchBounds.js +86 -0
  63. package/lib/util/createHash.js +13 -7
  64. package/lib/util/internalSerializables.js +2 -0
  65. package/lib/util/processAsyncTree.js +61 -0
  66. package/lib/util/runtime.js +12 -1
  67. package/package.json +3 -3
  68. package/schemas/WebpackOptions.json +330 -140
  69. package/schemas/plugins/container/ContainerPlugin.json +2 -1
  70. package/schemas/plugins/container/ModuleFederationPlugin.json +2 -1
  71. package/types.d.ts +320 -121
@@ -25,6 +25,7 @@ class Profiler {
25
25
  constructor(inspector) {
26
26
  this.session = undefined;
27
27
  this.inspector = inspector;
28
+ this._startTime = 0;
28
29
  }
29
30
 
30
31
  hasSession() {
@@ -44,6 +45,9 @@ class Profiler {
44
45
  return Promise.resolve();
45
46
  }
46
47
 
48
+ const hrtime = process.hrtime();
49
+ this._startTime = hrtime[0] * 1000000 + Math.round(hrtime[1] / 1000);
50
+
47
51
  return Promise.all([
48
52
  this.sendCommand("Profiler.setSamplingInterval", {
49
53
  interval: 100
@@ -78,7 +82,22 @@ class Profiler {
78
82
  }
79
83
 
80
84
  stopProfiling() {
81
- return this.sendCommand("Profiler.stop");
85
+ return this.sendCommand("Profiler.stop").then(({ profile }) => {
86
+ const hrtime = process.hrtime();
87
+ const endTime = hrtime[0] * 1000000 + Math.round(hrtime[1] / 1000);
88
+ if (profile.startTime < this._startTime || profile.endTime > endTime) {
89
+ // In some cases timestamps mismatch and we need to adjust them
90
+ // Both process.hrtime and the inspector timestamps claim to be relative
91
+ // to a unknown point in time. But they do not guarantee that this is the
92
+ // same point in time.
93
+ const duration = profile.endTime - profile.startTime;
94
+ const ownDuration = endTime - this._startTime;
95
+ const untracked = Math.max(0, ownDuration - duration);
96
+ profile.startTime = this._startTime + untracked / 2;
97
+ profile.endTime = endTime - untracked / 2;
98
+ }
99
+ return { profile };
100
+ });
82
101
  }
83
102
  }
84
103
 
@@ -79,7 +79,7 @@ const DEFINITIONS = {
79
79
  lof: {
80
80
  definition: "var XXX, XXXfactory, XXXmodule;",
81
81
  content:
82
- "!(XXXfactory = (#), (typeof XXXfactory === 'function' ? (XXXmodule = { id: YYY, exports: {}, loaded: false }), (XXX = XXXfactory.call(XXXmodule.exports, __webpack_require__, XXXmodule.exports, XXXmodule)), (XXXmodule.loaded = true), XXX === undefined && (XXX = XXXmodule.exports) : XXX = XXXfactory))",
82
+ "!(XXXfactory = (#), (typeof XXXfactory === 'function' ? ((XXXmodule = { id: YYY, exports: {}, loaded: false }), (XXX = XXXfactory.call(XXXmodule.exports, __webpack_require__, XXXmodule.exports, XXXmodule)), (XXXmodule.loaded = true), XXX === undefined && (XXX = XXXmodule.exports)) : XXX = XXXfactory))",
83
83
  requests: [RuntimeGlobals.require, RuntimeGlobals.module]
84
84
  },
85
85
  laf: {
@@ -28,16 +28,14 @@ const ConstDependency = require("./ConstDependency");
28
28
  const LocalModuleDependency = require("./LocalModuleDependency");
29
29
  const UnsupportedDependency = require("./UnsupportedDependency");
30
30
 
31
- /** @typedef {import("../../declarations/WebpackOptions").ModuleOptions} ModuleOptions */
31
+ /** @typedef {import("../../declarations/WebpackOptions").ModuleOptionsNormalized} ModuleOptions */
32
32
  /** @typedef {import("../Compiler")} Compiler */
33
33
 
34
34
  class AMDPlugin {
35
35
  /**
36
- * @param {ModuleOptions} options the plugin options
37
36
  * @param {Record<string, any>} amdOptions the AMD options
38
37
  */
39
- constructor(options, amdOptions) {
40
- this.options = options;
38
+ constructor(amdOptions) {
41
39
  this.amdOptions = amdOptions;
42
40
  }
43
41
 
@@ -47,7 +45,6 @@ class AMDPlugin {
47
45
  * @returns {void}
48
46
  */
49
47
  apply(compiler) {
50
- const options = this.options;
51
48
  const amdOptions = this.amdOptions;
52
49
  compiler.hooks.compilation.tap(
53
50
  "AMDPlugin",
@@ -151,8 +148,10 @@ class AMDPlugin {
151
148
  );
152
149
  };
153
150
 
154
- new AMDRequireDependenciesBlockParserPlugin(options).apply(parser);
155
- new AMDDefineDependencyParserPlugin(options).apply(parser);
151
+ new AMDRequireDependenciesBlockParserPlugin(parserOptions).apply(
152
+ parser
153
+ );
154
+ new AMDDefineDependencyParserPlugin(parserOptions).apply(parser);
156
155
 
157
156
  tapOptionsHooks("define.amd", "define", () => "amd");
158
157
  tapOptionsHooks("require.amd", "require", () => ["amd"]);
@@ -5,7 +5,9 @@
5
5
 
6
6
  "use strict";
7
7
 
8
+ const CommentCompilationWarning = require("../CommentCompilationWarning");
8
9
  const RuntimeGlobals = require("../RuntimeGlobals");
10
+ const UnsupportedFeatureWarning = require("../UnsupportedFeatureWarning");
9
11
  const {
10
12
  evaluateToIdentifier,
11
13
  evaluateToString,
@@ -24,7 +26,12 @@ const RequireResolveContextDependency = require("./RequireResolveContextDependen
24
26
  const RequireResolveDependency = require("./RequireResolveDependency");
25
27
  const RequireResolveHeaderDependency = require("./RequireResolveHeaderDependency");
26
28
 
29
+ /** @typedef {import("../../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */
30
+
27
31
  class CommonJsImportsParserPlugin {
32
+ /**
33
+ * @param {JavascriptParserOptions} options parser options
34
+ */
28
35
  constructor(options) {
29
36
  this.options = options;
30
37
  }
@@ -173,8 +180,43 @@ class CommonJsImportsParserPlugin {
173
180
  parser.state.current.addDependency(dep);
174
181
  return true;
175
182
  };
176
-
177
183
  const createRequireHandler = callNew => expr => {
184
+ if (options.commonjsMagicComments) {
185
+ const {
186
+ options: requireOptions,
187
+ errors: commentErrors
188
+ } = parser.parseCommentOptions(expr.range);
189
+
190
+ if (commentErrors) {
191
+ for (const e of commentErrors) {
192
+ const { comment } = e;
193
+ parser.state.module.addWarning(
194
+ new CommentCompilationWarning(
195
+ `Compilation error while processing magic comment(-s): /*${comment.value}*/: ${e.message}`,
196
+ comment.loc
197
+ )
198
+ );
199
+ }
200
+ }
201
+ if (requireOptions) {
202
+ if (requireOptions.webpackIgnore !== undefined) {
203
+ if (typeof requireOptions.webpackIgnore !== "boolean") {
204
+ parser.state.module.addWarning(
205
+ new UnsupportedFeatureWarning(
206
+ `\`webpackIgnore\` expected a boolean, but received: ${requireOptions.webpackIgnore}.`,
207
+ expr.loc
208
+ )
209
+ );
210
+ } else {
211
+ // Do not instrument `require()` if `webpackIgnore` is `true`
212
+ if (requireOptions.webpackIgnore) {
213
+ return true;
214
+ }
215
+ }
216
+ }
217
+ }
218
+ }
219
+
178
220
  if (expr.arguments.length !== 1) return;
179
221
  let localModule;
180
222
  const param = parser.evaluateExpression(expr.arguments[0]);
@@ -31,12 +31,7 @@ const {
31
31
  const CommonJsExportRequireDependency = require("./CommonJsExportRequireDependency");
32
32
 
33
33
  class CommonJsPlugin {
34
- constructor(options) {
35
- this.options = options;
36
- }
37
-
38
34
  apply(compiler) {
39
- const options = this.options;
40
35
  compiler.hooks.compilation.tap(
41
36
  "CommonJsPlugin",
42
37
  (compilation, { contextModuleFactory, normalModuleFactory }) => {
@@ -212,7 +207,7 @@ class CommonJsPlugin {
212
207
  evaluateToIdentifier("module.hot", "module", () => ["hot"], null)
213
208
  );
214
209
 
215
- new CommonJsImportsParserPlugin(options).apply(parser);
210
+ new CommonJsImportsParserPlugin(parserOptions).apply(parser);
216
211
  new CommonJsExportsParserPlugin(compilation.moduleGraph).apply(
217
212
  parser
218
213
  );
@@ -8,7 +8,8 @@
8
8
  const { parseResource } = require("../util/identifier");
9
9
 
10
10
  /** @typedef {import("estree").Node} EsTreeNode */
11
- /** @typedef {import("../../declarations/WebpackOptions").ModuleOptions} ModuleOptions */
11
+ /** @typedef {import("../../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */
12
+ /** @typedef {import("../../declarations/WebpackOptions").ModuleOptionsNormalized} ModuleOptions */
12
13
  /** @typedef {import("../javascript/BasicEvaluatedExpression")} BasicEvaluatedExpression */
13
14
  /** @typedef {import("../javascript/JavascriptParser")} JavascriptParser */
14
15
  /** @typedef {import("./ContextDependency")} ContextDependency */
@@ -45,7 +46,7 @@ const splitContextFromPrefix = prefix => {
45
46
  * @param {[number, number]} range source range
46
47
  * @param {BasicEvaluatedExpression} param context param
47
48
  * @param {EsTreeNode} expr expr
48
- * @param {ModuleOptions} options options for context creation
49
+ * @param {Pick<JavascriptParserOptions, `${"expr"|"wrapped"}Context${"Critical"|"Recursive"|"RegExp"}` | "exprContextRequest">} options options for context creation
49
50
  * @param {PartialContextDependencyOptions} contextOptions options for the ContextModule
50
51
  * @param {JavascriptParser} parser the parser
51
52
  * @returns {ContextDependency} the created Dependency
@@ -83,26 +83,6 @@ class ExportsInfoDependency extends NullDependency {
83
83
  this.property = property;
84
84
  }
85
85
 
86
- /**
87
- * Update the hash
88
- * @param {Hash} hash hash to be updated
89
- * @param {UpdateHashContext} context context
90
- * @returns {void}
91
- */
92
- updateHash(hash, context) {
93
- const { chunkGraph, runtime } = context;
94
- const { moduleGraph } = chunkGraph;
95
- const module = moduleGraph.getParentModule(this);
96
- const value = getProperty(
97
- moduleGraph,
98
- module,
99
- this.exportName,
100
- this.property,
101
- runtime
102
- );
103
- hash.update(value === undefined ? "undefined" : JSON.stringify(value));
104
- }
105
-
106
86
  serialize(context) {
107
87
  const { write } = context;
108
88
  write(this.range);
@@ -18,8 +18,7 @@ const HarmonyImportSideEffectDependency = require("./HarmonyImportSideEffectDepe
18
18
 
19
19
  module.exports = class HarmonyExportDependencyParserPlugin {
20
20
  constructor(options) {
21
- const { module: moduleOptions } = options;
22
- this.strictExportPresence = moduleOptions.strictExportPresence;
21
+ this.strictExportPresence = options.strictExportPresence;
23
22
  }
24
23
 
25
24
  apply(parser) {
@@ -680,35 +680,6 @@ class HarmonyExportImportedSpecifierDependency extends HarmonyImportDependency {
680
680
  return errors;
681
681
  }
682
682
 
683
- /**
684
- * Update the hash
685
- * @param {Hash} hash hash to be updated
686
- * @param {UpdateHashContext} context context
687
- * @returns {void}
688
- */
689
- updateHash(hash, context) {
690
- const { chunkGraph, runtime } = context;
691
- super.updateHash(hash, context);
692
-
693
- const mode = this.getMode(chunkGraph.moduleGraph, runtime);
694
-
695
- hash.update(mode.type);
696
- if (mode.items) {
697
- for (const item of mode.items) {
698
- hash.update(item.name);
699
- hash.update(item.ids.join());
700
- if (item.checked) hash.update("checked");
701
- }
702
- }
703
- if (mode.ignored) {
704
- hash.update("ignored");
705
- for (const k of mode.ignored) {
706
- hash.update(k);
707
- }
708
- }
709
- hash.update(mode.name || "");
710
- }
711
-
712
683
  serialize(context) {
713
684
  const { write } = context;
714
685
 
@@ -196,47 +196,6 @@ class HarmonyImportDependency extends ModuleDependency {
196
196
  }
197
197
  }
198
198
 
199
- /**
200
- * Update the hash
201
- * @param {Hash} hash hash to be updated
202
- * @param {UpdateHashContext} context context
203
- * @returns {void}
204
- */
205
- updateHash(hash, context) {
206
- const { chunkGraph, runtime, runtimeTemplate } = context;
207
- const { moduleGraph } = chunkGraph;
208
- super.updateHash(hash, context);
209
- hash.update(`${this.sourceOrder}`);
210
- const connection = moduleGraph.getConnection(this);
211
- if (connection) {
212
- const importedModule = connection.module;
213
- if (importedModule) {
214
- const parentModule = moduleGraph.getParentModule(this);
215
- hash.update(
216
- importedModule.getExportsType(
217
- moduleGraph,
218
- parentModule.buildMeta && parentModule.buildMeta.strictHarmonyModule
219
- )
220
- );
221
- if (moduleGraph.isAsync(importedModule)) hash.update("async");
222
- }
223
- if (runtimeTemplate) {
224
- const runtimeRequirements = new Set();
225
- hash.update(
226
- runtimeTemplate.runtimeConditionExpression({
227
- chunkGraph,
228
- runtimeCondition: filterRuntime(runtime, runtime => {
229
- return connection.isTargetActive(runtime);
230
- }),
231
- runtime,
232
- runtimeRequirements
233
- })
234
- );
235
- for (const rr of runtimeRequirements) hash.update(rr);
236
- }
237
- }
238
- }
239
-
240
199
  serialize(context) {
241
200
  const { write } = context;
242
201
  write(this.sourceOrder);
@@ -33,9 +33,8 @@ const harmonySpecifierTag = Symbol("harmony import");
33
33
 
34
34
  module.exports = class HarmonyImportDependencyParserPlugin {
35
35
  constructor(options) {
36
- const { module: moduleOptions } = options;
37
- this.strictExportPresence = moduleOptions.strictExportPresence;
38
- this.strictThisContextOnImports = moduleOptions.strictThisContextOnImports;
36
+ this.strictExportPresence = options.strictExportPresence;
37
+ this.strictThisContextOnImports = options.strictThisContextOnImports;
39
38
  }
40
39
 
41
40
  /**
@@ -6,7 +6,7 @@
6
6
  "use strict";
7
7
 
8
8
  const Dependency = require("../Dependency");
9
- const { UsageState } = require("../ExportsInfo");
9
+ const { isDependencyUsedByExports } = require("../optimize/InnerGraph");
10
10
  const makeSerializable = require("../util/makeSerializable");
11
11
  const propertyAccess = require("../util/propertyAccess");
12
12
  const HarmonyImportDependency = require("./HarmonyImportDependency");
@@ -84,7 +84,7 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency {
84
84
  */
85
85
  getCondition(moduleGraph) {
86
86
  return (connection, runtime) =>
87
- this.checkUsedByExports(moduleGraph, runtime);
87
+ isDependencyUsedByExports(this, this.usedByExports, moduleGraph, runtime);
88
88
  }
89
89
 
90
90
  /**
@@ -95,21 +95,6 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency {
95
95
  return false;
96
96
  }
97
97
 
98
- checkUsedByExports(moduleGraph, runtime) {
99
- if (this.usedByExports === false) return false;
100
- if (this.usedByExports !== true && this.usedByExports !== undefined) {
101
- const selfModule = moduleGraph.getParentModule(this);
102
- const exportsInfo = moduleGraph.getExportsInfo(selfModule);
103
- let used = false;
104
- for (const exportName of this.usedByExports) {
105
- if (exportsInfo.getUsed(exportName, runtime) !== UsageState.Unused)
106
- used = true;
107
- }
108
- if (!used) return false;
109
- }
110
- return true;
111
- }
112
-
113
98
  /**
114
99
  * Returns list of exports referenced by this dependency
115
100
  * @param {ModuleGraph} moduleGraph module graph
@@ -196,25 +181,6 @@ class HarmonyImportSpecifierDependency extends HarmonyImportDependency {
196
181
  return 0;
197
182
  }
198
183
 
199
- /**
200
- * Update the hash
201
- * @param {Hash} hash hash to be updated
202
- * @param {UpdateHashContext} context context
203
- * @returns {void}
204
- */
205
- updateHash(hash, context) {
206
- const { chunkGraph, runtime } = context;
207
- super.updateHash(hash, context);
208
- const moduleGraph = chunkGraph.moduleGraph;
209
- const importedModule = moduleGraph.getModule(this);
210
- const ids = this.getIds(moduleGraph);
211
- hash.update(ids.join());
212
- if (importedModule) {
213
- const exportsInfo = moduleGraph.getExportsInfo(importedModule);
214
- hash.update(`${exportsInfo.getUsedName(ids, runtime)}`);
215
- }
216
- }
217
-
218
184
  serialize(context) {
219
185
  const { write } = context;
220
186
  write(this.ids);
@@ -103,8 +103,8 @@ class HarmonyModulesPlugin {
103
103
  return;
104
104
 
105
105
  new HarmonyDetectionParserPlugin(this.options).apply(parser);
106
- new HarmonyImportDependencyParserPlugin(this.options).apply(parser);
107
- new HarmonyExportDependencyParserPlugin(this.options).apply(parser);
106
+ new HarmonyImportDependencyParserPlugin(parserOptions).apply(parser);
107
+ new HarmonyExportDependencyParserPlugin(parserOptions).apply(parser);
108
108
  new HarmonyTopLevelThisParserPlugin().apply(parser);
109
109
  };
110
110
 
@@ -14,17 +14,12 @@ const ImportWeakDependency = require("./ImportWeakDependency");
14
14
  /** @typedef {import("../Compiler")} Compiler */
15
15
 
16
16
  class ImportPlugin {
17
- constructor(options) {
18
- this.options = options;
19
- }
20
-
21
17
  /**
22
18
  * Apply the plugin
23
19
  * @param {Compiler} compiler the compiler instance
24
20
  * @returns {void}
25
21
  */
26
22
  apply(compiler) {
27
- const options = this.options;
28
23
  compiler.hooks.compilation.tap(
29
24
  "ImportPlugin",
30
25
  (compilation, { contextModuleFactory, normalModuleFactory }) => {
@@ -68,7 +63,7 @@ class ImportPlugin {
68
63
  if (parserOptions.import !== undefined && !parserOptions.import)
69
64
  return;
70
65
 
71
- new ImportParserPlugin(options).apply(parser);
66
+ new ImportParserPlugin(parserOptions).apply(parser);
72
67
  };
73
68
 
74
69
  normalModuleFactory.hooks.parser
@@ -73,7 +73,6 @@ class JsonExportsDependency extends NullDependency {
73
73
  */
74
74
  updateHash(hash, context) {
75
75
  hash.update(this.exports ? JSON.stringify(this.exports) : "undefined");
76
- super.updateHash(hash, context);
77
76
  }
78
77
 
79
78
  serialize(context) {
@@ -69,7 +69,6 @@ class ModuleDecoratorDependency extends NullDependency {
69
69
  * @returns {void}
70
70
  */
71
71
  updateHash(hash, context) {
72
- super.updateHash(hash, context);
73
72
  hash.update(this.decorator);
74
73
  hash.update(`${this.allowExportsAccess}`);
75
74
  }
@@ -20,14 +20,6 @@ class NullDependency extends Dependency {
20
20
  return "null";
21
21
  }
22
22
 
23
- /**
24
- * Update the hash
25
- * @param {Hash} hash hash to be updated
26
- * @param {UpdateHashContext} context context
27
- * @returns {void}
28
- */
29
- updateHash(hash, context) {}
30
-
31
23
  serialize({ write }) {
32
24
  write(this.loc);
33
25
  }
@@ -51,7 +51,6 @@ class ProvidedDependency extends ModuleDependency {
51
51
  * @returns {void}
52
52
  */
53
53
  updateHash(hash, context) {
54
- super.updateHash(hash, context);
55
54
  hash.update(this.identifier);
56
55
  hash.update(this.path ? this.path.join(",") : "null");
57
56
  }
@@ -43,18 +43,6 @@ class StaticExportsDependency extends NullDependency {
43
43
  };
44
44
  }
45
45
 
46
- /**
47
- * Update the hash
48
- * @param {Hash} hash hash to be updated
49
- * @param {UpdateHashContext} context context
50
- * @returns {void}
51
- */
52
- updateHash(hash, context) {
53
- hash.update(JSON.stringify(this.exports));
54
- if (this.canMangle) hash.update("canMangle");
55
- super.updateHash(hash, context);
56
- }
57
-
58
46
  serialize(context) {
59
47
  const { write } = context;
60
48
  write(this.exports);
@@ -19,10 +19,6 @@ const SystemRuntimeModule = require("./SystemRuntimeModule");
19
19
  /** @typedef {import("../Compiler")} Compiler */
20
20
 
21
21
  class SystemPlugin {
22
- constructor(options) {
23
- this.options = options;
24
- }
25
-
26
22
  /**
27
23
  * Apply the plugin
28
24
  * @param {Compiler} compiler the compiler instance
@@ -6,6 +6,7 @@
6
6
  "use strict";
7
7
 
8
8
  const RuntimeGlobals = require("../RuntimeGlobals");
9
+ const { isDependencyUsedByExports } = require("../optimize/InnerGraph");
9
10
  const makeSerializable = require("../util/makeSerializable");
10
11
  const ModuleDependency = require("./ModuleDependency");
11
12
 
@@ -15,16 +16,23 @@ const ModuleDependency = require("./ModuleDependency");
15
16
  /** @typedef {import("../Dependency").UpdateHashContext} UpdateHashContext */
16
17
  /** @typedef {import("../DependencyTemplate").DependencyTemplateContext} DependencyTemplateContext */
17
18
  /** @typedef {import("../ModuleGraph")} ModuleGraph */
19
+ /** @typedef {import("../ModuleGraphConnection")} ModuleGraphConnection */
20
+ /** @typedef {import("../ModuleGraphConnection").ConnectionState} ConnectionState */
18
21
  /** @typedef {import("../util/Hash")} Hash */
22
+ /** @typedef {import("../util/runtime").RuntimeSpec} RuntimeSpec */
19
23
 
20
24
  class URLDependency extends ModuleDependency {
21
25
  /**
22
26
  * @param {string} request request
23
- * @param {[number, number]} range range
27
+ * @param {[number, number]} range range of the arguments of new URL( |> ... <| )
28
+ * @param {[number, number]} outerRange range of the full |> new URL(...) <|
24
29
  */
25
- constructor(request, range) {
30
+ constructor(request, range, outerRange) {
26
31
  super(request);
27
32
  this.range = range;
33
+ this.outerRange = outerRange;
34
+ /** @type {Set<string> | boolean} */
35
+ this.usedByExports = undefined;
28
36
  }
29
37
 
30
38
  get type() {
@@ -34,6 +42,29 @@ class URLDependency extends ModuleDependency {
34
42
  get category() {
35
43
  return "url";
36
44
  }
45
+
46
+ /**
47
+ * @param {ModuleGraph} moduleGraph module graph
48
+ * @returns {function(ModuleGraphConnection, RuntimeSpec): ConnectionState} function to determine if the connection is active
49
+ */
50
+ getCondition(moduleGraph) {
51
+ return (connection, runtime) =>
52
+ isDependencyUsedByExports(this, this.usedByExports, moduleGraph, runtime);
53
+ }
54
+
55
+ serialize(context) {
56
+ const { write } = context;
57
+ write(this.outerRange);
58
+ write(this.usedByExports);
59
+ super.serialize(context);
60
+ }
61
+
62
+ deserialize(context) {
63
+ const { read } = context;
64
+ this.outerRange = read();
65
+ this.usedByExports = read();
66
+ super.deserialize(context);
67
+ }
37
68
  }
38
69
 
39
70
  URLDependency.Template = class URLDependencyTemplate extends (
@@ -50,9 +81,20 @@ URLDependency.Template = class URLDependencyTemplate extends (
50
81
  chunkGraph,
51
82
  moduleGraph,
52
83
  runtimeRequirements,
53
- runtimeTemplate
84
+ runtimeTemplate,
85
+ runtime
54
86
  } = templateContext;
55
87
  const dep = /** @type {URLDependency} */ (dependency);
88
+ const connection = moduleGraph.getConnection(dep);
89
+ // Skip rendering depending when dependency is conditional
90
+ if (connection && !connection.isTargetActive(runtime)) {
91
+ source.replace(
92
+ dep.outerRange[0],
93
+ dep.outerRange[1] - 1,
94
+ "/* unused asset import */ undefined"
95
+ );
96
+ return;
97
+ }
56
98
 
57
99
  runtimeRequirements.add(RuntimeGlobals.baseURI);
58
100
  runtimeRequirements.add(RuntimeGlobals.require);
@@ -6,6 +6,7 @@
6
6
  "use strict";
7
7
 
8
8
  const { approve } = require("../javascript/JavascriptParserHelpers");
9
+ const InnerGraph = require("../optimize/InnerGraph");
9
10
  const URLDependency = require("./URLDependency");
10
11
 
11
12
  /** @typedef {import("estree").NewExpression} NewExpressionNode */
@@ -32,10 +33,12 @@ class URLPlugin {
32
33
  */
33
34
  const parserCallback = (parser, parserOptions) => {
34
35
  if (parserOptions.url === false) return;
35
- parser.hooks.canRename.for("URL").tap("URLPlugin", approve);
36
- parser.hooks.new.for("URL").tap("URLPlugin", _expr => {
37
- const expr = /** @type {NewExpressionNode} */ (_expr);
38
36
 
37
+ /**
38
+ * @param {NewExpressionNode} expr expression
39
+ * @returns {undefined | string} request
40
+ */
41
+ const getUrlRequest = expr => {
39
42
  if (expr.arguments.length !== 2) return;
40
43
 
41
44
  const [arg1, arg2] = expr.arguments;
@@ -59,16 +62,39 @@ class URLPlugin {
59
62
 
60
63
  const request = parser.evaluateExpression(arg1).asString();
61
64
 
65
+ return request;
66
+ };
67
+
68
+ parser.hooks.canRename.for("URL").tap("URLPlugin", approve);
69
+ parser.hooks.new.for("URL").tap("URLPlugin", _expr => {
70
+ const expr = /** @type {NewExpressionNode} */ (_expr);
71
+
72
+ const request = getUrlRequest(expr);
73
+
62
74
  if (!request) return;
63
75
 
64
- const dep = new URLDependency(request, [
65
- arg1.range[0],
66
- arg2.range[1]
67
- ]);
76
+ const [arg1, arg2] = expr.arguments;
77
+ const dep = new URLDependency(
78
+ request,
79
+ [arg1.range[0], arg2.range[1]],
80
+ expr.range
81
+ );
68
82
  dep.loc = expr.loc;
69
83
  parser.state.module.addDependency(dep);
84
+ InnerGraph.onUsage(parser.state, e => (dep.usedByExports = e));
70
85
  return true;
71
86
  });
87
+ parser.hooks.isPure.for("NewExpression").tap("URLPlugin", _expr => {
88
+ const expr = /** @type {NewExpressionNode} */ (_expr);
89
+ const { callee } = expr;
90
+ if (callee.type !== "Identifier") return;
91
+ const calleeInfo = parser.getFreeInfoFromVariable(callee.name);
92
+ if (!calleeInfo || calleeInfo.name !== "URL") return;
93
+
94
+ const request = getUrlRequest(expr);
95
+
96
+ if (request) return true;
97
+ });
72
98
  };
73
99
 
74
100
  normalModuleFactory.hooks.parser