fix(ivy): ensure that changes to component resources trigger incremental builds (#30954)

Optimizations to skip compiling source files that had not changed
did not account for the case where only a resource file changes,
such as an external template or style file.

Now we track such dependencies and trigger a recompilation
if any of the previously tracked resources have changed.

This will require a change on the CLI side to provide the list of
resource files that changed to trigger the current compilation by
implementing `CompilerHost.getModifiedResourceFiles()`.

Closes #30947

PR Close #30954
This commit is contained in:
Pete Bacon Darwin
2019-06-10 16:22:56 +01:00
committed by Kara Erickson
parent dc613b336d
commit 48def92cad
13 changed files with 159 additions and 43 deletions

View File

@ -20,6 +20,7 @@ import {ClassDeclaration, Decorator, ReflectionHost, reflectObjectLiteral} from
import {LocalModuleScopeRegistry} from '../../scope';
import {AnalysisOutput, CompileResult, DecoratorHandler, DetectResult, HandlerPrecedence, ResolveResult} from '../../transform';
import {TypeCheckContext} from '../../typecheck';
import {NoopResourceDependencyRecorder, ResourceDependencyRecorder} from '../../util/src/resource_recorder';
import {tsSourceMapBug29300Fixed} from '../../util/src/ts_source_map_bug_29300';
import {ResourceLoader} from './api';
@ -48,7 +49,9 @@ export class ComponentDecoratorHandler implements
private resourceLoader: ResourceLoader, private rootDirs: string[],
private defaultPreserveWhitespaces: boolean, private i18nUseExternalIds: boolean,
private moduleResolver: ModuleResolver, private cycleAnalyzer: CycleAnalyzer,
private refEmitter: ReferenceEmitter, private defaultImportRecorder: DefaultImportRecorder) {}
private refEmitter: ReferenceEmitter, private defaultImportRecorder: DefaultImportRecorder,
private resourceDependencies:
ResourceDependencyRecorder = new NoopResourceDependencyRecorder()) {}
private literalCache = new Map<Decorator, ts.ObjectLiteralExpression>();
private elementSchemaRegistry = new DomElementSchemaRegistry();
@ -182,6 +185,7 @@ export class ComponentDecoratorHandler implements
}
const templateUrl = this.resourceLoader.resolve(evalTemplateUrl, containingFile);
const templateStr = this.resourceLoader.load(templateUrl);
this.resourceDependencies.recordResourceDependency(node.getSourceFile(), templateUrl);
template = this._parseTemplate(
component, templateStr, sourceMapUrl(templateUrl), /* templateRange */ undefined,
@ -236,7 +240,9 @@ export class ComponentDecoratorHandler implements
}
for (const styleUrl of styleUrls) {
const resourceUrl = this.resourceLoader.resolve(styleUrl, containingFile);
styles.push(this.resourceLoader.load(resourceUrl));
const resourceStr = this.resourceLoader.load(resourceUrl);
styles.push(resourceStr);
this.resourceDependencies.recordResourceDependency(node.getSourceFile(), resourceUrl);
}
}
if (component.has('styles')) {
@ -506,6 +512,7 @@ export class ComponentDecoratorHandler implements
if (templatePromise !== undefined) {
return templatePromise.then(() => {
const templateStr = this.resourceLoader.load(resourceUrl);
this.resourceDependencies.recordResourceDependency(node.getSourceFile(), resourceUrl);
const template = this._parseTemplate(
component, templateStr, sourceMapUrl(resourceUrl), /* templateRange */ undefined,
/* escapedString */ false);

View File

@ -22,6 +22,7 @@ ts_library(
"//packages/compiler-cli/src/ngtsc/scope",
"//packages/compiler-cli/src/ngtsc/testing",
"//packages/compiler-cli/src/ngtsc/translator",
"//packages/compiler-cli/src/ngtsc/util",
"@npm//typescript",
],
)