How to Cache npm Dependencies in GitHub Actions
Cache ~/.npm, key it on the package-lock.json hash, and npm ci reuses the download cache instead of refetching every package.
The right thing to cache for npm is ~/.npm (the install download cache), not node_modules. Key it on a hash of package-lock.json so the entry rotates only when dependencies change, and add a restore-keys prefix for partial hits.
Steps
- Cache the
~/.npmdirectory, notnode_modules. - Key the cache on
hashFiles('**/package-lock.json'). - Add a
npm-prefix underrestore-keysfor a warm start on lockfile changes. - Run
npm ciafter the restore step.
Workflow
.github/workflows/ci.yml
steps:
- uses: actions/checkout@v4
- uses: actions/cache@v4
with:
path: ~/.npm
key: npm-${{ runner.os }}-${{ hashFiles('**/package-lock.json') }}
restore-keys: |
npm-${{ runner.os }}-
- run: npm ciGotchas
- The built-in
cache: npminput ofactions/setup-nodedoes the same thing with less YAML; reach foractions/cachewhen you need a custom key. - Including
runner.osin the key avoids restoring a Linux cache onto a Windows runner.
Related guides
How to Use restore-keys for Partial Cache Hits in GitHub ActionsUse restore-keys in GitHub Actions actions/cache to fall back to the most recent matching prefix when the exa…
How to Cache the pnpm Store in GitHub ActionsCache the global pnpm content-addressable store in GitHub Actions by resolving the store path with pnpm store…