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

Vit*_*kov 1872 node.js npm

本文档很难回答我的问题.我不明白这些解释.有人可以用简单的话说吗?也许有例子,如果难以选择简单的单词?

编辑还补充说peerDependencies,这是密切相关的,可能会引起混淆.

Cir*_*四事件 2210

重要行为差异摘要:

  • dependencies 安装在两个:

    • npm install 从包含的目录 package.json
    • npm install $package 在任何其他目录上
  • devDependencies 是:

    • 也安装在npm install一个包含的目录上package.json,除非你传递--production旗帜(go upvote 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的测试依赖性.

相关选项未在此处讨论:

devDependencies

dependencies需要运行,devDependencies仅用于开发,例如:单元测试,CoffeeScript到JavaScript的转换,缩小,...

如果你要开发一个软件包,你可以下载它(例如通过git clone),转到它包含的root package.json,然后运行:

npm install
Run Code Online (Sandbox Code Playgroud)

由于您拥有实际的源代码,因此很明显您要开发它,因此默认情况下,两者dependencies(当然,您必须运行以进行开发)和devDependency依赖项也都会​​安装.

但是,如果您只是一个只想安装软件包才能使用它的最终用户,您可以从任何目录进行操作:

npm install "$package"
Run Code Online (Sandbox Code Playgroud)

在这种情况下,您通常不需要开发依赖项,因此您只需获得使用该软件包所需的内容:dependencies.

如果您确实希望在这种情况下安装开发包,可以将dev配置选项设置为true,可能从命令行设置为:

npm install "$package" --dev
Run Code Online (Sandbox Code Playgroud)

false默认情况下,该选项是一种不太常见的情况.

peerDependencies

(3.0之前测试过)

资料来源:https://nodejs.org/en/blog/npm/peer-dependencies/

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

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

root/node_modules/
                 |
                 +- dependency1/node_modules/
                 |                          |
                 |                          +- dependency3 v1.0/
                 |
                 |
                 +- dependency2/node_modules/
                                            |
                                            +- dependency3 v2.0/
Run Code Online (Sandbox Code Playgroud)

但是,插件通常不需要其他包,在此上下文中称为主机.代替:

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

例如if dependency1dependency2peer依赖dependency3,项目树将如下所示:

root/node_modules/
                 |
                 +- dependency1/
                 |
                 +- dependency2/
                 |
                 +- dependency3 v1.0/
Run Code Online (Sandbox Code Playgroud)

即使您从未dependency3package.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.
Run Code Online (Sandbox Code Playgroud)

  • 这很棒!我从来没有意识到,但是这个答案告诉我,依赖关系vs devDependencies的区别仅适用于你要发布npm包的情况.如果您只是在处理应用程序或站点,那应该不会太重要.谢谢! (167认同)
  • 此外,依赖包不会传递devDependencies.示例:程序包A依赖于程序包B.程序包B依赖于程序包C,而B也依赖于程序包D.如果从程序包A运行`npm install`,则会得到B和C但不会得到D. (8认同)
  • 值得注意的是,当`NODE_ENV`设置为`production`时,没有安装`devDependencies`. (8认同)
  • 啊.我看到我误解了.您的答案读起来好像`npm install package`是一个命令,您将用它来安装所有非依赖项的软件包,而不是我现在认为您的意思,即"安装名为[package]的软件包",这是在阅读本文之前我认为它是如何工作的.如果我是你,我会编辑说[package-name],这清楚地表明你的意思是'insert-name-here'. (4认同)
  • 感谢您提供这个很好的答案,但您说“运行需要依赖项,开发依赖项仅用于开发,例如:[...] Coffeescript 到 Javascript 转换”,但如果您的项目是一个应用程序而不是一个应用程序,那么这是不正确的作为 npm 包分发。在这种情况下,您将需要“依赖项”部分中的所有构建工具(包括转译)。就我个人而言,我认为这种区别值得在您的答案顶部提及。干杯。 (3认同)
  • 应该更新这篇文章,以反映即将到来的npm @ 3中改变的`peerDependencies`行为.来自http://blog.npmjs.org/post/110924823920/npm-weekly-5:"我们不会再自动下载对等依赖项了.相反,如果尚未安装对等依赖项,我们会发出警告这需要你自己手动解决peerDependency冲突,但从长远来看,这应该会让你不太可能在你的包的依赖关系中陷入困境." (2认同)
  • 您“在其他任何目录上安装$ npm install $ package”到底意味着什么...我无法推断出缺少的单词来在这里解释您的半句 (2认同)
  • @JerilKuruvila我不明白他的意思.如果不发布到NPM,区分"dependencies"和"devDependencies"也可能很有用.例如,您不希望生产配置脚本获取dev依赖项. (2认同)

Gay*_*ith 456

如果您不想安装devDependencies,则可以使用 npm install --production

  • npm install将安装所有依赖项.如果要将特定模块添加到package.json,则使用--save标志.例如: - npm install uglify --save会在你的项目文件夹中安装uglify并将uglify添加到project,package.json文件中. (18认同)
  • 截至5月5日,不再需要`--save`选项.如果你执行"npm install my-package",它会在你的`package.json`文件中添加my-package作为依赖项. (8认同)
  • 因为我们正在讨论devDependencies,所以可以使用--save-dev将新模块保存为devDependency.示例:npm install uglify --save-dev (6认同)
  • *从 npm 5 开始,不再需要 --save 选项*。这真是个好消息!我以前没有意识到这一点。我总是觉得很烦人的是,大多数文档都忽略了“--save”选项,而实际上,不保存添加了依赖项的事实几乎没有意义。 (3认同)

Dan*_*ohn 108

例如,mocha通常是devDependency,因为在生产中测试不是必需的,而express则是依赖.

  • 我建议使用像Hudson或CircleCI这样的持续集成服务来运行您的测试,然后在它们通过时部署到生产中. (44认同)
  • 我倾向于将测试作为依赖项,因为您可能希望在启动生产服务器之前运行自检 (4认同)
  • 再说一遍,将测试依赖项添加为常规依赖项会引入一大堆额外的库,每个库都可能会以某种方式失败。我倾向于(双关语!)轻量级生产服务器,其上的代码尽可能少。请记住,最好的代码就是没有代码! (3认同)
  • @Nicole 为什么要让临时服务器的配置与产品不同? (2认同)

Moh*_*eer 62

要将包保存为package.json作为dev依赖项:

npm install "$package" --save-dev
Run Code Online (Sandbox Code Playgroud)

当你运行npm install它将安装devDependenciesdependencies.为避免安装devDependencies运行:

npm install --production
Run Code Online (Sandbox Code Playgroud)

  • 你也可以使用:npm i -S (2认同)

qwe*_*guy 57

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

devDependencies
开发或发布时只需要的依赖关系,比如将代码编译成javascript,编译框架或文档生成器的编译器.
它们没有传递安装(如果A依赖于B dev-依赖于C,则A上的npm安装将仅安装B).
示例:grunt:您的项目使用grunt构建自己.

peerDependencies
项目在父项目中挂钩或修改的依赖项,通常是其他库或工具的插件.它只是一个检查,确保父项目(将依赖于您的项目的项目)依赖于您挂钩的项目.因此,如果您创建一个向库B添加功能的插件C,那么制作项目A的人如果对C具有依赖关系则需要依赖于B.
他们没有安装(除非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

  • 此线程中peerDependencies的最佳解释 (4认同)
  • 最终对peerDependency 的回答满足了“为什么?” 而不是“如何?”。很有帮助! (3认同)
  • 应该将市场作为“答案” - 清晰而简洁,“peerDependency”下的第一句话正确解释了所有内容,而无需深入研究 npm 中如何解析版本,而这不需要了解 peerDependency 的用途。 (2认同)
  • 对等依赖性的明确答案!谢谢 (2认同)

Amb*_*mps 35

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

如果有人计划在他们的程序中下载和使用您的模块,那么他们可能不希望或不需要下载和构建您使用的外部测试或文档框架.在这种情况下,最好在devDependencies哈希中列出这些附加项.


ruf*_*fin 17

peerDependencies直到我从上面提到的关于Ciro主题的博客文章中阅读了这个片段,才对我来说很有意义:

[ plugins ] 需要的是一种表达插件与其宿主包之间的“依赖关系”的方法。某种说法,“我只在插入我的主机包的 1.2.x 版时才能工作,所以如果你安装我,请确保它与兼容的主机一起使用。” 我们称这种关系为对等依赖。

该插件不期望主机的特定版本...

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

也就是说,如果我PluginX v1为之写作HostLibraryX v3并离开,则无法保证PluginX v1HostLibraryX v4(甚至HostLibraryX v3.0.1)发布时会起作用。

...但插件不依赖于主机...

从插件的角度来看,它只是给宿主库增加了功能。我并不真的“需要”主机向插件添加依赖项,而且插件通常并不真正依赖于它们的主机。如果您没有主机,则该插件无害地执行任何操作。

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

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

但是现在,[如果我们将 HostLibraryX 的当代版本视为 PluginX 的依赖项,] 运行会npm install导致意外的依赖关系图

??? HostLibraryX@4.0.0
??? PluginX@1.0.0
  ??? HostLibraryX@3.0.0
Run Code Online (Sandbox Code Playgroud)

我将使用与主应用程序不同的 [HostLibraryX] API 的插件带来的细微故障留给您想象。

...而主机显然不依赖于插件...

...这就是插件的全部意义所在。现在,如果主机足够好以包含其所有插件的依赖信息,那将解决问题,但这也会引入一个巨大的新文化问题:插件管理!

插件的全部意义在于它们可以匿名配对。在一个完美的世界里,让主人来管理它们会很整洁,但我们不会要求图书馆放猫。

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

相反,我们有成为同龄人的概念。主机和插件都不位于对方的依赖项桶中。两者都位于依赖图的同一级别。


...但这不是一种可自动化的关系。<<<点球大战!!!

如果我PluginX v1期望的对等(也就是,有一个peerDependencyHostLibraryX v3,我会这么说。如果您已自动升级到最新HostLibraryX v4版本(请注意是版本4Plugin v1安装,您需要知道,对吗?

npm 无法为我处理这种情况——

“嘿,我看到你在使用PluginX v1!我正在自动HostLibraryX从 v4降级到 v3,kk?”

... 或者...

“嘿,我看到你正在使用PluginX v1。那是期待HostLibraryX v3,你在上次更新期间把它留在了尘土中。为了安全起见,我会自动卸载Plugin v1!!1!

不怎么样,npm?!

所以 npm 没有。它会提醒您注意这种情况,并让您确定是否HostLibraryX v4适合Plugin v1.


结尾

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

一条建议:与常规依赖项不同,对等依赖项要求应该是宽松的。您不应该将您的对等依赖项锁定到特定的补丁版本。如果一个 Chai 插件对等依赖于 Chai 1.4.1,而另一个依赖于 Chai 1.5.0,那真的很烦人,仅仅是因为作者很懒,没有花时间弄清楚他们实际使用的 Chai 的最低版本兼容。


Jyo*_*han 15

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

部署应用程序时,需要安装依赖项中的模块,否则您的应用程序将无法运行.devDependencies中的模块不需要安装在生产服务器上,因为您没有在该计算机上进行开发. 链接

  • 所以,如果我们正在制作网站并且在 prod 版本中所有的库都将被内联到 `vendor.js` 中,如果编译的代码被提交到 repo 中,我们所有的 deps 都应该是 dev deps?它应该被提交,否则很奇怪你必须编译模块,而不仅仅是安装它(并且测试也在此处的某个地方,因为子模块的任何更改都可能导致回归)...... (3认同)

小智 12

我找到了一个简单的解释。

简答:

依赖项 “......是您的项目真正需要能够在生产中工作的那些。”

devDependencies “......是你在开发过程中需要的那些。”

peerDependencies “如果你想创建和发布你自己的库,以便它可以用作依赖项”

这篇文章中的更多详细信息:https : //code-trotter.com/web/dependencies-vs-devdependencies-vs-peerdependencies


Sîr*_*zar 11

我想在答案中添加我对这些依赖关系解释的看法

  • dependencies 用于在代码库中直接使用,通常最终出现在生产代码中的东西或代码块
  • devDependencies 用于构建过程,帮助您管理最终代码最终结果的工具,第三方测试模块,(例如webpack的东西)


che*_*ish 11

简而言之

  1. 依赖项- npm install <package> --save-prod在生产环境中安装应用程序所需的包。

  2. DevDependencies - npm install <package> --save-dev安装仅本地开发和测试所需的包

  3. 只需键入即可npm install安装 package.json 中提到的所有软件包

因此,如果您在本地计算机上工作,只需键入npm install并继续:)


Sel*_*thi 6

依赖与开发依赖

开发依赖项是仅在开发期间需要的模块,而在运行时需要依赖项。如果您正在部署应用程序,则必须安装依赖项,否则您的应用程序将无法运行。您从使程序运行的代码中调用的库可以被视为依赖项。

例如-反应,反应-dom

开发依赖模块不需要安装在生产服务器中,因为你不会在那台机器上开发。将你的代码转换为 javascript 的编译器,测试框架和文档生成器可以被视为开发依赖,因为它们只在开发过程中需要。

例如- ESLint , Babel , webpack

@供参考,

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
Run Code Online (Sandbox Code Playgroud)

如果您要发布到 npm,那么为正确的模块使用正确的标志很重要。如果它是你的 npm 模块需要运行的东西,那么使用“--save”标志将模块保存为依赖项。如果您的模块不需要运行但测试需要它,请使用“--save-dev”标志。

# For dependent modules
?npm install dependent-module --save

?# For dev-dependent modules
np?m install development-module --save-dev
Run Code Online (Sandbox Code Playgroud)


Jua*_*dez 6

依赖项:您的项目/包在生产中需要运行的包。

\n

devDependency:您的项目/包在开发时需要工作但在生产中不需要的包(例如:测试包)

\n

peerDependency:您的项目/包需要与它们协同工作的包(\xe2\x80\x9ccolaborating\xe2\x80\x9d)或作为基础,主要在您开发插件/组件时有用以让您知道使用哪个您的插件/组件应该使用的 \xe2\x80\x9cmain\xe2\x80\x9d 包的版本(例如:React 16)

\n