这个文档很难回答我的问题。我不明白这些解释。有人能用更简单的话说吗?如果很难选择简单的单词,可以举个例子吗?
EDIT还添加了peerDependencies,它密切相关,可能会引起混淆。
这个文档很难回答我的问题。我不明白这些解释。有人能用更简单的话说吗?如果很难选择简单的单词,可以举个例子吗?
EDIT还添加了peerDependencies,它密切相关,可能会引起混淆。
当前回答
直到我读了一篇关于Ciro的博客文章中的这段话,我才明白peerDependencies对我的意义:
[插件]需要的是一种表达插件及其宿主包之间的“依赖关系”的方式。用某种方式来说,“我只在插入到我的主机包的1.2.x版本时工作,所以如果您安装我,请确保它与兼容主机一起使用。”我们称这种关系为对等依赖关系。
插件确实需要主机的特定版本。。。
peerDependencies适用于插件,即需要“主机”库来执行其功能的库,但可能是在主机的最新版本发布之前编写的。
也就是说,如果我为HostLibraryX v3编写PluginX v1并走开,那么无法保证在发布HostLibraryXv4(甚至HostLibraryX-v3.0.1)时PluginX v1会工作。
…但插件不依赖于主机。。。
从插件的角度来看,它只向宿主库添加函数。我并不真的“需要”主机为插件添加依赖项,而且插件通常并不真正依赖于主机。如果你没有主机,插件就不会做任何有害的事情。
这意味着依赖并不是插件的正确概念。
更糟糕的是,如果我的主机被视为一个依赖,我们最终会遇到同一篇博客文章提到的情况(编辑了一点以使用这个答案的虚构主机和插件):
但是现在,[如果我们将当前版本的HostLibraryX视为PluginX的依赖项,]运行npm安装会导致意外的依赖关系图├── HostLibraryX@4.0.0└─┬ PluginX@1.0.0└── HostLibraryX@3.0.0我将把插件使用不同于主应用程序的[HostLibraryX]API而产生的细微故障留给你想象。
…而且主机显然不依赖于插件。。。
…这就是插件的全部意义。现在,如果主机足够好,能够包含所有插件的依赖信息,这将解决问题,但这也会引入一个巨大的新文化问题:插件管理!
插件的关键在于它们可以匿名配对。在一个完美的世界里,让主人管理它们会很整洁,但我们不会要求图书馆放猫。
如果我们不是等级依赖,也许我们是相互依赖的同龄人。。。
相反,我们有成为同龄人的概念。主机和插件都不在对方的依赖桶中。两者都位于依赖关系图的同一级别。
…但这不是一种自动的关系。<<<钱球!!!
如果我是PluginX v1,并且期望有HostLibraryX v3的对等(即,具有对等依赖关系),我会这么说。如果你已经自动升级到最新的HostLibraryX v4(请注意,这是版本4),并且安装了Plugin v1,你需要知道,对吗?
npm无法为我管理这种情况--
“嘿,我看到你在使用PluginX v1!我正在自动将HostLibraryX从v4降级到v3,kk?”
或
“嘿,我看到你在使用PluginX v1。这需要HostLibraryX v3,在上一次更新时,它已被遗忘。为了安全起见,我正在自动卸载插件v1!!1.
不怎么样,npm?!
所以npm没有。它会提醒您这种情况,并让您了解HostLibraryX v4是否适合插件v1。
Coda
插件中良好的peerDependency管理将使这一概念在实践中更加直观。从博客文章,再一次。。。
有一条建议:与常规依赖不同,对等依赖的要求应该宽松。您不应将对等依赖项锁定到特定的修补程序版本。如果一个Chai插件同行依赖Chai 1.4.1,而另一个依赖Chai 1.5.0,这真的很烦人,因为作者很懒,没有花时间找出他们所兼容的Chai的实际最低版本。
其他回答
重要行为差异总结:
依赖项安装在以下两者上:从包含package.json的目录安装npmnpm在任何其他目录上安装$packagedevDependencies是:也安装在npm上,安装在包含package.json的目录上,除非您传递--production标志(向上投票Gayan Charih的答案),或者设置了NODE_ENV=生产环境变量不安装在npm上,请在任何其他目录上安装“$package”,除非您为其提供--dev选项。未过渡安装。对等依赖关系:3.0之前版本:如果缺少,则始终安装,如果不同的依赖项将使用多个不兼容版本的依赖项,则会引发错误。预计从3.0开始(未经测试):如果在npm安装中缺失,则发出警告,您必须自己手动解决依赖关系。运行时,如果缺少依赖项,则会出现一个错误(由@nextgentech提到)。这很好地解释了这一点:https://flaviocopes.com/npm-peer-dependencies/在版本7中,除非存在无法自动解决的上游依赖关系冲突,否则将自动安装对等依赖关系传递性(Ben Hutchison提到):依赖项是以过渡方式安装的:如果A需要B,B需要C,那么C就会安装,否则,B无法工作,A也无法工作。devDependencies未以过渡方式安装。例如,我们不需要测试B来测试A,因此可以忽略B的测试依赖项。
此处未讨论的相关选项:
bundledDependencies,这是在以下问题上讨论的:在npm中,bundledDepdependencies比普通依赖项的优势可选依赖性(Aidan Feldman提到)
devDependencies
依赖项需要运行,devDependencies只需要开发,例如:单元测试、CoffeeScript到JavaScript转换、缩小等。。。
如果要开发包,请下载它(例如通过gitclone),转到包含package.json的根目录,然后运行:
npm install
因为您有实际的源代码,所以很明显您想要开发它,所以默认情况下,还安装了依赖项(当然,您必须运行才能开发)和devDependency依赖项。
但是,如果您只是一个最终用户,只想安装一个软件包来使用它,您可以从任何目录执行以下操作:
npm install "$package"
在这种情况下,您通常不需要开发依赖项,所以您只需要获得使用包所需的东西:依赖项。
如果您真的想在这种情况下安装开发包,可以将dev-configuration选项设置为true,可能在命令行中为:
npm install "$package" --dev
默认情况下,该选项为false,因为这种情况不太常见。
对等依赖关系
(3.0之前测试)
资料来源:https://nodejs.org/en/blog/npm/peer-dependencies/
使用常规依赖项,可以有多个版本的依赖项:它只需安装在依赖项的node_modules中。
例如,如果dependency1和dependency2都依赖于不同版本的dependency3,则项目树将如下所示:
root/node_modules/
|
+- dependency1/node_modules/
| |
| +- dependency3 v1.0/
|
|
+- dependency2/node_modules/
|
+- dependency3 v2.0/
然而,插件是通常不需要另一个包(在本文中称为主机)的包。相反:
主机需要插件插件提供主机期望找到的标准接口只有主机将由用户直接调用,因此必须有一个版本的主机。
例如,如果dependency1和dependency2对等体依赖于dependency3,则项目树将如下所示:
root/node_modules/
|
+- dependency1/
|
+- dependency2/
|
+- dependency3 v1.0/
即使在package.json文件中从未提及dependency3,也会发生这种情况。
我认为这是控制反转设计模式的一个例子。
对等依赖关系的一个典型例子是Grunt、主机及其插件。
例如,在Grunt插件上https://github.com/gruntjs/grunt-contrib-uglify,您将看到:
咕哝是同伴的依赖唯一的需求('runt')正在测试中/:程序实际上没有使用它。
然后,当用户使用插件时,他将通过添加grunt.loadNpmTasks('grunt-contrib-glify')行从Gruntfile中隐式地请求插件,但用户将直接调用它。
如果每个插件都需要不同的Grunt版本,那么这将不起作用。
手册
我认为文档很好地回答了这个问题,也许您对节点/其他包管理器不够熟悉。我可能只理解它,因为我对Ruby bundler有点了解。
关键一行是:
这些东西将在从包的根目录执行npm链接或npm安装时安装,并且可以像任何其他npm配置参数一样进行管理。有关该主题的更多信息,请参阅npm-config(7)。
然后在npm-config(7)下找到dev:
Default: false
Type: Boolean
Install dev-dependencies along with packages.
依赖项:项目/包需要在生产环境中工作的包。
devDependencies:您的项目/包在开发时需要工作但在生产中不需要的包(例如:测试包)
peerDependencies:您的项目/包需要与之协同工作(与它们“协同工作”)或作为基础的包,主要用于开发插件/组件以了解您的插件/组件应该与哪个版本的“主”包协同工作(例如:React 16)
一个简单的解释让我更加清楚:
部署应用程序时,需要安装依赖项中的模块,否则应用程序将无法工作。devDependencies中的模块不需要安装在生产服务器上,因为您不是在该机器上开发的。链接
当使用Webpack捆绑前端应用程序时,依赖项和devDependencies之间的区别不是很清楚。对于最终的捆绑包,将依赖项放置在何处并不重要(但对于其他工具来说可能很重要)。这就是为什么文档看起来很混乱。
我在这里找到了解释:在使用Webpack时,“依赖项”和“devDependencies”是否重要?
例如,mocha通常是一个devDependency,因为在生产中不需要测试,而express则是一个依赖项。