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', '
Hello, world! { + switch (index) { + case 0: + expect(result?.success).toBeFalse(); + debugger; + expect(logs).toContain( + jasmine.objectContaining({ + message: jasmine.stringMatching('Unexpected character "EOF"'), + }), + ); + + await harness.appendToFile('src/app/app.component.html', '>'); + + break; + case 1: + expect(result?.success).toBeTrue(); + expect(logs).not.toContain( + jasmine.objectContaining({ + message: jasmine.stringMatching('Unexpected character "EOF"'), + }), + ); + break; + } + }), + take(2), + count(), + ) + .toPromise(); + + expect(buildCount).toBe(2); + }); + }); +}); diff --git a/packages/angular/build/src/builders/dev-server/vite-server.ts b/packages/angular/build/src/builders/dev-server/vite-server.ts index 7ac866ad893a..d704e3a5161f 100644 --- a/packages/angular/build/src/builders/dev-server/vite-server.ts +++ b/packages/angular/build/src/builders/dev-server/vite-server.ts @@ -213,6 +213,8 @@ export async function* serveWithVite( }, }); } + + yield { baseUrl: '', success: false }; continue; } // Clear existing error overlay on successful result diff --git a/tests/legacy-cli/e2e/tests/build/jit-ngmodule.ts b/tests/legacy-cli/e2e/tests/build/jit-ngmodule.ts index a66311f0e27f..8d24b35e4e0f 100644 --- a/tests/legacy-cli/e2e/tests/build/jit-ngmodule.ts +++ b/tests/legacy-cli/e2e/tests/build/jit-ngmodule.ts @@ -32,6 +32,12 @@ export default async function () { }; } + // Remove bundle budgets due to the increased size from JIT + build.configurations.production = { + ...build.configurations.production, + budgets: undefined, + }; + build.options.aot = false; }); // Test it works