Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

NPM Best Practices for Continuous Integration

Tags:

npm

I am building a HTML5 front-end using NPM-based tools (grunt).

One of the first steps of my continuous integration build process is to run an npm install.

npm install is SLOW. Even with a local NPM proxy caching artifacts (Sonatype's Nexus 3), it is still taking 4 minutes!

$> time npm install
real    4m17.427s
user    0m0.170s
sys     0m0.290s

If I follow my usual best practices for continuous integration, I would start from a pristine SCM repository and run the build. This means that each time the CI build will have to do a fresh npm install and take on the cost of 4 minutes.

This is a significant proportion of my build time. I am discontent that the build is taking so long.


The alternative seems to be to keep the node_modules around between builds. However, I've had problems with the build becoming unstable as a result.

Removing dependencies from package.json does not remove them from node_modules with a simple npm install. I can work-around this with an npm prune first.

What is considered to be best practice here?

like image 258
jwa Avatar asked Aug 25 '16 07:08

jwa


2 Answers

Since March 5, 2018 and npm 5.7.1, you can use npm ci . This is much faster than a regular npm install because it omits some user-friendly features and installs packages for a userless CI environment.

The caveat here is that you'll need to make sure your package.json and package-lock.json files are in sync. If you install a new package, commit package.json but forget to do the same for package-lock.json, you'll get an error when running npm ci.

like image 82
walnut_salami Avatar answered Sep 28 '22 06:09

walnut_salami


Considering that in order to build you must install new packages, you have no choice but to call install. As for pristine, I strongly believe they refer to the "build" process and not the "dependency management" process.

Why are they different? Let's go through an example to make it more apparent.

As a developer, when you first start your job, you MUST "install" softwares that will enable to code. This is usually done once. Afterwards, you can start coding. The later is the "build" part as you are generating value for each feature your code produce. From time to time, you can update your tool list by removing, adding or updating one.

In this example, installing your tools everyday you arrive at work before starting coding would be hell.

I would suggest you to make sure that the building process, which means producing an artifact (like a Jar for example), is decoupled from the dependency installation process. Meaning that installation is done once and building can proceed without trouble. You don't mention what will be built, but grunt can take care of the rest for sure.

Hence, I believe pruning and installing is a good strategy. You shouldn't worry for the fist times. Think of it as a cold start. Any system implemented with sub components working together as a pipeline have this "issue". Take a car for example. It will not be as fuel efficient when you start it as when you drive it after an hour.

like image 36
gmolaire Avatar answered Sep 28 '22 06:09

gmolaire