Node.js is a JavaScript runtime for building servers, CLIs, and backend services. Nx scales your Node monorepo with caching, distributed task execution, and affected-only builds.
The Node plugin contains generators and executors to manage Node applications within an Nx workspace.
Requirements
Section titled “Requirements”Below is a reference table that matches the most recent major versions of Nx to the versions of Node.js that they officially support, and are tested against.
The Nx policy is to support the LTS versions (i.e. actively maintained even numbered versions) of Node.js, but we will only remove support for older versions in a major version of Nx to avoid unexpected disruption. We may add support for newer LTS versions in a minor version of Nx as long as it would not break existing projects.
| Nx Version | Node Version |
|---|---|
| 23.x (current) | 26.x, 24.x, ^22.12.0 |
| 22.x | 26.x, 24.x, ^22.12.0, ^20.19.0 |
| 21.x | 24.x, ^22.12.0, ^20.19.0 |
| 20.x | 22.x, 20.x, 18.x |
We intentionally do not include an "engines" field in the package.json file for Nx in order to allow for user flexibility, but this table should be considered the official compatibility matrix.
This table will be updated from time to time to reflect the latest versions of Node.js that are supported. If you encounter issues with Nx, please make sure you are using a supported version of Node.js before filing an issue.
Setting up @nx/node
Section titled “Setting up @nx/node”Installation
Section titled “Installation”In any Nx workspace, you can install @nx/node by running the following command:
nx add @nx/nodeThis will install the correct version of @nx/node.
Using the @nx/node plugin
Section titled “Using the @nx/node plugin”Creating applications
Section titled “Creating applications”You can add a new application with the following:
nx g @nx/node:application apps/my-new-appYou can run your application with nx serve my-new-app, which starts it in watch mode.
The serve task comes from the first two lines of src/main.ts:
#!/usr/bin/env node// @nx-target-name: serve@nx/js/node picks up files whose shebang names node, and @nx-target-name sets the task name. The generator adds that plugin to nx.json unless a registration already exists. The plugin runs scripts in watch mode by default, so nx serve runs the file with node --watch and restarts it on changes without a build step. Set watch: false in the plugin options to turn watch off for every script the registration covers, serve included. Workspace libraries the application depends on are built first, through dependsOn on the serve entry in the project configuration. Node runs the TypeScript source directly, which requires Node.js 22.18 or later. These applications are ES modules, with "type": "module" in their package.json, so relative imports name the .ts file (./message.ts). The build rewrites them to .js.
In workspaces that use TypeScript path aliases, and for esbuild, Jest, or JavaScript (--js) applications, the shebang names tsx instead, which resolves path aliases and extensionless imports. Applications that use webpack, or workspaces with inference plugins turned off, get an explicit serve target in project.json instead.
Creating libraries
Section titled “Creating libraries”Node libraries are a good way to separate features within your organization. To create a Node library run the following command:
nx g @nx/node:lib libs/my-new-lib
# If you want the library to be buildable or publishable to npmnx g @nx/node:lib libs/my-new-lib --buildablenx g @nx/node:lib libs/my-new-lib \--publishable \--importPath=@myorg/my-new-libUsing node
Section titled “Using node”Testing projects
Section titled “Testing projects”You can run unit tests with:
nx test my-new-appnx test my-new-libReplace my-new-app with the name or your project. This command works for both applications and libraries.
Building projects
Section titled “Building projects”Node applications can be build with:
nx build my-new-appAnd if you generated a library with --buildable, then you can build a library as well:
nx build my-new-libApplications build with tsc in TypeScript workspaces that use project references, and with Rolldown in workspaces that use TypeScript path aliases. Fastify applications use esbuild there instead. Pass --bundler when generating the application to choose tsc, rolldown, esbuild, or webpack. The tsc bundler needs project references.
The output is in a dist folder. To change it, set outDir in tsconfig.app.json for tsc, or output.dir in rolldown.config.ts for Rolldown.
Application proxies
Section titled “Application proxies”Generating Node applications has an option to configure other projects in the workspace to proxy API requests. This can be done by passing the --frontendProject with the project name you wish to enable proxy support for.
nx g @nx/node:application apps/my-new-app \--frontendProject my-react-appWaiting for the server to be ready
Section titled “Waiting for the server to be ready”Tasks that depend on serve with waitFor: "ready", such as Playwright and Cypress e2e tasks, start once the server reports that it's listening. Applications generated with the Express, Fastify, Koa, or NestJS framework report it. Their src/main.ts calls emitReadySignal from @nx/js/ready-signal once the server listens, and their serve entry sets "readyWhen": { "signal": true }.
To add this to an existing server, check that the root package.json lists @nx/js, so the server can import it. If it doesn't, add @nx/js at the same version as nx:
npm install -D @nx/js@<nx-version>Call emitReadySignal with the server once it listens:
const server = app.listen(port, host, async () => { // Set when Nx waits for this server to be ready if (process.env.NX_READY_SIGNAL_SOCKET) { try { // Function keeps TypeScript and bundlers from rewriting or bundling the import const load = new Function('s', 'return import(s)') as ( s: string ) => Promise<{ emitReadySignal(server: unknown): boolean }>; (await load('@nx/js/ready-signal')).emitReadySignal(server); } catch { // @nx/js isn't installed } }});Then set readyWhen on the serve entry in the project configuration:
"serve": { "readyWhen": { "signal": true }}emitReadySignal reads the address from the server and passes it to the waiting tasks as NX_READY_URL. Without readyWhen, a task that waits for serve starts as soon as serve starts. For why the import is guarded, and for the other checks, see wait for a continuous task to be ready.
Debugging
Section titled “Debugging”VSCode integration
Section titled “VSCode integration”When generating Node applications, Nx automatically creates a VSCode debugging configuration:
- Automatic setup: A
.vscode/launch.jsonfile is created with pre-configured debugging settings. - Smart port allocation: Debug ports are automatically assigned starting from 9229, preventing conflicts between multiple applications.
- Source map support: Webpack configurations include
devtoolModuleFilenameTemplatefor accurate source mapping.
To debug your Node application in VSCode:
- Open your workspace in VSCode.
- Set breakpoints in your TypeScript source files.
- Go to the Debug panel
(Ctrl+Shift+D). - Select "Debug
{your-app-name}with Nx" from the dropdown. - Click the play button or press
F5.
The debugger will automatically:
- Start your application with
nx serve. - Attach to the Node.js debugger on the allocated port.
- Stop on breakpoints in your TypeScript source files, which
nx serveruns directly.
Manual debugging
Section titled “Manual debugging”To open the debugger on a specific port, add Node's --inspect flag to the shebang in src/main.ts, after the existing node or tsx:
#!/usr/bin/env -S node --inspect=9230If the application has an explicit serve target in project.json, set its port option or run nx serve my-new-app --port <number> instead.
For additional information on Node.js debugging, see the Node.js debugging getting started guide.
More documentation
Section titled “More documentation”Set up CI for your Node.js monorepo
Section titled “Set up CI for your Node.js monorepo”In CI, Nx runs nx affected to rebuild and retest only the projects a change touches, and caches results to skip repeated work.
For a complete pipeline, see Set up CI.