Improve build time with npm CI and Jenkins

When building a project that uses npm, one of the first things to do is to install the needed npm modules under $PROJECT/npm_modules. That is accomplished with npm install. But that is quite time consuming, if we’re using a CI system like Jenkins or Travis that can slow down the builds a lot.

Since npm 5.7.0, there’s a new option: npm ci. That new option is used to improve the installation of modules in CI systems. Bottom line is that it uses the modules under ${HOME}/.npm, it skips some user oriented checks. However it does more strict checks used to catch inconsistencies.

Essentially, the differences between npm install and npm ci are:

  • The project must have an existing package-lock.json or npm-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 before npm ci begins its install.
  • It will never write to package.json or any of the package-locks: installs are essentially frozen.

That way, it saves you from checking if the contents of package.json have changed and keeping a copy of node_modules outside the project directory. Until now I had to keep a copy of the node_modules directory needed in my projects outside the Jenkins scope; when firing a build a special pipeline step had to check whether the package.json had changed and then that step had to copy the node_modules. Dirty work and very error prone. With npm ci I don’t have to do that anymore.