With the release of npm@5, it will now write a package-lock.json
unless a npm-shrinkwrap.json
already exists.
I installed npm@5 globally via:
npm install npm@5 -g
And now, if a npm-shrinkwrap.json
is found during:
npm install
a warning will be printed:
npm WARN read-shrinkwrap This version of npm
is compatible with lockfileVersion@1,
but npm-shrinkwrap.json was generated for lockfileVersion@0.
I'll try to do my best with it!
So my take-away is that I should replace the shrinkwrap with the package-lock.json
.
Yet why is there a new format for it? What can the package-lock.json
do that the npm-shrinkwrap.json
cannot?
The files have exactly the same content, but there are a handful of differences in how npm handles them, described on the docs site and also in a docs file in the npm repo that starts by explicitly addressing the difference between these two files:
package-lock.json
is never published to npm, whereas npm-shrinkwrap
is by default
package-lock.json
files that are not in the top-level package are ignored, but shrinkwrap files belonging to dependencies are respected
npm-shrinkwrap.json
is backwards-compatible with npm versions 2, 3, and 4, whereas package-lock.json
is only recognized by npm 5+
You can convert an existing package-lock.json
to an npm-shrinkwrap.json
by running npm shrinkwrap
.
Thus:
- If you are not publishing your package to npm, the choice between these two files is of little consequence. You may wish to use
package-lock.json
because it is the default and its name is clearer to npm beginners; alternatively, you may wish to use npm-shrinkwrap.json
for backwards compatibility with npm 2-4 if it is difficult for you to ensure everyone on your development team is on npm 5+. (Note that npm 5 was released on 25th May 2017; backwards compatibility will become less and less important the further we get from that date, as most people will eventually upgrade.)
If you are publishing your package to npm, you have a choice between:
- using a
package-lock.json
to record exactly which versions of dependencies you installed, but allowing people installing your package to use any version of the dependencies that is compatible with the version ranges dictated by your package.json
, or
- using an
npm-shrinkwrap.json
to guarantee that everyone who installs your package gets exactly the same version of all dependencies
The official view described (very tersely) in the docs is that option 1 should be used for libraries (presumably in order to reduce the amount of package duplication caused when lots of a package's dependencies all depend on slightly different versions of the same secondary dependency), but that option 2 might be reasonable for executables that are going to be installed globally.
Explanation from NPM Developer:
The idea is definitely for package-lock.json to be the Latest and
Greatest in shrinkwrap technology, and npm-shrinkwrap.json to be
reserved for those precious few folks out there who care very much
about their libraries having an exact node_modules -- and for people
who want CI using npm@>=2 to install a particular tree without having
to bump its npm version.
The new lockfile ("package-lock.json") shares basically all of the
same code, the exact same format as npm-shrinkwrap (you can rename
them between one another!). It's also something the community seems to
understand: "it has a lockfile" seems to click so much faster with
people. Finally, having a new file meant that we could have relatively
low-risk backwards-compat with shrinkwrap without having to do weird
things like allow-publication mentioned in the parent post.
I think the idea was to have --save and shrinkwrap happen by default but avoid any potential issues with a shrinkwrap happening where it wasn't wanted. So, they just gave it a new file name to avoid any conflicts. Someone from npm explained it more thoroughly here:
https://www.reddit.com/r/javascript/comments/6dgnnq/npm_v500_released_save_by_default_lockfile_better/di3mjuk/
The relevant quote:
npm publishes most files in your source directory by default, and
people have been publishing shrinkwraps for years. We didn't want to
break compatibility. With --save and shrinkwrap by default, there was
a great risk of it accidentally making it in and propagating through
the registry, and basically render our ability to update deps and
dedupe... null.
So we chose a new name. And we chose a new name kind of all of a
sudden. The new lockfile shares basically all of the same code, the
exact same format