引言

想必前端同学对npm的devDependencies和dependencies都比较熟悉,但是对peerDependencies可能就有点陌生,尤其是没有写过npm包插件的同学,比如之前使用grunt自动化工具的相关插件(如grunt-contrib-jasmine等)或者目前基于某个框架的ui组件库等等,这些都是需要对peerDependencies有一定了解的。下面我们就来说说peerDependencies。

npm2中dependencies与peerDependencies区别

假设我们当前的项目是MyProject,项目中有一些依赖,比方其中有一个依赖包PackageA,该包的package.json文件指定了对PackageB的依赖:

{
"dependencies": {
"PackageB": "1.0.0"
}
}

如果我们在我们的MyProject项目中执行npm install PackageA, 我们会发现我们项目的目录结构会是如下形式:

MyProject
|- node_modules
|- PackageA
|- node_modules
|- PackageB

那么在我们的项目中,我们能通过下面语句引入"PackageA":

var packageA = require('PackageA')

但是,如果你想在项目中直接引用PackageB:

var packageA = require('PackageA')
var packageB = require('PackageB')

这是不行的,即使PackageB被安装过;因为Node只会在“MyProject/node_modules”目录下查找PackageB,它不会在进入PackageA模块下的node_modules下查找。

所以,为了解决这个问题,在MyProject项目package.json中我们必须直接声明对PackageB的依赖并安装。

但是,有时我们不用在当前项目中声明对PackageB的依赖就可以直接引用,尤其是,PackageA是一个类似于grunt的插件,例如grunt-contrib-jshint。

为什么在项目中不用声明就可以直接使用呢?这就不得不说说peerDependencies的作用了。

peerDependencies的引入

为了解决这种问题:

如果你安装我,那么你最好也安装X,Y和Z.

于是peerDependencies就被引入了。例如上面PackageA的package.json文件如果是下面这样:

{
"peerDependencies": {
"PackageB": "1.0.0"
}
}

那么,它会告诉npm:如果某个package把我列为依赖的话,那么那个package也必需应该有对PackageB的依赖。

也就是说,如果你npm install PackageA,你将会得到下面的如下的目录结构:

MyProject
|- node_modules
|- PackageA
|- PackageB

你可能注意到:

在npm2中,即使当前项目MyProject中没有直接依赖PackageB,该PackageB包依然会安装到当前项目的node_modules文件夹中。

下面的代码现在可以正常工作了,因为两个包在"MyProject/node_modules"中被安装了:

var packageA = require('PackageA')
var packageB = require('PackageB')

总结一句话,peerDependencies的具体作用:

peerDependencies的目的是提示宿主环境去安装满足插件peerDependencies所指定依赖的包,然后在插件import或者require所依赖的包的时候,永远都是引用宿主环境统一安装的npm包,最终解决插件与所依赖包不一致的问题。

举个例子,就拿目前基于react的ui组件库ant-design@3.x来说,因该ui组件库只是提供一套react组件库,它要求宿主环境需要安装指定的react版本。具体可以看它package.json中的配置:

  "peerDependencies": {
"react": ">=16.0.0",
"react-dom": ">=16.0.0"
}

它要求宿主环境安装react@>=16.0.0和react-dom@>=16.0.0的版本,而在每个antd组件的定义文件顶部:

import * as React from 'react';
import * as ReactDOM from 'react-dom';

组件中引入的react和react-dom包其实都是宿主环境提供的依赖包。

npm2和npm3中peerDependencies的区别

正如上一节谈论的,在npm2中,PackageA包中peerDependencies所指定的依赖会随着npm install PackageA一起被强制安装,所以不需要在宿主环境的package.json文件中指定对PackageA中peerDependencies内容的依赖。

但是在npm3中,peerDependencies 的表现与npm2不同:

npm3中不会再要求peerDependencies所指定的依赖包被强制安装,相反npm3会在安装结束后检查本次安装是否正确,如果不正确会给用户打印警告提示。

就拿上面的例子来说,如果我们npm install PackageA安装PackageA时,你会得到一个警告提示说:

PackageB是一个需要的依赖,但是没有被安装。

这时,你需要手动的在MyProject项目的package.json文件指定PackageB的依赖。

另外,在npm3的项目中,可能存在一个问题就是你所依赖的一个package包更新了它peerDependencies的版本,那么你可能也需要在项目的package.json文件中手动更新到正确的版本。否则会出现类似下图所示的警告信息:

参考

1、Peer Dependencies

2、package.json文件

3、Dealing with the deprecation of peerDependencies in NPM 3

探讨npm依赖管理之peerDependencies的更多相关文章

  1. 谈谈npm依赖管理

    引言 现在的前端开发几乎都离不开nodejs的包管理器npm,比如前端在搭建本地开发服务以及打包编译前端代码等都会用到.在前端开发过程中,经常用到npm install来安装所需的依赖,至于其中的技术 ...

  2. npm依赖管理:冗余,依赖树

    npm的依赖树查询:原理都是查询文件夹node_modules的结构.比如mac的node_modules位置在/usr/local/lib下.具体项目的node_modules位置位于项目根目录下. ...

  3. nodejs Yarn替代npm的包管理——快速、安全、可靠性高的依赖管理

    Yarn能帮你解决的五件事 转自: http://www.qingpingshan.com/jb/javascript/185590.html 长话短说(TL;DR):在 JavaScript 领域有 ...

  4. 用CocoaPods做iOS程序的依赖管理(转摘)

    转摘自:http://blog.devtang.com/blog/2014/05/25/use-cocoapod-to-manage-ios-lib-dependency/ 文档更新说明 2012-1 ...

  5. Composer : php依赖管理工具

    原始时代 我记得在当时用php的时候还没有composer,只有个pear,但是不好用呀,还不如直接在互联网上到处复制代码了,更快更不容易出错,当时也没有github这么好的社区工具了 总结如下 代码 ...

  6. crossplatform---bower解决js的依赖管理

    从零开始nodejs系列文章,将介绍如何利Javascript做为服务端脚本,通过Nodejs框架web开发.Nodejs框架是基于V8的引擎,是目前速度最快的Javascript引擎.chrome浏 ...

  7. 用CocoaPods做iOS程序的依赖管理

    CocoaPods简介 每种语言发展到一个阶段,就会出现相应的依赖管理工具,例如Java语言的Maven,nodejs的npm.随着iOS开发者的增多,业界也出现了为iOS程序提供依赖管理的工具,它的 ...

  8. bower解决js的依赖管理

    bower解决js的依赖管理 前言: 一个新的web项目开始,我们总是很自然地去下载需要用到的js类库文件,比如jQuery,去官网下载名为jquery-1.10.2.min.js文件,放到我们的项目 ...

  9. Composer PHP 依赖管理工具

    composer 是 PHP 用来管理依赖(dependency)关系的工具.你可以在自己的项目中声明所依赖的外部工具库(libraries),Composer 会帮你安装这些依赖的库文件. 依赖管理 ...

随机推荐

  1. blender基础操作

    旋转:鼠标中键 左右移动:鼠标中键+左shift 放大缩小:鼠标滚轮滚动 blender旋转以锁定物件作为中心点旋转 blender选取物件用鼠标右键, 选中物件之后,利用数字键盘中的点(Del) 来 ...

  2. jQuery on() 方法 为选定已存在元素和未来元素绑定标准事件和自定义事件

    很有必要说说jQuery的on方法,这个方法存在大乾坤大奥秘,主要注意两点: 1.为已存在元素和未来元素(动态添加元素)绑定处理函数. 2.自定义一个非标准的事件并绑定处理函数. 定义和用法 on() ...

  3. nginx 添加response响应头

    硬添

  4. clean-room 洁净室软件工程

          众所周知,软件工程的主要目的是提高软件的开发效率和软件质量.近年来发展起来的洁净室软件工程(cleanroom software engineering)提出了用统计的质量控制方法管理软件 ...

  5. Could not load file or assembly (Exception from HRESULT: 0x80131047)-解决办法

    场景:.Net 4.0 MVC WebAPI 应用程序添加ApplicationInsights监控后在demo环境运行正常,发布到testing环境出现异常 异常信息: Could not load ...

  6. Biopython 安装使用

    Biopython 官网:https://biopython.org/ 安装 Biopython  https://biopython.org/wiki/Download 可以使用 pip 进行安装, ...

  7. Python之路(第三十九篇)管道、进程间数据共享Manager

    一.管道 概念 管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信. 先画一幅图帮助大家理解下管道的基本原理 现有2个 ...

  8. 微信小程序开发之搞懂flex布局5——cross axis

    Cross Axis——交叉轴,与Main Axis(主轴)垂直交叉. main axis is row or row-reverse the cross axis runs down the col ...

  9. 唉 调皮的ListView

    唉 调皮的ListView 本次任务是 运用LisTView和自定义Adapter 来实现资料以列表的形式展现 来看代码 *** 布局代码老规矩 直接贴上 <LinearLayout andro ...

  10. python 基础 ------字符串的调用详解(1)

    Python 字符串的的调用方法~~~ 废话不多说直接奔主题 >>>>>>>>>>>>>>>>> ...