You have a nice library published on npm but asking yourselve if you should declare
your dependencies as lodash: "3.10.0"
(known as "pin" a dependency) or lodash: "^3.10.0"
?
As library authors we should not pin dependencies but ask our users to do use npm shrinkwrap
in their own app.
Here's why:
If you pin your dependencies the issue is that anyone using your module will may not benefit
from shared dependencies. If your module user has lodash: "^3.11.0"
then since you declared
your library to use lodash: "3.10.0"
, there will be code duplication inside his build (or conflicts).
Of course even when using ^hats, if the major (Y.x.x) version is different between two libraries then you will get a different module.
But, with pinning it's a lot worse: As soon as the patch (x.x.Y) version of lodash will be different between your library lodash dependency and your user app lodash dependency, you will have duplicated lodash in your build!
Example of dependency pinning going wrong (duplicated code in the output): https://gist.github.com/vvo/5a2ec06c2752c6b35e48
When your library is used as a dependency. Depending on the moment a user does npm install super-pinned-library
, it could work in January but fail
in December.
You can protect your own library from bad minor upgrades of a first level dependency but all other sublevels dependencies could still fail given the way they are declared and the moment they are installed.
If your library as a dist/
, published on jsdelivr.com or cdnjs.com then to pin your dependencies
will not be enough. Because sub dependencies install state will depend on the day/state of the person/system
building your project.
For example even if you did not change any of your nicely pinned dependencies, when building your project in March you will get dependencies at a different state than when building in November.
A pattern I use for my frontend libraries that both needs to be on npm and builded somewhere is this:
- package.json has dependencies using ^hats (avoid code duplication when used as a dependency in a build system)
- npm-shrinkwrap.json generated for the library (
npm shrinkwrap
) - .npmignore has npm-shrinkwrap.json in it, because you do not want your npm users to use your npm-shrinkwrap.json, they will have their own
- build process do
npm install
andnpm run build
and then you have a reproducible build that is not time dependent, only dependent of the actual code of your library
With all this, should you still pin your npm dependencies? I would say no.
Last, npm package for example has all his dependencies in github, but that's a road you can avoid with npm shrinkwrap
even if it's still a bit buggy right now.
See http://ponyfoo.com/articles/immutable-npm-dependencies