> ## Documentation Index
> Fetch the complete documentation index at: https://tally.wharflab.com/llms.txt
> Use this file to discover all available pages before exploring further.

# tally/js/node-gyp-cache-mounts

> Native Node addon installs should cache node-gyp header downloads with BuildKit cache mounts.

Native Node addon installs should cache node-gyp header downloads with BuildKit cache mounts.

| Property | Value                                     |
| -------- | ----------------------------------------- |
| Severity | Info                                      |
| Category | Performance                               |
| Default  | Enabled                                   |
| Auto-fix | Yes (suggestion, requires `--fix-unsafe`) |

## Description

Flags JavaScript package install or rebuild `RUN` instructions in stages that look likely to compile native Node addons, but do not cache
node-gyp's header download directory.

The rule looks for native build signals such as:

* OS packages: `python3`, `make`, `gcc`, `g++`, `build-base`, or `build-essential`
* native addon helpers: `node-gyp`, `node-pre-gyp`, or `prebuild-install`
* rebuild commands: `npm rebuild`, `pnpm rebuild`, or `yarn rebuild`
* observable `package.json` dependencies such as `sharp`, `canvas`, `bcrypt`, `sqlite3`, `better-sqlite3`, `node-rdkafka`, `grpc`, or `isolated-vm`
* dev-only native dependencies, but only when the install command includes dev packages

## What The Fix Adds

The suggested fix adds a cache mount for node-gyp's devdir:

```dockerfile theme={null}
--mount=type=cache,target=/root/.cache/node-gyp,id=node-gyp,sharing=locked
```

When `tally/prefer-package-cache-mounts` is not enabled for the same run, the fix also adds the matching package-manager cache mount for `npm`,
`pnpm`, or `yarn`. When the generic cache-mount rule is enabled, this rule leaves package-manager caches to that rule to avoid duplicate suggestions.

For shell-form `RUN` instructions, the fix also inserts:

```dockerfile theme={null}
NPM_CONFIG_DEVDIR="/root/.cache/node-gyp"
```

If the stage already sets `NPM_CONFIG_DEVDIR`, `npm_config_devdir`, or `npm_package_config_node_gyp_devdir`, the rule uses that path for the cache
mount instead of adding another environment assignment.

## Examples

### Before

```dockerfile theme={null}
FROM node:22
RUN apt-get update && apt-get install -y python3 make g++
RUN npm ci --omit=dev
```

### After

```dockerfile theme={null}
FROM node:22
RUN apt-get update && apt-get install -y python3 make g++
RUN --mount=type=cache,target=/root/.npm,id=npm \
    --mount=type=cache,target=/root/.cache/node-gyp,id=node-gyp,sharing=locked \
    --mount=type=tmpfs,target=/tmp \
    NPM_CONFIG_DEVDIR="/root/.cache/node-gyp" npm ci --omit=dev
```

### Existing devdir

```dockerfile theme={null}
FROM node:22
ENV npm_package_config_node_gyp_devdir=/cache/node-gyp
RUN --mount=type=cache,target=/cache/node-gyp pnpm install --frozen-lockfile
```

No violation is reported because the install already uses an explicit node-gyp devdir cache.

## Guardrails

* Windows container stages are skipped because BuildKit `RUN --mount` is not supported there.
* Stages with explicit native build caches such as `ccache` or prebuild artifact cache mounts are skipped.
* The rule does not suggest tmpfs for `node_modules` or package `build/` directories. Compiled `.node` artifacts must remain in the image layer.

## References

* [node-gyp README](https://github.com/nodejs/node-gyp#readme)
* [Dockerfile `RUN --mount` reference](https://docs.docker.com/reference/dockerfile/#run---mount)
* [Docker cache optimization: Use cache mounts](https://docs.docker.com/build/cache/optimize/#use-cache-mounts)
