探讨npm依赖管理之peerDependencies
引言
想必前端同学对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的更多相关文章
- 谈谈npm依赖管理
引言 现在的前端开发几乎都离不开nodejs的包管理器npm,比如前端在搭建本地开发服务以及打包编译前端代码等都会用到.在前端开发过程中,经常用到npm install来安装所需的依赖,至于其中的技术 ...
- npm依赖管理:冗余,依赖树
npm的依赖树查询:原理都是查询文件夹node_modules的结构.比如mac的node_modules位置在/usr/local/lib下.具体项目的node_modules位置位于项目根目录下. ...
- nodejs Yarn替代npm的包管理——快速、安全、可靠性高的依赖管理
Yarn能帮你解决的五件事 转自: http://www.qingpingshan.com/jb/javascript/185590.html 长话短说(TL;DR):在 JavaScript 领域有 ...
- 用CocoaPods做iOS程序的依赖管理(转摘)
转摘自:http://blog.devtang.com/blog/2014/05/25/use-cocoapod-to-manage-ios-lib-dependency/ 文档更新说明 2012-1 ...
- Composer : php依赖管理工具
原始时代 我记得在当时用php的时候还没有composer,只有个pear,但是不好用呀,还不如直接在互联网上到处复制代码了,更快更不容易出错,当时也没有github这么好的社区工具了 总结如下 代码 ...
- crossplatform---bower解决js的依赖管理
从零开始nodejs系列文章,将介绍如何利Javascript做为服务端脚本,通过Nodejs框架web开发.Nodejs框架是基于V8的引擎,是目前速度最快的Javascript引擎.chrome浏 ...
- 用CocoaPods做iOS程序的依赖管理
CocoaPods简介 每种语言发展到一个阶段,就会出现相应的依赖管理工具,例如Java语言的Maven,nodejs的npm.随着iOS开发者的增多,业界也出现了为iOS程序提供依赖管理的工具,它的 ...
- bower解决js的依赖管理
bower解决js的依赖管理 前言: 一个新的web项目开始,我们总是很自然地去下载需要用到的js类库文件,比如jQuery,去官网下载名为jquery-1.10.2.min.js文件,放到我们的项目 ...
- Composer PHP 依赖管理工具
composer 是 PHP 用来管理依赖(dependency)关系的工具.你可以在自己的项目中声明所依赖的外部工具库(libraries),Composer 会帮你安装这些依赖的库文件. 依赖管理 ...
随机推荐
- blender基础操作
旋转:鼠标中键 左右移动:鼠标中键+左shift 放大缩小:鼠标滚轮滚动 blender旋转以锁定物件作为中心点旋转 blender选取物件用鼠标右键, 选中物件之后,利用数字键盘中的点(Del) 来 ...
- jQuery on() 方法 为选定已存在元素和未来元素绑定标准事件和自定义事件
很有必要说说jQuery的on方法,这个方法存在大乾坤大奥秘,主要注意两点: 1.为已存在元素和未来元素(动态添加元素)绑定处理函数. 2.自定义一个非标准的事件并绑定处理函数. 定义和用法 on() ...
- nginx 添加response响应头
硬添
- clean-room 洁净室软件工程
众所周知,软件工程的主要目的是提高软件的开发效率和软件质量.近年来发展起来的洁净室软件工程(cleanroom software engineering)提出了用统计的质量控制方法管理软件 ...
- Could not load file or assembly (Exception from HRESULT: 0x80131047)-解决办法
场景:.Net 4.0 MVC WebAPI 应用程序添加ApplicationInsights监控后在demo环境运行正常,发布到testing环境出现异常 异常信息: Could not load ...
- Biopython 安装使用
Biopython 官网:https://biopython.org/ 安装 Biopython https://biopython.org/wiki/Download 可以使用 pip 进行安装, ...
- Python之路(第三十九篇)管道、进程间数据共享Manager
一.管道 概念 管道可用于具有亲缘关系进程间的通信,有名管道克服了管道没有名字的限制,因此,除具有管道所具有的功能外,它还允许无亲缘关系进程间的通信. 先画一幅图帮助大家理解下管道的基本原理 现有2个 ...
- 微信小程序开发之搞懂flex布局5——cross axis
Cross Axis——交叉轴,与Main Axis(主轴)垂直交叉. main axis is row or row-reverse the cross axis runs down the col ...
- 唉 调皮的ListView
唉 调皮的ListView 本次任务是 运用LisTView和自定义Adapter 来实现资料以列表的形式展现 来看代码 *** 布局代码老规矩 直接贴上 <LinearLayout andro ...
- python 基础 ------字符串的调用详解(1)
Python 字符串的的调用方法~~~ 废话不多说直接奔主题 >>>>>>>>>>>>>>>>> ...