前端运行时依赖(dependencies)和开发依赖(devDependencies)区分
参考文章:https://mp.weixin.qq.com/s/cSHCKRdMPLKyPP_pOH3nkg
以前一直对package.json中的dependencies和devDependencies抱有疑问,为什么依赖还要分为运行时(前者)和开发依赖(后者)呢?而且在安装一个依赖时,如何判断是应该放在dependencies还是devDependencies呢?
文章中说npm的依赖共分为以下五类(见npm官方文档https://docs.npmjs.com/files/package.json#dependencies):
- dependencies
- devDependencies
- peerDependencies
- bundledDependencies
- optionalDependencies
一、dependencies
这是npm最基本的依赖,写在一个简单的对象中,将依赖程序包映射到版本范围。比较常用,命令为
npm install/i xxx@version -S/--save
如果不指定版本号version,则默认安装最新版本。
二、devDependencies
顾名思义devDenpendencies是开发依赖,也就是开发中所使用的的依赖,线上生产环境上并不需要他们。命令为
npm install/i xxx -D/--save-dev
npm官方文档将它定义为开发中所使用的外部的测试或者文档框架。
文章中提到,开发依赖的目的是为了减少在安装依赖时node_modules的体积,提升安装依赖的速度,节省线上及其的硬盘资源以及部署上线的时间。那么那些依赖可以划分为开发依赖呢?
1、构建工具
点名webpack、webpack-cli、rollup(其实我没用过)等等。构建工具是为了生成生产环境的代码,在线上使用的代码其实是他们工作的结果,也就是说在线上时,并不需要他们,因此他们可以归为开发依赖。
当然他们衍生出来的插件,如xxx-webpack-plugin,也属于开发依赖。
2、预处理器
指的是对源代码进行一定的处理并生成最终代码的工具。常见的有css中的less、scss、sass、stylus,js中的typescript、coffee-script、babel等等。
以 babel 为例,常用的有两种使用方式。其一是内嵌在 webpack 或者 rollup 等构件工具中,一般以 loader 或者 plugin 的形式出现,例如 babel-loader。其二是单独使用(小项目较多),例如 babel-cli。babel 还额外有自己的插件体系,例如 xxx-babel-plugin。类似地,less 也有与之对应的 less-loader 和 lessc。这些都算作开发依赖。
在 babel 中还有一个注意点,那就是 babel-runtime 是 dependencies 而不是 devDependencies。
3、测试工具
当然在线上时是用不到测试工具的,因此他们归入开发依赖。常用如chai、e2e等等。
4、其他
最后一类很难概括,是开发时需要使用的,实际上显示要么是已经打包成最终代码了,要么是不需要了。比如 webpack-dev-server 支持开发热加载,线上是不用的;babel-register 因为性能原因也不能用在线上。其他还可能和具体业务相关。
三、peerDependencies、bundleDependencies、optionalDependencies
作为npm包的使用者,前两项其实已经足够日常使用了,后三项是作为npm包的发布者需要考虑使用的,在此不做过多赘述,如果有兴趣可以查阅原文章以及npm的文档。
补充:
在工作中偶然发现,安装某依赖a的时候,一般来说npm会自动收集需要安装的dependecies并且自动安装,但是某些情况下还是会提示需要安装另一依赖b,探究了下,一般是因为依赖a的peerDependencies是b。
为何要这么做呢?
我们都知道开发一个npm包,也不是所有代码都全部自己写,有时候也需要借助一下外部依赖的力量,特别是一些ui组件库,基本上都会基于特定框架(如react的ant-design,vue的element-ui)。这种情况下,这些npm包是要基于一些常见依赖的,即ant-deisgn需要基于react。
那么在使用这些包的时候,以ant-design举例,它需要依赖react,那么就需要给react指定一个版本,但是这个版本它也不能写死,因为我们作为使用者,项目本身肯定是会引入react的,我们对react的版本有自己的要求,这个时候为了避免依赖(ant-design)的依赖(react)和依赖(react)本身的版本冲突,包的开发者就会使用peerDependencies。我们在ant-design的仓库中也可以看到:
peerDependenciest通常指定使用这个包的时候,你也应该在项目中引入它的peerdDenpencies作为你的dependecies,同时它规定了支持的最低版本,安装时应注意此项。peerdDenpencies不会被npm收集,基本上需要你手动安装,并且根据自己需要指定版本。通常情况下,只有一些比较常见的依赖会作为peerDependenciest,以避免包的使用者和包的开发者在某些依赖上存在版本冲突或者一些预料之外的问题。