关于node.js:npm package.json文件中依赖项,devDependencies和peerDependencies之间有什么区别?

What's the difference between dependencies, devDependencies and peerDependencies in npm package.json file?

这份文件很难回答我的问题。我不明白那些解释。有人能说简单点的话吗?如果很难选择简单的词,可以举例说明?

edit还添加了peerDependencies,这是密切相关的,可能导致混淆。


重要行为差异总结:好的。

  • dependencies安装在两个:好的。

    • 来自包含package.json的目录的npm install
    • 任何其他目录上的npm install $package
  • devDependencies为:好的。

    • 也安装在包含package.json的目录中的npm install上,除非您通过--production标志(向上投票给gayan charith的答案)。
    • 不安装在任何其他目录的npm install"$package"上,除非您提供--dev选项。
    • 不可传递地安装。
  • peerDependencies:好的。

    • 3.0之前:如果缺少则始终安装,如果不同依赖项将使用多个不兼容版本的依赖项,则会引发错误。
    • 预计3.0开始(未测试):如果npm install上缺少,则发出警告,您必须自己手动解决依赖关系。运行时,如果缺少依赖项,则会出现错误(由@nextgentech提到)
  • 传递性(Ben Hutchison提到):好的。

    • dependencies是可传递安装的:如果a需要b,b需要c,则c安装,否则b不能工作,a也不能工作。好的。

    • devDependencies未过渡安装。例如,我们不需要测试B来测试A,因此可以忽略B的测试依赖性。好的。

此处未讨论的相关选项:好的。

  • bundledDependencies讨论了以下问题:在NPM中,bundleddependency比normal dependency的优势
  • optionalDependencies(Aidan Feldman提到)

依赖关系

需要运行dependenciesdevDependencies仅用于开发,例如:单元测试、coffeescript to javascript蒸腾、缩小……好的。

如果要开发一个包,请下载它(例如,通过git clone),转到包含package.json的根目录,然后运行:好的。

1
npm install

由于您有实际的源,很明显您希望开发它,因此默认情况下,也安装了dependencies(当然,必须运行以开发)和devDependency依赖项。好的。

但是,如果您只是一个只想安装一个包来使用它的最终用户,那么您可以从任何目录执行以下操作:好的。

1
npm install"$package"

在这种情况下,您通常不需要开发依赖项,所以您只需要得到使用包所需的:dependencies。好的。

如果您真的想在这种情况下安装开发包,可以从命令行将dev配置选项设置为true,可能是:好的。

1
npm install"$package" --dev

默认情况下,该选项为false,因为这是一种不太常见的情况。好的。对等依赖项

(3.0之前测试)好的。

来源:https://nodejs.org/en/blog/npm/peer-dependencies/好的。

使用常规依赖项,您可以拥有多个版本的依赖项:它只是安装在依赖项的node_modules中。好的。

例如,如果dependency1dependency2都依赖于dependency3的不同版本,则项目树将如下所示:好的。

1
2
3
4
5
6
7
8
9
10
root/node_modules/
                 |
                 +- dependency1/node_modules/
                 |                          |
                 |                          +- dependency3 v1.0/
                 |
                 |
                 +- dependency2/node_modules/
                                            |
                                            +- dependency3 v2.0/

然而,插件是通常不需要另一个包的包,在这个上下文中称为主机。而是:好的。

  • 主机需要插件
  • 插件提供了一个标准接口,主机希望能够找到
  • 只有主机将由用户直接调用,因此必须有单一版本的主机。

例如,如果dependency1dependency2对等依赖dependency3,则项目树将如下所示:好的。

1
2
3
4
5
6
7
root/node_modules/
                 |
                 +- dependency1/
                 |
                 +- dependency2/
                 |
                 +- dependency3 v1.0/

即使你从未在你的package.json文件中提到dependency3,这种情况也会发生。好的。

我认为这是控制设计模式反转的一个例子。好的。

对等依赖的一个典型例子是Grunt、主机及其插件。好的。

例如,在像https://github.com/gruntjs/grunt-contrib-uglify这样的grunt插件上,您将看到:好的。

  • gruntpeer-dependency
  • 唯一的require('grunt')tests/下:它实际上没有被程序使用。

然后,当用户使用一个插件时,他会通过添加一个grunt.loadNpmTasks('grunt-contrib-uglify')行隐式地从Gruntfile请求该插件,但用户将直接调用的是grunt。好的。

如果每个插件都需要不同的咕噜版本,那么这就不起作用。好的。手册

我认为文档很好地回答了这个问题,也许您对节点/其他包管理器不够熟悉。我可能只理解它,因为我对Ruby Bundler有点了解。好的。

关键是:好的。

These things will be installed when doing npm link or npm install from the root of a package and can be managed like any other npm configuration parameter. See npm-config(7) for more on the topic.

Ok.

然后在NPM配置(7)下找到dev:好的。

1
2
3
4
Default: false
Type: Boolean

Install dev-dependencies along with packages.

好啊。


如果不想安装devdependencies,可以使用npm install --production


例如,mocha通常是一个devdependency,因为在生产中不需要测试,而express则是一个dependency。


要将包保存到package.json作为dev依赖项,请执行以下操作:

1
npm install"$package" --save-dev

运行npm install时,它将同时安装devDependenciesdependencies。为避免安装devDependencies运行:

1
npm install --production


依赖关系项目需要运行的依赖项,如提供从代码调用的函数的库。它们是可传递安装的(如果A依赖于B依赖于C,则A上的NPM安装将安装B和C)。示例:lodash:您的项目调用了一些lodash函数。

依赖关系您只需要在开发或发布过程中需要的依赖项,比如编译器,它们将您的代码编译成JavaScript、测试框架或文档生成器。它们不是可传递安装的(如果a依赖b dev依赖c,则a上的npm安装将仅安装b)。示例:grunt:您的项目使用grunt来构建自己。

对等依赖项项目在父项目中挂接或修改的依赖项,通常是其他库或工具的插件。它只是一个检查,确保父项目(依赖于您的项目的项目)依赖于您所连接的项目。因此,如果您制作了一个插件C,将功能添加到库B中,那么一个项目A的开发人员需要依赖于B,如果他们依赖于C。未安装(除非NPM<3),仅对其进行检查。示例:grunt:您的项目向grunt添加功能,并且只能用于使用grunt的项目。

本文档很好地解释了对等依赖关系:https://nodejs.org/en/blog/npm/peer-dependencies/

此外,随着时间的推移,NPM文档得到了改进,现在可以更好地解释不同类型的依赖项:https://github.com/npm/cli/blob/latest/doc/files/package.json.md devdependencies


有些模块和包只是开发所必需的,在生产中不需要。就像文件里说的那样:

If someone is planning on downloading and using your module in their program, then they probably don't want or need to download and build the external test or documentation framework that you use. In this case, it's best to list these additional items in a devDependencies hash.


让我更清楚的一个简单解释是:

部署应用程序时,需要安装依赖项中的模块,否则应用程序将无法工作。devdependencies中的模块不需要安装在生产服务器上,因为您不需要在该计算机上开发。链接


我想在答案中加上我对这些依赖性解释的看法

  • dependencies用于代码库中的直接使用,通常在生产代码或代码块中结束。
  • devDependencies用于构建过程,它是帮助您管理最终代码将如何结束的工具,第三方测试模块(例如Webpack工具)。


直到我从一篇关于上述ciro主题的博客文章中读到这段话,peerDependencies才对我有意义:

What [plugins] need is a way of expressing these"dependencies" between plugins and their host package. Some way of saying,"I only work when plugged in to version 1.2.x of my host package, so if you install me, be sure that it’s alongside a compatible host." We call this relationship a peer dependency.

插件需要主机的特定版本…

peerDependencies用于插件,这些库需要"主机"库来执行其功能,但可能是在发布最新版本的主机之前编写的。

也就是说,如果我给HostLibraryX v3PluginX v1,然后离开,那么当HostLibraryX v4甚至HostLibraryX v3.0.1被释放时,PluginX v1将不起作用。

…但是插件不依赖主机…

从插件的角度来看,它只向主机库添加函数。我并不真正"需要"主机来添加一个插件的依赖关系,插件通常不依赖于他们的主机。如果没有主机,插件就不会有任何危害。

这意味着dependencies并不是插件的正确概念。

更糟糕的是,如果我的主机被视为一个依赖项,我们最终会遇到同一篇博文提到的情况(稍微编辑一下以使用这个答案的组合主机和插件):

But now, [if we treat the contemporary version of HostLibraryX as a dependency for PluginX,] running npm install results in the unexpected dependency graph of

1
2
3

I’ll leave the subtle failures that come from the plugin using a different [HostLibraryX] API than the main application to your imagination.

…主机显然不依赖于插件…

…这就是插件的关键所在。现在,如果主机足够好地包含所有插件的依赖关系信息,这就解决了问题,但这也引入了一个巨大的新文化问题:插件管理!

插件的关键是它们可以匿名配对。在一个完美的世界里,让主人来管理它们将是干净整洁的,但是我们不需要图书馆里的群猫。

如果我们不是等级依赖,也许我们是内部依赖的同龄人…

相反,我们有同龄人的概念。主机和插件都不在另一个的依赖桶中。两者都生活在依赖关系图的同一级别。

…但这不是一种自动的关系。

如果我是PluginX v1,希望有一个(也就是说,具有HostLibraryX v3的对等依赖关系),我会这么说。如果你已经自动升级到最新的HostLibraryX v4(注意这是版本4),并且安装了Plugin v1,你需要知道,对吗?

npm不能帮我处理这种情况。--

"Hey, I see you're using PluginX v1! I'm automatically downgrading HostLibraryX from v4 to v3, kk?"

…或者…

"Hey I see you're using PluginX v1. That expects HostLibraryX v3, which you've left in the dust during your last update. To be safe, I'm automatically uninstalling Plugin v1!!1!

不,NPM怎么样?!

所以NPM没有,它提醒你注意情况,让你知道HostLibraryX v4是否适合Plugin v1

尾波

插件中良好的peerDependency管理将使这个概念在实践中更直观地工作。从博客文章,再一次…

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. It would be really annoying if one Chai plugin peer-depended on Chai 1.4.1, while another depended on Chai 1.5.0, simply because the authors were lazy and didn’t spend the time figuring out the actual minimum version of Chai they are compatible with.


在尝试分发NPM包时,应避免使用dependencies。相反,您需要考虑将它添加到peerDependencies或从dependencies中删除它。