skip to content

Workspace File & Targets

angular.json declares each project's architect targets, named build configurations and fileReplacements. Interviewers ask how one workspace builds several apps for several environments.

part ofAngular CLIoverview, primer and where to startread it →
on this pageshow

explore

questions

5

With the Angular CLI, why does ng build produce an optimized, hashed bundle while ng serve does not, in a newly generated angular.json?

level: juniorimportance: must knowfreq 62%

answer

  1. targets, options, configurations
  2. each target names a default
  3. build defaults to production
  4. serve points at a build configuration

basics

~10 s

In a new Angular CLI project, the build target's defaultConfiguration is production, which adds budgets and outputHashing: 'all', while serve defaults to development, whose buildTarget turns optimization off and source maps on.

solid answer

~40 s

`angular.json` lists each project's **targets** under `architect`. A target has a `builder`, base `options`, named `configurations` that override those options, and a `defaultConfiguration` used when you pass no `--configuration`. In a project generated by Angular CLI 22, the `build` target uses `@angular/build:application` with `defaultConfiguration: "production"`; the `production` configuration adds `budgets` and `outputHashing: "all"`, and the builder's own defaults already enable `optimization`. The `serve` target uses `@angular/build:dev-server` with `defaultConfiguration: "development"`, and that configuration's `buildTarget` is `my-app:build:development`, which sets `optimization: false`, `extractLicenses: false` and `sourceMap: true`. So `ng build` gives a minified, cache-busted bundle and `ng serve` a fast, debuggable one; `ng serve -c production` or `ng build -c development` swaps them.

code

bash · 14 lines
bash
# build target, defaultConfiguration: production
ng build

# same target with the development overrides instead
ng build -c development

# serve target, defaultConfiguration: development (buildTarget my-app:build:development)
ng serve

# serve an optimized bundle to reproduce a production-only bug
ng serve -c production

# long form: project:target:configuration
ng run my-app:build:development

go deeper

for a junior

Recall that ng build defaults to production and ng serve to development, and that -c picks another named configuration.

for a middle

Explain targets, options, configurations and defaultConfiguration, and how serve reuses build through buildTarget strings.

for a senior

Reason about where each effective option comes from, including builder schema defaults, when a build behaves unexpectedly in one environment.

for a principal

Keep configurations minimal and intentional across many projects so that environment differences stay reviewable in one place.

## The shape of angular.json An Angular CLI **workspace** is described by `angular.json` at its root. Its `projects` map holds one entry per application or library, and each project lists **targets**, the tasks the CLI can run, under the `architect` key (the CLI also accepts the newer spelling `targets`). Commands such as `ng build`, `ng serve` and `ng test` are shortcuts that run the target of the same name. Every target has up to four parts: - **`builder`**: the package and builder that do the work, such as `@angular/build:application`. - **`options`**: the base option values. - **`configurations`**: named sets of overrides, for example `production` or `development`. - **`defaultConfiguration`**: the configuration applied when the command line names none. When a target runs, the CLI starts from `options` and spreads the selected configuration's values over them. Anything a configuration does not mention keeps its value from `options`, and anything `options` does not mention falls back to the builder's schema default. ## What a new project generates Angular CLI 22's application schematic writes this, abbreviated: ```json "build": { "builder": "@angular/build:application", "defaultConfiguration": "production", "options": { "browser": "src/main.ts", "tsConfig": "tsconfig.app.json" }, "configurations": { "production": { "budgets": [ ... ], "outputHashing": "all" }, "development": { "optimization": false, "extractLicenses": false, "sourceMap": true } } }, "serve": { "builder": "@angular/build:dev-server", "defaultConfiguration": "development", "configurations": { "production": { "buildTarget": "my-app:build:production" }, "development": { "buildTarget": "my-app:build:development" } } } ``` ## Why the two commands differ | | `ng build` | `ng serve` | |---|---|---| | Target run | `build` | `serve` | | Default configuration | `production` | `development` | | Build options actually used | `options` + `production` | `options` + `development`, via `buildTarget` | | Optimization | on (builder default) | off | | Output file hashing | `all` | builder default, `none` | | Source maps | off (builder default) | on | | Budgets checked | yes | no | Note what the `production` configuration does **not** contain: `optimization: true`. It does not need it, because `optimization` defaults to `true` in the application builder's schema. The `development` configuration exists precisely to switch the expensive parts off. ## How serve reuses build The dev-server target does not duplicate build options. Its configurations hold a **`buildTarget`** string in the form `project:target:configuration`, telling the dev server which build target and configuration to compile. That is why adding a new build configuration, such as `staging`, is not enough to serve it: `ng serve -c staging` also needs a `staging` entry under the `serve` target pointing at `my-app:build:staging`, otherwise the CLI reports that the configuration is not set for the `serve` target. ## Switching configurations 1. `ng build` runs `build` with `production`. 2. `ng build --configuration development` (short form `-c development`) builds an unoptimized bundle with source maps. 3. `ng serve -c production` serves an optimized build, useful for checking a production-only bug locally. 4. `ng run my-app:build:development` is the long form that names project, target and configuration explicitly. ## Command-line flags come last On top of `options` and the selected configuration, flags typed on the command line override both. `ng build --source-map` produces source maps even in the production configuration, for that one run only. Two spelling rules apply: - In `angular.json` every option is **camelCase** (`sourceMap`, `outputHashing`). - On the command line the same option is **dash-case** (`--source-map`, `--output-hashing`). The full precedence, lowest to highest, is therefore: the builder's schema default, the target's `options`, each selected configuration in order, and finally the command-line flags. The builder's schema also validates the merged result, so a misspelled option in `angular.json` is reported as an error rather than silently ignored. ## Why this matters in practice Knowing where defaults come from prevents two common mistakes: assuming `ng build` is a development build (it has been production by default since Angular CLI 12), and editing `options` when only one environment should change. Values that differ per environment belong in the named configuration; values shared by all belong in `options`.

  • Why does the generated production configuration not set optimization to true?
    The application builder's schema already defaults `optimization` to `true`, so production inherits it from the builder. The generated `development` configuration is what turns it off, together with `extractLicenses: false` and `sourceMap: true`.
  • How can you change a value in angular.json from a script without editing the JSON by hand?
    Use `ng config <json-path> [value]`. Without a value it prints the current setting; with one it writes it and validates the workspace against the schema, for example `ng config cli.cache.enabled false`. `--global` edits the user-level CLI configuration file instead of the workspace's `angular.json`.

saying these in an interview costs you the question

  • ng build produces a development build unless you pass --prod.
  • The production configuration must set optimization: true or nothing is minified.
  • ng serve builds with the production configuration by default.
  • Adding a build configuration automatically makes it available to ng serve.
  • Options outside configurations are ignored once a configuration is selected.
open as a page

In an Angular CLI project, how do you add a staging build configuration with its own environment file, and what does fileReplacements do?

level: middleimportance: must knowfreq 65%

basics

~10 s

Add a staging entry under the Angular CLI build target's configurations whose fileReplacements swaps src/environments/environment.ts for environment.staging.ts at compile time, give serve a matching buildTarget, and build with ng build -c staging.

open as a page

In angular.json, which budget types can the Angular CLI enforce, and how do maximumWarning, maximumError and baseline decide whether a build fails?

level: middleimportance: should knowfreq 45%

basics

~10 s

Angular CLI budgets in angular.json have a type (initial, bundle, all, allScript, any, anyScript, anyComponentStyle) and thresholds. Crossing maximumWarning logs a warning; crossing maximumError fails the build. Percentages are relative to a baseline.

open as a page

In a multi-project Angular CLI workspace, how does ng build decide which project to build, and how do you target one explicitly?

level: middleimportance: should knowfreq 40%

basics

~20 s

An Angular CLI command such as ng build picks the only project with that target, or the project containing the current directory; otherwise it errors. Name the project explicitly, as in ng build admin or ng run admin:build:production.

open as a page

An Angular CLI app built with ng build -c staging ships unhashed file names and skips budgets; why, and how should angular.json be fixed?

level: seniorimportance: should knowfreq 38%

basics

~20 s

An Angular CLI configuration named with -c replaces defaultConfiguration instead of stacking on it, so staging gets only the base options and its own overrides. Repeat production's settings in staging, or build with -c production,staging.

open as a page