Skip to content

Commit ec19736

Browse files
committed
refactor(@angular/cli): provide default serve target for applications
The `serve` command will now use a default project target and builder name if the target entry is not explicitly defined. This allows the removal of additional configuration from an `angular.json` file. If the target is already present than it will take priority over any default builder behavior. The default logic will use the appropriate development server builder for officially supported packages (`@angular/build`/`@angular-devkit/build-angular`). The `dev-server` builder from these packages will currently assume a `development` configuration is present within the `build` target. The default behavior may be expanded in the future to support more arbitrary `build` target configurations. If there is third-party package usage within the `build` target, the CLI will attempt to discover a `dev-server` builder within the same package used by the `build` target. If none is found, no default will be added and the `serve` command will issue an error when no explicit target is present.
1 parent ee7f962 commit ec19736

File tree

1 file changed

+38
-0
lines changed
  • packages/angular/cli/src/commands/serve

1 file changed

+38
-0
lines changed

packages/angular/cli/src/commands/serve/cli.ts

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

9+
import { workspaces } from '@angular-devkit/core';
910
import { ArchitectCommandModule } from '../../command-builder/architect-command-module';
1011
import { CommandModuleImplementation } from '../../command-builder/command-module';
1112
import { RootCommands } from '../command-config';
@@ -19,4 +20,41 @@ export default class ServeCommandModule
1920
aliases = RootCommands['serve'].aliases;
2021
describe = 'Builds and serves your application, rebuilding on file changes.';
2122
longDescriptionPath?: string | undefined;
23+
24+
override async findDefaultBuilderName(
25+
project: workspaces.ProjectDefinition,
26+
): Promise<string | undefined> {
27+
// Only application type projects have a dev server target
28+
if (project.extensions['projectType'] !== 'application') {
29+
return;
30+
}
31+
32+
const buildTarget = project.targets.get('build');
33+
if (!buildTarget) {
34+
// No default if there is no build target
35+
return;
36+
}
37+
38+
// Provide a default based on the defined builder for the 'build' target
39+
switch (buildTarget.builder) {
40+
case '@angular-devkit/build-angular:application':
41+
case '@angular-devkit/build-angular:browser-esbuild':
42+
case '@angular-devkit/build-angular:browser':
43+
return '@angular-devkit/build-angular:dev-server';
44+
case '@angular/build:application':
45+
return '@angular/build:dev-server';
46+
}
47+
48+
// For other builders, attempt to resolve a 'dev-server' builder from the 'build' target package name
49+
const [buildPackageName] = buildTarget.builder.split(':', 1);
50+
if (buildPackageName) {
51+
try {
52+
const qualifiedBuilderName = `${buildPackageName}:dev-server`;
53+
await this.getArchitectHost().resolveBuilder(qualifiedBuilderName);
54+
55+
// Use builder if it resolves successfully
56+
return qualifiedBuilderName;
57+
} catch {}
58+
}
59+
}
2260
}

0 commit comments

Comments
 (0)