Skip to content

Commit b0b643e

Browse files
committedMar 19, 2025·
fix(@angular/build): ensure errors for missing component resources
Compile time errors will now always be generated when an HTML template and/or CSS component stylesheet are not present on disk. The Angular compiler expects a return value of `null` from the `resourceNameToFileName` function to indicate that a resource path does not exist. JIT mode previously and continues to generate errors as expected. (cherry picked from commit cb2ab43)
1 parent 0a4e96b commit b0b643e

File tree

3 files changed

+75
-0
lines changed

3 files changed

+75
-0
lines changed
 

‎packages/angular/build/src/builders/application/tests/behavior/component-stylesheets_spec.ts

+39
Original file line numberDiff line numberDiff line change
@@ -44,5 +44,44 @@ describeBuilder(buildApplication, APPLICATION_BUILDER_INFO, (harness) => {
4444

4545
harness.expectFile('dist/browser/main.js').content.not.toContain('variables');
4646
});
47+
48+
it('should generater an error for a missing stylesheet with AOT', async () => {
49+
await harness.modifyFile('src/app/app.component.ts', (content) => {
50+
return content.replace('./app.component.css', './not-present.css');
51+
});
52+
53+
harness.useTarget('build', {
54+
...BASE_OPTIONS,
55+
});
56+
57+
const { result, logs } = await harness.executeOnce({ outputLogsOnFailure: false });
58+
expect(result?.success).toBeFalse();
59+
expect(logs).toContain(
60+
jasmine.objectContaining({
61+
level: 'error',
62+
message: jasmine.stringContaining(`Could not find stylesheet file './not-present.css'`),
63+
}),
64+
);
65+
});
66+
67+
it('should generater an error for a missing stylesheet with JIT', async () => {
68+
await harness.modifyFile('src/app/app.component.ts', (content) => {
69+
return content.replace('./app.component.css', './not-present.css');
70+
});
71+
72+
harness.useTarget('build', {
73+
...BASE_OPTIONS,
74+
aot: false,
75+
});
76+
77+
const { result, logs } = await harness.executeOnce({ outputLogsOnFailure: false });
78+
expect(result?.success).toBeFalse();
79+
expect(logs).toContain(
80+
jasmine.objectContaining({
81+
level: 'error',
82+
message: jasmine.stringContaining('Could not resolve'),
83+
}),
84+
);
85+
});
4786
});
4887
});
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/**
2+
* @license
3+
* Copyright Google LLC All Rights Reserved.
4+
*
5+
* Use of this source code is governed by an MIT-style license that can be
6+
* found in the LICENSE file at https://angular.dev/license
7+
*/
8+
9+
import { buildApplication } from '../../index';
10+
import { APPLICATION_BUILDER_INFO, BASE_OPTIONS, describeBuilder } from '../setup';
11+
12+
describeBuilder(buildApplication, APPLICATION_BUILDER_INFO, (harness) => {
13+
describe('Behavior: "Component Templates"', () => {
14+
it('should generater an error for a missing template', async () => {
15+
await harness.modifyFile('src/app/app.component.ts', (content) => {
16+
return content.replace('./app.component.html', './not-present.html');
17+
});
18+
19+
harness.useTarget('build', {
20+
...BASE_OPTIONS,
21+
});
22+
23+
const { result, logs } = await harness.executeOnce({ outputLogsOnFailure: false });
24+
expect(result?.success).toBeFalse();
25+
expect(logs).toContain(
26+
jasmine.objectContaining({
27+
level: 'error',
28+
message: jasmine.stringContaining(`Could not find template file './not-present.html'`),
29+
}),
30+
);
31+
});
32+
});
33+
});

‎packages/angular/build/src/tools/angular/angular-host.ts

+3
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,9 @@ export function createAngularCompilerHost(
208208

209209
host.resourceNameToFileName = function (resourceName, containingFile) {
210210
const resolvedPath = nodePath.join(nodePath.dirname(containingFile), resourceName);
211+
if (!this.fileExists(resolvedPath)) {
212+
return null;
213+
}
211214

212215
// All resource names that have template file extensions are assumed to be templates
213216
// TODO: Update compiler to provide the resource type to avoid extension matching here.

0 commit comments

Comments
 (0)
Please sign in to comment.