Nx and the Angular CLI
Nx evolved from being an extension of the Angular CLI to a fully standalone CLI working with multiple frameworks. As a result, adopting Nx as an Angular user is relatively straightforward. This guide explores some of the similarities and in particular, added benefits of using Nx over the Angular CLI for your Angular project.
TL;DR: Why should I use Nx for my Angular project?
Nx...
- helps define clear architectural guidelines and promotes best practices to organize and scale your codebase.
- helps integrate modern tooling by actively working with devtool authors to make sure they work well with Nx and your framework of choice.
- is adaptable: start small with a single-project setup and grow it to a monorepo when needed.
- has an active community of contributors and plugin authors.
- has been proven in large enterprise-level projects.
Note, the Nx team's focus is on building the best possible developer productivity tool.
Quick Overview Comparison
Here's a quick side-by-side overview comparing the features between the Angular CLI and Nx. (Kudos to Daniel Glejzner for helping with this)
Feature/Tool | Angular CLI | Nx |
---|---|---|
Create Angular Apps | ✅ | ✅ |
Generate Angular Components, Services, etc. | ✅ | ✅ |
Building & Bundling | ✅ | ✅ |
Local Development Server | ✅ | ✅ |
Code Schematics | ✅ | ✅ |
Automated Update with Migrations | ✅ | ✅ (Enhanced) |
Generators | ✅ (Schematics) | ✅ |
Executors | ✅ (Builders) | ✅ |
Advanced Generators (e.g. Module Federation, Tailwind,...) | ❌ | ✅ |
Integrated Tooling (Jest, Cypress, Playwright etc.) | ❌ | ✅ |
Support for single-project Workspaces | ✅ | ✅ |
First-Class Monorepo Support | ❌* | ✅ |
Enforced Module Boundaries | ❌ | ✅ |
Interactive Project Graph | ❌ | ✅ |
Task Graph | ❌ | ✅ |
Running Tasks in Parallel | ❌ | ✅ |
Building, Testing Only What is Affected | ❌ | ✅ |
Local Caching | ❌** | ✅ |
Distributed Caching | ❌ | ✅ |
Distributed Task Execution on CI | ❌ | ✅ |
Custom Hashers | ❌ | ✅ |
Extensible Plugin System | ❌ | ✅ |
* You can setup a monorepo with the Angular CLI creating buildable Angular ng-packagr projects, but the DX is not as optimized compared to what you'd get with Nx.`
** The Angular CLI has a caching mechanism which persists the Webpack/ESBuild/"TS incremental build info" cache to disk. Nx leverages that cache as well but in addition adds a more powerful process-level caching on top that is framework agnostic.`
Similarities and Differences
Learn about the similarities between the Angular CLI and Nx which makes it easy to migrate but also about how Nx goes beyond to further improve your developer productivity.
Not just for Monorepos: Project Setup & Structure
Nx is not just exclusively for monorepos, but can create
- a single-project workspace (basically what the Angular CLI gives you)
- a monorepo workspace (multiple projects in a single repo)
You can check out the Angular single-project workspace tutorial to learn more about it.
Generate a new project
You can create a new Nx single-project workspace using the following command:
❯
npx create-nx-workspace myngapp --preset=angular-standalone
You can use the --preset=angular-monorepo
to start with a monorepo structure. Note, however, that you can start simple and migrate to a monorepo later.
The single-project workspace setup follows a similar structure to what the Angular CLI generates.
1└─ myngapp
2 ├─ ...
3 ├─ src
4 │ ├─ app
5 │ │ ├─ app.component.css
6 │ │ ├─ app.component.html
7 │ │ ├─ app.component.spec.ts
8 │ │ ├─ app.component.ts
9 │ │ └─ app.module.ts
10 │ ├─ assets
11 │ ├─ favicon.ico
12 │ ├─ index.html
13 │ ├─ main.ts
14 │ └─ styles.css
15 ├─ nx.json
16 ├─ package.json
17 ├─ project.json
18 ├─ ...
19
project.json vs angular.json
Nx configures projects and their targets in a format similar to angular.json
. However, instead of storing the configuration for every project in a single large angular.json
file at the root, the configuration is split into multiple project.json
files, one for each project.
Smaller, focused config files allow you to quickly find the relevant configuration for the project you are working on, and editing a single project configuration does not cause the nx affected
command to rerun all the tests in the repo. This conversion is done automatically when you run nx init
.
Note that even though the configuration is split, everything works similarly. Migrations and schematics written with the Angular devkit that expect a single angular.json
file will receive a single file. Nx is smart, so it merges all the files in memory to make those migrations and schematics work.
More details: Nx project configuration.
Executors vs. Builders, Generators vs. Schematics
Nx comes with slightly different terminology than the Angular CLI for some features.
Angular Builders are called Executors in Nx but work very much similarly. You use them in your project configuration to define how to build, test, lint, and serve your project. You can use both Nx executors from Nx Plugins or Angular Builders from the Angular Devkit.
1{
2 "name": "myngapp",
3 ...
4 "targets": {
5 "build": {
6 "executor": "@angular-devkit/build-angular:browser",
7 ...
8 },
9 ...
10 }
11}
12
Angular Schematics are called Generators in Nx. You can invoke them in the same way as you would with the Angular CLI, but you use the nx
command instead of ng
:
❯
npx nx g @nx/angular:component my-component
You can also run Angular Schematics through the Nx ClI. So something like this works as well:
❯
npx nx g @schematics/angular:component my-component
Running Commands
Commands are run in the very same way as with the Angular CLI. You just switch ng
with nx
. For example:
❯
npx nx serve
Nx has more abilities to run commands in parallel, just for specific projects etc. Find out more in the docs.
Integrating with Modern Tools
An Angular-based Nx Workspace already comes with a lot of batteries included:
- Prettier preconfigured
- ESLint
- e2e testing with Cypress or Playwright
- unit testing with Jest
But Nx expands beyond just that, offering automated integration with a lot of modern tools such as Storybook or Tailwind just to mention a few.
'ng update' vs. 'nx migrate'
Like the Angular CLI, Nx has a command that allows you to upgrade your existing workspace tools, packages, and source code to the next version. Instead of ng update
, you run nx migrate
:
❯
npx nx migrate latest
What's the difference?
nx migrate
is a much-improved version of ng update
. It runs the same migrations but allows you to:
- Rerun the same migration multiple times.
- Reorder migrations.
- Skip migrations.
- Fix migrations that "almost work".
- Commit a partially migrated state.
- Change versions of packages to match org requirements.
- Opt out of Angular updates when updating Nx versions as long as the Angular version is still supported
nx migrate
does this by splitting the process into two steps. nx migrate latest
creates a migrations.json
file with a list of all the migrations needed by Nx, Angular, and other packages. You can then modify that file before running nx migrate --run-migrations
to execute those migrations.
To reiterate: nx migrate
runs the migrations written by the Angular team the same way ng update
runs them. So everything should still work. You just get more control over how it works. You can learn more in our docs about Automate Updating Dependencies.
'ng add'
ng add
is not natively supported by Nx. We want a consistent package install experience for developers working with Angular or non-Angular packages.
Instead, we recommend running:
❯
npm install [package] && nx g [package]:ng-add
Replace [package]
with the package name you're trying to add.
Speed
Nx is designed to be fast. The Angular CLI leverages Webpack's caching, which Nx also does since it relies on the Angular Devkit when it comes to compiling or running apps. But Nx goes way beyond that, introducing features vital for a fast CI experience, mainly when you have a monorepo.
Features like
- only running tasks on affected projects
- running tasks in parallel
- applying computation caching
- offering remote caching abilities on CI
- offering task distribution across machines (DTE)
And, Nx already uses fast, modern tooling like ESBuild, Vite, Vitest and Rspack for non-Angular stacks. So once Angular is ready to use these tools, Nx will also be ready.
Editor Integration
Nx goes beyond being just a CLI and comes with Nx Console, a VSCode and WebStorm extension allowing you to run commands, generate code and visualize your workspace.
Scaling: Start Simple, Grow to a Monorepo
Nx is really made to scale with you. You can
- start small with a single-project workspace
- modularize your application into more fine-grained libraries for better maintainability as your application (and team) grows (more about that here), including mechanisms to make sure things stay within their boundaries
- you can then migrate to a monorepo when you are ready and need one (more here)
- or even add Webpack Module Federation support
Visualize your Workspace
As you start modularizing your Angular workspace, Nx can visualize it using the nx graph
command or via Nx Console directly in your editor.
Learn more about the graph features here.
Extensible and Customizable: Make it fit your own needs
Nx is built to be extensible. Just like the packages published by the Nx core team you can create your own Nx plugins by extending Nx. This can be as simple as using run-commands to integrate custom commands into the project configuration or as complex as creating your own local executor.
And if you ever need to expand beyond Angular or diversify your stack, you can still keep using Nx, which is battle-tested with many different technologies.
Migrate from the Angular CLI?
Migrating an Angular CLI project to Nx can be done by running
❯
npx nx@latest init
or alternatively using the --integrated
flag if you want to create an Nx monorepo right away. Learn more about all the details on the dedicated docs page.
There are also guides describing how to:
- manually migrate an Angular CLI app and
- how to consolidate multiple Angular CLI projects into a single Nx monorepo
You can learn more about Angular & Nx by following our dedicated tutorials: