背景
考虑这样一种场景:
- 开发者针对`[email protected]
开发了一个名为
[email protected]`的插件 - `[email protected]
不需要引用
[email protected],两者不存在显式的依赖关系。但从逻辑上讲,
[email protected]是
[email protected]`的宿主 - `[email protected]
不兼容
[email protected]`
为了避免用户在`[email protected]的环境上安装
[email protected],显然此时开发者需要声明
[email protected]和
[email protected]`的宿主关系。
于是peerDependencies
应运而生。
peer的中文意思为同辈的、同龄的。peerDependencies
可以理解为同伴依赖,它表示包和包之间的宿主关系。
最近在搞[email protected]的时候,安装各种插件后总是会出现UNMET PEER DEPENDENCY
这个东西,它到底是个什么错误呢?在通读了Domenic Denicola的这篇文章后,才有了个大致的理解。
我们还记得刚接触node(node<5.0, npm<3.0)的时候,依赖是层层安装的,比如某个项目同时依赖了a和b,a和b又同时依赖了c,那么项目的结构会是这样的:
|--a--c
|--b--c
是的,c会被安装两次,虽然看起来有些蠢,但这很好的解决了a和b可能会同时依赖不同版本的c的情况。
后来(node>=5.0, npm>=3.0)的时候做了一些优化,还是上面的例子,如果a和b所依赖的c在同一个版本区间,那么将会只装一个c,并且装到顶层和a、b同级:
|--a
|--b
|--c
更详细的规则在我的这篇文章中有提到。这样就解决了重复安装的问题,但是还有一个问题没有得到解决,那就是插件的问题。比如我们发布了一个名字叫做webpack-plugin-a
的插件,他只是webpack
的一个插件,并不依赖webpack
,所以不会把webpack
写入自身的dependencies
或者devDependencies
,但是它又确实需要针对特定的webpack
版本来进行开发。设想以下场景:
1.我们开发[email protected]
的时候是针对[email protected]
来开发的
2.webpack
发布了最新的[email protected]
并且做了不兼容升级,导致[email protected]
已经不能在该版本使用
3.有不明真相的开发者,安装了[email protected]
和我们的[email protected]
悲剧发生了,由于webpack
版本不兼容,当该开发者执行编译的时候肯定是要报错的。那么如何避免这种问题的发生呢?聪明的npm维护者们想到了使用peerDependencies
来指定所需要兼容的宿主包的版本,我们在[email protected]
的package.json
中添加如下配置:
"peerDependencies": {
"webpack": "^2.0.0" }
这样就指定了[email protected]
只兼容[email protected]
,当用户同时安装[email protected]
和[email protected]
的时候就会抛出:
UNMET PEER DEPENDENCY [email protected]
npm WARN [email protected] requires a peer of webpack@^2.0.0 but none was installed
以上提示,足够让开发者认识到当前所存在的风险了,该特性添加于Node.js 0.8.19(npm 1.2.10)版本