Adding Nx to NPM/Yarn/PNPM Workspace
Migrating from Lerna?Interested in migrating from Lerna in particular? In case you missed it, Lerna v6 is powering Nx underneath. As a result, Lerna gets all the modern features such as caching and task pipelines. Read more on https://lerna.js.org/upgrade.
Nx has first-class support for monorepos. As a result, if you have an existing NPM/Yarn or PNPM-based monorepo setup, you can easily add Nx to get
- fast task scheduling
- support for task pipelines
- caching
- remote caching with Nx Cloud
- distributed task execution with Nx Cloud
This is a low-impact operation because all that needs to be done is to install the nx
package at the root level and add an nx.json
for configuring caching and task pipelines.
Installing Nx
Run the following command to automatically set up Nx:
โฏ
npx nx@latest init
This will set up Nx for you - updating the package.json
file and creating a new nx.json
file with Nx configuration based on your answers during the set up process. The set up process will suggest installing Nx plugins that might be useful based on your existing repository. The example below is using the @nx/eslint
and @nx/next
plugins to run ESLint and Next.js tasks with Nx:
1{
2 "plugins": [
3 {
4 "plugin": "@nx/eslint/plugin",
5 "options": {
6 "targetName": "eslint:lint"
7 }
8 },
9 {
10 "plugin": "@nx/next/plugin",
11 "options": {
12 "buildTargetName": "next:build",
13 "devTargetName": "dev",
14 "startTargetName": "start"
15 }
16 }
17 ]
18}
19
When Nx updates your package.json
scripts, it looks for scripts that can be replaced with an Nx command that has caching automatically enabled:
1{
2 "name": "my-workspace",
3 ...
4 "scripts": {
5- "build": "next build && echo 'Build complete'",
6+ "build": "nx next:build && echo 'Build complete'",
7- "lint": "eslint ./src",
8+ "lint": "nx eslint:lint",
9 "test": "node ./run-tests.js"
10 },
11 ...
12}
13
The @nx/next/plugin
plugin adds a next:build
target which runs next build
and sets up caching correctly. In other words, running nx next:build
is the same as running next build
with the added benefit of it being cacheable. Hence, Nx replaces next build
in the package.json
build
script to add caching to anywhere running npm run build
. Similarly, @nx/eslint/plugin
sets up the nx eslint:lint
command to run eslint ./src
with caching enabled. The test
script was not recognized by any Nx plugin, so it was left as is. After Nx has been setup, running npm run build
or npm run lint
multiple times, will be instant when possible.
You can also run any npm scripts directly through Nx with nx build
or nx lint
which will run the npm run build
and npm run lint
scripts respectively. In the later portion of the setup flow, Nx will ask if you would like some of those npm scripts to be cacheable. By making those cacheable, running nx build
rather than npm run build
will add another layer of cacheability. However, nx build
must be run instead of npm run build
to take advantage of the cache.
Inferred Tasks
You may have noticed that @nx/next
provides dev
and start
tasks in addition to the next:build
task. Those tasks were created by the @nx/next/plugin
plugin from your existing Next.js configuration. To view all available tasks, open the Project Details view with Nx Console or use the terminal to launch the project details in a browser window.
โฏ
nx show project my-workspace --web
my-workspace
Root: .
Type: Library
Targets
eslint:lint
eslint ./src
Cacheablenext:build
next build
Cacheabledev
next dev
start
next start
The project detail view lists all available tasks, the configuration values for those tasks and where those configuration values are being set.
Configure an Existing Script to Run with Nx
If you want to run one of your existing scripts with Nx, you need to tell Nx about it.
- Preface the script with
nx exec --
to havenpm run test
invoke the command with Nx. - Add the script to
includedScripts
. - Define caching settings.
The nx exec
command allows you to keep using npm test
or npm run test
(or other package manager's alternatives) as you're accustomed to. But still get the benefits of making those operations cacheable. Configuring the test
script from the example above to run with Nx would look something like this:
1{
2 "name": "my-workspace",
3 ...
4 "scripts": {
5 "build": "nx next:build",
6 "lint": "nx eslint:lint",
7 "test": "nx exec -- node ./run-tests.js"
8 },
9 ...
10 "nx": {
11 "targets": {
12 "test": {
13 "cache": "true",
14 "inputs": [
15 "default",
16 "^default"
17 ],
18 "outputs": []
19 }
20 }
21 }
22}
23
Now if you run npm run test
or nx test
twice, the results will be retrieved from the cache. The inputs
used in this example are as cautious as possible, so you can significantly improve the value of the cache by customizing Nx Inputs for each task.
Incrementally Adopting Nx
All the features of Nx can be enabled independently of each other. Hence, Nx can easily be adopted incrementally by initially using Nx just for a subset of your scripts and then gradually adding more.
For example, use Nx to run your builds:
โฏ
npx nx run-many -t build
But instead keep using NPM/Yarn/PNPM workspace commands for your tests and other scripts. Here's an example of using PNPM commands to run tests across packages
โฏ
pnpm run -r test
This allows for incrementally adopting Nx in your existing workspace.