Skip to main content

Documentation Index

Fetch the complete documentation index at: https://mintlify.com/nrwl/nx/llms.txt

Use this file to discover all available pages before exploring further.

Nx is a VSCode of build tools — a powerful core driven by metadata and extensible through plugins. Everything Nx does flows from a small set of interconnected concepts: project graphs, task graphs, affected commands, computation hashing, and caching.

The three levels of an Nx workspace

Workspace

The root of your repository. Contains nx.json, one or more projects, and shared configuration.

Projects

Individual applications or libraries detected by package.json or project.json files. Each project has named targets (tasks) that Nx can run.

Tasks

An invocation of a target on a specific project. Running nx build myapp creates a single myapp:build task.

The project graph

Nx analyzes your file system to build a project graph — a directed acyclic graph where nodes are projects and edges are dependencies between them.
app1 ──depends on──► lib
app2 ──depends on──► lib
Nx identifies projects by looking for package.json or project.json files. It then infers dependencies by:
  • Statically analyzing TypeScript/JavaScript import statements
  • Reading installed node_modules versions
  • Respecting manually declared implicitDependencies in project configuration
  • Using plugin-provided dependency detection logic
Nx caches the project graph and only re-analyzes files that have changed since the last run, keeping graph computation fast even in large repositories.

Metadata-driven

Everything in Nx comes with metadata that enables toolability. Nx gathers information about your projects and tasks and uses that information to help you understand and interact with your codebase. With the right plugins installed, most of this metadata can be inferred directly from your existing configuration files — no manual definition required. This metadata powers:
  • The Nx CLI itself
  • VSCode and WebStorm integrations via Nx Console
  • GitHub PR integration
  • Third-party tools built on top of Nx

The task graph

Nx uses the project graph to construct a task graph for every command you run. The task graph and the project graph are related but not isomorphic — task dependencies are determined by target configuration, not purely by project dependencies. For example, running nx test lib produces a task graph with a single node:
lib:test
But running nx run-many -t test -p app1 app2 lib produces a task graph with three nodes that can run in parallel, because testing app1 does not depend on testing lib by default:
app1:test   (runs in parallel)
app2:test   (runs in parallel)
lib:test    (runs in parallel)
Now consider a test target that declares it depends on ^test (test of all dependencies):
apps/app1/project.json
{
  "test": {
    "executor": "@nx/jest:jest",
    "outputs": ["{workspaceRoot}/coverage/apps/app1"],
    "dependsOn": ["^test"],
    "options": {
      "jestConfig": "apps/app1/jest.config.js",
      "passWithNoTests": true
    }
  }
}
With this configuration, the same command produces a different task graph where lib:test must complete before app1:test and app2:test can start:
lib:test
  └──► app1:test
  └──► app2:test
Nx executes as many tasks in parallel as constraints allow, maximizing throughput.

Affected commands

As your workspace grows, running every task in the repository on every CI run becomes too slow. Nx solves this with the affected command, which performs code-change analysis to compute the minimum set of projects that could be impacted by your changes. When you run nx affected -t test, Nx:
  1. Looks at the files changed in your PR (compared to the base branch)
  2. Determines which projects own those files
  3. Walks the project graph to find all downstream dependents
  4. Runs nx run-many -t test for only that set of projects
For example, if your PR changes lib, and app1 and app2 both depend on lib, Nx runs:
nx run-many -t test -p app1 app2 lib
Nx also understands the nature of changes. Updating the version of next in package.json only affects projects that use Next.js — not every project in the repo.

Computation hashing and caching

Before running any cacheable task, Nx computes a computation hash based on:
  • All source files of the project and its dependencies
  • Relevant global configuration (e.g., nx.json, tsconfig.base.json)
  • Versions of external dependencies
  • Runtime values such as the Node.js version
  • CLI command flags
If a matching hash exists in the local cache (.nx/cache) or the remote cache (Nx Cloud), Nx replays the result — restoring output files and printing terminal output — without running the task. From the user’s perspective, the command ran the same, only much faster. If no match is found, Nx runs the task and stores its outputs for future use.
See How Caching Works for a complete description of hash inputs, cache storage, and configuration options.

Distributed task execution

For large workspaces, even aggressive caching may not be enough to keep CI fast. Nx Agents distribute the task graph across multiple machines. Tasks run in parallel across agents, sharing artifacts through remote caching. From your CI configuration’s perspective, results appear as if everything ran on a single machine.

Summary

Projects are detected from package.json and project.json files. Dependencies are inferred from import statements, installed packages, and plugin logic. The graph is cached and incrementally updated.
Tasks declare dependencies via dependsOn in target configuration. The task graph determines execution order and parallelism. The project graph and task graph are related but not identical.
Changed files map to affected projects via the project graph. Only those projects and their dependents have their tasks run.
The cache key is a hash of all inputs. Cache hits restore output files and terminal output. The cache can be local, remote, or both.