Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

ianflanagan1's avatar

Please rate my CI strategy for caching vendor/ :)

Currently my CI runs the following for every test/deployment

// TEST STAGE
git clone
composer install
npm install
npm run build
// run tests
// delete vendor

// DEPLOY STAGE
composer install --no-dev --classmap-authoritative
// copy to server

I want to speed this up by caching 3 directories: vendor/ (dev), vendor/ (no-dev) and node_modules/. In psuedocode, I plan to replace composer install with:

if (composer.lock == cached composer.lock)
	copy cached vendor
	if (is_deploy_stage) composer dump-autoload --no-dev --classmap-authoritative
else
	if (is_deploy_stage) composer install --no-dev --classmap-authoritative
	else composer install
	cache vendor

And replace npm install with:

if (package-lock.json == cached package-lock.json)
	copy cached node_modules
else
	npm install
	cache node_modules
  1. Can you see anything wrong with this? Or anything missing?
  2. I'm not familiar with npm. I assume there's no need for a 'dump-autoload' equivalent when using an old cache with new code?
  3. How about --dev --classmap-authoritative for Test Stage, so that bad class references might be caught?
  4. Is it ok for all developers to just run composer update and npm update as a morning/pre-commit ritual, or should they be run with more care (given that all dependencies are ^ed to major versions)?
0 likes
5 replies
ianflanagan1's avatar

It turns out npm install actually changes the package-lock.json file (which makes no sense to me, coming from Composer...), and that busts the cache. So npm ci is the better install command for caching the dependencies. Hope this is useful to someone!

maxxd's avatar

If you haven't changed the package.json file, npm install doesn't change the lock file. npm update will change the lock file, but install will attempt to install the versions of packages defined in the package.json file. Unless you're lock file was already out of date and running install actually did install new packages.

ianflanagan1's avatar

Unfortunately not true. For me, npm install changes package-lock.json's "name" attribute to the current directory name. In a multi-branch pipeline, the directory name includes the git branch, so that's always different from the "name" attribute in the freshly cloned package-lock.json

That's already frustrating for caching, but googling reveals claims that it can update packages versions too:

It seems to be a historical issue, and/or only happens if package-lock.json doesn't satisfy package.json's requirements.

Either way, my caching problem is solved by npm ci which leaves the lockfile locked, and throws an error instead of auto-updating, which is much safer in a CI setup, and what I'd expect to be the normal behaviour

maxxd's avatar

That makes sense - as I said, if you're lock file is out of date, install will in fact update package-lock. The bigger question you should ask is why is your lock file behind your package file?

ianflanagan1's avatar

It’s not behind. It’s in a differently-named directory.

And if it is ever behind, I want that to be an error that stops deployment, not ignored.

Please or to participate in this conversation.