首页 文章

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

提问于
浏览
1588

This documentation很难回答我的问题 . 我没有选择简单的单词吗?

EDIT 还添加了 peerDependencies ,这是密切相关的,可能会引起混淆 .

10 回答

  • 92

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

  • 387

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

    npm install "$package" --save-dev
    

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

    npm install --production
    
  • 11

    在尝试分发npm包时,应避免使用 dependencies . 相反,您需要考虑将其添加到 peerDependencies 或从 dependencies 中删除它 .

  • 51

    有些模块和软件包只是开发所必需的,在 生产环境 中不需要 . 就像它在_413167中所说:

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

  • 0

    如果您不想安装devDependencies,您只需使用 npm install --production

  • 25

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

    • dependencies 用于代码库中的直接使用,通常最终出现在 生产环境 代码中的内容或代码块

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

  • 1890

    重要行为差异摘要:

    • dependencies安装在两者上:

    • npm install 来自包含 package.json 的目录

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

    • devDependencies是:

    • 也安装在包含 package.json 的目录的 npm install 上,除非您传递 --production 标志(go upvote Gayan Charith's answer) .

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

    • 未经过传递安装 .

    • peerDependencies

    如果缺少,则始终安装3.0之前的

    • ,如果不同的依赖项将使用多个不兼容的依赖项版本,则会引发错误 .

    • expected to start on 3.0(未经测试):如果 npm install 上缺少则发出警告,您必须自己手动解决依赖关系 . 运行时,如果缺少依赖项,则会出现错误(由@nextgentech提及)

    • 传递性(由Ben Hutchison提及):

    • dependencies 是过渡安装的:如果A需要B,而B需要C,则安装C,否则B无法工作,A也不能安装 .

    • devDependencies 未传递安装 . 例如 . 我们没有't need to test B to test A, so B'的测试依赖关系可以省略 .

    相关选项未在此处讨论:

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

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

    root/node_modules/
                     |
                     +- dependency1/node_modules/
                     |                          |
                     |                          +- dependency3 v1.0/
                     |
                     |
                     +- dependency2/node_modules/
                                                |
                                                +- dependency3 v2.0/
    

    但是,插件通常不需要调用其他包的包在这种情况下的主持人 . 代替:

    主机需要

    • 个插件

    • plugins提供主机期望找到的标准接口

    • 只有主机将由用户直接调用,因此必须有一个版本的主机 .

    例如 . 如果 dependency1dependency2 peer依赖于 dependency3 ,则项目树将如下所示:

    root/node_modules/
                     |
                     +- dependency1/
                     |
                     +- dependency2/
                     |
                     +- dependency3 v1.0/
    

    即使您从未在 package.json 文件中提及 dependency3 ,也会发生这种情况 .

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

    对等依赖的典型示例是Grunt,主机及其插件 .

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

    • gruntpeer-dependency

    • 唯一 require('grunt')tests/ 之下:程序实际上并没有使用它 .

    然后,当用户使用插件时,他将通过添加 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.
    
  • 29

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

    部署应用程序时,需要安装依赖项中的模块,或者由于您未在该计算机上进行开发,因此需要在 生产环境 服务器上安装您的应用程序't work. Modules in devDependencies don' . link

  • 1

    dependencies
    项目需要运行的依赖项,例如提供从代码中调用的函数的库 .
    它们是可传递的安装(如果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/npm/blob/master/doc/files/package.json.md#devdependencies

  • 8

    peerDependencies 对我来说没有多大意义,直到我从主题Ciro mentioned above上读到a blog post的这个片段:

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

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

    peerDependencies 适用于需要"host"库来执行其功能的插件库,但可能是在最新版本的主机发布之前一次编写的 .

    也就是说,如果我为 HostLibraryX v3PluginX v1 并离开,那么当 HostLibraryX v4 (或甚至 HostLibraryX v3.0.1 )被释放时,无法保证 PluginX v1 将起作用 .

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

    从插件的角度来看,它只向主机库添加了功能 . 我不确切地依赖他们的主人 . 如果您没有主机,则插件无害地无效 .

    This means dependencies isn't really the right concept for plugins.

    更糟糕的是,如果我的主机被视为依赖,我们最终会遇到这种情况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 并且期望对等(即,具有peerDependency) HostLibraryX v3 ,我'll say so. If you'已自动升级到最新的 HostLibraryX v4 (注意版本 4 )并安装了 Plugin v1 ,您需要知道,对吗?

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

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

    ... 要么...

    “嘿,我看到你正在使用PluginX v1 . 那就是你想要的HostLibraryX v3,你在最后一片中留下了灰尘更新 . 为了安全起见,我正在自动卸载Plugin v1 !! 1!

    不,不,怎么样?!

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


    Coda

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

    一条建议:对象依赖性要求与常规依赖性要求不同,应该是宽松的 . 您不应将对等依赖项锁定到特定的修补程序版本 . 如果一个Chai插件依赖于Chai 1.4.1,而另一个依赖于Chai 1.5.0,那将是非常烦人的,仅仅是因为作者很懒,并且没有花时间搞清楚Chai的实际最小版本兼容 .

相关问题