Skip to content

Commit 0c3fab6

Browse files
authored
Merge pull request #14358 from webpack/bugfix/shared-cache
2 parents 5db3085 + 61569e2 commit 0c3fab6

File tree

3 files changed

+80
-37
lines changed

3 files changed

+80
-37
lines changed

lib/Compilation.js

+73-35
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,7 @@ const {
7878
createFakeHook
7979
} = require("./util/deprecation");
8080
const processAsyncTree = require("./util/processAsyncTree");
81-
const { getRuntimeKey, RuntimeSpecMap } = require("./util/runtime");
81+
const { getRuntimeKey } = require("./util/runtime");
8282
const { isSourceEqual } = require("./util/source");
8383

8484
/** @template T @typedef {import("tapable").AsArray<T>} AsArray<T> */
@@ -2178,7 +2178,39 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
21782178
let statNew = 0;
21792179
let statChanged = 0;
21802180
let statUnchanged = 0;
2181+
let statReferencesChanged = 0;
21812182
let statWithoutHash = 0;
2183+
2184+
const computeReferences = module => {
2185+
/** @type {WeakMap<Dependency, Module>} */
2186+
let references = undefined;
2187+
for (const connection of moduleGraph.getOutgoingConnections(module)) {
2188+
const d = connection.dependency;
2189+
const m = connection.module;
2190+
if (!d || !m || unsafeCacheDependencies.has(d)) continue;
2191+
if (references === undefined) references = new WeakMap();
2192+
references.set(d, m);
2193+
}
2194+
return references;
2195+
};
2196+
2197+
/**
2198+
* @param {Module} module the module
2199+
* @param {WeakMap<Dependency, Module>} references references
2200+
* @returns {boolean} true, when the references differ
2201+
*/
2202+
const compareReferences = (module, references) => {
2203+
if (references === undefined) return true;
2204+
for (const connection of moduleGraph.getOutgoingConnections(module)) {
2205+
const d = connection.dependency;
2206+
if (!d) continue;
2207+
const entry = references.get(d);
2208+
if (entry === undefined) continue;
2209+
if (entry !== connection.module) return false;
2210+
}
2211+
return true;
2212+
};
2213+
21822214
for (const module of modules) {
21832215
const hash = module.buildInfo && module.buildInfo.hash;
21842216
if (typeof hash === "string") {
@@ -2188,27 +2220,33 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
21882220
const memCache = new WeakTupleMap();
21892221
moduleMemCacheCache.set(module, {
21902222
hash: hash,
2223+
references: computeReferences(module),
21912224
memCache
21922225
});
21932226
moduleMemCaches.set(module, memCache);
21942227
affectedModules.add(module);
21952228
statNew++;
2196-
} else if (cachedMemCache.hash === hash) {
2197-
// keep the old mem cache
2198-
moduleMemCaches.set(module, cachedMemCache.memCache);
2199-
statUnchanged++;
2200-
} else {
2229+
} else if (cachedMemCache.hash !== hash) {
22012230
// use a new one
22022231
const memCache = new WeakTupleMap();
2203-
moduleMemCacheCache.set(module, {
2204-
hash: hash,
2205-
memCache
2206-
});
22072232
moduleMemCaches.set(module, memCache);
22082233
affectedModules.add(module);
22092234
cachedMemCache.hash = hash;
2235+
cachedMemCache.references = computeReferences(module);
22102236
cachedMemCache.memCache = memCache;
22112237
statChanged++;
2238+
} else if (!compareReferences(module, cachedMemCache.references)) {
2239+
// use a new one
2240+
const memCache = new WeakTupleMap();
2241+
moduleMemCaches.set(module, memCache);
2242+
affectedModules.add(module);
2243+
cachedMemCache.references = computeReferences(module);
2244+
cachedMemCache.memCache = memCache;
2245+
statReferencesChanged++;
2246+
} else {
2247+
// keep the old mem cache
2248+
moduleMemCaches.set(module, cachedMemCache.memCache);
2249+
statUnchanged++;
22122250
}
22132251
} else {
22142252
infectedModules.add(module);
@@ -2261,7 +2299,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
22612299
affectedModules.add(referencingModule);
22622300
}
22632301
const memCache = new WeakTupleMap();
2264-
const cache = moduleMemCacheCache.get(module);
2302+
const cache = moduleMemCacheCache.get(referencingModule);
22652303
cache.memCache = memCache;
22662304
moduleMemCaches.set(referencingModule, memCache);
22672305
}
@@ -2275,7 +2313,7 @@ BREAKING CHANGE: Asset processing hooks in Compilation has been merged into a si
22752313
infectedModules.size
22762314
} infected of ${
22772315
this.modules.size
2278-
}) modules flagged as affected (${statNew} new modules, ${statChanged} changed, ${statUnchanged} unchanged, ${statWithoutHash} without hash)`
2316+
}) modules flagged as affected (${statNew} new modules, ${statChanged} changed, ${statReferencesChanged} references changed, ${statUnchanged} unchanged, ${statWithoutHash} without hash)`
22792317
);
22802318
}
22812319

@@ -3095,16 +3133,11 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
30953133
// modules with async blocks depend on the chunk graph and can't be cached that way
30963134
module.blocks.length === 0 &&
30973135
moduleMemCaches.get(module);
3098-
/** @type {RuntimeSpecMap<Set<string>>} */
3099-
const moduleRuntimeRequirementsMemCache =
3100-
memCache &&
3101-
memCache.provide(
3102-
"moduleRuntimeRequirements",
3103-
() => new RuntimeSpecMap()
3104-
);
31053136
for (const runtime of chunkGraph.getModuleRuntimes(module)) {
3106-
if (moduleRuntimeRequirementsMemCache) {
3107-
const cached = moduleRuntimeRequirementsMemCache.get(runtime);
3137+
if (memCache) {
3138+
const cached = memCache.get(
3139+
`moduleRuntimeRequirements-${getRuntimeKey(runtime)}`
3140+
);
31083141
if (cached !== undefined) {
31093142
if (cached !== null) {
31103143
chunkGraph.addModuleRuntimeRequirements(
@@ -3125,8 +3158,11 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
31253158
} else if (additionalModuleRuntimeRequirements.isUsed()) {
31263159
set = new Set();
31273160
} else {
3128-
if (moduleRuntimeRequirementsMemCache) {
3129-
moduleRuntimeRequirementsMemCache.set(runtime, null);
3161+
if (memCache) {
3162+
memCache.set(
3163+
`moduleRuntimeRequirements-${getRuntimeKey(runtime)}`,
3164+
null
3165+
);
31303166
}
31313167
continue;
31323168
}
@@ -3137,12 +3173,18 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
31373173
if (hook !== undefined) hook.call(module, set, context);
31383174
}
31393175
if (set.size === 0) {
3140-
if (moduleRuntimeRequirementsMemCache) {
3141-
moduleRuntimeRequirementsMemCache.set(runtime, null);
3176+
if (memCache) {
3177+
memCache.set(
3178+
`moduleRuntimeRequirements-${getRuntimeKey(runtime)}`,
3179+
null
3180+
);
31423181
}
31433182
} else {
3144-
if (moduleRuntimeRequirementsMemCache) {
3145-
moduleRuntimeRequirementsMemCache.set(runtime, set);
3183+
if (memCache) {
3184+
memCache.set(
3185+
`moduleRuntimeRequirements-${getRuntimeKey(runtime)}`,
3186+
set
3187+
);
31463188
chunkGraph.addModuleRuntimeRequirements(
31473189
module,
31483190
runtime,
@@ -3555,13 +3597,9 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
35553597
// modules with async blocks depend on the chunk graph and can't be cached that way
35563598
module.blocks.length === 0 &&
35573599
moduleMemCaches.get(module);
3558-
/** @type {RuntimeSpecMap<string>} */
3559-
const moduleHashesMemCache =
3560-
memCache &&
3561-
memCache.provide("moduleHashes", () => new RuntimeSpecMap());
35623600
for (const runtime of chunkGraph.getModuleRuntimes(module)) {
3563-
if (moduleHashesMemCache) {
3564-
const digest = moduleHashesMemCache.get(runtime);
3601+
if (memCache) {
3602+
const digest = memCache.get(`moduleHash-${getRuntimeKey(runtime)}`);
35653603
if (digest !== undefined) {
35663604
chunkGraph.setModuleHashes(
35673605
module,
@@ -3583,8 +3621,8 @@ Or do you want to use the entrypoints '${name}' and '${runtime}' independently o
35833621
hashDigest,
35843622
hashDigestLength
35853623
);
3586-
if (moduleHashesMemCache) {
3587-
moduleHashesMemCache.set(runtime, digest);
3624+
if (memCache) {
3625+
memCache.set(`moduleHash-${getRuntimeKey(runtime)}`, digest);
35883626
}
35893627
}
35903628
}

lib/Compiler.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ const { isSourceEqual } = require("./util/source");
4040
/** @typedef {import("../declarations/WebpackOptions").WebpackOptionsNormalized} WebpackOptions */
4141
/** @typedef {import("../declarations/WebpackOptions").WebpackPluginInstance} WebpackPluginInstance */
4242
/** @typedef {import("./Chunk")} Chunk */
43+
/** @typedef {import("./Dependency")} Dependency */
4344
/** @typedef {import("./FileSystemInfo").FileSystemInfoEntry} FileSystemInfoEntry */
4445
/** @typedef {import("./Module")} Module */
4546
/** @typedef {import("./util/WeakTupleMap")} WeakTupleMap */
@@ -248,7 +249,7 @@ class Compiler {
248249

249250
this.cache = new Cache();
250251

251-
/** @type {WeakMap<Module, { hash: string, memCache: WeakTupleMap }> | undefined} */
252+
/** @type {WeakMap<Module, { hash: string, references: WeakMap<Dependency, Module>, memCache: WeakTupleMap }> | undefined} */
252253
this.moduleMemCaches = undefined;
253254

254255
this.compilerPath = "";

types.d.ts

+5-1
Original file line numberDiff line numberDiff line change
@@ -1909,7 +1909,11 @@ declare class Compiler {
19091909
cache: Cache;
19101910
moduleMemCaches?: WeakMap<
19111911
Module,
1912-
{ hash: string; memCache: WeakTupleMap<any, any> }
1912+
{
1913+
hash: string;
1914+
references: WeakMap<Dependency, Module>;
1915+
memCache: WeakTupleMap<any, any>;
1916+
}
19131917
>;
19141918
compilerPath: string;
19151919
running: boolean;

0 commit comments

Comments
 (0)