Skip to content

Commit 9136eb3

Browse files
clydinalan-agius4
authored andcommitted
fix(@angular/build): ensure transitive SCSS partial errors are tracked in watch mode
When stylesheet bundling fails due to an error in a SCSS partial, we now ensure that `referencedFiles` are still passed to the `FileReferenceTracker`. This prevents the dependency between the component and the error file from being lost, allowing the component to be correctly rebuilt when the error is fixed. (cherry picked from commit 21d8aa4)
1 parent 107d1a9 commit 9136eb3

File tree

2 files changed

+89
-0
lines changed

2 files changed

+89
-0
lines changed

packages/angular/build/src/builders/application/tests/behavior/rebuild-component_styles_spec.ts

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,5 +58,85 @@ describeBuilder(buildApplication, APPLICATION_BUILDER_INFO, (harness) => {
5858
]);
5959
});
6060
}
61+
62+
it('rebuilds component after error on rebuild from transitive import', async () => {
63+
harness.useTarget('build', {
64+
...BASE_OPTIONS,
65+
watch: true,
66+
});
67+
68+
await harness.modifyFile('src/app/app.component.ts', (content) =>
69+
content.replace('app.component.css', 'app.component.scss'),
70+
);
71+
await harness.writeFile('src/app/app.component.scss', "@import './a';");
72+
await harness.writeFile('src/app/a.scss', '$primary: aqua;\\nh1 { color: $primary; }');
73+
74+
await harness.executeWithCases([
75+
async ({ result }) => {
76+
expect(result?.success).toBe(true);
77+
78+
harness.expectFile('dist/browser/main.js').content.toContain('color: aqua');
79+
80+
// Introduce a syntax error
81+
await harness.writeFile(
82+
'src/app/a.scss',
83+
'invalid-invalid-invalid\\nh1 { color: $primary; }',
84+
);
85+
},
86+
async ({ result }) => {
87+
expect(result?.success).toBe(false);
88+
89+
// Fix the syntax error
90+
await harness.writeFile('src/app/a.scss', '$primary: blue;\\nh1 { color: $primary; }');
91+
},
92+
({ result }) => {
93+
expect(result?.success).toBe(true);
94+
95+
harness.expectFile('dist/browser/main.js').content.toContain('color: blue');
96+
},
97+
]);
98+
});
99+
100+
it('rebuilds component after error on rebuild from deep transitive import with partials', async () => {
101+
harness.useTarget('build', {
102+
...BASE_OPTIONS,
103+
watch: true,
104+
});
105+
106+
await harness.modifyFile('src/app/app.component.ts', (content) =>
107+
content.replace('app.component.css', 'app.component.scss'),
108+
);
109+
await harness.writeFile('src/app/app.component.scss', "@import './intermediary';");
110+
await harness.writeFile('src/app/_intermediary.scss', "@import './partial';");
111+
await harness.writeFile('src/app/_partial.scss', '$primary: aqua;\\nh1 { color: $primary; }');
112+
113+
await harness.executeWithCases([
114+
async ({ result }) => {
115+
expect(result?.success).toBe(true);
116+
117+
harness.expectFile('dist/browser/main.js').content.toContain('color: aqua');
118+
119+
// Introduce a syntax error deeply
120+
await harness.writeFile(
121+
'src/app/_partial.scss',
122+
'invalid-invalid-invalid\\nh1 { color: $primary; }',
123+
);
124+
},
125+
async ({ result }) => {
126+
expect(result?.success).toBe(false);
127+
128+
// Fix the syntax error deeply
129+
await harness.writeFile(
130+
'src/app/_partial.scss',
131+
'$primary: blue;\\nh1 { color: $primary; }',
132+
);
133+
},
134+
({ result }) => {
135+
expect(result?.success).toBe(true);
136+
137+
harness.expectFile('dist/browser/main.js').content.toContain('color: blue');
138+
},
139+
]);
140+
});
61141
});
62142
});

packages/angular/build/src/tools/esbuild/angular/compiler-plugin.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,10 +220,19 @@ export function createCompilerPlugin(
220220
if (stylesheetResult.errors) {
221221
(result.errors ??= []).push(...stylesheetResult.errors);
222222

223+
const { referencedFiles } = stylesheetResult;
224+
if (referencedFiles) {
225+
referencedFileTracker.add(containingFile, referencedFiles);
226+
if (stylesheetFile) {
227+
referencedFileTracker.add(stylesheetFile, referencedFiles);
228+
}
229+
}
230+
223231
return '';
224232
}
225233

226234
const { contents, outputFiles, metafile, referencedFiles } = stylesheetResult;
235+
227236
additionalResults.set(resultSource, {
228237
outputFiles,
229238
metafile,

0 commit comments

Comments
 (0)