Nx
Monorepo development with Nx including project graph, generators, executors, and computation caching
You are an expert in Nx for managing monorepo projects, including project graphs, code generation, task execution, and distributed caching. ## Key Points 1. **Use tags and module boundaries** — Enforce architectural constraints so feature libs don't import from app-specific code. 2. **Keep libraries small and focused** — Many small libs give Nx a finer-grained dependency graph and better cache hit rates. 3. **Use `namedInputs`** — Define reusable input sets to keep target definitions DRY and cache keys accurate. 4. **Prefer `affected` in CI** — Run `nx affected -t test,build,lint` to skip unchanged projects entirely. 5. **Enable Nx Cloud for teams** — Distributed caching and task execution prevent redundant CI work across branches. 6. **Use generators for consistency** — Create workspace generators for common patterns (new service, new feature lib) to enforce conventions. 7. **Visualize with `nx graph`** — Regularly inspect the project graph to catch unintended dependencies early. - **Circular dependencies** — Nx will detect these, but they often signal poor library boundaries. Extract shared code into a new lib. - **Over-coupling with barrel exports** — An `index.ts` that re-exports everything creates implicit dependencies. Export only the public API. - **Ignoring cache misses** — If caching seems broken, run `nx build my-app --verbose` and check which inputs changed. - **Not setting `defaultBase`** — Affected commands compare against `defaultBase` in `nx.json`. Set it to your trunk branch (`main` or `master`). - **Massive projects with no library extraction** — A single large app can't benefit from Nx's parallelism or caching. Break it into composable libraries.
skilldb get monorepo-skills/NxFull skill: 246 linesNx — Monorepo Management
You are an expert in Nx for managing monorepo projects, including project graphs, code generation, task execution, and distributed caching.
Core Philosophy
Overview
Nx is a build system with first-class monorepo support. It provides project graph analysis, computation caching, distributed task execution, code generators, and rich plugin ecosystem. Nx works with any language or framework but has deep integrations for JavaScript/TypeScript ecosystems including React, Angular, Node.js, and more.
Setup & Configuration
Creating a New Nx Workspace
# Create an integrated monorepo
npx create-nx-workspace@latest myorg --preset=ts
# Create with a specific framework
npx create-nx-workspace@latest myorg --preset=react-monorepo
# Add Nx to an existing monorepo
npx nx@latest init
nx.json Configuration
{
"$schema": "./node_modules/nx/schemas/nx-schema.json",
"namedInputs": {
"default": ["{projectRoot}/**/*", "sharedGlobals"],
"sharedGlobals": ["{workspaceRoot}/.github/workflows/*"],
"production": [
"default",
"!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)",
"!{projectRoot}/tsconfig.spec.json",
"!{projectRoot}/.eslintrc.json"
]
},
"targetDefaults": {
"build": {
"dependsOn": ["^build"],
"inputs": ["production", "^production"],
"cache": true
},
"test": {
"inputs": ["default", "^production", "{workspaceRoot}/jest.preset.js"],
"cache": true
},
"lint": {
"inputs": ["default", "{workspaceRoot}/.eslintrc.json"],
"cache": true
}
},
"defaultBase": "main"
}
Project Configuration (project.json)
{
"name": "my-app",
"sourceRoot": "apps/my-app/src",
"projectType": "application",
"targets": {
"build": {
"executor": "@nx/webpack:webpack",
"outputs": ["{options.outputPath}"],
"options": {
"outputPath": "dist/apps/my-app",
"main": "apps/my-app/src/main.ts",
"tsConfig": "apps/my-app/tsconfig.app.json"
},
"configurations": {
"production": {
"optimization": true,
"sourceMap": false
}
}
},
"serve": {
"executor": "@nx/webpack:dev-server",
"options": {
"buildTarget": "my-app:build"
}
}
}
}
Core Patterns
Running Tasks
# Run a target for a single project
nx build my-app
# Run a target for all projects
nx run-many -t build
# Run affected projects only (changes since base branch)
nx affected -t build
# Run with specific configuration
nx build my-app --configuration=production
# Visualize the project graph
nx graph
Code Generation
# Generate a new library
nx g @nx/js:library shared-utils --directory=libs/shared-utils
# Generate a new application
nx g @nx/react:application dashboard --directory=apps/dashboard
# Generate a component
nx g @nx/react:component button --project=ui-components
# Remove a project
nx g @nx/workspace:remove old-lib
Affected Commands
# See what's affected by current changes
nx affected:graph
# Test only affected projects
nx affected -t test --base=main --head=HEAD
# Lint affected projects
nx affected -t lint
Module Boundary Rules
In .eslintrc.json at workspace root:
{
"overrides": [
{
"files": ["*.ts", "*.tsx"],
"rules": {
"@nx/enforce-module-boundaries": [
"error",
{
"enforceBuildableLibDependency": true,
"allow": [],
"depConstraints": [
{
"sourceTag": "scope:app",
"onlyDependOnLibsWithTags": ["scope:shared", "scope:feature"]
},
{
"sourceTag": "scope:feature",
"onlyDependOnLibsWithTags": ["scope:shared"]
},
{
"sourceTag": "scope:shared",
"onlyDependOnLibsWithTags": ["scope:shared"]
}
]
}
]
}
}
]
}
Nx Cloud / Remote Caching
# Connect to Nx Cloud
npx nx connect
# Or configure manually in nx.json
{
"nxCloudAccessToken": "your-token"
}
Custom Executors
// libs/my-plugin/src/executors/custom/executor.ts
import { ExecutorContext } from '@nx/devkit';
export interface CustomExecutorOptions {
outputPath: string;
}
export default async function runExecutor(
options: CustomExecutorOptions,
context: ExecutorContext
) {
const projectName = context.projectName;
console.log(`Running custom executor for ${projectName}`);
// Your build logic here
return { success: true };
}
Best Practices
- Use tags and module boundaries — Enforce architectural constraints so feature libs don't import from app-specific code.
- Keep libraries small and focused — Many small libs give Nx a finer-grained dependency graph and better cache hit rates.
- Use
namedInputs— Define reusable input sets to keep target definitions DRY and cache keys accurate. - Prefer
affectedin CI — Runnx affected -t test,build,lintto skip unchanged projects entirely. - Enable Nx Cloud for teams — Distributed caching and task execution prevent redundant CI work across branches.
- Use generators for consistency — Create workspace generators for common patterns (new service, new feature lib) to enforce conventions.
- Visualize with
nx graph— Regularly inspect the project graph to catch unintended dependencies early.
Common Pitfalls
- Circular dependencies — Nx will detect these, but they often signal poor library boundaries. Extract shared code into a new lib.
- Over-coupling with barrel exports — An
index.tsthat re-exports everything creates implicit dependencies. Export only the public API. - Ignoring cache misses — If caching seems broken, run
nx build my-app --verboseand check which inputs changed. - Not setting
defaultBase— Affected commands compare againstdefaultBaseinnx.json. Set it to your trunk branch (mainormaster). - Massive projects with no library extraction — A single large app can't benefit from Nx's parallelism or caching. Break it into composable libraries.
Anti-Patterns
Over-engineering for hypothetical scale. Building for millions of users when you have hundreds adds complexity without value. Solve today's problems first.
Ignoring the existing ecosystem. Reinventing functionality that mature libraries already provide well wastes time and introduces unnecessary risk.
Premature abstraction. Creating elaborate frameworks and utilities before you have enough concrete cases to know what the abstraction should look like produces the wrong abstraction.
Neglecting error handling at boundaries. Internal code can trust its inputs, but system boundaries (user input, APIs, file I/O) require defensive validation.
Skipping documentation for obvious code. What is obvious to you today will not be obvious to your colleague next month or to you next year.
Install this skill directly: skilldb add monorepo-skills
Related Skills
Changesets
Versioning and changelog management with Changesets for coordinated monorepo package releases
CI Optimization
CI/CD optimization for monorepos including affected detection, caching strategies, and parallel execution
Dependency Management
Managing internal package dependencies, versioning strategies, and dependency graph health in monorepos
Lerna
Multi-package repository management with Lerna for versioning, publishing, and task orchestration
Pnpm Workspaces
Managing monorepo packages with pnpm workspaces including linking, filtering, and dependency hoisting
Shared Configs
Sharing ESLint, TypeScript, Prettier, and other tool configurations across monorepo packages