Peer dependencies are almost like normal dependencies, but instead of defining a strong requirement between A and B (i.e the project you're developing and the project it depends on), they're meant to specify a package that your code requires, but doesn't directly require it.
A peer dependency specifies that our package is compatible with a particular version of an npm package. If a package doesn't already exist in the node_modules directory, then it is automatically added. As you install a package, npm will automatically install the dev dependencies.
Having a peer dependency means that your package needs a dependency that is the same exact dependency as the person installing your package. This is useful for packages like react that need to have a single copy of react-dom that is also used by the person installing it.
With npm version 4 through to 6, a warning is issued when you run npm install to remind you to install the peer dependencies. Prior to version 4, npm automatically included peer dependencies if they weren't explicitly included.
TL;DR: peerDependencies
are for dependencies that are exposed to (and expected to be used by) the consuming code, as opposed to "private" dependencies that are not exposed, and are only an implementation detail.
NPM's module system is hierarchical. One big advantage for simpler scenarios is that when you install an npm package, that package brings its own dependencies with it so it will work out of the box.
But problems arise when:
Let's say you are building YourCoolProject
and you're using both JacksModule 1.0
and JillsModule 2.0
. And let's suppose that JacksModule
also depends on JillsModule
, but on a different version, say 1.0
. As long as those 2 versions don't meet, there is no problem. The fact that JacksModule
is using JillsModule
below the surface is just an implementation detail. We are bundling JillsModule
twice, but that's a small price to pay when we get stable software out of the box.
But now what if JacksModule
exposes its dependency on JillsModule
in some way. It accepts an instance of JillsClass
for example... What happens when we create a new JillsClass
using version 2.0
of the library and pass it along to jacksFunction
? All hell will break loose! Simple things like jillsObject instanceof JillsClass
will suddenly return false
because jillsObject
is actually an instance of another JillsClass
, the 2.0
version.
They tell npm
I need this package, but I need the version that is part of the project, not some version private to my module.
When npm sees that your package is being installed into a project that does not have that dependency, or that has an incompatible version of it, it will warn the user during the installation process.
Common scenarios are plugins for larger frameworks. Think of things like Gulp, Grunt, Babel, Mocha, etc. If you write a Gulp plugin, you want that plugin to work with the same Gulp that the user's project is using, not with your own private version of Gulp.
I would recommend you to read the article again first. It's a bit confusing but the example with winston-mail shows you the answer why:
For example, let's pretend that
[email protected]
specified"winston": "0.5.x"
in its"dependencies"
object because that's the latest version it was tested against. As an app developer, you want the latest and greatest stuff, so you look up the latest versions ofwinston
and ofwinston-mail
and put them in your package.json as{ "dependencies": { "winston": "0.6.2", "winston-mail": "0.2.3" } }
But now, running npm install results in the unexpected dependency graph of
├── [email protected] └─┬ [email protected] └── [email protected]
In this case, it is possible to have multiple versions of a package which would cause some issues. Peer dependencies allow npm developers to make sure that the user has the specific module (in the root folder). But you're correct with the point that describing one specific version of a package would lead to issues with other packages using other versions. This issue has to do with npm developers, as the articles states
One piece of advice: peer dependency requirements, unlike those for regular dependencies, should be lenient. You should not lock your peer dependencies down to specific patch versions.
Therefore developers should follow semver for defining peerDependencies. You should open an issue for the grunt-steroids package on GitHub...
peerDependencies
explained with the simplest example possible:
{
"name": "myPackage",
"dependencies": {
"foo": "^4.0.0",
"react": "^15.0.0"
}
}
{
"name": "foo"
"peerDependencies": {
"react": "^16.0.0"
}
}
running npm install in myPackage will throw an error because it is trying to install React version ^15.0.0
AND foo
which is only compatible with React ^16.0.0
.
peerDependencies are NOT installed.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With