node.js 为什么在 npm 中为插件使用对等依赖项?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26737819/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-02 18:04:37  来源:igfitidea点击:

Why use peer dependencies in npm for plugins?

node.jsnpmpackage-managers

提问by Thomas Stock

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

例如,为什么 Grunt 插件将其对 grunt 的依赖定义为“对等依赖”?

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

为什么插件不能在grunt-plug/node_modules 中将Grunt 作为它自己的依赖

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

此处描述了对等依赖项:https: //nodejs.org/en/blog/npm/peer-dependencies/

But I don't really get it.

但我真的不明白。

Example

例子

I'm working with AppGyver Steroids at the moment which uses Grunt tasks to build my source files into a /dist/ folder to be served on a local device. I'm quite new at npm and grunt so I want to fully comprehend what is going on.

我目前正在使用 AppGyver Steroids,它使用 Grunt 任务将我的源文件构建到 /dist/ 文件夹中,以便在本地设备上提供服务。我是 npm 和 grunt 的新手,所以我想完全理解发生了什么。

So far I get this:

到目前为止,我得到了这个:

[rootfolder]/package.jsontells npm it depends on the grunt-steroidsnpm package for development:

[rootfolder]/package.json告诉 npm 它依赖于grunt-steroidsnpm 包进行开发:

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

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

好的。在[rootfolder] 中运行 npm install检测依赖关系并在[rootfolder]/node_modules/grunt-steroids 中安装grunt-steroids

Npm then reads [rootfolder]/node_modules/grunt-steroids/package.jsonso it can install grunt-steroidsown dependencies.:

然后Npm读取[rootfolder]/node_modules/grunt-steroids/package.json以便它可以安装grunt-steroids自己的依赖项。:

"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"
  },

The "dependencies" packages are installed into [rootfolder]/node_modules/grunt-steroids/node_moduleswhich is logical for me.

依赖项”包安装到[rootfolder]/node_modules/grunt-steroids/node_modules 中,这对我来说是合乎逻辑的。

The "devDependencies" aren't installed, which I'm sure is controlled by npm detecting I'm just trying to use grunt-steroids, and not develop on it.

未安装“ devDependencies”,我确定它是由 npm 检测到的grunt-steroids,我只是尝试使用,而不是在其上进行开发。

But then we have the "peerDependencies".

但是我们有了“ peerDependencies”。

These are installed in [rootfolder]/node_modules, and I don't understand why there and not in [rootfolder]/node_modules/grunt-steroids/node_modulesso that conflicts with other grunt plugins (or whatever) are avoided?

这些安装在[rootfolder]/node_modules 中,我不明白为什么在那里而不是在[rootfolder]/node_modules/grunt-steroids/node_modules 中,以避免与其他 grunt 插件(或其他)发生冲突?

回答by Stijn de Witt

TL;DR:[1]peerDependenciesare 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.

TL;DR:[1]peerDependencies用于暴露给(并预期被使用)使用代码的依赖项,而不是未公开的“私有”依赖项,并且只是一个实现细节。

The problem peer dependencies solve

对等依赖解决的问题

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.

NPM 的模块系统是分层的。简单场景的一大优势是,当您安装 npm 包时,该包会带来自己的依赖项,因此它可以开箱即用。

But problems arise when:

但是在以下情况下会出现问题:

  • Both your project and some module you are using depend on another module.
  • The three modules have to talk to each other.
  • 您的项目和您正在使用的某个模块都依赖于另一个模块。
  • 这三个模块必须相互通信。

In Example

在示例中

Let's say you are building YourCoolProjectand you're using both HymansModule 1.0and JillsModule 2.0. And let's suppose that HymansModulealso 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 HymansModuleis using JillsModulebelow the surface is just an implementation detail. We are bundling JillsModuletwice, but that's a small price to pay when we get stable software out of the box.

假设您正在构建YourCoolProject并且同时使用HymansModule 1.0JillsModule 2.0。让我们假设这HymansModule也取决于JillsModule,但取决于不同的版本,比如1.0。只要这两个版本不符合,就没有问题。在表面之下HymansModule使用的事实JillsModule只是一个实现细节。我们捆绑了JillsModule两次,但是当我们获得开箱即用的稳定软件时,这是一个很小的代价。

But now what if HymansModuleexposes its dependency on JillsModulein some way. It accepts an instance of JillsClassfor example... What happens when we create a new JillsClassusing version 2.0of the library and pass it along to HymansFunction? All hell will break loose! Simple things like jillsObject instanceof JillsClasswill suddenly return falsebecause jillsObjectis actually an instance of anotherJillsClass, the 2.0version.

但是现在如果以某种方式HymansModule暴露它的依赖JillsModule呢?例如,它接受一个实例JillsClass...当我们创建库的new JillsClassusing 版本2.0并将其传递给 时会发生HymansFunction什么?所有的地狱都会崩溃!简单的事情想jillsObject instanceof JillsClass会突然返回false,因为jillsObject实际上是一个实例另一个JillsClass2.0版本。

How peer dependencies solve this

对等依赖如何解决这个问题

They tell npm

他们告诉 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 nothave that dependency, or that has an incompatible versionof it, it will warn the user during the installation process.

当 npm 发现您的包被安装到一个没有该依赖项的项目中,或者它的版本不兼容时,它会在安装过程中警告用户。

When should you use peer dependencies?

什么时候应该使用对等依赖?

  • When you are building a library to be used by other projects, and
  • This library is using some other library, and
  • You expect/need the user to work with that other library as well
  • 当您正在构建供其他项目使用的库时,以及
  • 这个库正在使用其他一些库,并且
  • 您希望/需要用户也使用其他库

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.

常见的场景是大型框架的插件。想想 Gulp、Grunt、Babel、Mocha 等。如果您编写 Gulp 插件,您希望该插件与用户项目使用的相同 Gulp 一起工作,而不是与您自己的 Gulp 私有版本一起工作。



Annotations

注释

  1. Too long; didn't read. Used to indicate a short summary for a text that one has deemed too long.
  1. 太长; 没读。用于表示人们认为太长的文本的简短摘要。

回答by Fer To

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:

我建议你先再读一遍这篇文章。这有点令人困惑,但 winston-mail 的示例向您展示了原因的答案:

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 of winstonand of winston-mailand 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]

例如,让我们假设它的对象中[email protected]指定"winston": "0.5.x"了它,"dependencies"因为这是它测试的最新版本。作为应用程序开发人员,您想要最新最好的东西,因此您查找winston和的最新版本winston-mail并将它们放入您的 package.json 中

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

但是现在,运行 npm install 会导致意外的依赖关系图

├── [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

在这种情况下,一个包可能有多个版本,这会导致一些问题。对等依赖项允许 npm 开发人员确保用户具有特定模块(在根文件夹中)。但是您的观点是正确的,即描述一个包的一个特定版本会导致使用其他版本的其他包出现问题。这个问题与 npm 开发人员有关,如文章所述

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 semverfor defining peerDependencies. You should open an issue for the grunt-steroids package on GitHub...

因此,开发人员应该遵循semver来定义 peerDependencies。你应该在 GitHub 上为 grunt-steroids 包打开一个问题......

回答by Christopher Tokar

peerDependenciesexplained with the simplest example possible:

peerDependencies用最简单的例子来解释:

{
  "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.0AND foowhich is only compatible with React ^16.0.0.

运行NPM在MyPackage的安装将抛出一个错误,因为它正试图安装版本做出反应^15.0.0foo这是唯一与之反应兼容^16.0.0

peerDependencies are NOT installed.

未安装 peerDependencies。