Nx adoption guide: Overview, examples, and alternatives
Tags: nx, webdev
Published: 2024-04-04 14:39:29

**Written by [Andrew Evans](https://blog.logrocket.com/author/andrewevans/)✏️**

Nx is an open source build system that can be used to build applications and increase developer productivity. In this guide, we’ll go over its features, use cases, alternatives, and more to help you assess whether Nx is the right tool for your needs.

* * *

## What is Nx?

Nx was built by [Nrwl](https://nx.app/company), a very active company in the open source community and a maintainer of [Lerna, a monorepo manager tool](https://blog.logrocket.com/setting-up-monorepo-lerna-typescript/). Started roughly around 2019, Nx was originally focused on Angular development, but expanded to include full-stack development and integrations with frontend libraries like React.

From the beginning, Nx has had CLI commands as well as a visual integrations with popular IDE’s like VSCode. Nx commands include everything from generating code to building and even deploying projects. Nx can be used for standalone projects as well as monorepos for development. 

Nx starts as an [npm package](https://www.npmjs.com/package/nx) that can be added to a project or run globally. If you install the Nx package globally, it gives you access to the Nx CLI, which you can use to run Nx commands. You can also use npx commands to generate a `workspace` in which you can run Nx commands. 

Nx as a whole is composed of the following high level parts:

*   **Nx Package**: Main part of Nx that includes the base commands and tooling
*   **Nx Console**: Visual tool that provides visual interface for commands
*   **Nx Cloud**: Free management of project dependencies and distributed tasks
*   **Nx Devkit**: Used to build Nx Plugins
*   **Nx Plugins**: Extensions of Nx that have specialized tools for frameworks or libraries like React, Angular, Cypress, Jest, etc.

This visual from the [Nx documentation](https://nx.dev/getting-started/why-nx#how-does-nx-work) helps explain its high-level architecture: ![Diagram of The Nx High Level Architecture](https://blog.logrocket.com/wp-content/uploads/2024/03/img1-High-level-architecture-diagram-Nx-docs.png) If you wanted to install Nx to use in an existing project, there is also an npx command that allows you to install it as a project dependency:

```bash
npx nx@latest init
```

Nx also provides an [analysis of your projects and dependencies](https://nx.dev/core-features/explore-graph). This analysis is a great Nx feature as it allows you to visualize how the parts of your project are interconnected: ![Nx Analysis Allowing Developer To Visualize How Parts Of The Project Interconnect](https://blog.logrocket.com/wp-content/uploads/2024/03/img2-Nx-analysis-visualize-parts-project-connect.png) In addition to all of these features, another great aspect of Nx is that the maintainers have provided a [great set of documentation and tutorials](https://nx.dev/getting-started/why-nx) to help you get started. The documentation allows you to “learn by doing,” which really helps when learning and adopting Nx for projects.

#### _Further reading:_

*   [Developing Next.js microservices with Nx](https://blog.logrocket.com/developing-next-js-microservices-nx/)
*   [Building Nx monorepos with Remix](https://blog.logrocket.com/building-nx-monorepos-remix/)
*   [Building an application with React and Nx](https://blog.logrocket.com/building-an-application-with-react-and-nx/)
*   [Meetup: Building an application with React and Nx](https://blog.logrocket.com/meetups/building-an-application-with-react-and-nx-recap/)

* * *

## Why choose Nx?

Nx provides solutions to many common challenges facing developers today. In particular, Nx can help enhance:

*   **Performance**: Improve speed for routine tasks like building, linting, and testing through distributed task management and caching
*   **Developer experience**: Structure development and maintenance through a common set of commands that can be used to scaffold a project, package output, and run tests. Enable quick integration of tooling like Storybook, Tailwind, and others via Nx Commands. Allow for managed upgrades of projects through Nx commands in lieu of manual changes and breaking changes
*   **Community & ecosystem**: Very broad set of documentation with tutorials for most major use cases; minimal learning curve with [an active GitHub project](https://github.com/nrwl/nx/)
*   **Integrations**: [Nx Plugins](https://nx.dev/plugin-registry) provided for popular frameworks and tools like Cypress, Express, Angular, Next.js, and more

All of these features really sell Nx for new projects. However, if you have an existing project, many people question the logic of switching to Nx tooling. 

Fortunately, Nx has a command to add the Nx package to your existing project and make it available for use:

```bash
npx nx@latest init
```

Once added, it’s up to you to decide which features of Nx you want to use. Nx also provides [several adoption guides](https://nx.dev/recipes/adopting-nx) to help you integrate it with an existing project.

* * *

## Key Nx features to know

The main goal of Nx is to make developers’ lives easier so they can spend less time on tooling and more time on actually writing code. To achieve this goal, Nx offers many features, but some highlights include:

*   [**A modular plugin system**](https://nx.dev/nx-api/plugin): Nx has many custom plugins that both generate code as well as execute tasks. There are special plugins for different frameworks and libraries like Angular, Cypress, Next, and many others
*   [**Inferring tasks with plugins**](https://nx.dev/concepts/inferred-tasks): When you add Nx to a project, it will attempt to recognize tooling for whatever type of project you are working. For example, if you’re using webpack, Nx will identify this and attempt to cache webpack-specific files when running builds
*   [**Caching**](https://nx.dev/concepts/how-caching-works): Wherever possible, Nx will attempt to cache anything in a task that can be reused. This is commonly seen in builds, but also in tests and other outputs
*   [**Automate updating dependencies**](https://nx.dev/features/automate-updating-dependencies): With the `nx migrate` command, Nx will attempt to upgrade packages in your project to either the latest version or a specific version. The result is a `migrations.json` file that you can use to understand what Nx did. When running this command, Nx will attempt to update your source code according to the newer versions of the packages. Then, it’s up to you to review the changes before committing
*   [**Managing releases**](https://nx.dev/features/manage-releases): Nx has an `nx release` command that you can use to do a code release in your project. Nx offers a full API with different variations of releases and features like a change log that you can use for your team
*   [**IDE integrations**](https://nx.dev/features/integrate-with-editors): Nx has integrations for common editors like VS Code and Webstorms that enable visual components for using Nx
*   [**CI/CD integrations with Nx Cloud**](https://nx.dev/ci/intro/ci-with-nx): Nx has a cloud offering where things like cached builds or test results can be shared among distributed teams. Nx has recipes for multiple source control options, and can be customized to meet different team’s demands

* * *

## Practical business use cases for Nx

Nx appeals to both large and small teams. The goal in both cases is to improve developer productivity and automate whenever possible. 

Nx can help a small team of developers to get started with shared tooling and an initial setup for a project. This is particularly helpful with setting up things like linting or build rules. 

Larger teams can add Nx to an existing project and still be able to use the same suite of tools that smaller teams use at scale. The only thing that is required is to add Nx as a dependency to a project. From there, all of the Nx commands are at your disposal.

* * *

## Getting started with Nx

Nx allows you to create both monorepos and standalone projects. In the next few sections we’ll create a React monorepo as an example of how you can get started. I encourage you to check the [many tutorials that are available on the Nx site.](https://nx.dev/getting-started/why-nx) 

First, go to a terminal and navigate to a folder you want to work in. Then, run the following:

```bash
npx create-nx-workspace@latest react-monorepo --preset=react-monorepo
```

Let’s look at that command:

*   `npx create-nx-workspace@latest` is the npx command to generate a workspace or work area that your projects will live
*   `react-monorepo` is the name of your project
*   `--preset=react-monorepo` is the settings or overrides applicable to the project

Typically, any Nx command that you run will have the above three pieces. When you run the command above, you’ll first be asked a set of questions: ![Developer Terminal Showing Questions To Set Up Project After Running Nx Command](https://blog.logrocket.com/wp-content/uploads/2024/03/img3-Developer-terminal-questions-running-Nx-command.jpeg) Once you’ve answered the questions, this is what that initial project structure should look like: ![Initial Nx Project Structure Setup](https://blog.logrocket.com/wp-content/uploads/2024/03/img4-Initial-Nx-project-structure-setup.jpeg) 

You may have noticed there is an `apps` folder as well as a `nx.json` and `package.json` folder at the root. The `package.json` file is what you would normally see in any JavaScript application with the project dependencies. The `nx.json` file has the information about what builders and generators are used by Nx: ![Nx Json File Showing Builders And Generators Used By Nx](https://blog.logrocket.com/wp-content/uploads/2024/03/img5-Nx-JSON-file-builders-generators.jpeg) The `apps` folder has two projects:

*   `react-monorepo`: The main React application
*   `react-monorepo-e2e`: The end-to-end tests for the React application

You may have noticed that in the base of the project, there is already an `eslintrc.json` file as well as a `prettierrc.json` file. The created project is already wired up for linting with [ESLint and Prettier](https://blog.logrocket.com/using-prettier-eslint-automate-formatting-fixing-javascript/). 

Within the `react-monorepo` project, there is also a `project.json` file which shows what the various Nx commands like `serve`, `build`, and `preview` will do: ![Nx Project Json File Showing What Various Nx Commands Will Do](https://blog.logrocket.com/wp-content/uploads/2024/03/img6-Nx-project-json-file-Nx-command-descriptions.jpeg) If you run the `nx serve react-monorepo` command, the project will be served locally: ![Nx React Monorepo Project Served Locally](https://blog.logrocket.com/wp-content/uploads/2024/03/img7-Nx-project-served-locally.jpeg) Now, let’s add another project to this new monorepo. One of Nx’s greatest assets is the amount of documentation and help that the CLI provides in general development. Watch what happens if you just run this command:

```bash
npx nx list @nx/react
```

This provides a list of the generators specific to React. You now can see the different commands that you could potentially run to generate pieces of a React project: ![List Of Nx Generators Specific To React Showing Different Commands That Can Be Used To Generate Pieces Of A React Project](https://blog.logrocket.com/wp-content/uploads/2024/03/img8-Nx-generators-specific-React.jpeg) Let’s go ahead and add a secondary application to the main project with the following:

```bash
npx nx g @nx/react:app inventory --directory=apps/inventory
```

Note that if you added `--dry-run` to this command, it would show you what would be generated without creating anything. This is another great aspect of the Nx CLI, as it allows developers to see what will be created before doing anything. 

When it runs, you should see a few quick questions and output similar to the following:

```plaintext
➜  react-monorepo git:(master) npx nx g @nx/react:app inventory --directory=apps/inventory          

>  NX  Generating @nx/react:application

✔ Would you like to add React Router to this application? (y/N) · true
✔ Which E2E test runner would you like to use? · cypress
✔ What should be the project name and where should it be generated? · inventory @ apps/inventory
CREATE apps/inventory/index.html
CREATE apps/inventory/public/favicon.ico
CREATE apps/inventory/src/app/app.spec.tsx
CREATE apps/inventory/src/assets/.gitkeep
CREATE apps/inventory/src/main.tsx
CREATE apps/inventory/tsconfig.app.json
CREATE apps/inventory/src/app/nx-welcome.tsx
CREATE apps/inventory/src/app/app.module.scss
CREATE apps/inventory/src/app/app.tsx
CREATE apps/inventory/src/styles.scss
CREATE apps/inventory/tsconfig.json
CREATE apps/inventory/project.json
UPDATE nx.json
CREATE apps/inventory/tsconfig.spec.json
CREATE apps/inventory/vite.config.ts
CREATE apps/inventory/.eslintrc.json
CREATE apps/inventory-e2e/project.json
UPDATE package.json
CREATE apps/inventory-e2e/src/e2e/app.cy.ts
CREATE apps/inventory-e2e/src/support/app.po.ts
CREATE apps/inventory-e2e/src/support/e2e.ts
CREATE apps/inventory-e2e/src/fixtures/example.json
CREATE apps/inventory-e2e/src/support/commands.ts
CREATE apps/inventory-e2e/cypress.config.ts
CREATE apps/inventory-e2e/tsconfig.json
CREATE apps/inventory-e2e/.eslintrc.json

added 93 packages, and audited 989 packages in 18s

227 packages are looking for funding
  run `npm fund` for details

found 0 vulnerabilities
```

Looking back at our project, you’ll now see `inventory` and `inventory-e2e` projects alongside our `react-monorepo` and `react-monorepo-e2e` projects: ![Project Structure Showing Inventory And Inventory E2e Projects Alongside Original Projects](https://blog.logrocket.com/wp-content/uploads/2024/03/img9-Project-structure-inventory-inventory-e2e-projects-added.jpeg) With the project built above, we can go ahead and run a build of the main `react-monorepo` project: ![Developer Terminal Showing Build Of Main React Monorepo Project Being Run](https://blog.logrocket.com/wp-content/uploads/2024/03/img10-Run-build-main-react-monorepo-project.jpeg) Now, let’s do the same for the `inventory` project: ![Developer Terminal Showing Build Of Inventory Project Being Run](https://blog.logrocket.com/wp-content/uploads/2024/03/img11-Run-build-inventory-project.jpeg) This is pretty standard for the process, but what if we want to run them together? Run `nx run-many -t build`: ![Developer Terminal Showing Build Of Both React Monorepo And Inventory Projects Being Run](https://blog.logrocket.com/wp-content/uploads/2024/03/img12-Run-projects-together.jpeg) Notice that unlike the original build commands, these builds only took one second and were cached. This is one of many optimizations that Nx provides for the regular development process. There are many more that are outlined in their docs as well as a [the React monorepo tutorial](https://nx.dev/getting-started/tutorials/react-monorepo-tutorial). 

In addition to the local commands, I should also mention that Nx has a Nx Cloud that allows you to distribute builds and tasks into the cloud. This is a really powerful optimization because it enables multiple individuals working on the same project share things like test results and dependencies. 

I encourage you to watch [this video tutorial](https://www.youtube.com/watch?v=NZF0ZJpgaJM) by the Nx team to see Nx Cloud in action.

* * *

## Deploying your Nx project

Deploying any project can be difficult, but Nx has multiple integrations that help you in the form of [executors](https://nx.dev/ci/recipes/other/ci-deployment) as well as [CI options with Nx Cloud](https://nx.dev/ci/recipes/set-up). 

Executors allow you to dictate how Nx will run tasks, and in the case of deployment, bundle results. There are supported executors within Nx for TypeScript and JavaScript. There is also a way you can build your own executor for your deployment. 

Here is an example from the official Nx documentation of a custom executor:

```javascript
// example copied from the official Nx Documentation at
// https://nx.dev/ci/recipes/other/ci-deployment

import { createPackageJson, createLockFile } from '@nx/devkit';
import { writeFileSync } from 'fs';

export default async function buildExecutor(
  options: Schema,
  context: ExecutorContext
) {
  // ...your executor code

  const packageJson = createPackageJson(
    context.projectName,
    context.projectGraph,
    {
      root: context.root,
      isProduction: true, // We want to strip any non-prod dependencies
    }
  );

  // do any additional manipulations to "package.json" here

  const lockFile = createLockFile(packageJson);
  writeJsonFile(`${options.outputPath}/package.json`, builtPackageJson);
  writeFileSync(`${options.outputPath}/${packageLockFileName}}`, lockFile, {
    encoding: 'utf-8',
  });

  // any subsequent executor code
}
```

Note how you can use the `createPackageJson` to dicate how your `package.json` file is generated for output as well as where to store your lockfile when the dependencies are installed. 

With [Nx Cloud](https://nx.dev/ci/intro/ci-with-nx), you can make use of several optimizations, including:

*   Remote caching
*   Distributing tasks across different machines
*   Controlling testing so only code impacted by a PR is tested

And many more.

* * *

## Nx vs. similar tools

Alternatives to Nx include Rush Stack, Lerna, Turborepo, and Yarn Workspaces:

<table>

<thead>

<tr>

<th>Tool</th>

<th>Purpose</th>

<th>Managing team</th>

<th>Target platform</th>

<th>Features</th>

</tr>

</thead>

<tbody>

<tr>

<td>Rush Stack</td>

<td>A collection of tools for Node.js applications that can be used to manage monorepos; built to work with Rush, a monorepo building tool</td>

<td>Backed by Microsoft</td>

<td>Web applications (JavaScript and TypeScript projects)</td>

<td>Monorepo scaffolding, API documentation generation, ESLint integration, and much more</td>

</tr>

<tr>

<td>Lerna</td>

<td>A monorepo package manager; also does many of the same things Nx does with task management and caching</td>

<td>Was taken over by Nrwl in recent years, so it integrates well with Nx</td>

<td>Node.js apps</td>

<td>A great tool if you have multiple appls in a monorepo and want to optimize things like build times and caching</td>

</tr>

<tr>

<td>Turborepo</td>

<td>A monorepo management tool that aims to maximize running speed for tasks and build times in your web projects</td>

<td>Was acquired by Vercel in recent years</td>

<td>Web applications</td>

<td>A highly efficient caching mechanism that it uses when running tasks; CI integrations; multiple ways to optimize your project’s builds and caching</td>

</tr>

<tr>

<td>Yarn Workspaces</td>

<td>A package management tool that helps you optimize the ways packages are installed and shared in a monorepo project</td>

<td></td>

<td>Web applications</td>

<td>Doesn’t have the higher level tools like Rush Stack or Nx, but provides a common set of commands that allow you to efficiently manage package installations and dependencies in your web projects</td>

</tr>

</tbody>

</table>

All four of these options are great tools by themselves that offer much more beyond what’s covered above. However, they are also focused on their specific use cases, whereas Nx offers a wide range of services and configurations that can be applied to a large variety of projects.

The tools listed above are great for specific needs, but if you’re looking for a more robust set of features, then Nx will likely be your tool of choice. Nonetheless, the tools listed here offer great features for any project and should still be utilized if your team needs more intentional tooling.

#### _Further reading:_

*   [Setting up a Monorepo with Lerna for a TypeScript project](https://blog.logrocket.com/setting-up-monorepo-lerna-typescript/#what-lerna)
*   [Building a Fullstack TypeScript Application with Turborepo](https://blog.logrocket.com/build-full-stack-typescript-application-turborepo/#what-is-turborepo)
*   [Advanced Package Manager Features for npm, Yarn, and pnpm](https://blog.logrocket.com/advanced-package-manager-features-npm-yarn-pnpm/)

* * *

## Conclusion

In this post, I have walked through Nx and provided details on how you could adopt it in your projects. 

I included a high level overview of the features, solid use cases, and a getting-started section that covers how you could build a project with Nx. I also included a comparative section where I covered some other tools that do similar things to what Nx does. 

I encourage you to review the [Nx documentation](https://nx.dev/getting-started/intro) and try out their tools with a new project or add to an existing one. This post covered several features at a high level, but there are even more specifics offered for projects. 

It will be exciting to see the development of Nx in the future as these features continue to grow and develop.

---

##Get set up with LogRocket's modern error tracking in minutes:

1. Visit https://logrocket.com/signup/ to get an app ID.
2. Install LogRocket via NPM or script tag. `LogRocket.init()` must be called client-side, not server-side.

NPM:
```bash
$ npm i --save logrocket 

// Code:

import LogRocket from 'logrocket'; 
LogRocket.init('app/id');
```
Script Tag:
```javascript
Add to your HTML:

<script src="https://cdn.lr-ingest.com/LogRocket.min.js"></script>
<script>window.LogRocket && window.LogRocket.init('app/id');</script>
```

3.(Optional) Install plugins for deeper integrations with your stack:
*   Redux middleware
*   ngrx middleware
*   Vuex plugin

[Get started now](https://lp.logrocket.com/blg/signup)