A static site’s CI has three layers: installing dependencies, building the site, and verifying the result. Timing them showed dependency installation taking one minute forty seconds of a two-and-a-half-minute run. Caching that single layer is where the payoff concentrates.
Designing the cache key
The cache is keyed on the lockfile hash. As long as the lockfile is unchanged the dependency tree is identical, so a wholesale restore is safe.
- Key:
deps-${{ hashFiles('package-lock.json') }} - Restore target: the package manager’s store directory
- A full install runs only when the lockfile changes, replacing the cache
Caching node_modules directly is a scheme that had broken for me before when the OS or toolchain moved; restoring through the store keeps the integrity checks in play.
Measured result
After the change, dependency installation went from 1m40s to 12 seconds, and the whole CI run from about 2m30s to just under a minute. Caching build artifacts themselves (optimized images and the like) has a hit rate that is hard to predict, so it stays deferred as the next step.
Takeaway
The fast route to a fast CI is to measure the slowest layer first and touch only that layer. Cache everything at once and you lose the ability to tell what broke when something does.