Skip to content

Commit 00c34d8

Browse files
filipesilvaZhicheng Wang
authored and
Zhicheng Wang
committed
fix(@ngtools/webpack): fix dependency for non-css style factories
1 parent a044c05 commit 00c34d8

File tree

4 files changed

+49
-20
lines changed

4 files changed

+49
-20
lines changed

packages/@ngtools/webpack/src/angular_compiler_plugin.ts

+11-4
Original file line numberDiff line numberDiff line change
@@ -828,7 +828,7 @@ export class AngularCompilerPlugin implements Tapable {
828828
this._emitSkipped = !emitResult || emitResult.emitSkipped;
829829

830830
// Reset changed files on successful compilation.
831-
if (this._emitSkipped && this._compilation.errors.length === 0) {
831+
if (!this._emitSkipped && this._compilation.errors.length === 0) {
832832
this._compilerHost.resetChangedFileTracker();
833833
}
834834
timeEnd('AngularCompilerPlugin._update');
@@ -872,7 +872,9 @@ export class AngularCompilerPlugin implements Tapable {
872872
// We also need to all changed files as dependencies of this file, so that all of them
873873
// will be watched and trigger a rebuild next time.
874874
outputText = '';
875-
errorDependencies = this._getChangedCompilationFiles();
875+
errorDependencies = this._getChangedCompilationFiles()
876+
// These paths are used by the loader so we must denormalize them.
877+
.map((p) => this._compilerHost.denormalizePath(p));
876878
}
877879
} else {
878880
// Check if the TS file exists.
@@ -923,9 +925,14 @@ export class AngularCompilerPlugin implements Tapable {
923925
.reduce((prev, curr) => prev.concat(curr), [])
924926
.map((resourcePath) => path.resolve(path.dirname(resolvedFileName), resourcePath))
925927
.reduce((prev, curr) =>
926-
prev.concat(...this._resourceLoader.getResourceDependencies(curr)), []);
928+
prev.concat(...this.getResourceDependencies(curr)), []);
927929

928-
return [...esImports, ...resourceImports];
930+
// These paths are meant to be used by the loader so we must denormalize them.
931+
return [...esImports, ...resourceImports].map((p) => this._compilerHost.denormalizePath(p));
932+
}
933+
934+
getResourceDependencies(fileName: string): string[] {
935+
return this._resourceLoader.getResourceDependencies(fileName);
929936
}
930937

931938
// This code mostly comes from `performCompilation` in `@angular/compiler-cli`.

packages/@ngtools/webpack/src/compiler_host.ts

+9-2
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,10 @@ export class WebpackCompilerHost implements ts.CompilerHost {
118118
return path.replace(/\\/g, '/');
119119
}
120120

121+
denormalizePath(path: string) {
122+
return path.replace(/\//g, sep);
123+
}
124+
121125
resolve(path: string) {
122126
path = this._normalizePath(path);
123127
if (path[0] == '.') {
@@ -161,7 +165,9 @@ export class WebpackCompilerHost implements ts.CompilerHost {
161165

162166
getNgFactoryPaths(): string[] {
163167
return Object.keys(this._files)
164-
.filter(fileName => fileName.endsWith('.ngfactory.js') || fileName.endsWith('.ngstyle.js'));
168+
.filter(fileName => fileName.endsWith('.ngfactory.js') || fileName.endsWith('.ngstyle.js'))
169+
// These paths are used by the virtual file system decorator so we must denormalize them.
170+
.map((path) => this.denormalizePath(path));
165171
}
166172

167173
invalidate(fileName: string): void {
@@ -291,7 +297,8 @@ export class WebpackCompilerHost implements ts.CompilerHost {
291297

292298
readResource(fileName: string) {
293299
if (this._resourceLoader) {
294-
const denormalizedFileName = fileName.replace(/\//g, sep);
300+
// These paths are meant to be used by the loader so we must denormalize them.
301+
const denormalizedFileName = this.denormalizePath(fileName);
295302
const resourceDeps = this._resourceLoader.getResourceDependencies(denormalizedFileName);
296303

297304
if (this._cachedResources[fileName] === undefined

packages/@ngtools/webpack/src/loader.ts

+28-11
Original file line numberDiff line numberDiff line change
@@ -581,18 +581,35 @@ export function ngcLoader(this: LoaderContext & { _compilation: any }, source: s
581581
result.sourceMap = JSON.stringify(sourceMap);
582582
}
583583

584-
// Dependencies must use system path separator.
585-
// TODO: move the denormalizer into it's own helper.
586-
result.errorDependencies.forEach(dep => this.addDependency(dep.replace(/\//g, path.sep)));
587-
const dependencies = plugin.getDependencies(sourceFileName);
588-
dependencies.forEach(dep => this.addDependency(dep.replace(/\//g, path.sep)));
589-
590-
// Also add the original file dependencies to virtual files.
591-
const virtualFilesRe = /\.(?:ngfactory|css\.shim\.ngstyle)\.js$/;
592-
if (virtualFilesRe.test(sourceFileName)) {
593-
const originalFile = sourceFileName.replace(virtualFilesRe, '.ts');
584+
// Manually add the dependencies for TS files.
585+
// Type only imports will be stripped out by compilation so we need to add them as
586+
// as dependencies.
587+
// Component resources files (html and css templates) also need to be added manually for
588+
// AOT, so that this file is reloaded when they change.
589+
if (sourceFileName.endsWith('.ts')) {
590+
result.errorDependencies.forEach(dep => this.addDependency(dep));
591+
const dependencies = plugin.getDependencies(sourceFileName);
592+
dependencies.forEach(dep => this.addDependency(dep));
593+
}
594+
595+
// NgFactory files depend on the component template, but we can't know what that file
596+
// is (if any). So we add all the dependencies that the original component file has
597+
// to the factory as well, which includes html and css templates.
598+
const ngFactoryRe = /\.ngfactory.js$/;
599+
if (ngFactoryRe.test(sourceFileName)) {
600+
const originalFile = sourceFileName.replace(ngFactoryRe, '.ts');
594601
const origDependencies = plugin.getDependencies(originalFile);
595-
origDependencies.forEach(dep => this.addDependency(dep.replace(/\//g, path.sep)));
602+
origDependencies.forEach(dep => this.addDependency(dep));
603+
}
604+
605+
// NgStyle files depend on the style file they represent.
606+
// E.g. `some-style.less.shim.ngstyle.js` depends on `some-style.less`.
607+
// Those files can in turn depend on others, so we have to add them all.
608+
const ngStyleRe = /\.shim\.ngstyle\.js$/;
609+
if (ngStyleRe.test(sourceFileName)) {
610+
const styleFile = sourceFileName.replace(ngStyleRe, '');
611+
const styleDependencies = plugin.getResourceDependencies(styleFile);
612+
styleDependencies.forEach(dep => this.addDependency(dep));
596613
}
597614

598615
timeEnd(timeLabel);

packages/@ngtools/webpack/src/virtual_file_system_decorator.ts

+1-3
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import { Stats } from 'fs';
2-
import { sep } from 'path';
32

43
import { InputFileSystem, NodeWatchFileSystemInterface, Callback } from './webpack';
54
import { WebpackCompilerHost } from './compiler_host';
@@ -31,8 +30,7 @@ export class VirtualFileSystemDecorator implements InputFileSystem {
3130
}
3231

3332
getVirtualFilesPaths() {
34-
return this._webpackCompilerHost.getNgFactoryPaths()
35-
.map((fileName) => fileName.replace(/\//g, sep));
33+
return this._webpackCompilerHost.getNgFactoryPaths();
3634
}
3735

3836
stat(path: string, callback: Callback<any>): void {

0 commit comments

Comments
 (0)