Why use peer dependencies in npm for plugins?

Why, for example, does the Grunt plugin define its dependency on grunt as " peer dependencies "?

Why can't a plugin just have Grunt as its own dependency in grunt-plug / node_modules ?

Peer dependencies are described here: https://nodejs.org/en/blog/npm/peer-dependencies/

But I do not quite understand.

example

I am currently working with AppGyver steroids, which use Grunt tasks to assemble my source files into the / dist / folder for maintenance on a local device. I am new to npm and grunt, so I want to fully understand what is happening.

While I get this:

[rootfolder] /package.json tells npm that it depends on the nru grunt-steroids development package:

  "devDependencies": { "grunt-steroids": "0.x" }, 

Good. Running npm install in [rootfolder] detects the dependency and installs grunt steroids in [rootfolder] / node_modules / grunt-steroids .

Npm then reads [rootfolder] /node_modules/grunt-steroids/package.json to install its own grunt-steroids dependencies:

 "devDependencies": { "grunt-contrib-nodeunit": "0.3.0", "grunt": "0.4.4" }, "dependencies": { "wrench": "1.5.4", "chalk": "0.3.0", "xml2js": "0.4.1", "lodash": "2.4.1" }, "peerDependencies": { "grunt": "0.4.4", "grunt-contrib-copy": "0.5.0", "grunt-contrib-clean": "0.5.0", "grunt-contrib-concat": "0.4.0", "grunt-contrib-coffee": "0.10.1", "grunt-contrib-sass": "0.7.3", "grunt-extend-config": "0.9.2" }, 

Dependency packages are installed in [rootfolder] / node_modules / grunt-steroids / node_modules, which is logical for me.

" DevDependencies " are not installed, which I am sure is controlled by npm, which detects that I am just trying to use grunt-steroids and not develop on it.

But then we have " mutual dependencies ."

They are installed in [rootfolder] / node_modules , and I don’t understand why there, and not in [rootfolder] / node_modules / grunt-steroids / node_modules, in order to avoid conflicts with other plugins (or something else)?

+166
npm package-managers
Nov 04 '14 at 2:36 on
source share
4 answers

TL; DR: [1] peerDependencies are for dependencies that are provided (and are supposed to be used) by consuming code, in contrast to "private" dependencies that are not provided and are just implementation details.

The problem of interdependence solves

The NPM module system is hierarchical. One of the big advantages for simpler scenarios is that when you install the npm package, this package brings its own dependencies, so it will work out of the box.

But problems arise when:

  • Both your project and the module you use depend on another module.
  • Three modules must communicate with each other.

In the example

Let's say you are YourCoolProject and use both JacksModule 1.0 and JillsModule 2.0 . And let's assume that JacksModule also depends on JillsModule , but on a different version, say 1.0 . While these 2 versions are not found, there are no problems. The fact that JacksModule uses the JillsModule below the surface is just an implementation detail. We are JillsModule twice, but it’s a small price when we get stable software out of the box.

But now what if JacksModule somehow JacksModule reveals its dependence on JillsModule . For example, it takes an instance of JillsClass ... What happens when we create a new JillsClass using the library version 2.0 and pass it to jacksFunction ? All hell will break free! Simple things like jillsObject instanceof JillsClass unexpectedly return false because jillsObject is actually an instance of another JillsClass , version 2.0 .

How do peer dependencies do this?

They say npm

I need this package, but I need a version that is part of the project, and not some version private to my module.

When npm detects that your package is being installed in a project that does not have this dependency or has an incompatible version, it will alert the user during the installation process.

When should you use peer dependency?

  • When you create a library for use by other projects, and
  • This library uses some other library, and
  • Do you expect / need user work with this other library

Common scripts are plugins for large frameworks. Think about things like Gulp, Grunt, Babel, Mocha, etc. If you are writing a Gulp plugin, you want this plugin to work with the same Gulp that the user project uses, and not with your own private version of Gulp.




Annotations

  1. Too long; not read Used to indicate a brief description of text that is considered too long.
+334
Jan 06 '16 at 23:57
source share

I would recommend you read the article again first. This is a bit confusing, but the winston-mail example shows you the answer:

For example, let's pretend winston-mail@0.2.3 indicated "winston": "0.5.x" in its "dependencies" object since this latest version has been verified. As an application developer, you need the latest and greatest things, so you look for the latest versions of winston and winston-mail and put them in your package.json as

 { "dependencies": { "winston": "0.6.2", "winston-mail": "0.2.3" } } 

But now running npm install leads to an unexpected dependency graph

 β”œβ”€β”€ winston@0.6.2 └─┬ winston-mail@0.2.3 └── winston@0.5.11 

In this case, it is possible to have several versions of the package, which may cause some problems. Peer dependencies allow npm developers to verify that the user has a specific module (in the root folder). But you are correct that the description of one specific version of a package can lead to problems with other packages using other versions. This problem is related to npm developers, as the articles say.

One tip : peer dependency requirements, in contrast to regular dependency requirements, should be lenient. You should not block your peer dependencies until certain versions of the fixes.

Therefore, developers should follow the semver to determine peerDependencies. You should open the question for the grunt-steroid package on GitHub ...

+23
Mar 04 '15 at 13:05
source share

peerDependencies is explained in the simplest possible example:

 { "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.

+3
May 24 '19 at 9:13
source share

As the official Blueprint says, if you see UNMET PEER DEPENDENCY errors, you must manually install React:

npm install --save react react-dom react-addons-css-transition-group

you can find it here

0
Sep 23 '17 at 14:07 on
source share



All Articles