webpack 5.18.0 → 5.20.2

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 (51) hide show
  1. package/README.md +10 -47
  2. package/bin/webpack.js +0 -0
  3. package/lib/CleanPlugin.js +357 -0
  4. package/lib/CodeGenerationResults.js +28 -26
  5. package/lib/Compilation.js +192 -12
  6. package/lib/Dependency.js +1 -1
  7. package/lib/FlagDependencyUsagePlugin.js +8 -4
  8. package/lib/Generator.js +1 -0
  9. package/lib/ModuleGraph.js +8 -0
  10. package/lib/ModuleGraphConnection.js +3 -3
  11. package/lib/ModuleProfile.js +31 -4
  12. package/lib/NormalModule.js +17 -3
  13. package/lib/ProgressPlugin.js +12 -10
  14. package/lib/RuntimeGlobals.js +14 -0
  15. package/lib/RuntimePlugin.js +8 -0
  16. package/lib/RuntimeTemplate.js +1 -1
  17. package/lib/WebpackOptionsApply.js +16 -7
  18. package/lib/asset/AssetGenerator.js +10 -1
  19. package/lib/asset/AssetModulesPlugin.js +14 -5
  20. package/lib/async-modules/AwaitDependenciesInitFragment.js +12 -2
  21. package/lib/cache/IdleFileCachePlugin.js +9 -3
  22. package/lib/config/defaults.js +13 -2
  23. package/lib/config/normalization.js +1 -0
  24. package/lib/container/ContainerEntryModule.js +4 -1
  25. package/lib/container/ContainerPlugin.js +4 -2
  26. package/lib/dependencies/HarmonyCompatibilityDependency.js +5 -4
  27. package/lib/dependencies/HarmonyExportImportedSpecifierDependency.js +1 -1
  28. package/lib/dependencies/HarmonyImportSideEffectDependency.js +1 -1
  29. package/lib/dependencies/HarmonyImportSpecifierDependency.js +13 -5
  30. package/lib/dependencies/URLDependency.js +9 -4
  31. package/lib/hmr/LazyCompilationPlugin.js +29 -3
  32. package/lib/hmr/lazyCompilationBackend.js +2 -3
  33. package/lib/index.js +4 -0
  34. package/lib/javascript/JavascriptModulesPlugin.js +2 -2
  35. package/lib/optimize/InnerGraph.js +28 -0
  36. package/lib/runtime/AsyncModuleRuntimeModule.js +137 -0
  37. package/lib/serialization/BinaryMiddleware.js +10 -2
  38. package/lib/sharing/ShareRuntimeModule.js +1 -1
  39. package/lib/util/ArrayQueue.js +103 -0
  40. package/lib/util/AsyncQueue.js +58 -27
  41. package/lib/util/ParallelismFactorCalculator.js +59 -0
  42. package/lib/util/fs.js +3 -0
  43. package/lib/util/runtime.js +135 -24
  44. package/lib/validateSchema.js +2 -2
  45. package/lib/wasm-async/AsyncWebAssemblyJavascriptGenerator.js +24 -22
  46. package/package.json +2 -3
  47. package/schemas/WebpackOptions.json +65 -0
  48. package/schemas/_container.json +4 -0
  49. package/schemas/plugins/container/ContainerPlugin.json +4 -0
  50. package/schemas/plugins/container/ModuleFederationPlugin.json +4 -0
  51. package/types.d.ts +111 -19
@@ -55,6 +55,7 @@ const StatsPrinter = require("./stats/StatsPrinter");
55
55
  const { equals: arrayEquals } = require("./util/ArrayHelpers");
56
56
  const AsyncQueue = require("./util/AsyncQueue");
57
57
  const LazySet = require("./util/LazySet");
58
+ const { provide } = require("./util/MapHelpers");
58
59
  const { cachedCleverMerge } = require("./util/cleverMerge");
59
60
  const {
60
61
  compareLocations,
@@ -817,23 +818,29 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
817
818
  /** @type {CodeGenerationResults} */
818
819
  this.codeGenerationResults = undefined;
819
820
 
820
- /** @type {AsyncQueue<FactorizeModuleOptions, string, Module>} */
821
- this.factorizeQueue = new AsyncQueue({
822
- name: "factorize",
821
+ /** @type {AsyncQueue<Module, Module, Module>} */
822
+ this.processDependenciesQueue = new AsyncQueue({
823
+ name: "processDependencies",
823
824
  parallelism: options.parallelism || 100,
824
- processor: this._factorizeModule.bind(this)
825
+ processor: this._processModuleDependencies.bind(this)
825
826
  });
826
827
  /** @type {AsyncQueue<Module, string, Module>} */
827
828
  this.addModuleQueue = new AsyncQueue({
828
829
  name: "addModule",
829
- parallelism: options.parallelism || 100,
830
+ parent: this.processDependenciesQueue,
830
831
  getKey: module => module.identifier(),
831
832
  processor: this._addModule.bind(this)
832
833
  });
834
+ /** @type {AsyncQueue<FactorizeModuleOptions, string, Module>} */
835
+ this.factorizeQueue = new AsyncQueue({
836
+ name: "factorize",
837
+ parent: this.addModuleQueue,
838
+ processor: this._factorizeModule.bind(this)
839
+ });
833
840
  /** @type {AsyncQueue<Module, Module, Module>} */
834
841
  this.buildQueue = new AsyncQueue({
835
842
  name: "build",
836
- parallelism: options.parallelism || 100,
843
+ parent: this.factorizeQueue,
837
844
  processor: this._buildModule.bind(this)
838
845
  });
839
846
  /** @type {AsyncQueue<Module, Module, Module>} */
@@ -842,12 +849,6 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
842
849
  parallelism: options.parallelism || 100,
843
850
  processor: this._rebuildModule.bind(this)
844
851
  });
845
- /** @type {AsyncQueue<Module, Module, Module>} */
846
- this.processDependenciesQueue = new AsyncQueue({
847
- name: "processDependencies",
848
- parallelism: options.parallelism || 100,
849
- processor: this._processModuleDependencies.bind(this)
850
- });
851
852
 
852
853
  /**
853
854
  * Modules in value are building during the build of Module in key.
@@ -1871,6 +1872,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
1871
1872
  });
1872
1873
  }
1873
1874
 
1875
+ this.processDependenciesQueue.invalidate(module);
1874
1876
  this.processModuleDependencies(module, err => {
1875
1877
  if (err) return callback(err);
1876
1878
  this.removeReasonsOfDependencyBlock(module, {
@@ -1891,6 +1893,184 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
1891
1893
  }
1892
1894
 
1893
1895
  finish(callback) {
1896
+ if (this.profile) {
1897
+ this.logger.time("finish module profiles");
1898
+ const ParallelismFactorCalculator = require("./util/ParallelismFactorCalculator");
1899
+ const p = new ParallelismFactorCalculator();
1900
+ const moduleGraph = this.moduleGraph;
1901
+ const modulesWithProfiles = new Map();
1902
+ for (const module of this.modules) {
1903
+ const profile = moduleGraph.getProfile(module);
1904
+ if (!profile) continue;
1905
+ modulesWithProfiles.set(module, profile);
1906
+ p.range(
1907
+ profile.buildingStartTime,
1908
+ profile.buildingEndTime,
1909
+ f => (profile.buildingParallelismFactor = f)
1910
+ );
1911
+ p.range(
1912
+ profile.factoryStartTime,
1913
+ profile.factoryEndTime,
1914
+ f => (profile.factoryParallelismFactor = f)
1915
+ );
1916
+ p.range(
1917
+ profile.integrationStartTime,
1918
+ profile.integrationEndTime,
1919
+ f => (profile.integrationParallelismFactor = f)
1920
+ );
1921
+ p.range(
1922
+ profile.storingStartTime,
1923
+ profile.storingEndTime,
1924
+ f => (profile.storingParallelismFactor = f)
1925
+ );
1926
+ p.range(
1927
+ profile.restoringStartTime,
1928
+ profile.restoringEndTime,
1929
+ f => (profile.restoringParallelismFactor = f)
1930
+ );
1931
+ if (profile.additionalFactoryTimes) {
1932
+ for (const { start, end } of profile.additionalFactoryTimes) {
1933
+ const influence = (end - start) / profile.additionalFactories;
1934
+ p.range(
1935
+ start,
1936
+ end,
1937
+ f =>
1938
+ (profile.additionalFactoriesParallelismFactor += f * influence)
1939
+ );
1940
+ }
1941
+ }
1942
+ }
1943
+ p.calculate();
1944
+
1945
+ const logger = this.getLogger("webpack.Compilation.ModuleProfile");
1946
+ const logByValue = (value, msg) => {
1947
+ if (value > 1000) {
1948
+ logger.error(msg);
1949
+ } else if (value > 500) {
1950
+ logger.warn(msg);
1951
+ } else if (value > 200) {
1952
+ logger.info(msg);
1953
+ } else if (value > 30) {
1954
+ logger.log(msg);
1955
+ } else {
1956
+ logger.debug(msg);
1957
+ }
1958
+ };
1959
+ const logNormalSummary = (category, getDuration, getParallelism) => {
1960
+ let sum = 0;
1961
+ let max = 0;
1962
+ for (const [module, profile] of modulesWithProfiles) {
1963
+ const p = getParallelism(profile);
1964
+ const d = getDuration(profile);
1965
+ if (d === 0 || p === 0) continue;
1966
+ const t = d / p;
1967
+ sum += t;
1968
+ if (t <= 10) continue;
1969
+ logByValue(
1970
+ t,
1971
+ ` | ${Math.round(t)} ms${
1972
+ p >= 1.1 ? ` (parallelism ${Math.round(p * 10) / 10})` : ""
1973
+ } ${category} > ${module.readableIdentifier(this.requestShortener)}`
1974
+ );
1975
+ max = Math.max(max, t);
1976
+ }
1977
+ if (sum <= 10) return;
1978
+ logByValue(
1979
+ Math.max(sum / 10, max),
1980
+ `${Math.round(sum)} ms ${category}`
1981
+ );
1982
+ };
1983
+ const logByLoadersSummary = (category, getDuration, getParallelism) => {
1984
+ const map = new Map();
1985
+ for (const [module, profile] of modulesWithProfiles) {
1986
+ const list = provide(
1987
+ map,
1988
+ module.type + "!" + module.identifier().replace(/(!|^)[^!]*$/, ""),
1989
+ () => []
1990
+ );
1991
+ list.push({ module, profile });
1992
+ }
1993
+
1994
+ let sum = 0;
1995
+ let max = 0;
1996
+ for (const [key, modules] of map) {
1997
+ let innerSum = 0;
1998
+ let innerMax = 0;
1999
+ for (const { module, profile } of modules) {
2000
+ const p = getParallelism(profile);
2001
+ const d = getDuration(profile);
2002
+ if (d === 0 || p === 0) continue;
2003
+ const t = d / p;
2004
+ innerSum += t;
2005
+ if (t <= 10) continue;
2006
+ logByValue(
2007
+ t,
2008
+ ` | | ${Math.round(t)} ms${
2009
+ p >= 1.1 ? ` (parallelism ${Math.round(p * 10) / 10})` : ""
2010
+ } ${category} > ${module.readableIdentifier(
2011
+ this.requestShortener
2012
+ )}`
2013
+ );
2014
+ innerMax = Math.max(innerMax, t);
2015
+ }
2016
+ sum += innerSum;
2017
+ if (innerSum <= 10) continue;
2018
+ const idx = key.indexOf("!");
2019
+ const loaders = key.slice(idx + 1);
2020
+ const moduleType = key.slice(0, idx);
2021
+ const t = Math.max(innerSum / 10, innerMax);
2022
+ logByValue(
2023
+ t,
2024
+ ` | ${Math.round(innerSum)} ms ${category} > ${
2025
+ loaders
2026
+ ? `${
2027
+ modules.length
2028
+ } x ${moduleType} with ${this.requestShortener.shorten(
2029
+ loaders
2030
+ )}`
2031
+ : `${modules.length} x ${moduleType}`
2032
+ }`
2033
+ );
2034
+ max = Math.max(max, t);
2035
+ }
2036
+ if (sum <= 10) return;
2037
+ logByValue(
2038
+ Math.max(sum / 10, max),
2039
+ `${Math.round(sum)} ms ${category}`
2040
+ );
2041
+ };
2042
+ logNormalSummary(
2043
+ "resolve to new modules",
2044
+ p => p.factory,
2045
+ p => p.factoryParallelismFactor
2046
+ );
2047
+ logNormalSummary(
2048
+ "resolve to existing modules",
2049
+ p => p.additionalFactories,
2050
+ p => p.additionalFactoriesParallelismFactor
2051
+ );
2052
+ logNormalSummary(
2053
+ "integrate modules",
2054
+ p => p.restoring,
2055
+ p => p.restoringParallelismFactor
2056
+ );
2057
+ logByLoadersSummary(
2058
+ "build modules",
2059
+ p => p.building,
2060
+ p => p.buildingParallelismFactor
2061
+ );
2062
+ logNormalSummary(
2063
+ "store modules",
2064
+ p => p.storing,
2065
+ p => p.storingParallelismFactor
2066
+ );
2067
+ logNormalSummary(
2068
+ "restore modules",
2069
+ p => p.restoring,
2070
+ p => p.restoringParallelismFactor
2071
+ );
2072
+ this.logger.timeEnd("finish module profiles");
2073
+ }
1894
2074
  this.logger.time("finish modules");
1895
2075
  const { modules } = this;
1896
2076
  this.hooks.finishModules.callAsync(modules, err => {
package/lib/Dependency.js CHANGED
@@ -128,7 +128,7 @@ class Dependency {
128
128
 
129
129
  /**
130
130
  * @param {ModuleGraph} moduleGraph module graph
131
- * @returns {function(ModuleGraphConnection, RuntimeSpec): ConnectionState} function to determine if the connection is active
131
+ * @returns {null | false | function(ModuleGraphConnection, RuntimeSpec): ConnectionState} function to determine if the connection is active
132
132
  */
133
133
  getCondition(moduleGraph) {
134
134
  return null;
@@ -9,6 +9,7 @@ const Dependency = require("./Dependency");
9
9
  const { UsageState } = require("./ExportsInfo");
10
10
  const ModuleGraphConnection = require("./ModuleGraphConnection");
11
11
  const { STAGE_DEFAULT } = require("./OptimizationStages");
12
+ const ArrayQueue = require("./util/ArrayQueue");
12
13
  const TupleQueue = require("./util/TupleQueue");
13
14
  const { getEntryRuntime, mergeRuntimeOwned } = require("./util/runtime");
14
15
 
@@ -166,9 +167,12 @@ class FlagDependencyUsagePlugin {
166
167
  /** @type {Map<Module, (string[] | ReferencedExport)[] | Map<string, string[] | ReferencedExport>>} */
167
168
  const map = new Map();
168
169
 
169
- /** @type {DependenciesBlock[]} */
170
- const queue = [module];
171
- for (const block of queue) {
170
+ /** @type {ArrayQueue<DependenciesBlock>} */
171
+ const queue = new ArrayQueue();
172
+ queue.enqueue(module);
173
+ for (;;) {
174
+ const block = queue.dequeue();
175
+ if (block === undefined) break;
172
176
  for (const b of block.blocks) {
173
177
  if (
174
178
  !this.global &&
@@ -177,7 +181,7 @@ class FlagDependencyUsagePlugin {
177
181
  ) {
178
182
  processModule(b, b.groupOptions.entryOptions.runtime);
179
183
  } else {
180
- queue.push(b);
184
+ queue.enqueue(b);
181
185
  }
182
186
  }
183
187
  for (const dep of block.dependencies) {
package/lib/Generator.js CHANGED
@@ -28,6 +28,7 @@
28
28
  * @property {RuntimeSpec} runtime the runtime
29
29
  * @property {ConcatenationScope=} concatenationScope when in concatenated module, information about other concatenated modules
30
30
  * @property {string} type which kind of code should be generated
31
+ * @property {function(): Map<string, any>=} getData get access to the code generation data
31
32
  */
32
33
 
33
34
  /**
@@ -655,6 +655,14 @@ class ModuleGraph {
655
655
  return meta;
656
656
  }
657
657
 
658
+ /**
659
+ * @param {any} thing any thing
660
+ * @returns {Object} metadata
661
+ */
662
+ getMetaIfExisting(thing) {
663
+ return this._metaMap.get(thing);
664
+ }
665
+
658
666
  // TODO remove in webpack 6
659
667
  /**
660
668
  * @param {Module} module the module
@@ -56,7 +56,7 @@ class ModuleGraphConnection {
56
56
  * @param {Module} module the referenced module
57
57
  * @param {string=} explanation some extra detail
58
58
  * @param {boolean=} weak the reference is weak
59
- * @param {function(ModuleGraphConnection, RuntimeSpec): ConnectionState=} condition condition for the connection
59
+ * @param {false | function(ModuleGraphConnection, RuntimeSpec): ConnectionState=} condition condition for the connection
60
60
  */
61
61
  constructor(
62
62
  originModule,
@@ -73,9 +73,9 @@ class ModuleGraphConnection {
73
73
  this.module = module;
74
74
  this.weak = weak;
75
75
  this.conditional = !!condition;
76
- this._active = true;
76
+ this._active = condition !== false;
77
77
  /** @type {function(ModuleGraphConnection, RuntimeSpec): ConnectionState} */
78
- this.condition = condition;
78
+ this.condition = condition || undefined;
79
79
  /** @type {Set<string>} */
80
80
  this.explanations = undefined;
81
81
  if (explanation) {
@@ -8,12 +8,37 @@
8
8
  class ModuleProfile {
9
9
  constructor() {
10
10
  this.startTime = Date.now();
11
+
12
+ this.factoryStartTime = 0;
13
+ this.factoryEndTime = 0;
11
14
  this.factory = 0;
15
+ this.factoryParallelismFactor = 0;
16
+
17
+ this.restoringStartTime = 0;
18
+ this.restoringEndTime = 0;
12
19
  this.restoring = 0;
20
+ this.restoringParallelismFactor = 0;
21
+
22
+ this.integrationStartTime = 0;
23
+ this.integrationEndTime = 0;
13
24
  this.integration = 0;
25
+ this.integrationParallelismFactor = 0;
26
+
27
+ this.buildingStartTime = 0;
28
+ this.buildingEndTime = 0;
14
29
  this.building = 0;
30
+ this.buildingParallelismFactor = 0;
31
+
32
+ this.storingStartTime = 0;
33
+ this.storingEndTime = 0;
15
34
  this.storing = 0;
35
+ this.storingParallelismFactor = 0;
36
+
37
+ this.additionalFactoryTimes = undefined;
16
38
  this.additionalFactories = 0;
39
+ this.additionalFactoriesParallelismFactor = 0;
40
+
41
+ /** @deprecated */
17
42
  this.additionalIntegration = 0;
18
43
  }
19
44
 
@@ -70,10 +95,12 @@ class ModuleProfile {
70
95
  * @returns {void}
71
96
  */
72
97
  mergeInto(realProfile) {
73
- if (this.factory > realProfile.additionalFactories)
74
- realProfile.additionalFactories = this.factory;
75
- if (this.integration > realProfile.additionalIntegration)
76
- realProfile.additionalIntegration = this.integration;
98
+ realProfile.additionalFactories = this.factory;
99
+ (realProfile.additionalFactoryTimes =
100
+ realProfile.additionalFactoryTimes || []).push({
101
+ start: this.factoryStartTime,
102
+ end: this.factoryEndTime
103
+ });
77
104
  }
78
105
  }
79
106
 
@@ -259,7 +259,8 @@ class NormalModule extends Module {
259
259
  this._lastSuccessfulBuildMeta = {};
260
260
  this._forceBuild = true;
261
261
  this._isEvaluatingSideEffects = false;
262
- this._addedSideEffectsBailout = new WeakSet();
262
+ /** @type {WeakSet<ModuleGraph> | undefined} */
263
+ this._addedSideEffectsBailout = undefined;
263
264
  }
264
265
 
265
266
  /**
@@ -934,7 +935,11 @@ class NormalModule extends Module {
934
935
  for (const dep of this.dependencies) {
935
936
  const state = dep.getModuleEvaluationSideEffectsState(moduleGraph);
936
937
  if (state === true) {
937
- if (!this._addedSideEffectsBailout.has(moduleGraph)) {
938
+ if (
939
+ this._addedSideEffectsBailout === undefined
940
+ ? ((this._addedSideEffectsBailout = new WeakSet()), true)
941
+ : !this._addedSideEffectsBailout.has(moduleGraph)
942
+ ) {
938
943
  this._addedSideEffectsBailout.add(moduleGraph);
939
944
  moduleGraph
940
945
  .getOptimizationBailout(this)
@@ -988,6 +993,13 @@ class NormalModule extends Module {
988
993
  runtimeRequirements.add(RuntimeGlobals.thisAsExports);
989
994
  }
990
995
 
996
+ /** @type {Map<string, any>} */
997
+ let data;
998
+ const getData = () => {
999
+ if (data === undefined) data = new Map();
1000
+ return data;
1001
+ };
1002
+
991
1003
  const sources = new Map();
992
1004
  for (const type of this.generator.getTypes(this)) {
993
1005
  const source = this.error
@@ -1002,6 +1014,7 @@ class NormalModule extends Module {
1002
1014
  runtimeRequirements,
1003
1015
  runtime,
1004
1016
  concatenationScope,
1017
+ getData,
1005
1018
  type
1006
1019
  });
1007
1020
 
@@ -1013,7 +1026,8 @@ class NormalModule extends Module {
1013
1026
  /** @type {CodeGenerationResult} */
1014
1027
  const resultEntry = {
1015
1028
  sources,
1016
- runtimeRequirements
1029
+ runtimeRequirements,
1030
+ data
1017
1031
  };
1018
1032
  return resultEntry;
1019
1033
  }
@@ -108,14 +108,13 @@ class ProgressPlugin {
108
108
  /**
109
109
  * @param {ProgressPluginArgument} options options
110
110
  */
111
- constructor(options) {
111
+ constructor(options = {}) {
112
112
  if (typeof options === "function") {
113
113
  options = {
114
114
  handler: options
115
115
  };
116
116
  }
117
117
 
118
- options = options || {};
119
118
  validate(schema, options, {
120
119
  name: "Progress Plugin",
121
120
  baseDataPath: "options"
@@ -203,12 +202,13 @@ class ProgressPlugin {
203
202
  const items = [];
204
203
  const percentByModules =
205
204
  doneModules /
206
- Math.max(lastModulesCount || this.modulesCount, modulesCount);
205
+ Math.max(lastModulesCount || this.modulesCount || 1, modulesCount);
207
206
  const percentByEntries =
208
207
  doneEntries /
209
- Math.max(lastEntriesCount || this.dependenciesCount, entriesCount);
208
+ Math.max(lastEntriesCount || this.dependenciesCount || 1, entriesCount);
210
209
  const percentByDependencies =
211
- doneDependencies / Math.max(lastDependenciesCount, dependenciesCount);
210
+ doneDependencies /
211
+ Math.max(lastDependenciesCount || 1, dependenciesCount);
212
212
  let percentageFactor;
213
213
 
214
214
  switch (this.percentBy) {
@@ -268,17 +268,19 @@ class ProgressPlugin {
268
268
 
269
269
  const factorizeAdd = () => {
270
270
  dependenciesCount++;
271
- if (dependenciesCount % 100 === 0) updateThrottled();
271
+ if (dependenciesCount < 50 || dependenciesCount % 100 === 0)
272
+ updateThrottled();
272
273
  };
273
274
 
274
275
  const factorizeDone = () => {
275
276
  doneDependencies++;
276
- if (doneDependencies % 100 === 0) updateThrottled();
277
+ if (doneDependencies < 50 || doneDependencies % 100 === 0)
278
+ updateThrottled();
277
279
  };
278
280
 
279
281
  const moduleAdd = () => {
280
282
  modulesCount++;
281
- if (modulesCount % 100 === 0) updateThrottled();
283
+ if (modulesCount < 50 || modulesCount % 100 === 0) updateThrottled();
282
284
  };
283
285
 
284
286
  // only used when showActiveModules is set
@@ -293,7 +295,7 @@ class ProgressPlugin {
293
295
 
294
296
  const entryAdd = (entry, options) => {
295
297
  entriesCount++;
296
- if (entriesCount % 10 === 0) updateThrottled();
298
+ if (entriesCount < 5 || entriesCount % 10 === 0) updateThrottled();
297
299
  };
298
300
 
299
301
  const moduleDone = module => {
@@ -312,7 +314,7 @@ class ProgressPlugin {
312
314
  }
313
315
  }
314
316
  }
315
- if (doneModules % 100 === 0) updateThrottled();
317
+ if (doneModules < 50 || doneModules % 100 === 0) updateThrottled();
316
318
  };
317
319
 
318
320
  const entryDone = (entry, options) => {
@@ -303,3 +303,17 @@ exports.systemContext = "__webpack_require__.y";
303
303
  * the baseURI of current document
304
304
  */
305
305
  exports.baseURI = "__webpack_require__.b";
306
+
307
+ /**
308
+ * Creates an async module. The body function must be a async function.
309
+ * "module.exports" will be decorated with an AsyncModulePromise.
310
+ * The body function will be called.
311
+ * To handle async dependencies correctly do this: "([a, b, c] = await handleDependencies([a, b, c]));".
312
+ * If "hasAwaitAfterDependencies" is truthy, "handleDependencies()" must be called at the end of the body function.
313
+ * Signature: function(
314
+ * module: Module,
315
+ * body: (handleDependencies: (deps: AsyncModulePromise[]) => Promise<any[]> & () => void,
316
+ * hasAwaitAfterDependencies?: boolean
317
+ * ) => void
318
+ */
319
+ exports.asyncModule = "__webpack_require__.a";
@@ -8,6 +8,7 @@
8
8
  const RuntimeGlobals = require("./RuntimeGlobals");
9
9
  const RuntimeRequirementsDependency = require("./dependencies/RuntimeRequirementsDependency");
10
10
  const JavascriptModulesPlugin = require("./javascript/JavascriptModulesPlugin");
11
+ const AsyncModuleRuntimeModule = require("./runtime/AsyncModuleRuntimeModule");
11
12
  const AutoPublicPathRuntimeModule = require("./runtime/AutoPublicPathRuntimeModule");
12
13
  const CompatGetDefaultExportRuntimeModule = require("./runtime/CompatGetDefaultExportRuntimeModule");
13
14
  const CompatRuntimeModule = require("./runtime/CompatRuntimeModule");
@@ -48,6 +49,7 @@ const GLOBALS_ON_REQUIRE = [
48
49
  RuntimeGlobals.publicPath,
49
50
  RuntimeGlobals.scriptNonce,
50
51
  RuntimeGlobals.uncaughtErrorHandler,
52
+ RuntimeGlobals.asyncModule,
51
53
  RuntimeGlobals.wasmInstances,
52
54
  RuntimeGlobals.instantiateWasm,
53
55
  RuntimeGlobals.shareScopeMap,
@@ -194,6 +196,12 @@ class RuntimePlugin {
194
196
  compilation.addRuntimeModule(chunk, new GlobalRuntimeModule());
195
197
  return true;
196
198
  });
199
+ compilation.hooks.runtimeRequirementInTree
200
+ .for(RuntimeGlobals.asyncModule)
201
+ .tap("RuntimePlugin", chunk => {
202
+ compilation.addRuntimeModule(chunk, new AsyncModuleRuntimeModule());
203
+ return true;
204
+ });
197
205
  compilation.hooks.runtimeRequirementInTree
198
206
  .for(RuntimeGlobals.systemContext)
199
207
  .tap("RuntimePlugin", chunk => {
@@ -103,7 +103,7 @@ class RuntimeTemplate {
103
103
 
104
104
  returningFunction(returnValue, args = "") {
105
105
  return this.supportsArrowFunction()
106
- ? `(${args}) => ${returnValue}`
106
+ ? `(${args}) => (${returnValue})`
107
107
  : `function(${args}) { return ${returnValue}; }`;
108
108
  }
109
109
 
@@ -177,6 +177,13 @@ class WebpackOptionsApply extends OptionsApply {
177
177
  );
178
178
  }
179
179
 
180
+ if (options.output.clean) {
181
+ const CleanPlugin = require("./CleanPlugin");
182
+ new CleanPlugin(
183
+ options.output.clean === true ? {} : options.output.clean
184
+ ).apply(compiler);
185
+ }
186
+
180
187
  if (options.devtool) {
181
188
  if (options.devtool.includes("source-map")) {
182
189
  const hidden = options.devtool.includes("hidden");
@@ -246,22 +253,24 @@ class WebpackOptionsApply extends OptionsApply {
246
253
 
247
254
  if (options.experiments.lazyCompilation) {
248
255
  const LazyCompilationPlugin = require("./hmr/LazyCompilationPlugin");
256
+ const lazyOptions =
257
+ typeof options.experiments.lazyCompilation === "object"
258
+ ? options.experiments.lazyCompilation
259
+ : null;
249
260
  new LazyCompilationPlugin({
250
261
  backend:
251
- (typeof options.experiments.lazyCompilation === "object" &&
252
- options.experiments.lazyCompilation.backend) ||
262
+ (lazyOptions && lazyOptions.backend) ||
253
263
  require("./hmr/lazyCompilationBackend"),
254
264
  client:
255
- (typeof options.experiments.lazyCompilation === "object" &&
256
- options.experiments.lazyCompilation.client) ||
265
+ (lazyOptions && lazyOptions.client) ||
257
266
  require.resolve(
258
267
  `../hot/lazy-compilation-${
259
268
  options.externalsPresets.node ? "node" : "web"
260
269
  }.js`
261
270
  ),
262
- entries:
263
- typeof options.experiments.lazyCompilation !== "object" ||
264
- options.experiments.lazyCompilation.entries !== false
271
+ entries: !lazyOptions || lazyOptions.entries !== false,
272
+ imports: !lazyOptions || lazyOptions.imports !== false,
273
+ test: lazyOptions && lazyOptions.test
265
274
  }).apply(compiler);
266
275
  }
267
276
 
@@ -47,7 +47,7 @@ class AssetGenerator extends Generator {
47
47
  */
48
48
  generate(
49
49
  module,
50
- { runtime, chunkGraph, runtimeTemplate, runtimeRequirements, type }
50
+ { runtime, chunkGraph, runtimeTemplate, runtimeRequirements, type, getData }
51
51
  ) {
52
52
  switch (type) {
53
53
  case "asset":
@@ -146,6 +146,15 @@ class AssetGenerator extends Generator {
146
146
  sourceFilename,
147
147
  ...info
148
148
  };
149
+ if (getData) {
150
+ // Due to code generation caching module.buildInfo.XXX can't used to store such information
151
+ // It need to be stored in the code generation results instead, where it's cached too
152
+ // TODO webpack 6 For back-compat reasons we also store in on module.buildInfo
153
+ const data = getData();
154
+ data.set("fullContentHash", fullHash);
155
+ data.set("filename", filename);
156
+ data.set("assetInfo", info);
157
+ }
149
158
 
150
159
  runtimeRequirements.add(RuntimeGlobals.publicPath); // add __webpack_require__.p
151
160
 
@@ -145,14 +145,23 @@ class AssetModulesPlugin {
145
145
  );
146
146
  if (modules) {
147
147
  for (const module of modules) {
148
+ const codeGenResult = codeGenerationResults.get(
149
+ module,
150
+ chunk.runtime
151
+ );
148
152
  result.push({
149
- render: () =>
150
- codeGenerationResults.getSource(module, chunk.runtime, type),
151
- filename: module.buildInfo.filename,
152
- info: module.buildInfo.assetInfo,
153
+ render: () => codeGenResult.sources.get(type),
154
+ filename:
155
+ module.buildInfo.filename ||
156
+ codeGenResult.data.get("filename"),
157
+ info:
158
+ module.buildInfo.assetInfo ||
159
+ codeGenResult.data.get("assetInfo"),
153
160
  auxiliary: true,
154
161
  identifier: `assetModule${chunkGraph.getModuleId(module)}`,
155
- hash: module.buildInfo.fullContentHash
162
+ hash:
163
+ module.buildInfo.fullContentHash ||
164
+ codeGenResult.data.get("fullContentHash")
156
165
  });
157
166
  }
158
167
  }