How Turborepo and Nx Cache JavaScript Builds

Monorepo build tools like Turborepo and Nx optimize JavaScript development by ensuring tasks are never executed twice if their inputs have not changed. By treating build scripts as deterministic functions, these tools calculate a unique cryptographic hash for each task, evaluate whether an identical run exists in a local or remote storage system, and instantly restore saved build artifacts and terminal logs instead of executing the actual compiler.

1. Generating the Input Hash (The Cache Key)

Before executing any script (such as build, lint, or test), the tool creates a fingerprint representing the exact state of that task. This hash is computed from several key inputs:

If any of these factors change, the calculated hash changes, resulting in a cache miss.

2. Output and Log Capture

When a task runs for the first time, a cache miss occurs. The tool executes the command normally while intercepting two primary types of data:

  1. Artifacts: The files and directories generated by the process (e.g., dist, build, or .next folders) as declared in the pipeline configuration.
  2. Terminal Logs: The standard output (stdout) and standard error (stderr) streams emitted during execution.

Once the process completes successfully, the tool packages the specified output directories and log files into an archive (typically a compressed tarball) and stores it using the input hash as the key.

3. Cache Retrieval and Replay

On subsequent executions, the tool recalculates the input hash:

4. Local vs. Remote Caching

5. Dependency Graph Integration

Turborepo and Nx analyze the project’s dependency graph to ensure correct cache invalidation across interdependent packages. If Package A depends on Package B, a modification to Package B changes Package B’s hash. Because Package A includes the hash of its dependencies in its own input calculation, Package A’s cache is invalidated automatically, ensuring that dependent code is always built against up-to-date upstream artifacts.