I'm using npm to install Node.js dependencies in my project. I want to cache Node.js packages (node_modules
) globally to speed up jobs in pipelines when deploying to Heroku. An example from the official docs of GitLab:
cache:
key: ${CI_COMMIT_REF_SLUG}
paths:
- .npm/
before_script:
- npm ci --cache .npm --prefer-offline
And here is another example in GitLab:
cache:
paths:
- node_modules/
Found some articles (Deploy Node.js App with GitLab CI/CD, Continuous Integration with Node.js, Heroku and GitLab CI/CD -Part 2) that used the second configuration above. I did give it a shot and I was able to deploy my app to Heroku with these settings successfully. But I'm not sure caching mechanism is working properly.
What is the difference between these configurations? Which one is the most convenient way to cache Node.js packages?
My current setup for gitlab-ci.yml
file:
image: node:latest
cache:
paths:
- node_modules/
stages:
- build
- deploy
build:
stage: build
script:
- npm i
- npm i -g gulp-cli
- gulp build
deploy:
image: ruby:latest
stage: deploy
script:
- apt-get update -qy
- apt-get install -y ruby-dev
- gem install dpl
- dpl --provider=heroku --app=$HEROKU_APP_NAME --api-key=$HEROKU_API_KEY
only:
- master
Not sure if I'm doing it the right way.
It depends if you want to use npm install
, aka npm i
, or if you want to use npm ci
.
npm install
will look first for an existent node_modules
folder and will re-use it. If not, will fetch the dependencies. Check the full algorithm.
npm ci
instead, removes an existing node_modules
folder to perform a clean install of the dependencies. From the docs:
In short, the main differences between using
npm install
andnpm ci
are:
- The project must have an existing
package-lock.json
ornpm-shrinkwrap.json
.- If dependencies in the package lock do not match those in package.json,
npm ci
will exit with an error, instead of updating the package lock.npm ci
can only install entire projects at a time: individual dependencies cannot be added with this command.- If a
node_modules
is already present, it will be automatically removed beforenpm ci
begins its install.- It will never write to
package.json
or any of thepackage-locks
: installs are essentially frozen.
Some tests having ~/.npm
and node_modules
populated:
$ npm i --prefer-offline
#...
updated 2 packages in 17.472s
$ rm -rf ~/.npm/ # removes global npm cache
$ npm i --prefer-offline
#...
up to date in 16.271s # removing npm cache does not affects to npm i
$ rm -rf node_modules/
$ npm i --prefer-offline
#...
added 2525 packages from 1197 contributors in 55.388s # removing node_modules affetcs to npm i
$ npm ci --prefer-offline
#...
updated 2 packages in 17.201s
$ rm -rf ~/.npm/ # removes global npm cache
$ npm ci --prefer-offline
#...
added 2532 packages in 48.362s # removing npm cache affects to npm ci
$ rm -rf node_modules/
$ npm ci --prefer-offline
#...
added 2532 packages in 18.695s # removing node_modules does not affetcs to npm ci
So ending up, npm ci
has CI oriented features which can be interesting to use with but if there are no benefits for you just cache node_modules
and use npm install
instead.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With