Skip to content

Commit 22ac3b3

Browse files
clydinjosephperrott
authored andcommitted
perf(@ngtools/webpack): cache results of processed inline resources
When in watch mode, both the file and inline resources will now be cached between rebuilds. This removes the need to reprocess inline resources that have not changed even if the containing TypeScript file has changed. (cherry picked from commit 8dfc8e7)
1 parent deea056 commit 22ac3b3

File tree

2 files changed

+32
-9
lines changed

2 files changed

+32
-9
lines changed

packages/ngtools/webpack/src/ivy/plugin.ts

+7-2
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ export class AngularWebpackPlugin {
150150
});
151151

152152
let ngccProcessor: NgccProcessor | undefined;
153-
const resourceLoader = new WebpackResourceLoader();
153+
let resourceLoader: WebpackResourceLoader | undefined;
154154
let previousUnused: Set<string> | undefined;
155155
compiler.hooks.thisCompilation.tap(PLUGIN_NAME, (thisCompilation) => {
156156
const compilation = thisCompilation as WebpackCompilation;
@@ -164,6 +164,11 @@ export class AngularWebpackPlugin {
164164
// Store watch mode; assume true if not present (webpack < 4.23.0)
165165
this.watchMode = compiler.watchMode ?? true;
166166

167+
// Initialize the resource loader if not already setup
168+
if (!resourceLoader) {
169+
resourceLoader = new WebpackResourceLoader(this.watchMode);
170+
}
171+
167172
// Initialize and process eager ngcc if not already setup
168173
if (!ngccProcessor) {
169174
const { processor, errors, warnings } = initializeNgccProcessor(
@@ -266,7 +271,7 @@ export class AngularWebpackPlugin {
266271
await this.rebuildRequiredFiles(modules, compilation, fileEmitter);
267272

268273
// Clear out the Webpack compilation to avoid an extra retaining reference
269-
resourceLoader.clearParentCompilation();
274+
resourceLoader?.clearParentCompilation();
270275

271276
// Analyze program for unused files
272277
if (compilation.errors.length > 0) {

packages/ngtools/webpack/src/resource_loader.ts

+25-7
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
* Use of this source code is governed by an MIT-style license that can be
66
* found in the LICENSE file at https://angular.io/license
77
*/
8+
import { createHash } from 'crypto';
89
import * as vm from 'vm';
910
import { Compilation, EntryPlugin, NormalModule, library, node, sources } from 'webpack';
1011
import { normalizePath } from './ivy/paths';
@@ -20,10 +21,18 @@ export class WebpackResourceLoader {
2021
private _fileDependencies = new Map<string, Set<string>>();
2122
private _reverseDependencies = new Map<string, Set<string>>();
2223

23-
private cache = new Map<string, CompilationOutput>();
24+
private fileCache?: Map<string, CompilationOutput>;
25+
private inlineCache?: Map<string, CompilationOutput>;
2426
private modifiedResources = new Set<string>();
2527
private outputPathCounter = 1;
2628

29+
constructor(shouldCache: boolean) {
30+
if (shouldCache) {
31+
this.fileCache = new Map();
32+
this.inlineCache = new Map();
33+
}
34+
}
35+
2736
update(
2837
parentCompilation: Compilation,
2938
changedFiles?: Iterable<string>,
@@ -35,12 +44,12 @@ export class WebpackResourceLoader {
3544
if (changedFiles) {
3645
for (const changedFile of changedFiles) {
3746
for (const affectedResource of this.getAffectedResources(changedFile)) {
38-
this.cache.delete(normalizePath(affectedResource));
47+
this.fileCache?.delete(normalizePath(affectedResource));
3948
this.modifiedResources.add(affectedResource);
4049
}
4150
}
4251
} else {
43-
this.cache.clear();
52+
this.fileCache?.clear();
4453
}
4554
}
4655

@@ -236,15 +245,15 @@ export class WebpackResourceLoader {
236245

237246
async get(filePath: string): Promise<string> {
238247
const normalizedFile = normalizePath(filePath);
239-
let compilationResult = this.cache.get(normalizedFile);
248+
let compilationResult = this.fileCache?.get(normalizedFile);
240249

241250
if (compilationResult === undefined) {
242251
// cache miss so compile resource
243252
compilationResult = await this._compile(filePath);
244253

245254
// Only cache if compilation was successful
246-
if (compilationResult.success) {
247-
this.cache.set(normalizedFile, compilationResult);
255+
if (this.fileCache && compilationResult.success) {
256+
this.fileCache.set(normalizedFile, compilationResult);
248257
}
249258
}
250259

@@ -256,7 +265,16 @@ export class WebpackResourceLoader {
256265
return '';
257266
}
258267

259-
const compilationResult = await this._compile(undefined, data, mimeType);
268+
const cacheKey = createHash('md5').update(data).digest('hex');
269+
let compilationResult = this.inlineCache?.get(cacheKey);
270+
271+
if (compilationResult === undefined) {
272+
compilationResult = await this._compile(undefined, data, mimeType);
273+
274+
if (this.inlineCache && compilationResult.success) {
275+
this.inlineCache.set(cacheKey, compilationResult);
276+
}
277+
}
260278

261279
return compilationResult.content;
262280
}

0 commit comments

Comments
 (0)