Skip to content

Commit b6ff520

Browse files
clydinKeen Yee Liau
authored andcommitted
refactor(@ngtools/webpack): avoid double caching of files
1 parent d29701f commit b6ff520

File tree

4 files changed

+160
-307
lines changed

4 files changed

+160
-307
lines changed

packages/ngtools/webpack/src/angular_compiler_plugin.ts

Lines changed: 48 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -314,6 +314,10 @@ export class AngularCompilerPlugin {
314314
}
315315

316316
private _getTsProgram() {
317+
if (!this._program) {
318+
return undefined;
319+
}
320+
317321
return this._JitMode ? this._program as ts.Program : (this._program as Program).getTsProgram();
318322
}
319323

@@ -360,17 +364,28 @@ export class AngularCompilerPlugin {
360364
// Use an identity function as all our paths are absolute already.
361365
this._moduleResolutionCache = ts.createModuleResolutionCache(this._basePath, x => x);
362366

367+
const tsProgram = this._getTsProgram();
368+
const oldFiles = new Set(tsProgram ?
369+
tsProgram.getSourceFiles().map(sf => sf.fileName)
370+
: [],
371+
);
372+
363373
if (this._JitMode) {
364374
// Create the TypeScript program.
365375
time('AngularCompilerPlugin._createOrUpdateProgram.ts.createProgram');
366376
this._program = ts.createProgram(
367377
this._rootNames,
368378
this._compilerOptions,
369379
this._compilerHost,
370-
this._program as ts.Program,
380+
tsProgram,
371381
);
372382
timeEnd('AngularCompilerPlugin._createOrUpdateProgram.ts.createProgram');
373383

384+
const newFiles = this._program.getSourceFiles().filter(sf => !oldFiles.has(sf.fileName));
385+
for (const newFile of newFiles) {
386+
this._compilerHost.invalidate(newFile.fileName);
387+
}
388+
374389
return Promise.resolve();
375390
} else {
376391
time('AngularCompilerPlugin._createOrUpdateProgram.ng.createProgram');
@@ -388,6 +403,12 @@ export class AngularCompilerPlugin {
388403
return this._program.loadNgStructureAsync()
389404
.then(() => {
390405
timeEnd('AngularCompilerPlugin._createOrUpdateProgram.ng.loadNgStructureAsync');
406+
407+
const newFiles = (this._program as Program).getTsProgram()
408+
.getSourceFiles().filter(sf => !oldFiles.has(sf.fileName));
409+
for (const newFile of newFiles) {
410+
this._compilerHost.invalidate(newFile.fileName);
411+
}
391412
});
392413
}
393414
})
@@ -396,7 +417,7 @@ export class AngularCompilerPlugin {
396417
if (!this._entryModule && this._mainPath) {
397418
time('AngularCompilerPlugin._make.resolveEntryModuleFromMain');
398419
this._entryModule = resolveEntryModuleFromMain(
399-
this._mainPath, this._compilerHost, this._getTsProgram());
420+
this._mainPath, this._compilerHost, this._getTsProgram() as ts.Program);
400421
timeEnd('AngularCompilerPlugin._make.resolveEntryModuleFromMain');
401422
}
402423
});
@@ -621,7 +642,6 @@ export class AngularCompilerPlugin {
621642
this._basePath,
622643
host,
623644
);
624-
webpackCompilerHost.enableCaching();
625645

626646
// Create and set a new WebpackResourceLoader.
627647
this._resourceLoader = new WebpackResourceLoader();
@@ -811,7 +831,7 @@ export class AngularCompilerPlugin {
811831
? { path: workaroundResolve(this.entryModule.path), className: this.entryModule.className }
812832
: this.entryModule;
813833
const getLazyRoutes = () => this._lazyRoutes;
814-
const getTypeChecker = () => this._getTsProgram().getTypeChecker();
834+
const getTypeChecker = () => (this._getTsProgram() as ts.Program).getTypeChecker();
815835

816836
if (this._JitMode) {
817837
// Replace resources in JIT.
@@ -868,13 +888,15 @@ export class AngularCompilerPlugin {
868888
// We need to run the `listLazyRoutes` the first time because it also navigates libraries
869889
// and other things that we might miss using the (faster) findLazyRoutesInAst.
870890
// Lazy routes modules will be read with compilerHost and added to the changed files.
871-
const changedTsFiles = this._getChangedTsFiles();
872891
if (this._ngCompilerSupportsNewApi) {
873892
this._processLazyRoutes(this._listLazyRoutesFromProgram());
874893
} else if (this._firstRun) {
875894
this._processLazyRoutes(this._getLazyRoutesFromNgtools());
876-
} else if (changedTsFiles.length > 0) {
877-
this._processLazyRoutes(this._findLazyRoutesInAst(changedTsFiles));
895+
} else {
896+
const changedTsFiles = this._getChangedTsFiles();
897+
if (changedTsFiles.length > 0) {
898+
this._processLazyRoutes(this._findLazyRoutesInAst(changedTsFiles));
899+
}
878900
}
879901
if (this._options.additionalLazyModules) {
880902
this._processLazyRoutes(this._options.additionalLazyModules);
@@ -887,7 +909,7 @@ export class AngularCompilerPlugin {
887909
// We now have the final list of changed TS files.
888910
// Go through each changed file and add transforms as needed.
889911
const sourceFiles = this._getChangedTsFiles()
890-
.map((fileName) => this._getTsProgram().getSourceFile(fileName))
912+
.map((fileName) => (this._getTsProgram() as ts.Program).getSourceFile(fileName))
891913
// At this point we shouldn't need to filter out undefined files, because any ts file
892914
// that changed should be emitted.
893915
// But due to hostReplacementPaths there can be files (the environment files)
@@ -973,7 +995,7 @@ export class AngularCompilerPlugin {
973995
} else {
974996
// Check if the TS input file and the JS output file exist.
975997
if (((fileName.endsWith('.ts') || fileName.endsWith('.tsx'))
976-
&& !this._compilerHost.fileExists(fileName, false))
998+
&& !this._compilerHost.fileExists(fileName))
977999
|| !this._compilerHost.fileExists(outputFile, false)) {
9781000
let msg = `${fileName} is missing from the TypeScript compilation. `
9791001
+ `Please make sure it is in your tsconfig via the 'files' or 'include' property.`;
@@ -1066,15 +1088,26 @@ export class AngularCompilerPlugin {
10661088
}
10671089

10681090
if (!hasErrors(allDiagnostics)) {
1069-
sourceFiles.forEach((sf) => {
1070-
const timeLabel = `AngularCompilerPlugin._emit.ts+${sf.fileName}+.emit`;
1071-
time(timeLabel);
1072-
emitResult = tsProgram.emit(sf, undefined, undefined, undefined,
1091+
if (this._firstRun || sourceFiles.length > 20) {
1092+
emitResult = tsProgram.emit(
1093+
undefined,
1094+
undefined,
1095+
undefined,
1096+
undefined,
10731097
{ before: this._transformers },
10741098
);
10751099
allDiagnostics.push(...emitResult.diagnostics);
1076-
timeEnd(timeLabel);
1077-
});
1100+
} else {
1101+
sourceFiles.forEach((sf) => {
1102+
const timeLabel = `AngularCompilerPlugin._emit.ts+${sf.fileName}+.emit`;
1103+
time(timeLabel);
1104+
emitResult = tsProgram.emit(sf, undefined, undefined, undefined,
1105+
{ before: this._transformers },
1106+
);
1107+
allDiagnostics.push(...emitResult.diagnostics);
1108+
timeEnd(timeLabel);
1109+
});
1110+
}
10781111
}
10791112
} else {
10801113
const angularProgram = program as Program;

0 commit comments

Comments
 (0)