提问人:Vitalii Korsakov 提问时间:9/18/2013 最后编辑:VLAZVitalii Korsakov 更新时间:3/27/2023 访问量:941929
NPM package.json文件中的 dependencies、devDependencies 和 peerDependencies 有什么区别?
What's the difference between dependencies, devDependencies, and peerDependencies in NPM package.json file?
答:
有些模块和包只有在开发时才需要,在生产中不需要。就像文档中所说的那样:
如果有人计划在他们的程序中下载和使用您的模块,那么他们可能不想或不需要下载和构建您使用的外部测试或文档框架。在这种情况下,最好在 devDependencies 哈希中列出这些附加项。
评论
例如,mocha 通常是一个 devDependency,因为在生产中不需要测试,而 express 则是一个依赖项。
评论
重要行为差异摘要:
依赖项
安装在两者上:npm install
从包含package.json
npm install $package
在任何其他目录上
devDependencies
包括:- 也安装在包含 的目录上,除非您传递标志(为 Gayan Charith 的答案投赞成票),或者如果设置了环境变量
npm install
package.json
--production
NODE_ENV=production
- 不安装在任何其他目录上,除非您给它选择。
npm install "$package"
--dev
- 不是可传递安装的。
- 也安装在包含 的目录上,除非您传递标志(为 Gayan Charith 的答案投赞成票),或者如果设置了环境变量
-
- 在 3.0 之前:如果缺少,则始终安装,如果不同的依赖项使用多个不兼容的依赖项版本,则会引发错误。
- 预计在 3.0 上启动(未经测试):如果缺少 ,则发出警告,您必须自己手动解决依赖关系。运行时,如果缺少依赖项,则会出现错误(@nextgentech提到) 这很好地解释了它: https://flaviocopes.com/npm-peer-dependencies/
npm install
- 在版本 7 中,除非存在无法自动解决的上游依赖关系冲突,否则会自动安装 peerDependencies
传递性(Ben Hutchison提到):
dependencies
可传递地安装:如果 A 需要 B,而 B 需要 C,则安装 C,否则,B 无法工作,A 也无法工作。devDependencies
不是可传递安装的。例如,我们不需要测试 B 来测试 A,因此可以省略 B 的测试依赖项。
此处未讨论的相关选项:
bundledDependencies
在以下问题上讨论: bundledDependencies 相对于 npm 中普通依赖项的优势optionalDependencies
(由 Aidan Feldman 提及))
dev依赖项
dependencies
需要运行,只能进行开发,例如:单元测试、CoffeeScript 到 JavaScript 的转译、缩小......devDependencies
如果你要开发一个包,你可以下载它(例如通过),转到它的根目录,其中包含,然后运行:git clone
package.json
npm install
既然你有实际的源代码,很明显你想开发它,所以默认情况下,也会安装(因为你必须运行才能开发)和依赖项。dependencies
devDependency
但是,如果您只是一个只想安装软件包来使用它的最终用户,则可以从任何目录执行以下操作:
npm install "$package"
在这种情况下,您通常不需要开发依赖项,因此您只需获得使用包所需的内容:.dependencies
在这种情况下,如果您确实想安装开发包,则可以将配置选项设置为 ,可能从命令行设置为:dev
true
npm install "$package" --dev
该选项是默认的,因为这种情况不太常见。false
peer依赖关系
(在 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/
但是,插件是通常不需要其他包的包,在此上下文中称为主机。相反:
- 主机需要插件
- 插件提供了一个标准接口,主机希望找到
- 只有主机会被用户直接调用,所以它必须有一个版本。
例如,if 和 peer depend on ,项目树将如下所示:dependency1
dependency2
dependency3
root/node_modules/
|
+- dependency1/
|
+- dependency2/
|
+- dependency3 v1.0/
即使您从未在文件中提及,也会发生这种情况。dependency3
package.json
我认为这是控制反转设计模式的一个实例。
对等依赖关系的一个典型示例是 Grunt、主机及其插件。
例如,在像 https://github.com/gruntjs/grunt-contrib-uglify 这样的 Grunt 插件上,你会看到:
grunt
是一个peer-dependency
- 唯一的是 :它实际上并没有被程序使用。
require('grunt')
tests/
然后,当用户使用插件时,他会通过添加一行来隐式要求插件,但用户会直接调用。Gruntfile
grunt.loadNpmTasks('grunt-contrib-uglify')
grunt
如果每个插件都需要不同的 Grunt 版本,这将不起作用。
手动
我认为文档很好地回答了这个问题,也许您只是对节点/其他包管理器不够熟悉。我可能只是因为对 Ruby bundler 有所了解而理解它。
关键线是:
当从包的根目录执行 npm link 或 npm install 时,将安装这些东西,并且可以像任何其他 npm 配置参数一样进行管理。参见 npm-config(7) 来了解这个主题。
然后在 npm-config(7) 下找到:dev
Default: false
Type: Boolean
Install dev-dependencies along with packages.
评论
npm install package
peerDependencies
npm install
devDependencies
NODE_ENV
production
如果你不想安装 devDependencies,你可以使用npm install --production
评论
--save
package.json
--save
要将包保存为开发依赖项package.json,请执行以下操作:
npm install "$package" --save-dev
当您运行时,它将同时安装 和 .若要避免安装,请运行:npm install
devDependencies
dependencies
devDependencies
npm install --production
评论
dependencies 项目需要运行的依赖项,例如提供从代码调用的函数的库。
它们是传递安装的(如果 A 依赖于 B 依赖于 C,则 A 上的 npm install 将安装 B 和 C)。
示例: lodash:您的项目调用了一些 lodash 函数。
devDependencies
仅在开发或发布期间需要的依赖项,例如获取代码并将其编译为 javascript、测试框架或文档生成器的编译器。
它们不是可传递安装的(如果 A 依赖于 B dev-depends on C,则 A 上的 npm install 将仅安装 B)。
示例: grunt:您的项目使用 grunt 自行构建。
peerDependencies
项目在父项目中挂接到或修改的依赖项,通常是其他库或工具的插件。它只是一个检查,确保父项目(将依赖于你的项目)对你挂钩的项目有依赖关系。因此,如果你制作了一个插件 C 来向库 B 添加功能,那么制作项目 A 的人如果依赖于 C<,就需要依赖 B。
示例: grunt:您的项目向 grunt 添加了功能,并且只能在使用 grunt 的项目上使用。
本文档很好地解释了对等依赖关系: https://nodejs.org/en/blog/npm/peer-dependencies/
此外,npm 文档随着时间的推移得到了改进,现在对不同类型的依赖项有了更好的解释: https://github.com/npm/cli/blob/latest/docs/content/configuring-npm/package-json.md#devdependencies
评论
一个简单的解释让我更清楚:
部署应用时,需要安装依赖项中的模块,否则应用将无法运行。devDependencies 中的模块不需要安装在生产服务器上,因为你不是在该计算机上进行开发。链接
评论
vendor.js
webpack -p
我想在答案中补充我对这些依赖关系解释的看法
dependencies
用于在代码库中直接使用,通常最终出现在生产代码中的内容或代码块devDependencies
用于构建过程,帮助您管理最终代码结束方式的工具,第三方测试模块,(例如 webpack 的东西)
评论
尝试分发 npm 包时,应避免使用 .相反,您需要考虑将其添加到 .dependencies
peerDependencies
更新
大多数时候,依赖项只是一堆描述生态系统的库。除非您确实使用的是特定版本的库,否则您应该让用户选择是否安装该库以及通过将该库添加到 peerDependencies 中来选择哪个版本。
评论
dependencies
peerDependencies
直到我从上面提到的 Ciro 主题的博客文章中读到这个片段,对我来说才完全有意义:
[插件]需要的是一种表达插件及其主机包之间这些“依赖关系”的方法。某种说法是,“我只有在插入到我的主机包的 1.2.x 版本时才能工作,所以如果你安装我,请确保它与兼容的主机一起。我们称这种关系为对等依赖关系。
该插件确实需要特定版本的主机...
peerDependencies
适用于插件,即需要“主机”库来执行其功能的库,但可能是在最新版本的主机发布之前编写的。
也就是说,如果我写了然后走开了,就不能保证在发布时(甚至)会起作用。PluginX v1
HostLibraryX v3
PluginX v1
HostLibraryX v4
HostLibraryX v3.0.1
...但是插件不依赖于主机...
从插件的角度来看,它只是向主机库添加函数。我真的不需要主机向插件添加依赖项,而且插件通常并不真正依赖于它们的主机。如果您没有主机,则该插件不会无害地执行任何操作。
这意味着依赖关系
并不是插件的正确概念。
更糟糕的是,如果我的主机被视为依赖项,我们最终会陷入同一篇博文提到的这种情况(编辑了一点以使用这个答案的虚构主机和插件):
但是现在,[如果我们将 HostLibraryX 的当代版本视为 PluginX 的依赖项,] 运行会导致意外的依赖关系图
npm install
├── [email protected] └─┬ [email protected] └── [email protected]
我将把使用与主应用程序不同的 [HostLibraryX] API 的插件带来的微妙故障留给您的想象。
...而且主机显然不依赖于插件......
...这就是插件的全部意义所在。现在,如果主机足够好,可以包含其所有插件的依赖信息,这将解决问题,但这也会带来一个巨大的新文化问题:插件管理!
插件的全部意义在于它们可以匿名配对。在一个完美的世界里,让主人管理它们会很整洁,但我们不会要求图书馆放猫。
如果我们不是分层依赖的,也许我们是内部依赖的对等方......
相反,我们有成为同行的概念。主机和插件都不位于对方的依赖项存储桶中。两者都位于依赖关系图的同一级别。
...但这不是一种自动化的关系。<<<点球成金!!
如果我是并期望有一个 peer 的 (即,有一个 peerDependency of) ,我会这么说。如果您已自动升级到最新版本(请注意,这是版本 4)并已安装,则需要知道,对吗?PluginX v1
HostLibraryX v3
HostLibraryX v4
Plugin v1
npm
无法为我管理这种情况——
“嘿,我看你在用!我会自动从 v4 降级到 v3,kk?
PluginX v1
HostLibraryX
...或。。。
“嘿,我看到你用的.这期望 ,您在上次更新期间将其留在了尘埃中。为了安全起见,我会自动卸载!1!
PluginX v1
HostLibraryX v3
Plugin v1
不,npm怎么样?!
所以 npm 没有。它会提醒您注意情况,并让您确定是否适合 .HostLibraryX v4
Plugin v1
尾
插件的良好管理将使这个概念在实践中更直观地发挥作用。从博客文章中,又一次......peerDependency
一条建议:与常规依赖关系不同,对等依赖关系的要求应该是宽松的。不应将对等依赖项锁定到特定的修补程序版本。如果一个 Chai 插件依赖于 Chai 1.4.1,而另一个依赖于 Chai 1.5.0,那将非常烦人,仅仅是因为作者很懒惰,没有花时间弄清楚他们兼容的实际 Chai 最低版本。
评论
peerDependencies
peerDependencies
HostLibraryX v4
是否是插件 v1
的合适对等体。peerDependencies
"
总之
依赖项 - 在生产环境中安装应用程序所需的包。
npm install <package> --save-prod
DevDependencies - 安装 仅本地开发和测试所需的软件包
npm install <package> --save-dev
只需键入即可安装 package.json
npm install
因此,如果您在本地计算机上工作,只需键入并继续:)npm install
依赖项与开发依赖项
开发依赖项是仅在开发过程中需要的模块,而依赖项在运行时是必需的。如果要部署应用程序,则必须安装依赖项,否则应用程序将无法运行。从代码中调用的使程序能够运行的库可以被视为依赖项。
例如-反应,反应-dom
Dev 依赖项模块不需要安装在生产服务器中,因为您不打算在该机器上进行开发,将您的代码转换为 javascript 的编译器,测试框架和文档生成器可以被视为开发依赖项,因为它们仅在开发过程中需要。
例如-ESLint、Babel、webpack
@FYI,
mod-a
dev-dependents:
- mod-b
dependents:
- mod-c
mod-d
dev-dependents:
- mod-e
dependents:
- mod-a
----
npm install mod-d
installed modules:
- mod-d
- mod-a
- mod-c
----
checkout the mod-d code repository
npm install
installed modules:
- mod-a
- mod-c
- mod-e
如果要发布到 npm,那么为正确的模块使用正确的标志非常重要。如果这是你的 npm 模块需要运行的东西,那么使用“--save”标志将模块保存为依赖项。如果您的模块不需要运行,但测试需要它,请使用“--save-dev”标志。
# For dependent modules
npm install dependent-module --save
# For dev-dependent modules
npm install development-module --save-dev
我找到了一个简单的解释。
简短的回答:
依赖"...是你的项目真正需要能够在生产中工作的那些。
dev依赖项"...是你在开发过程中需要的那些。
peer依赖关系“如果你想创建和发布你自己的库,以便它可以作为一个依赖项使用”
这篇文章中的更多详细信息: https://code-trotter.com/web/dependencies-vs-devdependencies-vs-peerdependencies
评论
peerDependencies
依赖
这些是你的包需要运行的包,因此它们将在用户运行时安装
npm install PACKAGE-NAME
例如,如果您在项目中使用了 jQuery。如果有人没有安装jQuery,那么它就不起作用。要另存为依赖项,请使用
npm install --save
开发依赖关系
这些是您在开发中使用的依赖项,但在人们使用它时不需要它,因此当人们运行时,它不会安装它们,因为这些不是必需的。例如,如果您用于测试,则人们不需要运行,因此不需要安装它。要另存为开发依赖项,请使用npm install
mocha
mocha
npm install
npm install PACKAGE --save-dev
对等依赖关系
如果要创建和发布自己的库,以便将其用作依赖项,则可以使用这些库。例如,如果您希望将包用作另一个项目中的依赖项,那么当有人安装将您的项目作为依赖项的项目时,也会安装这些包。大多数情况下,您不会使用对等依赖项。
依赖项是需要运行的,devDependencies 只需要开发
评论
dependencies:项目/包在生产环境中需要使用的包。
devDependencies:您的项目/包在开发时需要工作但在生产中不需要的包(例如:测试包)
peerDependencies:你的项目/包需要协同工作(与它们“合作”)或作为基础的包,主要在你开发插件/组件时有用,让你知道你的插件/组件应该使用哪个版本的“main”包(例如:React 16)
当使用 Webpack 捆绑前端应用程序时,dependencies 和 devDependencies 之间的区别并不那么清楚。对于最终的捆绑包,将依赖项放在哪里并不重要(但对于其他工具可能很重要)。这就是为什么文档看起来令人困惑的原因。
我在这里找到了解释:使用 Webpack 时,“依赖项”和“devDependencies”重要吗?
评论
optionalDependencies
。