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

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

例如,mocha通常是devDependency,因为在生产中不需要测试,而Express则是依赖项。

重要行为差异总结:

  • #0安装在两个:

    • npm install来自包含package.json的目录
    • npm install $package在任何其他目录
  • #0

    • 也安装在npm install上,在包含package.json的目录上,除非您传递--production标志(去投票Gayan Charith的回答),或者设置了NODE_ENV=production环境变量
    • 没有安装在任何其他目录的npm install "$package"上,除非您给它--dev选项。
    • 不安装传递。
  • #0

    • 3.0之前:如果缺少,则始终安装,如果不同的依赖项使用多个不兼容的依赖项版本,则会引发错误。
    • 预计从3.0开始(未经测试):如果缺少npm install,则发出警告,并且必须自己手动解决依赖项。运行时,如果缺少依赖项,则会出现错误(@陈志立提到)
    • 在版本7对等依赖项会自动安装,除非存在无法自动解决的上游依赖项冲突
  • 传递性(由benhutchison提到):

    • dependencies是传递安装的:如果A需要B,B需要C,则安装C,否则B无法工作,A也无法工作。

    • devDependencies不是传递安装的。例如。我们不需要测试B来测试A,所以可以省略B的测试依赖项。

此处未讨论的相关选项:

开发依赖

dependencies需要运行,devDependencies只需要开发,例如:单元测试、CoffeeScript到JavaScript的转换、缩小、…

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

npm install

由于您有实际的源代码,很明显您想要开发它,因此默认情况下,还安装了dependencies(因为您必须运行才能开发)和devDependency依赖项。

但是,如果您只是一个最终用户,只想安装一个包来使用它,您将从任何目录执行:

npm install "$package"

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

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

npm install "$package" --dev

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

依赖关系

(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/

然而,插件是通常不需要另一个包的包,在这种情况下称为主机。相反:

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

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

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

如果每个插件都需要不同的Grunt版本,这将无法工作。

手册

我认为留档很好地回答了这个问题,也许你只是对节点/其他包管理器不够熟悉。我可能只是因为我对Ruby捆绑器有所了解才理解它。

关键行是:

这些东西将在从包的根目录执行npm link或npm install时安装,并且可以像任何其他npm配置参数一样进行管理。有关该主题的更多信息,请参阅npm-config(7)。

然后在npm-config(7)下找到dev

Default: falseType: Boolean
Install dev-dependencies along with packages.

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

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

npm install "$package" --save-dev

当您运行npm install时,它将同时安装devDependenciesdependencies。要避免安装devDependencies,请运行:

npm install --production

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

开发依赖
仅在开发或发布期间需要的依赖项,例如将代码编译为javascript,测试框架或留档生成器的编译器。它们不是传递安装的(如果A依赖于B开发-依赖于C,则A上的npm install只会安装B)。
示例:grunt-您的项目使用grunt-构建自己。

依赖关系
你的项目在父项目中挂接或修改的依赖项,通常是其他库或工具的插件。它只是一个检查,确保父项目(将依赖于你的项目的项目)依赖于你挂接的项目。所以如果你制作了一个插件C向库B添加功能,那么制作项目A的人如果依赖于C,就需要依赖于B。
它们没有安装(除非npm<3),它们只被检查。
示例:grant:您的项目为gr要不添加了功能,并且只能在使用gr要不的项目上使用。

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

此外,随着时间的推移,npm留档得到了改进,现在对不同类型的依赖关系有了更好的解释:https://github.com/npm/cli/blob/latest/docs/content/configuring-npm/package-json.md#devdependencies

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

部署应用时,需要安装依赖项中的模块,否则应用无法运行。不需要在正式服上安装devDepend的模块,因为你不在正式服上开发。链接

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

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

当尝试分发npm包时,您应该避免使用dependencies。相反,您需要考虑将其添加到peerDependencies中。

更新

大多数情况下,依赖项只是描述您的生态系统的一堆库。除非您真的使用库的特定版本,否则您应该让用户选择是否安装该库以及通过将其添加到peerDepend的版本来选择哪个版本。

peerDependencies对我来说没有多大意义,直到我读到一篇博客文章关于主题上面提到的Ciro的这段片段:

[插件]需要的是一种表达插件和它们的主机包之间“依赖关系”的方式。换句话说,“我只在插入主机包的1.2. x版本时工作,所以如果你安装我,请确保它与兼容的主机一起运行。”我们称这种关系为对等依赖。

该插件期望是主机的特定版本…

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

也就是说,如果我为HostLibraryX v3PluginX v1然后走开,当HostLibraryX v4(甚至HostLibraryX v3.0.1)被释放时,不能保证PluginX v1会起作用。

…但是插件在主机上没有取决于

从插件的角度来看,它对主机库只有增加的功能。我并不真正“需要”主机向插件添加依赖项,而且插件通常不会在它们的主机上名列第一。如果你没有主机,插件什么也不做。

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

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

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

├── 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,您在上次更新时已将其留在尘埃中。为了安全起见,我自动卸载Plugin v1!!1!

不,npm怎么样?!

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


Coda

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

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

总之

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

  2. 开发流程-npm install <package> --save-dev安装仅用于本地开发和测试的包

  3. 只需键入npm install即可安装package.json

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

依赖vs开发依赖

开发人员依赖是在开发过程中才需要的模块,而依赖是在运行时需要的。如果你正在部署应用程序,必须安装依赖项,否则你的应用根本无法工作。你从代码中调用的使程序能够运行的库可以被视为依赖项。

Eg-反应,反应-dom

开发依赖模块不需要安装在正式服中,因为你不会在那台机器上开发.编译器将代码转换为javascript,测试框架和文档生成器可以被视为开发依赖项,因为它们仅在开发期间需要。

Eg-ESLint、Babel、webpack

@刘志强

mod-adev-dependents:- mod-bdependents:- mod-c
mod-d  dev-dependents:- mod-edependents:- 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 modulesnpm install dependent-module --save
# For dev-dependent modulesnpm install development-module --save-dev

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

简短回答:

<强>依赖"…是您的项目真正需要能够在生产中工作的那些。"

开发依赖“……是开发过程中需要的那些。”

对等依赖"如果您想创建和发布自己的库,以便它可以用作依赖项"

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

依赖关系

这些是您的包需要运行的包,因此它们将在人们运行时安装

 npm install PACKAGE-NAME

例如,如果您在项目中使用jQuery。如果有人没有安装jQuery,那么它就无法工作。要保存为依赖项,请使用

 npm install --save

开发依赖

这些是您在开发中使用的依赖项,但当人们使用它时不需要,因此当人们运行npm install时,它不会安装它们,因为不需要。例如,如果您使用mocha进行测试,人们不需要mocha来运行,因此npm install不会安装它。要保存为开发依赖项,请使用

npm install PACKAGE --save-dev

对等依赖关系

如果您想创建和发布自己的库,以便将其用作依赖项,则可以使用这些。例如,如果您希望您的包在另一个项目中用作依赖项,那么当有人安装将您的项目作为依赖项的项目时,也会安装这些。大多数情况下,您不会使用对等依赖项。

运行需要依赖,开发只需要依赖

依赖关系:您的项目/包需要在生产环境中工作的包。

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

依赖关系:您的项目/包需要与之协同工作的包(与它们“协同”)或作为基础,主要在开发插件/组件时有用让您知道您的插件/组件应该使用哪个版本的“主”包(例如:React 16)

当使用Webpack捆绑前端应用程序时,依赖项和devDepend的区别并不那么清楚。对于最终的捆绑包,你把依赖项放在哪里并不重要(但对其他工具来说可能很重要)。这就是留档看起来令人困惑的原因。

我在这里找到了解释:使用Webpack时,“依赖项”和“devDepend的”重要吗?