perf(ivy): use module resolution cache (#34332)

During TypeScript module resolution, a lot of filesystem requests are
done. This is quite an expensive operation, so a module resolution cache
can be used to speed up the process significantly.

This commit lets the Ivy compiler perform all module resolution with a
module resolution cache. Note that the module resolution behavior can be
changed with a custom compiler host, in which case that custom host
implementation is responsible for caching. In the case of the Angular
CLI a custom compiler host with proper module resolution caching is
already in place, so the CLI already has this optimization.

PR Close #34332
This commit is contained in:
JoostK
2019-12-07 22:38:36 +01:00
committed by Kara Erickson
parent 2f5ddd9c96
commit 8c2cbdd385
13 changed files with 56 additions and 46 deletions

View File

@ -8,13 +8,14 @@
import {Expression, ExternalExpr, ExternalReference, WrappedNodeExpr} from '@angular/compiler';
import * as ts from 'typescript';
import {LogicalFileSystem, LogicalProjectPath, PathSegment, absoluteFrom, absoluteFromSourceFile, basename, dirname, relative, resolve} from '../../file_system';
import {LogicalFileSystem, LogicalProjectPath, PathSegment, absoluteFromSourceFile, dirname, relative} from '../../file_system';
import {stripExtension} from '../../file_system/src/util';
import {ReflectionHost} from '../../reflection';
import {getSourceFile, getSourceFileOrNull, isDeclaration, nodeNameForError, resolveModuleName} from '../../util/src/typescript';
import {getSourceFile, isDeclaration, nodeNameForError} from '../../util/src/typescript';
import {findExportedNameOfNode} from './find_export';
import {ImportMode, Reference} from './references';
import {ModuleResolver} from './resolver';
@ -118,8 +119,7 @@ export class AbsoluteModuleStrategy implements ReferenceEmitStrategy {
constructor(
protected program: ts.Program, protected checker: ts.TypeChecker,
protected options: ts.CompilerOptions, protected host: ts.CompilerHost,
private reflectionHost: ReflectionHost) {}
protected moduleResolver: ModuleResolver, private reflectionHost: ReflectionHost) {}
emit(ref: Reference<ts.Node>, context: ts.SourceFile, importMode: ImportMode): Expression|null {
if (ref.bestGuessOwningModule === null) {
@ -165,13 +165,7 @@ export class AbsoluteModuleStrategy implements ReferenceEmitStrategy {
protected enumerateExportsOfModule(specifier: string, fromFile: string):
Map<ts.Declaration, string>|null {
// First, resolve the module specifier to its entry point, and get the ts.Symbol for it.
const resolvedModule = resolveModuleName(specifier, fromFile, this.options, this.host);
if (resolvedModule === undefined) {
return null;
}
const entryPointFile =
getSourceFileOrNull(this.program, absoluteFrom(resolvedModule.resolvedFileName));
const entryPointFile = this.moduleResolver.resolveModule(specifier, fromFile);
if (entryPointFile === null) {
return null;
}

View File

@ -8,12 +8,6 @@
import * as ts from 'typescript';
import {absoluteFrom} from '../../file_system';
import {getSourceFileOrNull, resolveModuleName} from '../../util/src/typescript';
import {Reference} from './references';
export interface ReferenceResolver {
resolve(decl: ts.Declaration, importFromHint: string|null, fromFile: string):
Reference<ts.Declaration>;
}
/**
* Used by `RouterEntryPointManager` and `NgModuleRouteAnalyzer` (which is in turn is used by
@ -24,11 +18,12 @@ export interface ReferenceResolver {
export class ModuleResolver {
constructor(
private program: ts.Program, private compilerOptions: ts.CompilerOptions,
private host: ts.CompilerHost) {}
private host: ts.CompilerHost, private moduleResolutionCache: ts.ModuleResolutionCache|null) {
}
resolveModuleName(module: string, containingFile: ts.SourceFile): ts.SourceFile|null {
const resolved =
resolveModuleName(module, containingFile.fileName, this.compilerOptions, this.host);
resolveModule(moduleName: string, containingFile: string): ts.SourceFile|null {
const resolved = resolveModuleName(
moduleName, containingFile, this.compilerOptions, this.host, this.moduleResolutionCache);
if (resolved === undefined) {
return null;
}