Angular CLI and Nx - Why?

coly010

Colum Ferry

Posted on June 22, 2022

Angular CLI and Nx - Why?

In this blog, I’ll present a comparison of both the Angular CLI and the Nx CLI and present some evaluations on the current state of each.

What is Nx?

One of the more powerful additions to Angular 2+ was when the Angular CLI was introduced. This dramatically lowered the entry barrier for newcomers, allowing them to focus on learning Angular instead of having to deal with the underlying tooling setup. Also, features like code generation as well as automated code migrations (ng update) help during the development and the maintenance of the project.

When Nrwl founders Jeff Cross and Victor Savkin left the Angular Team at Google they saw the huge potential of such developer tooling, but with the aim to improve it with a particular focus on the needs of the community and companies outside of Google. Nx was heavily inspired by the Angular CLI and is now years later a fully standalone, widely adopted, and quickly growing build system with almost 2 million downloads per week. The Nx core team closely collaborates with the Angular team as well as with other teams on Jest, Cypress, Storybook, ESLint, and more, effectively serving as an integrative part with a mission to deliver the best possible integration between the various tools.

When Angular CLI users try out Nx they immediately feel at home due to the familiarity of the commands, but also get to experience the increased power and particularly the focus on modern community tooling. Let's explore more.

The Current State of Affairs

Angular CLI

In recent releases, the Angular CLI kept reducing its feature set, mainly due to tools such as Protractor as well as TSLint being deprecated. As a result, starting with Angular 14, the Angular CLI provides the following when generating a new application:

  • Angular application
  • Unit testing solution with Karma
  • (note, linting doesn't come out of the box, however, when trying to run the lint command it can be set up automatically for you)

Nx CLI

Nx, on the other hand, generates an Angular workspace with the following setup:

  • Angular Application
  • Jest for Unit Testing
  • Cypress for E2E Testing
  • ESLint for Linting
  • Prettier for improving code style consistency and readability

But it offers even more tooling integrations via generators:

  • Storybook
  • NgRx
  • Tailwind
  • Micro Frontend Support
  • Module Federation Support
  • Standalone Component-based Applications and Libraries Support

Command Comparison

Everything you’re used to running with the Angular CLI will still work in the Nx CLI.
As a quick reference, here is a list of commands provided by the Angular CLI and their counterparts in the Nx CLI.

Angular CLI Nx CLI
ng build app1 nx build app1
ng serve app1 nx serve app1
ng test app1 nx test app1
ng lint app1 nx lint app1
ng upgrade nx migrate

Feature Comparison

The Nx CLI can do everything the Angular CLI can do, and more. Let’s take a look at a more comprehensive feature comparison between the two CLIs.

Angular CLI Nx CLI
Code Generation Yes Yes
Caching Cache of build Cache of build, lint, test (and others!)
Migrations Yes Yes
Out-of-box Unit Testing Yes Yes
Out-of-box Linting No* Yes
Out-of-box E2E Testing No Yes
Micro Frontend Support No Yes
Publishable Libraries Yes Yes
Remote Caching None Yes

* It’s worth noting that if you run ng lint in a new project, the command will ask if you want to install ESLint. You can then lint your project. However, it does not have a linting setup provided out of the box.


Code Generation

Both CLIs offer built-in code schematics/generators to help scaffold code quickly. However, Nx provides all the schematics that Angular provides as well as additional generators to help improve your developer experience even further.

We have generators to integrate tools such as

  • Tailwind - nx g setup-tailwind <projectName>
  • Storybook - nx g storybook-configuration <projectName>
  • NgRx - nx g ngrx <storeName> --project=<projectName>

As well as generators to help you scaffold out

  • Micro Frontends - nx g host shell & nx g remote remoteApp
  • Single Component Angular Modules (SCAMs) - nx g scam myscam
    • Standalone Component-based applications - nx g app --standalone
    • Standalone Component-based libraries - nx g library --standalone
  • Web Workers - nx g web-worker <workerName> --project=<projectName>

Caching

Angular's caching solution is built on top of Webpack's incremental build cache. This helps speed up rebuilds as the cache is persisted onto disk. Nx doesn't change that. It leverages Angular's builder but in addition, also adds Nx's own computation cache on top.

See the graphic below where we compare the result of getting a cache hit on the Angular CLI with the result of getting a cache hit on the Nx CLI.

Angular CLI comparison to Nx CLI

The initial webpack build with Angular CLI takes ~12s, the following cache hit build takes ~4s.
The initial webpack build with Nx CLI takes ~10s, the following cache hit build takes ~14ms.

Being tied to Webpack, Angular's cache is just local to your workstation and only for builds. Nx instead is able to cache any custom operation you specify, including your builds, lint, and tests. In addition, you have the ability to split your project into smaller consumable units, that can also be tested and linted. This means we can take advantage of parallelization to run tests and lints in parallel and take better advantage of the cache of any projects that have not changed! All of this results in faster CI times and a better local developer experience.

By integrating with Nx Cloud you also get the opportunity to


Migrations

Angular has always been committed to ensuring evergreen development. It introduced the concept of automatically upgrading your workspace and running code migrations to reduce the chance of running into breaking changes between versions. This can be done using the ng update command. Once the command is run, Angular will install the new versions of packages and run any code migrations that will be required.

Nx is also committed to providing the same experience, however, it is a little bit more nuanced about it. The nx migrate command should be used in two steps. The first run of nx migrate will update the dependencies versions in the package.json file and also generate a file named migrations.json. However, it will not automatically install the new packages or run the code migrations. You can do this by running nx migrate --run-migrations.

The reason behind this comes from what we have learned from working with large multi-team organizations. Some automatic code migrations will generate a lot of changes and this can become difficult to review in a subsequent PR. It can be even more difficult for reviewers if there are multiple different code migrations within a single PR.

By creating a migrations.json file that contains each of the migrations to be run, we can be more selective with the migrations we run, meaning we can create multiple PRs to focus on each migration, allowing for incremental updates and the ability re-run migrations.

This can also be helpful when we have teams that have long-lived feature branches and we need to reduce the impact of changes and risk of merge conflicts and it also allows these teams to re-run migrations on their own branches.

You can read more about our approach to updating and migrations here: https://nx.dev/using-nx/updating-nx or watch this Egghead video on leveraging Nx migrations.


Configuration

The Angular CLI and Nx CLI uses a very similar approach to configuration to manage your projects and workspaces.

The Angular CLI uses a root angular.json file that contains the configuration of all projects in the workspace. This configuration is used to dictate how the project should be built and tested. Other tools may also configure how they should work within this configuration file.

The Nx CLI will place an angular.json configuration file at the root of your workspace which points to individual project.json files for each of the projects in your workspace. Each of these project.json files follows a similar structure to projects within Angular’s angular.json, except scoped to just one project.

This configuration splitting is extremely useful as it allows configuration to live beside the project it targets, making it much easier to find and reason about, as well as preventing large git merge conflicts when multiple teams have added new projects in their feature branches.

There is a very slight naming difference between some of the properties in both configuration files. You can see a mapping of those in the table below.

Angular CLI Nx CLI
architect targets
builder executor
schematics generator

Despite that, Nx contains a compatibility layer between itself and the Angular Devkit, allowing for Angular CLI configuration and Angular Schematics to work correctly, even when used in an Nx Workspace!


Architecture

A typical Angular Workspace consists of an application at the root of the workspace and then allows for the development of additional applications and libraries under a folder named projects.
While this can allow for the splitting of large applications into smaller manageable chunks, the tooling to manage this architecture is not provided by the Angular CLI.

Nx, on the other hand, embraces this separation of applications and libraries, encouraging the concept that an application is a composition of small, focused chunks (or libraries). This lends itself well to a Domain-driven architecture. Nx allows better separation of applications themselves into an apps folder and libraries into a libs folder. By breaking down our applications into these smaller, domain-focused libraries, Nx can increase the number of cacheable units within your workspace to dramatically increase developer experience and reduce testing and lint times.

Using an ESLint rule provided by Nx, we can also enforce some rules around what libraries can be used by other libraries and applications.
You can read more about that here: https://blog.nrwl.io/mastering-the-project-boundaries-in-nx-f095852f5bf4


Extensibility

The Angular CLI can be extended with schematics and builders that aim to allow library authors to provide opinionated code generation and different approaches to executing code in the workspace. An example of this would be ngx-build-plus which allows for an additional webpack configuration to be taken into account when building the Angular application. However, the Angular CLI isn’t fully pluggable and the Angular Devkit, which utilizes RxJS, can be difficult to approach if you ever do find the need to offer schematics as part of your package.

The Nx CLI is fully pluggable and embraces the idea of Nx Plugins that can be used to enhance your development experience. Nx offers some official plugins, but it also has a large listing of community plugins (https://nx.dev/community#plugin-directory) that aim to provide support for many tools and integrations!

Nx Plugins can be built with the Nx Devkit, which uses Async Generators and provides many helper functions to make it super easy to build your own code generators and code executors.

Nx even understands the concept of local plugins, which allows you to build a plugin in the same workspace as your application. This provides the opportunity to create opinionated code generators for your full organization to maintain consistency in development practices across all teams working on the application.

You can read more about the Nx Devkit here: https://nx.dev/guides/nx-devkit-angular-devkit


Switching from the Angular CLI to the Nx CLI

Have you been convinced to try out the Nx CLI but already have an Angular application using the Angular CLI? Don’t worry! The Nx CLI offers a single command that will automatically migrate most Angular workspaces to use Nx. It has been recently refactored to support multi-project workspaces as well as some known standard deviations from Angular’s opinionated workspace scaffolding.

You can use the command below in your Angular Workspace to kick off the migration.

ng add @nrwl/angular 
Enter fullscreen mode Exit fullscreen mode

Note: You need to ensure you use the correct command based on the version of Angular your workspace is using. The easiest way would be to ensure your Angular workspace is at the latest Angular version and then run the command!

Otherwise, you can read more about migrating to Nx here, including the command to run based on your version of Angular: https://nx.dev/migration/migration-angular


Conclusion

Looking objectively across everything discussed within this post, it becomes clear that the Nx CLI offers everything that the Angular CLI does and then some. From more out-of-the-box tooling support to faster builds and more features, the Nx CLI dramatically improves your Angular development experience, while allowing you to reuse most of the knowledge you have gained from using the Angular CLI. And the large ecosystem of Nx Plugins means you can take advantage of all the features of Nx for more than just Angular applications if you need to!

💖 💪 🙅 🚩
coly010
Colum Ferry

Posted on June 22, 2022

Join Our Newsletter. No Spam, Only the good stuff.

Sign up to receive the latest update from our blog.

Related

Angular CLI and Nx - Why?
angular Angular CLI and Nx - Why?

June 22, 2022