Introduction to building an Angular app with Nx Workspace
Tags: angular, webdev, monorepo, nx
Published: 2021-04-08 16:17:18

[Nx Workspace](https://nx.dev) is a tool suite designed to architect, build and manage monorepos at any scale. It has an out of the box support for multiple frontend frameworks like Angular and React as well as backend technologies including Nest, Next and Express. In this article, we will focus on building a workspace for an Angular-based project.

## Monorepo fundamentals

The most basic definition of a monorepo is that it is a single repository that consists of multiple applications and libraries. This all is accompanied by a set of tooling which enables to work with those projects. This approach has several benefits as following:
- **shared code** - it enables to share the code across the whole company or organization. This can result in code that is more DRY as we can reuse the common patterns, components, and types. This enables to share the logic between frontend and backend as well.
- **atomic changes** - without the monorepo approach whenever we need to make a change that will affect multiple projects we might need to coordinate those changes across multiple repositories and possibly by multiple teams. Ie. API change might need to be reflected both on a server app and a client app. With monorepo all of those changes can be applied in one commit on one repository which greatly limits the coordination efforts necessary
- **developer mobility** - with a monorepo approach we get one, consistent way of performing similar tasks even when using multiple technologies. The developers can now contribute to other team's projects and make sure that their changes are safe across the whole organization.
- **single set of dependencies** - By using a single repository with one set of dependencies we make sure that our whole codebase depends on one single version of the given dependency. This way there are no version conflicts between libraries. It is also less likely that the less used part of the repository will be left with an obsolete dependency because it will be updated along the way when other parts of the repository do this update.

## Create a new workspace

With all that said about the monorepo how do we actually create one using Nx Workspace and Angular? Just like with Angular CLI there is an Nx CLI that does all the heavy lifting for us. With the following command we can create a new workspace that leverages all of the aforementioned benefits of a monorepo:

```sh
npx create-nx-workspace --preset=angular
```

The tool will ask for a project name, stylesheet format, and linting tool. For the linting I recommend using ESLint which is a more modern tool. The CLI will also ask whether we want to use [Nx Cloud](https://nx.app) in our workspace. We can opt-out from this for now as we can easily add that later on. After the command finishes, we end up with a brand new project all set up. Let's start by analyzing what has been generated for us.

Nx uses certain toolset by default:
- **[Jest](https://jestjs.io)** for testing (instead of Karma and Jasmine)
- **[Cypress](https://www.cypress.io)** for e2e testing (instead of Protractor)
- **[ESLint](https://eslint.org)** for linting (instead of TSLint) in case you have decided so when creating a workspace
All of these are a modern tools and I recommend sticking to them as they provide very good developer's experience and are actively maintained.

The base structure that is created for us looks as following:

```
- apps/
  - {{appName}}
  - {{appName}}-e2e
- libs
- tools
```

- `apps/*`: here go all the application projects - by default it'll be the app we created and an accompanying e2e tests app
- `libs/*`: here go all the libraries that we create
- `tools/*`: here we can put all the necessary tooling scripts etc. that are necessary in our project
- and all the root configuration files like angular.json, config files for Jest, ESLint, Prettier etc

This whole structure is created for us so that we can focus on building the solution right from the beginning.

## Migration from an existing Angular project

If you already have an existing Angular app that was build using Angular CLI you can still easily migrate to an Nx Workspace. A project that contains only a single Angular app can be migrated automatically with just one command:

```sh
ng add @nrwl/workspace
```

This will install all the dependencies required by Nx and create the folder structure mentioned in the previous section. It will also migrate the app into `apps` folder and e2e suite into `apps/{{appName}}-e2e` folder. Nx modifies `package.json` script and decorates Angular CLI so you can still use the same commands like `ng build`, `ng serve`, or `npm start`.
It is important to remember that the version of Angular and Nx must match so that this process goes smoothly. Ie. if your project is using version 10 of Angular please make sure to use the latest `10.x.x` version of Nx CLI.

In case you already have multiple projects you still can migrate with few manual steps described in the [Nx docs](https://nx.dev/latest/angular/migration/migration-angular#transitioning-manually)

## Create a library

One of the core ideas behind the Nx Workspace monorepo approach is to divide our code into small, manageable libraries. So by using Nx we will end up creating a library often. Luckily this is done as simple as typing one command in the terminal:

```sh
nx g @nrwl/angular:lib mylib
```

This will create a `libs/mylib` folder with the library set up so we can build, test, and use it in other libraries or applications right away. To group your libraries you can use `--directory={{subfolderName}}` additional parameter to specify a subfolder under which a library should be created. You don't have to worry though about choosing the perfect place for your library from the start. You can always move it around later on using `@nrwl/workspace:move` [schematics](https://nx.dev/latest/angular/workspace/move). And you can find all the other options for generating a new Angular library in the [official docs](https://nx.dev/latest/angular/angular/library#options)

Every library has an `index.ts` file at its root which should be the only access point to a library. Each part of the library that we want to be part of lib's public API should be exported from this file. Everything else is considered private to the library. This is important for maintaining the correct boundaries between libraries and applications which makes for a more well-structured code.

## Affected

One of the greatest things about Nx Workspace is that it understands dependencies within the workspace. This allows for testing and linting only the projects that are affected by a given change. Nx comes with a few built-in commands for that.

```sh
npx nx affected:lint
npx nx affected:test
npx nx affected:e2e
npx nx affected:build
```

Those commands will run `lint`, `test`, `e2e`, and `build` targets, but only on projects that are affected and therefore it will lower the execution time by a lot in most use-cases. The commands below are equivalent to the ones above but they use more generic syntax which can be extended to different targets if necessary.

```sh
nx affected --target=lint
nx affected --target=test
nx affected --target=e2e
nx affected --target=build
```

For all of the commands mentioned above we can parallelize them by using `--parallel` flag and `--maxParallel={{nr}}` to cap the number of parallel tasks. There are multiple additional useful parameters that the `affected` task can take. Please visit the [official docs](https://nx.dev/latest/angular/cli/affected#options) for more details.

## Conslusion

Working with a monorepo has a lot of advantages and Nx Workspace provides us with multiple tools to get the most of that. By using it we can speed up our development loop by being able to create atomic changes to the repository and make sure that the whole workspace is compatible with that change. All of this is done with blazing fast tooling that can be scaled to any project size we might have.

In case you have any questions you can always tweet or DM me [@ktrz](https://twitter.com/ktrz__). I'm always happy to help!

---

_This Dot Labs is a modern web consultancy focused on helping companies realize their digital transformation efforts. For expert architectural guidance, training, or consulting in React, Angular, Vue, Web Components, GraphQL, Node, Bazel, or Polymer, visit [thisdotlabs.com](https://www.thisdotlabs.com)._

_This Dot Media is focused on creating an inclusive and educational web for all. We keep you up to date with advancements in the modern web through events, podcasts, and free content. To learn, visit [thisdot.co](https://www.thisdot.co)._