NPM package.json 文件中的 dependency、devDependencies 和 peerDependencies 有什么区别?
此文档 对我的问题回答得非常糟糕。我不明白那些解释。有人能用更简单的语言说一下吗?如果很难选择简单的词语,也许可以举例说明?
还添加了
peerDependencies
,它密切相关并且可能会引起混淆。
重要行为差异摘要:
-
dependencies
安装在两者上:-
npm install
来自包含package.json
的目录 -
npm install $package
在任何其他目录上
-
-
-
也安装在包含
package.json
的目录中的npm install
上,除非您传递--production
标志(为 Gayan Charith 的答案 点赞),或者设置了NODE_ENV=production
环境变量 -
不会安装在任何其他目录中的
npm install "$package"
上,除非您为其提供--dev
选项。 - 不会间接安装。
-
也安装在包含
-
- 3.0 之前:如果缺失,则始终安装,如果不同依赖项使用多个不兼容版本的依赖项,则会引发错误。
-
预计从 3.0 开始
(未经测试):如果
npm install
上缺少依赖项,则会发出警告,您必须手动解决依赖关系。运行时,如果缺少依赖项,则会收到错误(由 @nextgentech 提及)这很好地解释了这一点: https://flaviocopes.com/npm-peer-dependencies/ - 在版本 7 中,除非存在无法自动解决的上游依赖项冲突,否则将自动安装 peerDependencies
-
传递性(由 Ben Hutchison ):
-
依赖项
是可传递安装的:如果 A 需要 B,而 B 需要 C,则 C 会被安装,否则,B 无法工作,A 也无法工作。 -
devDependencies
不是可传递安装的。例如我们不需要测试 B 来测试 A,因此可以省略 B 的测试依赖项。
-
此处未讨论的相关选项:
-
bundledDependencies
在以下问题中进行了讨论: npm 中 bundledDependencies 相对于普通依赖项的优势 -
optionalDependencies
(提到 作者:Aidan Feldman )
devDependencies
运行需要
dependencies
,开发只需要
devDependencies
,例如:单元测试、CoffeeScript 到 JavaScript 的转译、压缩……
如果您要开发一个包,您可以下载它(例如通过
git clone
),转到包含
package.json
的根目录,然后运行:
npm install
由于您拥有实际源代码,因此很明显您想要开发它,因此默认情况下,还会安装
dependencies
(因为您必须运行才能开发)和
devDependency
依赖项。
但是,如果您只是一个只想安装包来使用它的最终用户,您可以从任何目录执行此操作:
npm install "$package"
在该目录中在这种情况下,您通常不需要开发依赖项,因此您只需获取使用包所需的内容:
dependencies
。
如果您确实想在这种情况下安装开发包,可以将
dev
配置选项设置为
true
,可能从命令行执行如下操作:
npm install "$package" --dev
默认情况下,该选项为
false
,因为这种情况不太常见。
peerDependencies
(在 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 )上,您将看到:
-
grunt
是对等依赖
-
唯一的
require('grunt')
位于tests/
下:程序实际上并未使用它。
然后,当用户使用插件时,他将通过添加
grunt.loadNpmTasks('grunt-contrib-uglify')
行从
Gruntfile
隐式地请求该插件,但用户将直接调用
grunt
。
如果每个插件都需要不同的 Grunt 版本,那么这将不起作用。
手册
我认为文档很好地回答了这个问题,也许你只是对节点/其他包管理器不够熟悉。我可能只是因为我对 Ruby 捆绑器了解一点才理解它。
关键行是:
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.
然后在 npm-config(7) 下找到
dev
:
Default: false
Type: Boolean
Install dev-dependencies along with packages.
如果您不想安装 devDependencies,您可以使用
npm install --production
依赖项
您的项目需要运行的依赖项,例如提供您从代码中调用的函数的库。
它们是可传递安装的(如果 A 依赖于 B,而 B 又依赖于 C,则 A 上的 npm install 将安装 B 和 C)。
示例:lodash:您的项目调用了一些 lodash 函数。
devDependencies
您仅在开发或发布期间需要的依赖项,例如获取您的代码并将其编译为 javascript、测试框架或文档生成器的编译器。
它们不是可传递安装的(如果 A 依赖于 B,而 B 依赖于 C,则 A 上的 npm install 将仅安装 B)。
示例:grunt:您的项目使用 grunt 来构建自身。
peerDependencies
您的项目在父项目中挂接或修改的依赖项,通常是其他库或工具的插件。它只是用来检查,确保父项目(将依赖于您的项目的项目)依赖于您挂接的项目。因此,如果您制作了一个插件 C,为库 B 添加了功能,那么制作项目 A 的人如果对 C 有依赖,就需要对 B 有依赖。
它们不会安装(除非 npm < 3),只会检查它们。
示例: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