NPM Homepage

Create an NPM lock file for your packages with shrinkwrap

The other day I published a post on how the `–save-dev` flag in NPM is often used incorrectly. Hopefully some people will read it and somewhere a DevOps engineer will be able to lead a happy and peaceful life.

Alas though, it’s not quite all roses in DevOps NPM world. You see there’s still a problem with versioning. As with any good package manager, in NPM you can specify a version or range of versions that is acceptable to be installed for a package. For example:

“gulp-compass”: “~1.2.3” – will install the highest 1.2.x version available

“grunt-ruby-sass”: “^1.1.1” – will install the latest version 1.x.x version available.

Which is all fine and dandy. However,  as we know things change between versions, both major and minor, a lesson that was painfully reenforced yesterday. Developer A had added “gulp-“ruby-sass” at the start of the project and configured it as normal. Several days later Developer B jumped on the project and, ran `gulp` and the world imploded. 40 frustrating minutes later it turns out that gulp-ruby-sass had changed their input syntax and Developer B was running a slightly newer version.

Enter NPM Shrinkwrap

Any modern PHP developer uses Composer and will be able to tell you that when run it creates a composer.lock file. This lock file saves the exact version of each package and the packages’ packages installed so that whenever `composer install` is run in the future the exact same version of each package is installed. Of course if `composer update` is run the packages are resolved from the composer.json file and any new package versions (within the specified version range) are installed, in much the same way as NPM, and a new lock file is automatically created.

It turns out that NPM has the exact same functionality, they just keep very quiet about it and don’t do it automatically like composer or bundler (a Ruby Gem package manager). It’s called shrinkwrap. Once you’ve installed your NPM packages you can run `npm shrinkwrap` and it will create an npm-shrinkwrap.json file. Then in the future whenever `npm install` is run it will resolve the exact package versions (and your packages’ package versions etc etc) found in the shrinkwrap file, meaning no more discrepancies in versions used between developers. Just like composer, if you need to update just run `npm update && npm shrinkwrap`.

Bear in mind that shrinkwrap is intended for production use so won’t save devDependencies by default, if you want it to you can pass the `–dev` flag to it.


tldr: You can lock down your exact npm package versions by using ‘npm’shrinkwrap’

2 thoughts on “Create an NPM lock file for your packages with shrinkwrap

Why would you consider the use of these features “using npm wrong” though? If you first only update on your development environment first, I don’t think it’s “wrong” to occasionally update your libraries to a reasonable degree. If you have a project that’s many years old you’d be better off carefully upgrading your dependancies so you’re not stuck with a version of jQuery from half a decade ago.

Also I wouldn’t quite say npm keeps quiet about being able to lock your versioning down. You can simply just choose not to use these operators in your package.json file. It’s right here in their docs:

I was actually considering changing the title of this post to “Locking down your NPM version with shinkwrap” as I agree the title isn’t as clear as it could be. I don’t mean using shrinkwrap is wrong, I mean one’s usage of NPM could be improved by using shrinkwrap if that makes sense.

I actually disagree and feel NPM does keep very quite about it. If you use any other package manger, such as composer or bundler, they all generate a .lock file automatically which can be committed and used in production. Specifying an exact version in the package.json file isn’t quite the same either as that package’s dependencies may be loosely assigned and you could end up with different versions. Not want you want for production. And of course upgrading your packages is fine but you only want it to happen in development, everywhere else you should ideally be using the exact same packages, hence the lock (shrinkwrap) file.

Comments are closed.