Blog

Caching your Node modules in Azure DevOps

23 Aug, 2019
Xebia Background Header Wave

How can you make your builds complete faster so that you can build more often and have earlier feedback?
You could do this by caching your node modules in Azure DevOps. I’ll explain how to do this in this blog post.

Creating a build pipeline in Azure DevOps for a Node.js based application is straightforward. You only need a few lines of code to achieve this. You’ll likely add tasks, such as linting, running tests, and maybe even more. As a result, the pipeline will take longer to complete with each added task. Let’s start speeding things up using caching.

You can find the repository for node modules caching in Azure DevOps here.

Suppose the pipeline YAML file looks as follows:

https://gist.github.com/corradin/10b55229454a7fb1c220a683ac4a526f

The first step is to install all dependencies. The second step needs these dependencies in order to start the build. In this example, I used a React application. However, any application that needs NPM packages will profit from the caching solution.

The results are as follows:

image
Azure DevOps pipeline run results without node caching

A build time of under a minute is not bad at all, but we can do better.

Add caching

The azure-pipelines.yml in the repository will be changed to the following:

https://gist.github.com/corradin/1b2db5c54f85c818f093ddd028351bd7

The Cache task takes different inputs. There is a key input, which can be a normal string value or in this case a file path. The contents of package-lock.json will be hashed and produce a dynamic cache key. This means that if the contents of the package-lock.json file change, a new key will be generated.

The second input is the path of the folder that needs to be cached. NPM uses ~/.npm on POSIX and %LocalAppData%\npm-cache on Windows machines. On the Ubuntu image, I haven’t found a way to access ~/.npm, so instead, I set the .npm folder in the workspace as a cache location. This can be done by adding the cache argument to the npm ci command. Next to this, it is recommended to set your cache folder, since it will keep running when you switch to a Windows agent for example.

After committing the YAML file and waiting for the build to complete, let’s look at the results:

image 1
Azure DevOps pipeline first run results with node caching

This run takes longer because the cache needs to be saved. I.e.: The cache key has not been found, so there is a cache miss.

Let’s run the pipeline again and check the results:

image 2
Azure DevOps pipeline subsequent run with node caching

It still takes somewhat longer, but now the cache is downloaded and the npm ci command will take the node modules it needs from the .npm folder. The “NPM install dependencies” task went from 28 to 10 seconds.

Depending on the number of tasks in your build pipeline your mileage may vary. I managed to improve the build time 5m 29s to 3m 22s minutes at my client.

Conclusion

Node modules caching in Azure DevOps will reduce your pipeline run duration when your solution relies on node packages. In my opinion, you should start doing node module caching when creating a pipeline. I believe the performance benefits will outweigh the time needed to implement this.

Questions?

Get in touch with us to learn more about the subject and related solutions

Explore related posts