webpack 5.53.0 → 5.54.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/lib/AsyncDependenciesBlock.js +9 -2
- package/lib/CacheFacade.js +10 -3
- package/lib/ChunkGraph.js +19 -8
- package/lib/CodeGenerationResults.js +7 -2
- package/lib/Compilation.js +207 -16
- package/lib/Compiler.js +9 -1
- package/lib/DependencyTemplates.js +8 -2
- package/lib/EvalDevToolModulePlugin.js +2 -1
- package/lib/EvalSourceMapDevToolPlugin.js +2 -1
- package/lib/ExternalModule.js +18 -9
- package/lib/FileSystemInfo.js +101 -170
- package/lib/FlagDependencyExportsPlugin.js +43 -16
- package/lib/JavascriptMetaInfoPlugin.js +6 -1
- package/lib/MemCache.js +45 -0
- package/lib/ModuleFilenameHelpers.js +21 -7
- package/lib/SourceMapDevToolPlugin.js +7 -3
- package/lib/WebpackOptionsApply.js +19 -1
- package/lib/cache/PackFileCacheStrategy.js +2 -1
- package/lib/cache/getLazyHashedEtag.js +35 -8
- package/lib/config/defaults.js +18 -7
- package/lib/dependencies/CachedConstDependency.js +4 -3
- package/lib/dependencies/ConstDependency.js +12 -4
- package/lib/dependencies/JsonExportsDependency.js +7 -1
- package/lib/dependencies/ModuleDecoratorDependency.js +5 -2
- package/lib/dependencies/ProvidedDependency.js +6 -2
- package/lib/dependencies/PureExpressionDependency.js +5 -1
- package/lib/dependencies/RuntimeRequirementsDependency.js +5 -1
- package/lib/ids/IdHelpers.js +21 -8
- package/lib/ids/NamedChunkIdsPlugin.js +3 -0
- package/lib/ids/NamedModuleIdsPlugin.js +3 -1
- package/lib/index.js +6 -0
- package/lib/javascript/BasicEvaluatedExpression.js +3 -0
- package/lib/javascript/JavascriptParser.js +22 -4
- package/lib/javascript/JavascriptParserHelpers.js +0 -2
- package/lib/optimize/ConcatenatedModule.js +25 -4
- package/lib/optimize/InnerGraph.js +22 -2
- package/lib/optimize/ModuleConcatenationPlugin.js +2 -1
- package/lib/schemes/HttpUriPlugin.js +1 -2
- package/lib/serialization/BinaryMiddleware.js +11 -2
- package/lib/serialization/FileMiddleware.js +24 -7
- package/lib/serialization/ObjectMiddleware.js +19 -8
- package/lib/util/createHash.js +10 -0
- package/lib/util/hash/BatchedHash.js +65 -0
- package/lib/util/hash/xxhash64.js +154 -0
- package/lib/util/serialization.js +4 -4
- package/package.json +10 -6
- package/schemas/WebpackOptions.check.js +1 -1
- package/schemas/WebpackOptions.json +12 -0
- package/schemas/plugins/HashedModuleIdsPlugin.check.js +1 -1
- package/schemas/plugins/HashedModuleIdsPlugin.json +20 -2
- package/types.d.ts +157 -10
@@ -35,6 +35,7 @@ class AsyncDependenciesBlock extends DependenciesBlock {
|
|
35
35
|
this.request = request;
|
36
36
|
/** @type {DependenciesBlock} */
|
37
37
|
this.parent = undefined;
|
38
|
+
this._stringifiedGroupOptions = undefined;
|
38
39
|
}
|
39
40
|
|
40
41
|
/**
|
@@ -49,7 +50,10 @@ class AsyncDependenciesBlock extends DependenciesBlock {
|
|
49
50
|
* @returns {void}
|
50
51
|
*/
|
51
52
|
set chunkName(value) {
|
52
|
-
this.groupOptions.name
|
53
|
+
if (this.groupOptions.name !== value) {
|
54
|
+
this.groupOptions.name = value;
|
55
|
+
this._stringifiedGroupOptions = undefined;
|
56
|
+
}
|
53
57
|
}
|
54
58
|
|
55
59
|
/**
|
@@ -59,7 +63,10 @@ class AsyncDependenciesBlock extends DependenciesBlock {
|
|
59
63
|
*/
|
60
64
|
updateHash(hash, context) {
|
61
65
|
const { chunkGraph } = context;
|
62
|
-
|
66
|
+
if (this._stringifiedGroupOptions === undefined) {
|
67
|
+
this._stringifiedGroupOptions = JSON.stringify(this.groupOptions);
|
68
|
+
}
|
69
|
+
hash.update(this._stringifiedGroupOptions);
|
63
70
|
const chunkGroup = chunkGraph.getBlockChunkGroup(this);
|
64
71
|
hash.update(chunkGroup ? chunkGroup.id : "");
|
65
72
|
super.updateHash(hash, context);
|
package/lib/CacheFacade.js
CHANGED
@@ -13,6 +13,7 @@ const mergeEtags = require("./cache/mergeEtags");
|
|
13
13
|
/** @typedef {import("./Cache").Etag} Etag */
|
14
14
|
/** @typedef {import("./WebpackError")} WebpackError */
|
15
15
|
/** @typedef {import("./cache/getLazyHashedEtag").HashableObject} HashableObject */
|
16
|
+
/** @typedef {typeof import("./util/Hash")} HashConstructor */
|
16
17
|
|
17
18
|
/**
|
18
19
|
* @template T
|
@@ -198,10 +199,12 @@ class CacheFacade {
|
|
198
199
|
/**
|
199
200
|
* @param {Cache} cache the root cache
|
200
201
|
* @param {string} name the child cache name
|
202
|
+
* @param {string | HashConstructor} hashFunction the hash function to use
|
201
203
|
*/
|
202
|
-
constructor(cache, name) {
|
204
|
+
constructor(cache, name, hashFunction) {
|
203
205
|
this._cache = cache;
|
204
206
|
this._name = name;
|
207
|
+
this._hashFunction = hashFunction;
|
205
208
|
}
|
206
209
|
|
207
210
|
/**
|
@@ -209,7 +212,11 @@ class CacheFacade {
|
|
209
212
|
* @returns {CacheFacade} child cache
|
210
213
|
*/
|
211
214
|
getChildCache(name) {
|
212
|
-
return new CacheFacade(
|
215
|
+
return new CacheFacade(
|
216
|
+
this._cache,
|
217
|
+
`${this._name}|${name}`,
|
218
|
+
this._hashFunction
|
219
|
+
);
|
213
220
|
}
|
214
221
|
|
215
222
|
/**
|
@@ -230,7 +237,7 @@ class CacheFacade {
|
|
230
237
|
* @returns {Etag} an etag that is lazy hashed
|
231
238
|
*/
|
232
239
|
getLazyHashedEtag(obj) {
|
233
|
-
return getLazyHashedEtag(obj);
|
240
|
+
return getLazyHashedEtag(obj, this._hashFunction);
|
234
241
|
}
|
235
242
|
|
236
243
|
/**
|
package/lib/ChunkGraph.js
CHANGED
@@ -34,6 +34,7 @@ const {
|
|
34
34
|
/** @typedef {import("./Module")} Module */
|
35
35
|
/** @typedef {import("./ModuleGraph")} ModuleGraph */
|
36
36
|
/** @typedef {import("./RuntimeModule")} RuntimeModule */
|
37
|
+
/** @typedef {typeof import("./util/Hash")} Hash */
|
37
38
|
/** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */
|
38
39
|
|
39
40
|
/** @type {ReadonlySet<string>} */
|
@@ -217,8 +218,9 @@ class ChunkGraphChunk {
|
|
217
218
|
class ChunkGraph {
|
218
219
|
/**
|
219
220
|
* @param {ModuleGraph} moduleGraph the module graph
|
221
|
+
* @param {string | Hash} hashFunction the hash function to use
|
220
222
|
*/
|
221
|
-
constructor(moduleGraph) {
|
223
|
+
constructor(moduleGraph, hashFunction = "md4") {
|
222
224
|
/** @private @type {WeakMap<Module, ChunkGraphModule>} */
|
223
225
|
this._modules = new WeakMap();
|
224
226
|
/** @private @type {WeakMap<Chunk, ChunkGraphChunk>} */
|
@@ -230,6 +232,8 @@ class ChunkGraph {
|
|
230
232
|
/** @type {ModuleGraph} */
|
231
233
|
this.moduleGraph = moduleGraph;
|
232
234
|
|
235
|
+
this._hashFunction = hashFunction;
|
236
|
+
|
233
237
|
this._getGraphRoots = this._getGraphRoots.bind(this);
|
234
238
|
|
235
239
|
// Caching
|
@@ -1372,22 +1376,29 @@ Caller might not support runtime-dependent code generation (opt-out via optimiza
|
|
1372
1376
|
/**
|
1373
1377
|
* @param {Module} module the module
|
1374
1378
|
* @param {RuntimeSpec} runtime the runtime
|
1375
|
-
* @param {Set<string>} items runtime requirements to be added (ownership of this Set is given to ChunkGraph)
|
1379
|
+
* @param {Set<string>} items runtime requirements to be added (ownership of this Set is given to ChunkGraph when transferOwnership not false)
|
1380
|
+
* @param {boolean} transferOwnership true: transfer ownership of the items object, false: items is immutable and shared and won't be modified
|
1376
1381
|
* @returns {void}
|
1377
1382
|
*/
|
1378
|
-
addModuleRuntimeRequirements(
|
1383
|
+
addModuleRuntimeRequirements(
|
1384
|
+
module,
|
1385
|
+
runtime,
|
1386
|
+
items,
|
1387
|
+
transferOwnership = true
|
1388
|
+
) {
|
1379
1389
|
const cgm = this._getChunkGraphModule(module);
|
1380
1390
|
const runtimeRequirementsMap = cgm.runtimeRequirements;
|
1381
1391
|
if (runtimeRequirementsMap === undefined) {
|
1382
1392
|
const map = new RuntimeSpecMap();
|
1383
|
-
|
1393
|
+
// TODO avoid cloning item and track ownership instead
|
1394
|
+
map.set(runtime, transferOwnership ? items : new Set(items));
|
1384
1395
|
cgm.runtimeRequirements = map;
|
1385
1396
|
return;
|
1386
1397
|
}
|
1387
1398
|
runtimeRequirementsMap.update(runtime, runtimeRequirements => {
|
1388
1399
|
if (runtimeRequirements === undefined) {
|
1389
|
-
return items;
|
1390
|
-
} else if (runtimeRequirements.size >= items.size) {
|
1400
|
+
return transferOwnership ? items : new Set(items);
|
1401
|
+
} else if (!transferOwnership || runtimeRequirements.size >= items.size) {
|
1391
1402
|
for (const item of items) runtimeRequirements.add(item);
|
1392
1403
|
return runtimeRequirements;
|
1393
1404
|
} else {
|
@@ -1487,7 +1498,7 @@ Caller might not support runtime-dependent code generation (opt-out via optimiza
|
|
1487
1498
|
cgm.graphHashes = new RuntimeSpecMap();
|
1488
1499
|
}
|
1489
1500
|
const graphHash = cgm.graphHashes.provide(runtime, () => {
|
1490
|
-
const hash = createHash(
|
1501
|
+
const hash = createHash(this._hashFunction);
|
1491
1502
|
hash.update(`${cgm.id}`);
|
1492
1503
|
hash.update(`${this.moduleGraph.isAsync(module)}`);
|
1493
1504
|
this.moduleGraph.getExportsInfo(module).updateHash(hash, runtime);
|
@@ -1575,7 +1586,7 @@ Caller might not support runtime-dependent code generation (opt-out via optimiza
|
|
1575
1586
|
connectedModules.size > 1
|
1576
1587
|
? Array.from(connectedModules).sort(([a], [b]) => (a < b ? -1 : 1))
|
1577
1588
|
: connectedModules;
|
1578
|
-
const hash = createHash(
|
1589
|
+
const hash = createHash(this._hashFunction);
|
1579
1590
|
const addModuleToHash = module => {
|
1580
1591
|
hash.update(
|
1581
1592
|
this._getModuleGraphHashBigInt(
|
@@ -13,12 +13,17 @@ const { runtimeToString, RuntimeSpecMap } = require("./util/runtime");
|
|
13
13
|
/** @typedef {import("webpack-sources").Source} Source */
|
14
14
|
/** @typedef {import("./Module")} Module */
|
15
15
|
/** @typedef {import("./Module").CodeGenerationResult} CodeGenerationResult */
|
16
|
+
/** @typedef {typeof import("./util/Hash")} Hash */
|
16
17
|
/** @typedef {import("./util/runtime").RuntimeSpec} RuntimeSpec */
|
17
18
|
|
18
19
|
class CodeGenerationResults {
|
19
|
-
|
20
|
+
/**
|
21
|
+
* @param {string | Hash} hashFunction the hash function to use
|
22
|
+
*/
|
23
|
+
constructor(hashFunction = "md4") {
|
20
24
|
/** @type {Map<Module, RuntimeSpecMap<CodeGenerationResult>>} */
|
21
25
|
this.map = new Map();
|
26
|
+
this._hashFunction = hashFunction;
|
22
27
|
}
|
23
28
|
|
24
29
|
/**
|
@@ -124,7 +129,7 @@ Caller might not support runtime-dependent code generation (opt-out via optimiza
|
|
124
129
|
getHash(module, runtime) {
|
125
130
|
const info = this.get(module, runtime);
|
126
131
|
if (info.hash !== undefined) return info.hash;
|
127
|
-
const hash = createHash(
|
132
|
+
const hash = createHash(this._hashFunction);
|
128
133
|
for (const [type, source] of info.sources) {
|
129
134
|
hash.update(type);
|
130
135
|
source.updateHash(hash);
|
package/lib/Compilation.js
CHANGED
@@ -38,6 +38,7 @@ const {
|
|
38
38
|
tryRunOrWebpackError
|
39
39
|
} = require("./HookWebpackError");
|
40
40
|
const MainTemplate = require("./MainTemplate");
|
41
|
+
const MemCache = require("./MemCache");
|
41
42
|
const Module = require("./Module");
|
42
43
|
const ModuleDependencyError = require("./ModuleDependencyError");
|
43
44
|
const ModuleDependencyWarning = require("./ModuleDependencyWarning");
|
@@ -76,7 +77,7 @@ const {
|
|
76
77
|
createFakeHook
|
77
78
|
} = require("./util/deprecation");
|
78
79
|
const processAsyncTree = require("./util/processAsyncTree");
|
79
|
-
const { getRuntimeKey } = require("./util/runtime");
|
80
|
+
const { getRuntimeKey, RuntimeSpecMap } = require("./util/runtime");
|
80
81
|
const { isSourceEqual } = require("./util/source");
|
81
82
|
|
82
83
|
/** @template T @typedef {import("tapable").AsArray<T>} AsArray<T> */
|
@@ -852,7 +853,8 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|
852
853
|
this.fileSystemInfo = new FileSystemInfo(this.inputFileSystem, {
|
853
854
|
managedPaths: compiler.managedPaths,
|
854
855
|
immutablePaths: compiler.immutablePaths,
|
855
|
-
logger: this.getLogger("webpack.FileSystemInfo")
|
856
|
+
logger: this.getLogger("webpack.FileSystemInfo"),
|
857
|
+
hashFunction: compiler.options.output.hashFunction
|
856
858
|
});
|
857
859
|
if (compiler.fileTimestamps) {
|
858
860
|
this.fileSystemInfo.addFileTimestamps(compiler.fileTimestamps, true);
|
@@ -891,6 +893,10 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|
891
893
|
};
|
892
894
|
defineRemovedModuleTemplates(this.moduleTemplates);
|
893
895
|
|
896
|
+
/** @type {MemCache | undefined} */
|
897
|
+
this.memCache = undefined;
|
898
|
+
/** @type {WeakMap<Module, MemCache> | undefined} */
|
899
|
+
this.moduleMemCaches = undefined;
|
894
900
|
this.moduleGraph = new ModuleGraph();
|
895
901
|
/** @type {ChunkGraph} */
|
896
902
|
this.chunkGraph = undefined;
|
@@ -2011,6 +2017,79 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|
2011
2017
|
});
|
2012
2018
|
}
|
2013
2019
|
|
2020
|
+
_computeAffectedModules(modules) {
|
2021
|
+
const moduleMemCacheCache = this.compiler.moduleMemCaches;
|
2022
|
+
if (!moduleMemCacheCache) return;
|
2023
|
+
if (!this.moduleMemCaches) this.moduleMemCaches = new WeakMap();
|
2024
|
+
if (!this.memCache) this.memCache = new MemCache();
|
2025
|
+
const { moduleGraph, memCache, moduleMemCaches } = this;
|
2026
|
+
const affectedModules = new Set();
|
2027
|
+
const infectedModules = new Set();
|
2028
|
+
let statNew = 0;
|
2029
|
+
let statChanged = 0;
|
2030
|
+
let statUnchanged = 0;
|
2031
|
+
let statWithoutHash = 0;
|
2032
|
+
for (const module of modules) {
|
2033
|
+
const hash = module.buildInfo && module.buildInfo.hash;
|
2034
|
+
if (typeof hash === "string") {
|
2035
|
+
const cachedMemCache = moduleMemCacheCache.get(module);
|
2036
|
+
if (cachedMemCache === undefined) {
|
2037
|
+
// create a new entry
|
2038
|
+
moduleMemCacheCache.set(module, {
|
2039
|
+
hash: hash,
|
2040
|
+
memCache
|
2041
|
+
});
|
2042
|
+
moduleMemCaches.set(module, memCache);
|
2043
|
+
affectedModules.add(module);
|
2044
|
+
statNew++;
|
2045
|
+
} else if (cachedMemCache.hash === hash) {
|
2046
|
+
// keep the old mem cache
|
2047
|
+
moduleMemCaches.set(module, cachedMemCache.memCache);
|
2048
|
+
statUnchanged++;
|
2049
|
+
} else {
|
2050
|
+
// use a new one
|
2051
|
+
moduleMemCaches.set(module, memCache);
|
2052
|
+
affectedModules.add(module);
|
2053
|
+
cachedMemCache.hash = hash;
|
2054
|
+
cachedMemCache.memCache = memCache;
|
2055
|
+
statChanged++;
|
2056
|
+
}
|
2057
|
+
} else {
|
2058
|
+
infectedModules.add(module);
|
2059
|
+
statWithoutHash++;
|
2060
|
+
}
|
2061
|
+
}
|
2062
|
+
for (const module of infectedModules) {
|
2063
|
+
for (const referencingModule of moduleGraph
|
2064
|
+
.getIncomingConnectionsByOriginModule(module)
|
2065
|
+
.keys()) {
|
2066
|
+
if (infectedModules.has(referencingModule)) continue;
|
2067
|
+
infectedModules.add(referencingModule);
|
2068
|
+
}
|
2069
|
+
}
|
2070
|
+
for (const module of affectedModules) {
|
2071
|
+
for (const referencingModule of moduleGraph
|
2072
|
+
.getIncomingConnectionsByOriginModule(module)
|
2073
|
+
.keys()) {
|
2074
|
+
if (!referencingModule) continue;
|
2075
|
+
if (infectedModules.has(referencingModule)) continue;
|
2076
|
+
if (affectedModules.has(referencingModule)) continue;
|
2077
|
+
affectedModules.add(referencingModule);
|
2078
|
+
moduleMemCaches.set(referencingModule, memCache);
|
2079
|
+
}
|
2080
|
+
}
|
2081
|
+
this.logger.log(
|
2082
|
+
`${Math.round(
|
2083
|
+
(100 * (affectedModules.size + infectedModules.size)) /
|
2084
|
+
this.modules.size
|
2085
|
+
)}% (${affectedModules.size} affected + ${
|
2086
|
+
infectedModules.size
|
2087
|
+
} infected of ${
|
2088
|
+
this.modules.size
|
2089
|
+
}) modules flagged as affected (${statNew} new modules, ${statChanged} changed, ${statUnchanged} unchanged, ${statWithoutHash} without hash)`
|
2090
|
+
);
|
2091
|
+
}
|
2092
|
+
|
2014
2093
|
finish(callback) {
|
2015
2094
|
this.factorizeQueue.clear();
|
2016
2095
|
if (this.profile) {
|
@@ -2191,17 +2270,29 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|
2191
2270
|
);
|
2192
2271
|
this.logger.timeEnd("finish module profiles");
|
2193
2272
|
}
|
2273
|
+
this.logger.time("compute affected modules");
|
2274
|
+
this._computeAffectedModules(this.modules);
|
2275
|
+
this.logger.timeEnd("compute affected modules");
|
2194
2276
|
this.logger.time("finish modules");
|
2195
|
-
const { modules } = this;
|
2277
|
+
const { modules, moduleMemCaches } = this;
|
2196
2278
|
this.hooks.finishModules.callAsync(modules, err => {
|
2197
2279
|
this.logger.timeEnd("finish modules");
|
2198
2280
|
if (err) return callback(err);
|
2199
2281
|
|
2200
2282
|
// extract warnings and errors from modules
|
2201
|
-
this.logger.time("report dependency errors and warnings");
|
2202
2283
|
this.moduleGraph.freeze();
|
2284
|
+
// TODO keep a cacheToken (= {}) for each module in the graph
|
2285
|
+
// create a new one per compilation and flag all updated files
|
2286
|
+
// and parents with it
|
2287
|
+
this.logger.time("report dependency errors and warnings");
|
2203
2288
|
for (const module of modules) {
|
2204
|
-
|
2289
|
+
// TODO only run for modules with changed cacheToken
|
2290
|
+
// global WeakMap<CacheToken, WeakSet<Module>> to keep modules without errors/warnings
|
2291
|
+
const memCache = moduleMemCaches && moduleMemCaches.get(module);
|
2292
|
+
if (memCache && memCache.get(module, "noWarningsOrErrors")) continue;
|
2293
|
+
let hasProblems = this.reportDependencyErrorsAndWarnings(module, [
|
2294
|
+
module
|
2295
|
+
]);
|
2205
2296
|
const errors = module.getErrors();
|
2206
2297
|
if (errors !== undefined) {
|
2207
2298
|
for (const error of errors) {
|
@@ -2209,6 +2300,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|
2209
2300
|
error.module = module;
|
2210
2301
|
}
|
2211
2302
|
this.errors.push(error);
|
2303
|
+
hasProblems = true;
|
2212
2304
|
}
|
2213
2305
|
}
|
2214
2306
|
const warnings = module.getWarnings();
|
@@ -2218,8 +2310,11 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|
2218
2310
|
warning.module = module;
|
2219
2311
|
}
|
2220
2312
|
this.warnings.push(warning);
|
2313
|
+
hasProblems = true;
|
2221
2314
|
}
|
2222
2315
|
}
|
2316
|
+
if (!hasProblems && memCache)
|
2317
|
+
memCache.set(module, "noWarningsOrErrors", true);
|
2223
2318
|
}
|
2224
2319
|
this.moduleGraph.unfreeze();
|
2225
2320
|
this.logger.timeEnd("report dependency errors and warnings");
|
@@ -2255,7 +2350,10 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
|
|
2255
2350
|
this.addModuleQueue.clear();
|
2256
2351
|
return callback(err);
|
2257
2352
|
};
|
2258
|
-
const chunkGraph = new ChunkGraph(
|
2353
|
+
const chunkGraph = new ChunkGraph(
|
2354
|
+
this.moduleGraph,
|
2355
|
+
this.outputOptions.hashFunction
|
2356
|
+
);
|
2259
2357
|
this.chunkGraph = chunkGraph;
|
2260
2358
|
|
2261
2359
|
for (const module of this.modules) {
|
@@ -2573,9 +2671,10 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
|
|
2573
2671
|
/**
|
2574
2672
|
* @param {Module} module module to report from
|
2575
2673
|
* @param {DependenciesBlock[]} blocks blocks to report from
|
2576
|
-
* @returns {
|
2674
|
+
* @returns {boolean} true, when it has warnings or errors
|
2577
2675
|
*/
|
2578
2676
|
reportDependencyErrorsAndWarnings(module, blocks) {
|
2677
|
+
let hasProblems = false;
|
2579
2678
|
for (let indexBlock = 0; indexBlock < blocks.length; indexBlock++) {
|
2580
2679
|
const block = blocks[indexBlock];
|
2581
2680
|
const dependencies = block.dependencies;
|
@@ -2590,6 +2689,7 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
|
|
2590
2689
|
|
2591
2690
|
const warning = new ModuleDependencyWarning(module, w, d.loc);
|
2592
2691
|
this.warnings.push(warning);
|
2692
|
+
hasProblems = true;
|
2593
2693
|
}
|
2594
2694
|
}
|
2595
2695
|
const errors = d.getErrors(this.moduleGraph);
|
@@ -2599,17 +2699,22 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
|
|
2599
2699
|
|
2600
2700
|
const error = new ModuleDependencyError(module, e, d.loc);
|
2601
2701
|
this.errors.push(error);
|
2702
|
+
hasProblems = true;
|
2602
2703
|
}
|
2603
2704
|
}
|
2604
2705
|
}
|
2605
2706
|
|
2606
|
-
this.reportDependencyErrorsAndWarnings(module, block.blocks)
|
2707
|
+
if (this.reportDependencyErrorsAndWarnings(module, block.blocks))
|
2708
|
+
hasProblems = true;
|
2607
2709
|
}
|
2710
|
+
return hasProblems;
|
2608
2711
|
}
|
2609
2712
|
|
2610
2713
|
codeGeneration(callback) {
|
2611
2714
|
const { chunkGraph } = this;
|
2612
|
-
this.codeGenerationResults = new CodeGenerationResults(
|
2715
|
+
this.codeGenerationResults = new CodeGenerationResults(
|
2716
|
+
this.outputOptions.hashFunction
|
2717
|
+
);
|
2613
2718
|
/** @type {{module: Module, hash: string, runtime: RuntimeSpec, runtimes: RuntimeSpec[]}[]} */
|
2614
2719
|
const jobs = [];
|
2615
2720
|
for (const module of this.modules) {
|
@@ -2790,12 +2895,41 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
|
|
2790
2895
|
chunkGraphEntries = this._getChunkGraphEntries()
|
2791
2896
|
} = {}) {
|
2792
2897
|
const context = { chunkGraph, codeGenerationResults };
|
2898
|
+
const { moduleMemCaches } = this;
|
2899
|
+
this.logger.time("runtime requirements.modules");
|
2793
2900
|
const additionalModuleRuntimeRequirements =
|
2794
2901
|
this.hooks.additionalModuleRuntimeRequirements;
|
2795
2902
|
const runtimeRequirementInModule = this.hooks.runtimeRequirementInModule;
|
2796
2903
|
for (const module of modules) {
|
2797
2904
|
if (chunkGraph.getNumberOfModuleChunks(module) > 0) {
|
2905
|
+
const memCache =
|
2906
|
+
moduleMemCaches &&
|
2907
|
+
// modules with async blocks depend on the chunk graph and can't be cached that way
|
2908
|
+
module.blocks.length === 0 &&
|
2909
|
+
moduleMemCaches.get(module);
|
2910
|
+
/** @type {RuntimeSpecMap<Set<string>>} */
|
2911
|
+
const moduleRuntimeRequirementsMemCache =
|
2912
|
+
memCache &&
|
2913
|
+
memCache.provide(
|
2914
|
+
module,
|
2915
|
+
"moduleRuntimeRequirements",
|
2916
|
+
() => new RuntimeSpecMap()
|
2917
|
+
);
|
2798
2918
|
for (const runtime of chunkGraph.getModuleRuntimes(module)) {
|
2919
|
+
if (moduleRuntimeRequirementsMemCache) {
|
2920
|
+
const cached = moduleRuntimeRequirementsMemCache.get(runtime);
|
2921
|
+
if (cached !== undefined) {
|
2922
|
+
if (cached !== null) {
|
2923
|
+
chunkGraph.addModuleRuntimeRequirements(
|
2924
|
+
module,
|
2925
|
+
runtime,
|
2926
|
+
cached,
|
2927
|
+
false
|
2928
|
+
);
|
2929
|
+
}
|
2930
|
+
continue;
|
2931
|
+
}
|
2932
|
+
}
|
2799
2933
|
let set;
|
2800
2934
|
const runtimeRequirements =
|
2801
2935
|
codeGenerationResults.getRuntimeRequirements(module, runtime);
|
@@ -2804,6 +2938,9 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
|
|
2804
2938
|
} else if (additionalModuleRuntimeRequirements.isUsed()) {
|
2805
2939
|
set = new Set();
|
2806
2940
|
} else {
|
2941
|
+
if (moduleRuntimeRequirementsMemCache) {
|
2942
|
+
moduleRuntimeRequirementsMemCache.set(runtime, null);
|
2943
|
+
}
|
2807
2944
|
continue;
|
2808
2945
|
}
|
2809
2946
|
additionalModuleRuntimeRequirements.call(module, set, context);
|
@@ -2812,11 +2949,29 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
|
|
2812
2949
|
const hook = runtimeRequirementInModule.get(r);
|
2813
2950
|
if (hook !== undefined) hook.call(module, set, context);
|
2814
2951
|
}
|
2815
|
-
|
2952
|
+
if (set.size === 0) {
|
2953
|
+
if (moduleRuntimeRequirementsMemCache) {
|
2954
|
+
moduleRuntimeRequirementsMemCache.set(runtime, null);
|
2955
|
+
}
|
2956
|
+
} else {
|
2957
|
+
if (moduleRuntimeRequirementsMemCache) {
|
2958
|
+
moduleRuntimeRequirementsMemCache.set(runtime, set);
|
2959
|
+
chunkGraph.addModuleRuntimeRequirements(
|
2960
|
+
module,
|
2961
|
+
runtime,
|
2962
|
+
set,
|
2963
|
+
false
|
2964
|
+
);
|
2965
|
+
} else {
|
2966
|
+
chunkGraph.addModuleRuntimeRequirements(module, runtime, set);
|
2967
|
+
}
|
2968
|
+
}
|
2816
2969
|
}
|
2817
2970
|
}
|
2818
2971
|
}
|
2972
|
+
this.logger.timeEnd("runtime requirements.modules");
|
2819
2973
|
|
2974
|
+
this.logger.time("runtime requirements.chunks");
|
2820
2975
|
for (const chunk of chunks) {
|
2821
2976
|
const set = new Set();
|
2822
2977
|
for (const module of chunkGraph.getChunkModulesIterable(chunk)) {
|
@@ -2834,7 +2989,9 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
|
|
2834
2989
|
|
2835
2990
|
chunkGraph.addChunkRuntimeRequirements(chunk, set);
|
2836
2991
|
}
|
2992
|
+
this.logger.timeEnd("runtime requirements.chunks");
|
2837
2993
|
|
2994
|
+
this.logger.time("runtime requirements.entries");
|
2838
2995
|
for (const treeEntry of chunkGraphEntries) {
|
2839
2996
|
const set = new Set();
|
2840
2997
|
for (const chunk of treeEntry.getAllReferencedChunks()) {
|
@@ -2857,6 +3014,7 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
|
|
2857
3014
|
|
2858
3015
|
chunkGraph.addTreeRuntimeRequirements(treeEntry, set);
|
2859
3016
|
}
|
3017
|
+
this.logger.timeEnd("runtime requirements.entries");
|
2860
3018
|
}
|
2861
3019
|
|
2862
3020
|
// TODO webpack 6 make chunkGraph argument non-optional
|
@@ -3201,12 +3359,35 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
|
|
3201
3359
|
|
3202
3360
|
createModuleHashes() {
|
3203
3361
|
let statModulesHashed = 0;
|
3204
|
-
|
3362
|
+
let statModulesFromCache = 0;
|
3363
|
+
const { chunkGraph, runtimeTemplate, moduleMemCaches } = this;
|
3205
3364
|
const { hashFunction, hashDigest, hashDigestLength } = this.outputOptions;
|
3206
3365
|
for (const module of this.modules) {
|
3366
|
+
const memCache =
|
3367
|
+
moduleMemCaches &&
|
3368
|
+
// modules with async blocks depend on the chunk graph and can't be cached that way
|
3369
|
+
module.blocks.length === 0 &&
|
3370
|
+
moduleMemCaches.get(module);
|
3371
|
+
/** @type {RuntimeSpecMap<string>} */
|
3372
|
+
const moduleHashesMemCache =
|
3373
|
+
memCache &&
|
3374
|
+
memCache.provide(module, "moduleHashes", () => new RuntimeSpecMap());
|
3207
3375
|
for (const runtime of chunkGraph.getModuleRuntimes(module)) {
|
3376
|
+
if (moduleHashesMemCache) {
|
3377
|
+
const digest = moduleHashesMemCache.get(runtime);
|
3378
|
+
if (digest !== undefined) {
|
3379
|
+
chunkGraph.setModuleHashes(
|
3380
|
+
module,
|
3381
|
+
runtime,
|
3382
|
+
digest,
|
3383
|
+
digest.substr(0, hashDigestLength)
|
3384
|
+
);
|
3385
|
+
statModulesFromCache++;
|
3386
|
+
continue;
|
3387
|
+
}
|
3388
|
+
}
|
3208
3389
|
statModulesHashed++;
|
3209
|
-
this._createModuleHash(
|
3390
|
+
const digest = this._createModuleHash(
|
3210
3391
|
module,
|
3211
3392
|
chunkGraph,
|
3212
3393
|
runtime,
|
@@ -3215,11 +3396,16 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
|
|
3215
3396
|
hashDigest,
|
3216
3397
|
hashDigestLength
|
3217
3398
|
);
|
3399
|
+
if (moduleHashesMemCache) {
|
3400
|
+
moduleHashesMemCache.set(runtime, digest);
|
3401
|
+
}
|
3218
3402
|
}
|
3219
3403
|
}
|
3220
3404
|
this.logger.log(
|
3221
|
-
`${statModulesHashed} modules hashed (${
|
3222
|
-
Math.round(
|
3405
|
+
`${statModulesHashed} modules hashed, ${statModulesFromCache} from cache (${
|
3406
|
+
Math.round(
|
3407
|
+
(100 * (statModulesHashed + statModulesFromCache)) / this.modules.size
|
3408
|
+
) / 100
|
3223
3409
|
} variants per module in average)`
|
3224
3410
|
);
|
3225
3411
|
}
|
@@ -4071,7 +4257,10 @@ This prevents using hashes of each other and should be avoided.`);
|
|
4071
4257
|
if (err) return callback(err);
|
4072
4258
|
|
4073
4259
|
// Create new chunk graph, chunk and entrypoint for the build time execution
|
4074
|
-
const chunkGraph = new ChunkGraph(
|
4260
|
+
const chunkGraph = new ChunkGraph(
|
4261
|
+
this.moduleGraph,
|
4262
|
+
this.outputOptions.hashFunction
|
4263
|
+
);
|
4075
4264
|
const runtime = "build time";
|
4076
4265
|
const { hashFunction, hashDigest, hashDigestLength } =
|
4077
4266
|
this.outputOptions;
|
@@ -4114,7 +4303,9 @@ This prevents using hashes of each other and should be avoided.`);
|
|
4114
4303
|
);
|
4115
4304
|
}
|
4116
4305
|
|
4117
|
-
const codeGenerationResults = new CodeGenerationResults(
|
4306
|
+
const codeGenerationResults = new CodeGenerationResults(
|
4307
|
+
this.outputOptions.hashFunction
|
4308
|
+
);
|
4118
4309
|
/** @type {WebpackError[]} */
|
4119
4310
|
const errors = [];
|
4120
4311
|
/**
|
package/lib/Compiler.js
CHANGED
@@ -41,6 +41,7 @@ const { isSourceEqual } = require("./util/source");
|
|
41
41
|
/** @typedef {import("../declarations/WebpackOptions").WebpackPluginInstance} WebpackPluginInstance */
|
42
42
|
/** @typedef {import("./Chunk")} Chunk */
|
43
43
|
/** @typedef {import("./FileSystemInfo").FileSystemInfoEntry} FileSystemInfoEntry */
|
44
|
+
/** @typedef {import("./MemCache")} MemCache */
|
44
45
|
/** @typedef {import("./Module")} Module */
|
45
46
|
/** @typedef {import("./util/fs").InputFileSystem} InputFileSystem */
|
46
47
|
/** @typedef {import("./util/fs").IntermediateFileSystem} IntermediateFileSystem */
|
@@ -247,6 +248,9 @@ class Compiler {
|
|
247
248
|
|
248
249
|
this.cache = new Cache();
|
249
250
|
|
251
|
+
/** @type {WeakMap<Module, { hash: string, memCache: MemCache }> | undefined} */
|
252
|
+
this.moduleMemCaches = undefined;
|
253
|
+
|
250
254
|
this.compilerPath = "";
|
251
255
|
|
252
256
|
/** @type {boolean} */
|
@@ -276,7 +280,11 @@ class Compiler {
|
|
276
280
|
* @returns {CacheFacade} the cache facade instance
|
277
281
|
*/
|
278
282
|
getCache(name) {
|
279
|
-
return new CacheFacade(
|
283
|
+
return new CacheFacade(
|
284
|
+
this.cache,
|
285
|
+
`${this.compilerPath}${name}`,
|
286
|
+
this.options.output.hashFunction
|
287
|
+
);
|
280
288
|
}
|
281
289
|
|
282
290
|
/**
|
@@ -9,14 +9,20 @@ const createHash = require("./util/createHash");
|
|
9
9
|
|
10
10
|
/** @typedef {import("./Dependency")} Dependency */
|
11
11
|
/** @typedef {import("./DependencyTemplate")} DependencyTemplate */
|
12
|
+
/** @typedef {typeof import("./util/Hash")} Hash */
|
13
|
+
|
12
14
|
/** @typedef {new (...args: any[]) => Dependency} DependencyConstructor */
|
13
15
|
|
14
16
|
class DependencyTemplates {
|
15
|
-
|
17
|
+
/**
|
18
|
+
* @param {string | Hash} hashFunction the hash function to use
|
19
|
+
*/
|
20
|
+
constructor(hashFunction = "md4") {
|
16
21
|
/** @type {Map<Function, DependencyTemplate>} */
|
17
22
|
this._map = new Map();
|
18
23
|
/** @type {string} */
|
19
24
|
this._hash = "31d6cfe0d16ae931b73c59d7e0c089c0";
|
25
|
+
this._hashFunction = hashFunction;
|
20
26
|
}
|
21
27
|
|
22
28
|
/**
|
@@ -41,7 +47,7 @@ class DependencyTemplates {
|
|
41
47
|
* @returns {void}
|
42
48
|
*/
|
43
49
|
updateHash(part) {
|
44
|
-
const hash = createHash(
|
50
|
+
const hash = createHash(this._hashFunction);
|
45
51
|
hash.update(this._hash);
|
46
52
|
hash.update(part);
|
47
53
|
this._hash = /** @type {string} */ (hash.digest("hex"));
|