Skip to content

Commit 657f782

Browse files
clydinalan-agius4
authored andcommitted
fix(@angular-devkit/build-angular): avoid dev server update analysis when build fails with vite
When using an esbuild-based builder (`application` or `browser-esbuild`) with the development server, a build that fails due to an TypeScript, Angular, or bundling error will now skip all output file result processing. This avoids unnecessary work since an update of the client code will not take place. This also allows for an error overlay to be displayed showing the first error available. The full list of errors will still be shown in the console used to execute the `ng serve` command. Fixing the error will automatically clear the error overlay but if there were multiple errors the next unfixed error will be shown instead. (cherry picked from commit 08c1229)
1 parent 6bed286 commit 657f782

File tree

3 files changed

+35
-2
lines changed

3 files changed

+35
-2
lines changed

packages/angular_devkit/build_angular/src/builders/application/execute-build.ts

+2
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,8 @@ export async function executeBuild(
146146

147147
// Return if the bundling has errors
148148
if (bundlingResult.errors) {
149+
executionResult.addErrors(bundlingResult.errors);
150+
149151
return executionResult;
150152
}
151153

packages/angular_devkit/build_angular/src/builders/dev-server/vite-server.ts

+24
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,7 @@ export async function* serveWithVite(
115115

116116
let server: ViteDevServer | undefined;
117117
let listeningAddress: AddressInfo | undefined;
118+
let hadError = false;
118119
const generatedFiles = new Map<string, OutputFileRecord>();
119120
const assetFiles = new Map<string, string>();
120121
const build =
@@ -134,6 +135,29 @@ export async function* serveWithVite(
134135
)) {
135136
assert(result.outputFiles, 'Builder did not provide result files.');
136137

138+
// If build failed, nothing to serve
139+
if (!result.success) {
140+
// If server is active, send an error notification
141+
if (result.errors?.length && server) {
142+
hadError = true;
143+
server.ws.send({
144+
type: 'error',
145+
err: {
146+
message: result.errors[0].text,
147+
stack: '',
148+
loc: result.errors[0].location,
149+
},
150+
});
151+
}
152+
continue;
153+
} else if (hadError && server) {
154+
// Send an empty update to clear the error overlay
155+
server.ws.send({
156+
'type': 'update',
157+
updates: [],
158+
});
159+
}
160+
137161
// Analyze result files for changes
138162
analyzeResultFiles(normalizePath, htmlIndexPath, result.outputFiles, generatedFiles);
139163

packages/angular_devkit/build_angular/src/tools/esbuild/bundler-execution-result.ts

+9-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* found in the LICENSE file at https://angular.io/license
77
*/
88

9+
import type { Message } from 'esbuild';
910
import type { ChangedFiles } from '../../tools/esbuild/watcher';
1011
import type { SourceFileCache } from './angular/source-file-cache';
1112
import type { BuildOutputFile, BuildOutputFileType, BundlerContext } from './bundler-context';
@@ -28,6 +29,7 @@ export interface RebuildState {
2829
export class ExecutionResult {
2930
outputFiles: BuildOutputFile[] = [];
3031
assetFiles: BuildOutputAsset[] = [];
32+
errors: Message[] = [];
3133

3234
constructor(
3335
private rebuildContexts: BundlerContext[],
@@ -42,17 +44,22 @@ export class ExecutionResult {
4244
this.assetFiles.push(...assets);
4345
}
4446

47+
addErrors(errors: Message[]): void {
48+
this.errors.push(...errors);
49+
}
50+
4551
get output() {
4652
return {
47-
success: this.outputFiles.length > 0,
53+
success: this.errors.length === 0,
4854
};
4955
}
5056

5157
get outputWithFiles() {
5258
return {
53-
success: this.outputFiles.length > 0,
59+
success: this.errors.length === 0,
5460
outputFiles: this.outputFiles,
5561
assetFiles: this.assetFiles,
62+
errors: this.errors,
5663
};
5764
}
5865

0 commit comments

Comments
 (0)