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

问题描述 投票:159回答:2

例如,为什么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"
  },

“dependencies”包安装在[rootfolder] / node_modules / grunt-steroids / node_modules中,这对我来说是合乎逻辑的。

没有安装“devDependencies”,我确信这是由npm控制我只是试图使用grunt-steroids,而不是在它上面开发。

但后来我们有了“peerDependencies”。

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

node.js npm package-managers
2个回答
318
投票

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

The problem peer dependencies solve

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版本的实例。

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

他们告诉npm

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

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

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

  • 在构建要由其他项目使用的库时,以及
  • 这个库正在使用其他一些库,和
  • 您期望/需要用户也可以使用其他库

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


Annotations

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

23
投票

我建议你先重新阅读这篇文章。这有点令人困惑,但winston-mail的例子显示了答案原因:

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

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

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

├── [email protected]  
└─┬ [email protected]                
  └── [email protected]

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

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

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

© www.soinside.com 2019 - 2024. All rights reserved.