Why did you study peerDependencies?

Because I saw this in package.json in our group’s component library, I realized that all of these dependencies were needed in our project as well.

Our component library is angular based, but it does not count Angular as dependencies.

Then I looked at some third-party component libraries or plug-ins, and I found that they did not directly rely on some core libraries (React, Vue, Angular, jquery), but only added them to peerDependencies, which made me wonder, What exactly does peerDependencies do?

How do we want our plug-ins or third-party libraries to behave with respect to shared dependencies in the project?

The versions of the react and react-dom dependencies in my packageA should be the same as the versions of the React and react-dom installed on the main system. You should rely on react and react-DOM in the main system.

Tell me about peerDependencies

Peer dependencies, or peer dependencies, are used to specify which host version of the current package (that is, the package you wrote) is compatible with. Used to resolve inconsistencies between plug-ins and packages on which they depend.

PeerDependencies are often used in the development of some plug-ins. For example, the development of ANTD relies on React

To summarize the characteristics:

  • The premise of the correct operation of the plug-in is that the core dependency library must be downloaded and installed first, and cannot be independently relied on and referenced from the core dependency library.
  • The design of plug-in entry API must conform to the specification of core dependent library.
  • The core logic of the plug-in runs in calls to the dependent library;
  • In practice, under the same plug-in system, it is better to have the same version of the core dependency library;

This may not sound obvious, but let me give you an example. Antd only provides a library of REACT based UI components, but it requires the host environment to install the specified React version, so you can see antD’s package.json configuration in node_modules:


"peerDependencies": {

    "react": "> = 16.0.0"."react-dom": "> = 16.0.0"

},

Copy the code

It requires the host environment to install version 16.0.0 or higher of React, which means antD relies on the react installation package provided by the host environment to run in that range.

When installing the plug-in, peerDependencies behave differently in NPM 2.x and NPM 3.x. X will automatically install the same dependency, nPM3. x will no longer automatically install, will generate a warning! This can be done by manually adding dependencies to the package.json file.

When someone else uses our plug-in, peerDependencies tells the user exactly which host version of the plug-in you want to install.

Typically, we use many plug-ins from one host (such as gulp) in a project, and if there are host incompatibations between them, when NPM install is executed, the CLI will throw an error message telling us, for example:


npm ERR! peerinvalid The package gulp does not satisfy its siblings' peerDependencies requirements!

npm ERR! peerinvalid Peer [email protected] wants gulp@~3.1.9

npm ERR! peerinvalid Peer [email protected] wants gulp@~2.3.0

Copy the code

When you install a package, its dependencies and devDependencies are automatically installed by NPM. PeerDependencies are different in that they are not installed automatically. When a dependency C is listed in a package B’s peerDependency, it is not installed automatically. Instead, library A containing package B must include the corresponding dependency C as its dependency.

For example, about

Let’s say we have a helloWorld project that already declares packageA in its package.json dependencies. Plugin1 and plugin2 also depend on packageA. If you declare packageA with dependencies instead of peerDependencies, $NPM install will install plugin1 and plugin2 dependency graphs like this: (Depending on the version of packageA)

.├ ── ├─ ├─ │ ├─ │ ├─ │ ├─ │ ├─ │ ├─ │ ├─ │ ├─ │ ├─ │ ├─ │ ├─ │ ├─ │ ├─ │ ├ ─ garbage ─ garbage │ ├ ─ garbageCopy the code

As you can see from the dependency diagram above, helloWorld itself has already installed packageA once, but because of the

PackageA dependencies in plugin1 and plugin2 also declare packageA, so packageA is installed three times, two of which are redundant.

Note that NPM now automatically flattens packages that depend on the same version at install (as it did after NPM V3), that is, when multiple packages rely on the same package and their versions are the same, Only one copy will be installed at the root node_modules of the project

PeerDependency, on the other hand, avoids the problem of similar core dependency libraries being downloaded repeatedly.

If you use peerDependency to declare core dependency libraries in package.json in plugin1 and plugin2, for example, plugin1/package.json


{

    "peerDependencies": {

        "packageA": "1.0.1"}}Copy the code

plugin2/package.json


{

    "peerDependencies": {

        "packageA": "1.0.1"}}Copy the code

Declare packageA: helloWord/package.json on the main system


{

    "dependencies": {

        "packageA": "1.0.1"}}Copy the code

When $NPM install is executed on the main system, the dependency graph looks like this:

.├ ── helloWorld │ ├── ├─ │ ├─ ├─ ├ 2Copy the code

As you can see, the generated dependency graph is flat and packageA is installed only once. To summarize the characteristics of declaring a dependency library using peerDependency in the plug-in:

  • If the user explicitly relies on the core library, the peerDependency declarations of each plug-in can be ignored.

  • If the user does not explicitly rely on the core library, install the library in the project root directory as stated in the plug-in peerDependencies;

  • When the version that the user depends on and the version that each plug-in depends on are not compatible with each other, an error will be reported for the user to repair by himself.