乐趣区

关于npm:dependencies-和-devDependencies-和-peerDependencies

写在后面

在平时的我的项目开发中,咱们只须要晓得 dependencies 和 devDependencies 的区别就好了,环境依赖放在 devDependencies 里,非环境依赖放在 dependencies。然而在波及到开发一个 npm 包的时候,咱们就须要深刻理解 package.json 里依赖相干字段的区别了。

dependencies

dependencies 翻译过去就是依赖的意思,咱们新开发一个包,外面如果齐全没有依赖任何第三方包,那么该字段就能够没有。然而实际上,这种状况很少,咱们新开发的包个别都会援用到一些第三方包,就是在外部 require 或者 import 一些第三方应用,那么此时,这些被咱们外部援用的第三方包就应该放在 dependencies 字段里,这是规范的地位。

那么在他人装置咱们的这个包的时候,npm 会如何解决 dependencies 字段里的依赖包呢?

首先,dependencies 字段里的第三方包是咱们这个包失常运行必须的包,因而,npm 为了保障咱们的包能被失常运行,就会去查看并确保这些第三方包必须有。

  1. 当援用咱们的包的工程里的 node_modules 里没有咱们的包的 dependencies 字段里的包时,npm 会在咱们的包被装置时,将咱们包里 dependencies 字段里的第三方包平铺装置在 node_modules 里。
    (这也是为什么咱们在装置一个包的时候,node_modules 里呈现了一堆包的起因之一)
  1. 当援用咱们的包的工程里的 node_modules 里有咱们的包的 dependencies 字段里的包时,npm 就开始查看了,查看版本,若现有的版本合乎能用,就不再反复装置了。比方本地工程里的版本是 1.0.0 , 咱们包的 dependencies 里要求的是 ^1.0.0,是合乎的。
  1. 当援用咱们的包的工程里的 node_modules 里有咱们的包的 dependencies 字段里的包,但 npm 查看进去版本不匹配,比方本地工程里的版本是 1.0.0,但咱们包的 dependencies 里要求的版本是 ^1.0.2 , 显然版本不匹配,因为有的第三方包不同版本在 api 上有可能会有很大差别,因而 npm 为了确保咱们的包能失常工作,就会在咱们包里新建一个 node_modules,在外面装置依赖。那看起来就是会有 node_modules 的嵌套,如下:

PS: 看到有些人会说,这种存在两个版本的状况会有问题,就是当这个存在两个版本的第三方包和工程有数据交互的时候,因为两个包都会被引入应用,就会有抵触或者数据笼罩的状况。是有这个可能,但我感觉,这种状况很少,咱们公布的包里依赖的第三方包应该只为咱们的包提供特定的性能,实现性能就好了,算是咱们的包完整性的一部分。如果真的波及到数据的,那我感觉不应该放在 dependencies 字段里。能够放在 peerDependencies 里。

devDependencies

devDependencies 翻译过去就是开发环境依赖,咱们在开发一个 npm 包的时候,会波及到编译和打包等等,这些操作依赖一些开发环境的包,依照规范,这些包应该放在 devDependencies 字段里。

那么在他人装置咱们的这个包的时候,npm 会如何解决 devDependencies 字段里的依赖包呢?

答案就是,漠视它!npm 不会去管该字段的,因为这个字段里的第三方包仅仅是在其开发的时候用到的,不是咱们的 npm 包的一部分。该字段只是在咱们的包在本地开发的时候应用的。

peerDependencies

peerDependencies 这个词不太好翻译,直译过去就是等同依赖,对等依赖。我感觉依据其理论的作用,其实翻译为 适配依赖 比拟好。

那么这个字段具体是干嘛呢?

是这样的,你想,咱们开发一个第三方包的时候,咱们会援用到第三方包,那咱们开发的这个包是不是也会被别的第三方包援用呢?咱们应用 dependencies 字段向 npm 阐明了咱们依赖的包,那咱们是不是也应该向 npm 告知咱们以后版本实用于哪些第三方包呢?

因为咱们在开发的时候不晓得会被哪个第三方包援用,因而这种状况个别是咱们依据某个会援用咱们的第三方包进行的特定开发,常见的就是插件开发。比方咱们开发一个 webpack 插件,webpack 不同版本的插件开发的标准和提供的 api 是不一样的,咱们开发一个 webpack 3 的插件,那咱们就要通知 npm 咱们这个插件只能适配 webpack 3,不适配 webpack 5。用什么通知呢?

就是应用 peerDependencies 字段。

例如 babel-loader 的 package.json 文件里的 peerDependencies 字段

peerDependencies 字段里的第三方包并不是咱们的 npm 包里应用的,也不是在开发环境中会用到的包,而是咱们适配的包。

那么在他人装置咱们的这个包的时候,npm 会如何解决 peerDependencies 字段里的依赖包呢?

为了阐明这个字段,npm 还真的是纠结了良久。在 npm v1-v2 版本的时候,npm 对这个字段的解决就是主动帮你装置,然而起初大家认为太蛊惑了,性能太像 dependencies 字段了。为了让大家不蛊惑,npm 在 v3-v6 的时候,对这个字段的解决是我不帮你主动装置了,给你个正告,提醒你说你得本人装置这个依赖。起初,不晓得 npm 听到了什么倡议,在 v7-v8(目前最新) 版本又复原到了主动帮你装置的状态。

因为 npm v1-v2 版本太老了,就不再钻研了。在这里比照了下 npm v3-v6 和 npm v7-v8 版本对 peerDependencies 字段的解决。

npm v3-v6

  1. 当援用咱们的包的工程里的 node_modules 里没有咱们的包的 peerDependencies 字段里的包时,npm 会在咱们的包被装置时,给出正告⚠️,提醒用户本人装置。
  1. 当援用咱们的包的工程里的 node_modules 里有咱们的包的 peerDependencies 字段里的包,但 npm 比照出版本不合乎是,给出正告⚠️,提醒用户。
  1. 当援用咱们的包的工程里的 node_modules 里有咱们的包的 peerDependencies 字段里的包,npm 查看后发现版本合乎,无正告,输入失常。

npm v7-v8

  1. 当援用咱们的包的工程里的 node_modules 里没有咱们的包的 peerDependencies 字段里的包时,npm 会在咱们的包被装置时,将咱们包里 peerDependencies 字段里的第三方包平铺装置在 node_modules 里。
  1. 当援用咱们的包的工程里的 node_modules 里有咱们的包的 peerDependencies 字段里的包, 但 npm 比照后发现版本不合乎,则报错,装置失败。npm 会让用户解决这个抵触谬误,若用户不解决,则能够应用其提醒的,运行 npm i --forcenpm i --legacy-peer-deps。强行装置抵触中的一个版本。可解决报错,但出了问题用户本人负责。
  1. 当援用咱们的包的工程里的 node_modules 里有咱们的包的 peerDependencies 字段里的包, npm 比照后发现版本合乎,不报错,失常装置。

PS: 总结下来,peerDependenciesdependencies 最大的区别就是,dependencies 字段会呈现 node_modules 嵌套的状况,但 peerDependencies 字段是不会呈现 node_modules 嵌套的状况的。

写在前面

以上内容里,dependenciesdevDependencies 都好了解。就是 peerDependencies 了解起来吃力点。坦白讲,包管理工具面对包与包之间的依赖的解决是最麻烦的,当依赖的包版本呈现抵触时,按理说为了包不被反复装置和在数据交互时呈现问题,应该由用户去解决包版本的抵触的。

npm 在 v7-v8 版本里尽管复原了 peerDependencies 的主动帮你装置的状态,但又新增了一个字段叫 peerDependenciesMeta,这个字段就是能够将 peerDependencies 里的包设置为可选的状态,设置为可选的状态就是不会帮你主动装置,也不会报错。

在一些简单状况的时候,还得综合思考这些字段的灵活运用。还有一个字段叫 bundledDependencies 在某些时候也很有用。这些有工夫再聊吧。

退出移动版