为什么在npm中使用插件的对等依赖?

时间:2014-11-04 14:36:35

标签: node.js npm package-managers

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

为什么插件只能让Grunt在 grunt-plug / node_modules 中作为自己的依赖?

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

但我真的不明白。

实施例

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

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

[rootfolder] /package.json 告诉npm它取决于用于开发的grunt-steroids npm包:

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

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

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

" 依赖"软件包安装在 [rootfolder] / node_modules / grunt-steroids / node_modules 中,这对我来说是合乎逻辑的。

" devDependencies "没有安装,我肯定是由npm控制我只是试图使用grunt-steroids,而不是在它上面开发。

但是我们有" peerDependencies "。

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

3 个答案:

答案 0 :(得分:325)

TL; DR: [1] peerDependencies用于消费代码公开(并且预期由消费代码使用)的依赖项到“私有”未公开的依赖关系,并且只是一个实现细节。

问题对等依赖关系解决

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

但问题出现在:

  • 您使用的项目和某个模块都依赖于另一个模块。
  • 这三个模块必须互相交谈。

在示例中

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

但是现在如果JacksModule以某种方式公开其对JillsModule的依赖性会怎样。它接受JillsClass的实例例如......当我们使用库的new JillsClass版本创建2.0并将其传递给jacksFunction时会发生什么?一切都会破裂!像jillsObject instanceof JillsClass这样的简单内容会突然返回false,因为jillsObject实际上是另一个 JillsClass2.0版本的实例。< / p>

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

他们告诉npm

  

我需要这个包,但我需要的版本是该版本的一部分   项目,而不是我的模块私有版本。

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

何时应该使用对等依赖项?

  • 当您构建要由其他项目使用的库时,
  • 此库正在使用其他库
  • 您希望/需要用户也可以使用其他库

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

注解

  1. 太久了;没看过。用于表示一个人认为太长的文本的简短摘要。

答案 1 :(得分:23)

我建议你先阅读这篇文章。这有点令人困惑但是winston-mail的例子向你展示了答案:

  

例如,我们假装winston-mail@0.2.3 "winston": "0.5.x"对象中指定了"dependencies",因为它是针对其进行测试的最新版本。作为应用程序开发人员,您需要最新且最好的内容,因此您需要查找最新版本的winstonwinston-mail并将它们放在package.json中

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

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

├── winston@0.6.2  
└─┬ winston-mail@0.2.3                
  └── winston@0.5.11

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

  

一条建议:对等依赖性要求,与常规依赖性要求不同,应该是宽松的。您不应将对等依赖项锁定到特定的修补程序版本。

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

答案 2 :(得分:0)

peerDependencies以最简单的示例进行了解释:

{ “名称”:“ myPackage”   “依赖关系”:{     “ foo”:“ ^ 4.0.0”,     “反应”:“ ^ 15.0.0”   } }

{   “ name”:“ foo”   “ peerDependencies”:{     “反应”:“ ^ 16.0.0”   } }

在myPackage中运行npm install将抛出错误,因为它试图安装React版本^ 15.0.0 AND foo,该版本仅与React ^ 16.0.0兼容。

peerDependencies未安装。