Skip to main content
The Bitwarden Clients repository uses Nx as its monorepo build system. Nx provides intelligent build orchestration, computation caching, and task scheduling across all applications and libraries.

Nx Configuration

The primary Nx configuration lives in nx.json at the repository root:
nx.json

Key Concepts

Named Inputs

Named inputs define file sets that Nx uses to determine if a task needs to be re-run:
All files in the project root plus shared global files:
All default files excluding test files:
Used for production builds to avoid cache invalidation from test changes.
Root configuration files that affect all projects:
Changes to these files invalidate all project caches.

Target Defaults

Target defaults apply configuration to all projects with a matching target:
What this means:
  • "dependsOn": ["^build"] - Build all dependencies before building this project (the ^ means upstream dependencies)
  • "inputs" - Use production files for cache key calculation
  • "outputs" - Cache the build output directory
  • "cache": true - Enable Nx computation caching

Project Configuration

Each library has its own project.json defining available targets and configuration:
libs/auth/project.json

Project Tags

Tags enable enforcement of architectural boundaries:
You can create lint rules to prevent unwanted dependencies:
.eslintrc.js

Running Tasks

Single Project

Run a target for a specific project:

Multiple Projects

Run a target across multiple projects:

Affected Projects

Run tasks only for projects affected by changes:
How “affected” works:Nx analyzes your git changes and the dependency graph to determine which projects are affected. If you modify libs/auth, Nx knows that apps/web, apps/browser, apps/desktop, and apps/cli depend on it and marks them as affected.

Parallel Execution

Nx can run tasks in parallel for better performance:
nx.json
Override for specific commands:

Computation Caching

Nx caches task outputs to avoid redundant work. When you run a task, Nx:
  1. Computes a hash based on:
    • Input files (defined by inputs)
    • Task configuration
    • Dependency outputs (if dependsOn specified)
  2. Checks the cache for matching hash
  3. Restores from cache if found, or runs the task and caches the result

Cache Directory

Cached outputs are stored in .nx/cache:
Add .nx/cache to .gitignore - cache is local and should not be committed.

Clearing Cache

Skip Cache

Force execution even if cache exists:

Task Dependencies

Define task execution order with dependsOn:

Upstream Dependencies (^)

Build all upstream dependencies first. If apps/web depends on libs/auth, running nx build web will first build @bitwarden/auth.

Same-Project Dependencies

Run generate-types target in the same project before build.

Combined Dependencies

Run generate-types locally AND build upstream dependencies.

Custom Plugins

The repository includes a custom Nx plugin:
nx.json
This plugin lives in libs/nx-plugin and provides:
  • Custom executors for Bitwarden-specific build tasks
  • Generators for creating new libraries and applications
  • Additional linting rules and checks
See libs/nx-plugin/README.md for details.

Task Pipelines

Nx automatically creates a task pipeline based on dependencies: Running nx build web executes:
  1. nx build @bitwarden/common
  2. nx build @bitwarden/auth and nx build @bitwarden/vault (parallel)
  3. nx build web
Nx optimizes the pipeline to maximize parallelism while respecting dependencies.

Visualizing the Graph

Nx can generate a visual dependency graph:
The graph shows:
  • All projects in the workspace
  • Dependencies between projects
  • Affected projects (when using affected:graph)

Common Workflows

Development Workflow

CI/CD Workflow

Full Rebuild

Performance Optimization

Use Affected Commands

Only build/test what changed: nx affected -t test

Enable Caching

Ensure cache: true in target definitions

Increase Parallelism

Use --parallel=8 for CI environments with more CPU cores

Optimize Inputs

Exclude unnecessary files from inputs to improve cache hit rate

Integration with Angular

Angular projects use angular.json alongside Nx configuration:
angular.json
Nx integrates with Angular CLI:

Troubleshooting

Symptoms: Tasks always run even when nothing changed.Solutions:
  • Verify cache: true in target configuration
  • Check that inputs are defined correctly
  • Run nx reset to clear corrupted cache
  • Ensure timestamps are stable (watch for tools that modify files)
Symptoms: Affected detection misses dependencies or includes too much.Solutions:
  • Run nx graph to visualize actual dependencies
  • Check tsconfig.base.json path mappings are correct
  • Verify imports use path aliases, not relative paths
  • Update nx.json if you’ve added new projects
Symptoms: Build fails because dependencies aren’t built first.Solutions:
  • Add "dependsOn": ["^build"] to target configuration
  • Check that dependency relationships are correct in code
  • Verify project.json files have correct dependencies

Best Practices

1

Use affected commands in development

nx affected -t test is faster than testing everything
2

Keep tasks cacheable

Avoid non-deterministic operations (timestamps, random values) in build outputs
3

Define clear inputs

Specify exactly which files affect each task to maximize cache hits
4

Leverage parallelism

Let Nx run independent tasks in parallel - don’t serialize unnecessarily
5

Monitor cache effectiveness

Run with NX_VERBOSE_LOGGING=true to see cache hits/misses

Next Steps

Dependency Injection

Learn how services are registered and injected

Monorepo Structure

Understand the workspace organization

Additional Resources