diff --git a/packages/schematics/angular/migrations/use-application-builder/migration.ts b/packages/schematics/angular/migrations/use-application-builder/migration.ts index b481c4f30034..9df1e7df0c44 100644 --- a/packages/schematics/angular/migrations/use-application-builder/migration.ts +++ b/packages/schematics/angular/migrations/use-application-builder/migration.ts @@ -19,6 +19,7 @@ import { DependencyType, ExistingBehavior, addDependency, + getDependency, removeDependency, } from '../../utility/dependency'; import { JSONFile } from '../../utility/json-file'; @@ -270,10 +271,13 @@ function updateProjects(tree: Tree, context: SchematicContext) { } // Add direct @angular/build dependencies and remove @angular-devkit/build-angular + const buildAngularVersion = + getDependency(tree, '@angular-devkit/build-angular')?.version ?? + latestVersions.AngularBuild; rules.push( - addDependency('@angular/build', latestVersions.DevkitBuildAngular, { + addDependency('@angular/build', buildAngularVersion, { type: DependencyType.Dev, - existing: ExistingBehavior.Replace, + existing: ExistingBehavior.Skip, }), removeDependency('@angular-devkit/build-angular'), ); diff --git a/packages/schematics/angular/migrations/use-application-builder/migration_spec.ts b/packages/schematics/angular/migrations/use-application-builder/migration_spec.ts index fd10352c6eac..f5cc0002d534 100644 --- a/packages/schematics/angular/migrations/use-application-builder/migration_spec.ts +++ b/packages/schematics/angular/migrations/use-application-builder/migration_spec.ts @@ -9,6 +9,7 @@ import { JsonObject } from '@angular-devkit/core'; import { EmptyTree } from '@angular-devkit/schematics'; import { SchematicTestRunner, UnitTestTree } from '@angular-devkit/schematics/testing'; +import { latestVersions } from '../../utility/latest-versions'; import { Builders, ProjectType, WorkspaceSchema } from '../../utility/workspace-models'; function createWorkSpaceConfig(tree: UnitTestTree) { @@ -450,6 +451,49 @@ describe(`Migration to use the application builder`, () => { expect(devDependencies['postcss']).toBeUndefined(); }); + it('should reuse the installed builder version when migrating to "@angular/build"', async () => { + tree.overwrite( + '/package.json', + JSON.stringify({ + devDependencies: { + '@angular-devkit/build-angular': '~18.2.20', + }, + }), + ); + + const newTree = await schematicRunner.runSchematic(schematicName, {}, tree); + + const { devDependencies } = JSON.parse(newTree.readContent('/package.json')); + expect(devDependencies['@angular/build']).toBe('~18.2.20'); + expect(devDependencies['@angular-devkit/build-angular']).toBeUndefined(); + }); + + it('should use the latest "@angular/build" version when no builder is installed', async () => { + const newTree = await schematicRunner.runSchematic(schematicName, {}, tree); + + const { devDependencies } = JSON.parse(newTree.readContent('/package.json')); + expect(devDependencies['@angular/build']).toBe(latestVersions.AngularBuild); + expect(devDependencies['@angular-devkit/build-angular']).toBeUndefined(); + }); + + it('should preserve an existing "@angular/build" version when migrating', async () => { + tree.overwrite( + '/package.json', + JSON.stringify({ + devDependencies: { + '@angular-devkit/build-angular': '~18.2.20', + '@angular/build': '~18.2.10', + }, + }), + ); + + const newTree = await schematicRunner.runSchematic(schematicName, {}, tree); + + const { devDependencies } = JSON.parse(newTree.readContent('/package.json')); + expect(devDependencies['@angular/build']).toBe('~18.2.10'); + expect(devDependencies['@angular-devkit/build-angular']).toBeUndefined(); + }); + it('it should not add esModuleInterop and moduleResolution when module is preserve', async () => { tree.overwrite( 'tsconfig.json',