Angular CLI Beyond ng serve: Generators, Targets, Cache and Build Stats
Learn the Angular CLI options that remove routine work: generator flags, built-in help, per-project commands, ng run targets, cache cleanup and build stats.
This article is published in English.
Most Angular developers settle into four commands early on, ng serve, ng build, ng generate and ng test, and never look further. That works for a small app, but as a workspace grows, the time spent hand-writing boilerplate, hunting for version numbers, guessing at bundle size and nursing broken caches adds up. The CLI already has answers for most of those chores. This guide walks through the options worth making habitual, explains when each one helps, and ends with a compact daily workflow you can adopt as is.
If you are still at the stage of creating the workspace itself, the walkthrough on setting up a modern Angular project covers that part; everything below assumes a project already exists.
Get more out of ng generate
The generator is the command everyone knows in its long form:
ng generate component user-profile
Every generator has a short alias, so generate becomes g and component becomes c:
ng g c user-profile
The real savings come from the flags. When a small presentational component does not warrant a spec file, --skip-tests stops the CLI from creating one:
ng g c user-profile --skip-tests
By default each component lands in its own folder. --flat writes the files directly into the current directory instead, which suits tiny components that live next to their parent:
ng g c user-profile --flat
Flags compose, so you can ask for both at once:
ng g c user-profile --flat --skip-tests
The same options apply to services, directives, pipes, guards and the other schematics. Letting the generator create files keeps naming and layout consistent across the team. Add --dry-run to preview what a schematic would create without writing anything.
Ask the CLI instead of searching the web
The quickest way to discover what a generator can do is to ask it. This lists every available schematic:
ng generate --help
The alias works the same way:
ng g --help
Adding --help after a specific schematic prints all of its options with short descriptions:
ng g component --help
Options change between releases, and forum answers often describe older flags; the help output always matches the CLI installed in your project.
Read and change settings with ng config
Workspace configuration lives in angular.json, and it is tempting to edit that file directly. The CLI offers a command for reading and writing those values:
ng config
Called on its own, it prints configuration so you can see what is set:
ng config
You can also pass a JSON path to read one value, or a path followed by a value to set it, for example to change a CLI option for the whole workspace. In scripts, a repeatable ng config call beats fragile manual JSON edits: when the CLI owns a file, use the CLI to change it.
Report your environment with ng version
When something breaks, exact versions matter. Rather than opening package.json and piecing things together, run:
ng version
or its short form:
ng v
The output lists the Angular CLI version, the installed Angular packages, Node.js, the package manager and the operating system in one block. This is exactly what a teammate or maintainer needs when you ask for help. A report that only says the project stopped working gives them nothing to go on, while pasting the output of the following command answers their first five questions up front:
ng version
Measure the production bundle instead of guessing
This build flag deserves far more use than it gets:
ng build --stats-json
It writes a statistics file describing what went into each output chunk. Feed that file to a bundle analyzer and you get a visual breakdown of where the bytes come from. Be aware that the file format depends on the builder: older webpack-based builds produce webpack stats, while the newer esbuild-based application builder emits esbuild metadata, so pick an analyzer that understands your builder's output and check the current Angular docs for your version.
Typical findings when an app feels slow include:
- one oversized third-party library
- chunks that are much larger than expected
- the same dependency bundled more than once
- a few heavy components pulled into the initial load
- lazy-loaded features that ended up bigger than planned
None of these are visible from the source alone. Comparing stats before and after a dependency upgrade is a cheap way to catch regressions.
Clear the build cache before reinstalling everything
The CLI keeps a persistent disk cache so repeated builds are faster. The ng cache command manages it; ng cache info shows where the cache lives and whether it is enabled:
ng cache
When builds start behaving oddly, clearing that cache is often the fix:
ng cache clean
Stale cache entries tend to show up after a dependency change, an Angular upgrade, or a switch between branches with different package versions. Clearing it takes seconds, so try it before the slow route of deleting node_modules and reinstalling.
Lint locally and in CI
If your project has a linter configured, run it with:
ng lint
Recent Angular versions do not ship a linter by default, so ng lint only works after you add one, typically through the Angular ESLint integration. Once configured, it catches problems before a reviewer has to:
- unused variables and imports
- formatting inconsistencies
- likely bugs
- discouraged patterns
- general code-quality issues
Running the same command in the CI pipeline means problematic code is flagged before it reaches the main branch, and nobody has to rely on remembering to run it.
Run tests once in automation
Locally, test runs usually stay in watch mode and rerun on every save:
ng test
A CI job has no use for a process that waits for file changes. Disabling watch mode makes the command run the suite once and exit:
ng test --watch=false
The exit code then reflects whether the tests passed, which is what the pipeline uses to mark the job green or red. A pipeline left in watch mode just hangs until it times out. Local development and CI have different needs, and one command line need not serve both.
Target a single project in a multi-project workspace
Larger Angular repositories often hold several applications and libraries in one workspace. Most commands accept a project name, so you can build just one app:
ng build my-app
or test just one:
ng test my-app
In a monorepo-style workspace this becomes routine:
ng build admin
ng build customer
ng test shared-ui
Working on the shared UI library should not mean rebuilding every app; scoping commands keeps feedback loops short.
Call any architect target with ng run
Behind the familiar commands sits a more general one that few developers use directly:
ng run
It executes a named architect target from the workspace configuration, using the project:target form, optionally followed by a configuration name:
ng run my-app:build
The standard commands are really shortcuts for common targets. ng run becomes valuable once a workspace defines custom targets, for example a builder that generates code, deploys a preview or runs a specialised test setup. Think of it as "run exactly this target of this project", with nothing inferred.
Open the documentation from the terminal
When you need to check an API quickly, the CLI can start the search for you:
ng doc
Pass a keyword and it looks it up in the official Angular documentation:
ng doc signals
Note that the results open in your browser rather than printing in the terminal, so this is a shortcut to the right page rather than an offline reference.
Let help replace memorisation
Perhaps the most useful habit of all is this command:
ng help
It lists every top-level command. For the options of a particular command, append --help:
ng build --help
The same works for generators, down to a single schematic:
ng generate service --help
Nobody needs to memorise every flag. Productive developers are rarely the ones who remember everything; they are the ones who know where to look the moment they forget.
A daily workflow that puts it together
A practical routine might look like the following. Start the development server:
ng serve
While building features, generate what you need with the right flags:
ng g c profile --skip-tests
Before committing, lint and run the tests once:
ng lint
ng test --watch=false
For a production build, use the production configuration explicitly:
ng build --configuration production
When bundle size is in question, generate stats:
ng build --stats-json
When the build starts misbehaving, clear the cache first:
ng cache clean
And whenever an option slips your mind, ask the command itself:
ng <command> --help
Wrapping up
The Angular CLI is a productivity layer around the whole development loop, and the biggest wins come from a handful of options that remove repetitive work:
- generate code with flags instead of writing boilerplate by hand
- scope commands to one project in multi-project workspaces
- measure bundles with stats instead of guessing about performance
- clear the cache before resorting to a full reinstall
- run tests without watch mode in CI and lint on every change
- rely on
--help, which always matches your installed version
Next time you open a terminal in an Angular project, remember that there is a lot more behind ng than this:
ng serve