ChatGPT解决这个技术问题 Extra ChatGPT

npm package.json 文件中的依赖项、devDependencies 和 peerDependencies 有什么区别?

This documentation 对我的问题的回答很差。我不明白那些解释。有人能用更简单的话说吗?如果很难选择简单的单词,也许有例子?

EDIT 还添加了 peerDependencies,它密切相关,可能会引起混淆。

请注意,现在还有 optionalDependencies
@AidanFeldman “optionalDependencies” 是我今天的矛盾修饰语
npm 文档说:“依赖项”:您的应用程序在生产中所需的包。 “devDependencies”:仅用于本地开发和测试的包。见链接:docs.npmjs.com/…
依赖项是您的库使用的包引用,没有这些引用它就无法工作,并且会与您的库安装一起自动安装。在查看 peerDependencies 时,如果在节点模块中找不到指定的包,npm 只会抛出警告消息。它不会为您安装任何软件包。详细解释请参考链接:medium.com/p/16f43d6c7e45

C
Ciro Santilli Путлер Капут 六四事

重要行为差异总结:

依赖项安装在两者上: npm install 从包含 package.json 的目录 npm install $package 在任何其他目录

从包含 package.json 的目录中安装 npm

npm install $package 在任何其他目录上

devDependencies 是:也安装在 npm install 包含 package.json 的目录上,除非你通过 --production 标志(去投票 Gayan Charith 的答案),或者如果 NODE_ENV=production 环境变量设置为 not installed on npm install "$包”在任何其他目录上,除非你给它 --dev 选项。不会传递安装。

也安装在 npm install 包含 package.json 的目录上,除非您通过 --production 标志(去投票 Gayan Charith 的答案),或者如果设置了 NODE_ENV=production 环境变量

没有安装在任何其他目录上的 npm install "$package" 上,除非你给它 --dev 选项。

不会传递安装。

peerDependencies:在 3.0 之前:如果缺少,则始终安装,如果不同的依赖项将使用多个不兼容版本的依赖项,则会引发错误。预计从 3.0 开始(未经测试):如果在 npm install 上丢失,则发出警告,您必须自己手动解决依赖关系。运行时,如果缺少依赖项,则会出现错误(@nextgentech 提到)这很好地解释了这一点:https://flaviocopes.com/npm-peer-dependencies/ 在版本 7 中自动安装 peerDependencies 除非上游依赖项冲突存在无法自动解决

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 的测试依赖项。

依赖项是传递安装的:如果 A 需要 B,而 B 需要 C,则安装 C,否则,B 不能工作,A 也不能工作。

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

此处未讨论的相关选项:

bundledDependencies 在以下问题上进行了讨论:与 npm 中的正常依赖关系相比 bundledDependencies 的优势

optionalDependencies(由 Aidan Feldman 提到)

开发依赖

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 中。

例如,如果 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,也会发生这种情况。

我认为这是 Inversion of Control 设计模式的一个实例。

对等依赖的一个典型例子是 Grunt、主机和它的插件。

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

grunt 是对等依赖

唯一的 require('grunt') 正在测试中/:程序实际上并未使用它。

然后,当用户将使用插件时,他将通过添加 grunt.loadNpmTasks('grunt-contrib-uglify') 行隐式地从 Gruntfile 中要求插件,但用户将直接调用 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 是一个命令,您将使用它来安装所有不是开发依赖项的软件包,而不是我现在认为您的意思,即“安装名为 [package] 的软件包”,这就是我的方式在阅读本文之前认为它有效。如果我是你,我会编辑说 [package-name] 这清楚地表明你的意思是“插入名称-here”。
这很棒!我从来没有意识到,但是这个答案告诉我,依赖项与 devDependencies 的区别仅在您要发布 npm 包时才适用。如果您只是在开发应用程序或站点,那么它应该没有太大关系。谢谢!
应该更新这篇文章以反映即将发布的 npm@3 中更改的 peerDependencies 行为。来自 blog.npmjs.org/post/110924823920/npm-weekly-5:“我们将不再自动下载对等依赖项。相反,如果尚未安装对等依赖项,我们会警告您。这需要您手动解决 peerDependency 冲突,但在很长一段时间内运行它应该可以减少你最终遇到包依赖项的棘手问题。”
此外,依赖包不会传递地安装 devDependencies。示例:包 A 依赖于包 B。包 B 依赖于包 C,B 也依赖于包 D。如果从包 A 运行 npm install,您将获得 B 和 C,但不会获得 D。
请务必注意,当 NODE_ENV 设置为 production 时,不会安装 devDependencies
R
RobW

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


npm install --save 是为了软件依赖?
npm install 将安装所有依赖项。当您也想将特定模块添加到 package.json 时,使用 --save 标志。例如:- npm install uglify --save 将在您的项目文件夹中安装 uglify 并将 uglify 添加到项目 package.json 文件中。
因为我们正在讨论 devDependencies,所以您可以使用 --save-dev 将新模块保存为 devDependency。示例: npm install uglify --save-dev
从 npm 5 开始,不再需要 --save 选项。如果您执行“npm install my-package”,它会将 my-package 作为依赖项添加到您的 package.json 文件中。
从 npm 5 开始,不再需要 --save 选项。这真是个好消息!我以前没有意识到这一点。我总是觉得烦人的是大多数文档忽略了 --save 选项,而实际上不保存您添加依赖项的事实几乎没有意义。
D
Dan Kohn

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


我倾向于将测试作为依赖项,因为您可能希望在启动生产服务器之前运行自测
相反,我建议使用像 Hudson 或 CircleCI 这样的持续集成服务来运行您的测试,然后在测试通过时部署到生产环境。
测试实际服务器可能仍然相关,因为 CI 服务器可能与 prod 服务器有所不同,并且这种差异可能会阻止应用程序启动......
@Nicole 你为什么要让你的登台服务器在配置上与你的产品不同?
再说一次,将测试依赖项添加为常规依赖项会引入一大堆额外的库,每个库都可能以某种方式失败。我会倾向于(双关语!)使用尽可能少的代码的轻量级生产服务器。请记住,最好的代码是没有代码!
q
qwertzguy

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

devDependencies 您仅在开发或发布期间需要的依赖项,例如将您的代码编译成 javascript、测试框架或文档生成器的编译器。它们不是可传递安装的(如果 A 依赖于 B dev-依赖于 C,则 npm install on A 将仅安装 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/docs/content/configuring-npm/package-json.md#devdependencies


应该是市场作为“答案” - 清晰整洁,“peerDependencies”下的第一句话正确解释了所有内容,没有深入研究如何在 npm 中解析版本,这不需要了解 peerDependecies 的用途。
最后一个对 peerDependencies 的回答已经满足了“为什么?”而不是“如何?”。非常有帮助!
K
Kaushik NP

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

npm install "$package" --save-dev

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

npm install --production

你也可以使用:npm i -S
D
David Thery

有一些模块和包仅用于开发,而在生产中不需要。就像它在 documentation 中所说的那样:

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


如果您在生产环境中只运行 bundle.js 文件怎么办?你真的需要那些依赖吗?
如果你在服务器上运行 bundle.js,你正在做服务器端 webpack 或其他东西......请检查是否是这种情况,因为它通常不是,实际上需要大量工作才能使其正常运行(我知道,因为我这样做了)。我怀疑您的 bundle.js 只是提供给浏览器并包含客户端代码。
让我困惑的部分是,这里的生产是什么?是 CDN 服务器,我在其上部署构建还是运行构建的客户端浏览器?
r
ruffin

在我阅读了 a blog post 关于主题 Ciro mentioned above 的这段片段之前,peerDependencies 对我来说并不是很有意义:

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

该插件确实需要特定版本的主机...

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

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

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

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

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

更糟糕的是,如果我的主机被视为依赖项,我们最终会遇到这种情况 the same blog post mentions (稍作编辑以使用此答案由主机和插件组成):

但是现在,[如果我们将 HostLibraryX 的现代版本视为 PluginX 的依赖项,] 运行 npm install 会导致意外的依赖关系图 ├── HostLibraryX@4.0.0 └─┬ PluginX@1.0.0 └── HostLibraryX@ 3.0.0 我将把插件使用与主应用程序不同的 [HostLibraryX] API 带来的细微故障留给您想象。

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

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

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

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

相反,我们有成为同行的概念。主机和插件都不在对方的依赖桶中。两者都生活在依赖图的同一级别。

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

如果我是 PluginX v1 并且 期望HostLibraryX v3 的对等点(即 具有 的 peerDependency),我会这样说。如果您已自动升级到最新的 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

结尾

插件中良好的 peerDependency 管理将使这个概念在实践中更直观地工作。从the blog post,再次...

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


J
Jyoti Duhan

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

当您部署应用程序时,需要安装依赖项中的模块,否则您的应用程序将无法运行。 devDependencies 中的模块不需要安装在生产服务器上,因为您不是在该机器上开发。 link


那么,如果我们正在制作网站并且在 prod 版本中,所有库都将内联到 vendor.js 中,如果已编译的代码提交到 repo 中,我们所有的 deps 都应该是 dev deps?它应该被提交,否则很奇怪你必须编译模块,而不仅仅是安装它(并且测试也在这里的某个地方,因为子模块的任何变化都可能导致回归)......
很棒的答案,但有一个问题?可能的 Webpack 会构建损坏的包吗?我的猜测是 devDependencies 包在产品版本中不起作用,webpack -p 我的意思是。请回答我的问题。
如果在生产构建过程中出现任何问题,您的部署过程应该设计为在构建时显示错误并且不会将损坏的代码推送到生产环境(例如,您可以尝试 Jenkins)。无论如何,不需要在生产服务器上安装 Devdependencies。
那么对等依赖呢?
S
Sîrbu Nicolae-Cezar

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

依赖项用于在您的代码库中直接使用,通常最终出现在生产代码中的东西,或代码块

devDependencies 用于构建过程,帮助您管理最终代码的工具,第三方测试模块,(例如 webpack 的东西)


CSS资产呢?
u
user739DamQ

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

简短的回答:

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

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

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

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


最佳答案非常具有描述性和详细信息,但这个答案 ELI5'd peerDependencies 对我来说。
h
hatef

简而言之

依赖项 - npm install --save-prod 在生产环境中安装应用程序所需的包。 DevDependencies - npm install --save-dev 安装仅本地开发和测试所需的包 只需键入 npm install 即可安装 package.json 中提到的所有包

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


S
Selva Ganapathi

依赖与开发依赖

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

例如-反应,反应-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

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

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

# For dev-dependent modules
npm install development-module --save-dev

A
Asker

依赖项

这些是你的包需要运行的包,所以它们会在人们运行时安装

 npm install PACKAGE-NAME

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

 npm install --save

开发依赖

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

npm install PACKAGE --save-dev

对等依赖

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


J
Juanma Menendez

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

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

peerDependencies:您的项目/包需要协同工作(与它们“合作”)或作为基础的包,主要在您开发插件/组件时有用,以便了解您的插件使用哪个版本的“主”包/component 应该可以使用(例如:React 16)


M
Melchia

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

更新

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


请在您的答案中添加一些解释,以便其他人可以从中学习 - 为什么确切应该避免使用 dependencies
大多数时候,依赖关系只是一堆描述生态系统的库。除非,您真的使用特定版本的库,否则您应该让用户选择是否安装该库以及通过将其添加到 peerDependencies 中来选择哪个版本。
请通过编辑为您的答案添加所有说明
@NicoHaase 如果您有任何问题,请告诉我
K
Kodali444

这两者之间的区别在于 devDependencies 是仅在开发期间需要的模块,而依赖项是在运行时也需要的模块。

要在安装时将依赖项保存为 devDependency,我们需要执行 #npm install --save-dev,而不仅仅是 #npm install --save

安装我喜欢使用的 devDependency 的一个很好的简写是#npm i -D。保存常规依赖项的简写是 -S 而不是 -D。

运行时需要的一些很好的依赖关系示例包括 React、Redux、Express 和 Axios。

何时安装 devDependencies 的一些很好的例子是 Nodemon、Babel、ESLint 和测试框架,如 Chai、Mocha、Enzyme 等……


S
Sagar M

需要依赖项才能运行,devDependencies 仅用于开发


一个基本上提出与现有答案相同的解决方案的答案理论上仍然可以是一个有价值的贡献,如果它解释得更多,或者从不同的角度,或者更容易理解......但这篇文章没有。请不要指望用户会觉得这篇文章有帮助。
A
ArturZ

使用 Webpack 捆绑前端应用程序时,依赖项和 devDependencies 之间的区别不是很清楚。对于最终的捆绑包,放置依赖项的位置无关紧要(但对于其他工具可能很重要)。这就是文档看起来令人困惑的原因。

我在这里找到了解释:Do "dependencies" and "devDependencies" matter when using Webpack?