diff --git a/packages/angular/build/src/builders/application/build-action.ts b/packages/angular/build/src/builders/application/build-action.ts index 1236c6887855..0ded5bb5ef28 100644 --- a/packages/angular/build/src/builders/application/build-action.ts +++ b/packages/angular/build/src/builders/application/build-action.ts @@ -152,6 +152,10 @@ export async function* runEsBuildBuildAction( return; } + // Used to force a full result on next rebuild if there were initial errors. + // This ensures at least one full result is emitted. + let hasInitialErrors = result.errors.length > 0; + // Wait for changes and rebuild as needed const currentWatchFiles = new Set(result.watchFiles); try { @@ -201,10 +205,13 @@ export async function* runEsBuildBuildAction( result, outputOptions, changes, - incrementalResults ? rebuildState : undefined, + incrementalResults && !hasInitialErrors ? rebuildState : undefined, )) { yield outputResult; } + + // Clear initial build errors flag if no errors are now present + hasInitialErrors &&= result.errors.length > 0; } } finally { // Stop the watcher and cleanup incremental rebuild state diff --git a/packages/angular/build/src/builders/dev-server/tests/behavior/build-errors_spec.ts b/packages/angular/build/src/builders/dev-server/tests/behavior/build-errors_spec.ts new file mode 100644 index 000000000000..82467da0d249 --- /dev/null +++ b/packages/angular/build/src/builders/dev-server/tests/behavior/build-errors_spec.ts @@ -0,0 +1,66 @@ +/** + * @license + * Copyright Google LLC All Rights Reserved. + * + * Use of this source code is governed by an MIT-style license that can be + * found in the LICENSE file at https://angular.dev/license + */ + +import { concatMap, count, take, timeout } from 'rxjs'; +import { executeDevServer } from '../../index'; +import { describeServeBuilder } from '../jasmine-helpers'; +import { BASE_OPTIONS, BUILD_TIMEOUT, DEV_SERVER_BUILDER_INFO } from '../setup'; +import { logging } from '@angular-devkit/core'; + +describeServeBuilder(executeDevServer, DEV_SERVER_BUILDER_INFO, (harness, setupTarget) => { + describe('Behavior: "Rebuild Error Detection"', () => { + beforeEach(() => { + setupTarget(harness); + }); + + it('Emits full build result with incremental enabled and initial build has errors', async () => { + harness.useTarget('serve', { + ...BASE_OPTIONS, + watch: true, + }); + + // Missing ending `>` on the div will cause an error + await harness.appendToFile('src/app/app.component.html', '