We've all been there. You start with a simple app idea and get to work. With the vast number of packages available on npmjs.org, your dependency list begins to grow exponentially. You then hear about a neat npm CLI command called shrinkwrap
.
[Shrinkwrap] locks down the versions of a package's dependencies so that you can control exactly which versions of each dependency will be used when your package is installed. – npmjs
Because package.json
often specifies only a minimum version number, another person using your package could run npm install
and end up with different dependency versions than you.
For example, let's say Developer-A runs npm i --save-dev surprise-pkg@1.0.0
and pushes his changes to Github. Package.json
now reads "surprise-pkg: "^1.0.0"
. Developer-B comes along some time later, clones the same repo, and runs npm install
. To his surprise, he notices that surprise-pkg
installs version 1.9.9
, even though his package.json reads the same as Developer-A's.
Do you see why that could be a problem? Developer-A and Developer-B are now developing with different versions of surprise-pkg
!
The scenario above can be easily resolved with npm shrinkwrap
. Not without a few headaches, of course. But that's why this was written... so you could wrap your head around the mystery of shrinkwrapping!
So, let's backtrack. Developer-A runs npm i --save-dev surprise-pkg@1.0.0
again, but this time he runs npm shrinkwrap --dev
before committing and pushing his changes to Github. Package.json
still reads "surprise-pkg: "^1.0.0"
, but there is a new file- npm-shrinkwrap.json
. If Developer-A were to dig into this file, among all of the other dependencies he would find the following:
"surprise-pkg": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/surprise-pkg/-/surprise-pkg-1.0.0.tgz"
}
Now, when Developer-B comes along, clones the same repo, and runs npm install
, he would find surprise-pkg@1.0.0
was installed too. Now both developers can code in harmony with the same version of surprise-pkg
!
It is important to understand the precedence of package.json
and npm-shrinkwrap.json
. Here are a few pointers:
When you run npm install
...
- If
npm-shrinkwrap.json
exists, ONLY the dependencies specified in your shrinkwrap file will be installed. - Otherwise, dependencies in
package.json
will be installed according to the semantic version specified (like the above example).
You can also ignore an existing shrinkwrap with the --ignore-shrinkwrap
flag.
CAUTION: I don't advise you ignore shrinkwrap unless you know what you are doing.
When you are working on any repository that uses a shrinkwrap, you should follow these best practices to avoid causing you and your team shrinkwrap headaches.
-
Given there is an existing shrinkwrap file, you should always
npm install
before installing any new packages or updates and subsequently runningnpm shrinkwrap
.Why? Since a generated shrinkwrap is based upon what is in your
node_modules
folder, you should always make sure that your installednode_modules
match those that may have been recently updated & shrinkwrapped by others on your team. -
Don't forget about
package.json
. Whenever you install a new module, remember to--save
or--save-dev
.Why? It is possible to install a new module without saving it to
package.json
and still have the new version get shrinkwrapped. But then you end up with discrepancies betweenpackage.json
andnpm-shrinkwrap.json
– a developer headache.
- Tom Beute
Good stuff!