Speed up your CI and DX with node_modules/.cache
You may not need to cache your entire node_modules
node_modules/.cache
is a community-standard cache folder for storing files. Many projects such as ava
, nyc
, storybook
, and many webpack
loaders and plugins use this folder by default. With some configuration, you can speed up your CI and developer experience by pointing other caches to this folder and persisting it across builds.
GitHub Actions Setup
Here’s an example GitHub Action that caches node_modules/.cache
, creating a new cache value after every run with the suffix -run-id-${{ github.run_id }}
. This is in contrast to the node_modules
cache that relies strictly on the hash of the manifest files. In other words, the node_modules
cache should only change when the manifest changes, but the node_modules/.cache
cache should be constantly updated.
Use node_modules/.cache for your commands
Here are some commonly used modules and how to set up their cache directories:
- jest: set
cacheDirectory: 'node_modules/.cache/jest'
in your config - stylelint: run with
--cache --cache-location=node_modules/.cache/stylelint
- eslint: run with
--cache --cache-location=node_modules/.cache/eslint
- babel-loader: set
cacheDirectory: 'node_modules/.cache/babel-loader
in your config
With these cache directories set up, I have experienced subsequent test and lint runs take a fraction of the time, both locally and on CI. I’ve been able to eliminate a lot of workarounds with this performance gain such as hooks that only lints changed files.
Consider caching node_modules/.cache instead of node_modules
When set up properly, you may only need to set up caching on the .cache
folder, especially if your npm ci
runs very fast.
Some reasons you may not want to cache your entire node_modules
folder are:
- On a self-hosted runner, you can rely on
npm
's caching mechanism, which already caches package tarballs on the runner (actions do not run in isolation, so they will have access to this folder) - Self-hosted runners will probably have a weaker connection to the cache store, making the cache slower
node_modules
tends to become large and each GitHub repository has a cache limit (currently 5GB), so caching yournode_modules
may evict your other caches sooner
Here are some cases you may still want to cache your node_modules
:
- Your
node_modules
folder is very large and caching is significantly faster than runningnpm ci
- You have a lot of postinstall build scripts, e.g. binaries that need to be compiled
My recommendation is to start with just caching node_modules/.cache
, then check whether caching node_modules
as well will speed up your CI.