Skip to main content

Set Up Nx

Creating an Nx Workspace

If you are fortunate enough to start a new project from scratch, then you can simply generate a new Nx workspace using the following command:

bun create nx-workspace@latest <name> --preset <preset>

where preset is one of the following depending on your needs:

  • apps: creates an empty workspace.
  • ts: creates an empty workspace with TypeScript support.
  • angular|expo|express|nest|next|nuxt|react|react-native|vue: creates a workspace with a single application using the framework of your choice.
warning

There is also the npm preset but we only recommend it if you really know what you are doing.

Tell me more

The npm preset creates an empty workspace with two main differences (in order to align with the behavior of Lerna):

Note that these two behaviors can be controlled separately.

Curious about NPM workspaces along with Nx? Check out Analog & RxJS repositories. Note that analyzeSourceFiles is set to true in both repositories.

note

The exhaustive list of built-in presets is available here: https://nx.dev/nx-api/nx/documents/create-nx-workspace#preset.

Install Nx Globally

While this is optional, it is helpful to install Nx globally:

bun add -g nx@latest
info

Note that the global nx command will always use the workspace's version of Nx.

You don't have to worry about version mismatch.

Standalone vs. Integrated

With most presets, you will be asked to choose between a Standalone or an Integrated Monorepo workspace.

> Integrated monorepo, or standalone project? …
Integrated Monorepo: Nx creates a monorepo that contains multiple projects.
Standalone: Nx creates a single project and makes it fast.

Standalone mode will create an application at the root of the workspace. The file structure would look something like this:

├── README.md
├── index.html
├── nx.json
├── package.json
├── project.json
├── src
│ ├── app
│ │ ├── app.spec.ts
│ │ └── app.ts
│ └── main.ts
├── tsconfig.app.json
├── tsconfig.json
├── tsconfig.spec.json
└── vite.config.ts

It will also add scripts like build, start, and test to the package.json file.

Integrated Monorepo mode will create the application in the apps directory and create a tsconfig.base.json that all projects will extend from. The file structure would look something like this:

├── README.md
├── apps 👈
│ └── marmicode 👈
│ ├── index.html
│ ├── project.json
│ ├── src
│ │ ├── app
│ │ │ ├── app.spec.ts
│ │ │ ├── app.ts
│ │ └── main.ts
│ ├── tsconfig.app.json
│ ├── tsconfig.json
│ ├── tsconfig.spec.json
│ └── vite.config.ts
├── nx.json
├── package.json
└── tsconfig.base.json 👈
tip

Note that you can always switch from Standalone to Integrated Monorepo later on using the @nx/workspace:convert-to-monorepo generator:

nx g convert-to-monorepo

or by moving the application to the apps directory using the @nx/workspace:move generator:

nx g move --projectName <name> --destination apps/<name>

Make sure to add the @nx/workspace plugin:

nx add @nx/workspace
tip

Prefer Integrated Monorepo mode over Standalone.

In our experience, Standalone workspaces eventually end up being migrated to Integrated Monorepo.

In addition to this, note that even though it is possible to move the application using @nx/workspace:move generator later on, the process is not magic and might miss some things like files added after the initial creation. (e.g. docs, test setup files, etc...)

Migrating to Nx

If you are migrating an existing project to Nx, you have two options:

If you don't have a complex setup, we recommend the second option. In fact, the second option will provide a better starting point. (e.g. nx init will not set up a linter for you, but creating a new workspace will.)

Option 1: Add Nx to an Existing Workspace

Given an existing repository, we can add Nx to it using the following command:

nx init --integrated

Note that the --integrated option will only work on Angular CLI workspaces and Create React App (CRA) projects.

While this command works pretty well in most common cases, it is not perfect because:

  • it will generally reuse existing npm scripts (e.g. build, start, test, etc...) which might not be optimal compared to what Nx executors can offer,
  • it will prompt you to choose which of these scripts are cacheable and what are their outputs, but it will not ask about their inputs which we would have to configure later on in the nx.json file,
  • the final result will not be exactly aligned with an Nx workspace created from scratch.

Option 2: Merge a new Nx workspace into an existing repository

If you are migrating an existing repository to Nx, you can create a new Nx workspace and merge it into the existing repository.

This approach gives you more control while keeping you aligned with Nx defaults just as if you were starting a new project from scratch.

Step 1 - Create a new Nx workspace

bun create nx-workspace@latest <name> --preset <preset>

Step 2 - Merge the new Nx workspace into the existing repository

Go to your existing repository and merge the new Nx workspace into it:

# Add the new Nx workspace as a remote.
git remote add nx-workspace <path|url>

# Merge the new Nx workspace into the existing repository.
git fetch nx-workspace
git merge nx-workspace/main --allow-unrelated-histories
tip

The trick here resides in the --allow-unrelated-histories option which will allow you to merge two unrelated repositories.

Step 3 - Fix conflicts

You will most likely have conflicts to resolve. We recommend doing this using mob programming with your team.

We also recommend keeping Nx defaults as much as possible and only changing what is really necessary. The less you change, the less you diverge, and the easier it will be to upgrade Nx in the future.

Step 4 - Move app's source code into dedicated directory

If your existing repository has an app at the root, we recommend moving its source code into the apps/<name> directory created when generating the Nx workspace.

note

This makes it clear whether a file (configuration, documentation etc...) is specific to the app or to the whole workspace. It will also make things easier in the long run (e.g. configuring caching, adding apps/libs).

Using Nx

You can now run the Nx task of your choice to build, test or serve your applications.

List the projects in your workspace using the following command:

nx show projects

List the available targets for a specific project using the following command:

nx show project <project-name> --web
note

Learn more about Nx tasks in the Nx documentation.