探討npm依賴管理之peerDependencies

引言

想必前端同窗對npm的devDependencies和dependencies都比較熟悉,可是對peerDependencies可能就有點陌生,尤爲是沒有寫過npm包插件的同窗,好比以前使用grunt自動化工具的相關插件(如grunt-contrib-jasmine等)或者目前基於某個框架的ui組件庫等等,這些都是須要對peerDependencies有必定了解的。下面咱們就來講說peerDependencies。javascript

npm2中dependencies與peerDependencies區別

假設咱們當前的項目是MyProject,項目中有一些依賴,比方其中有一個依賴包PackageA,該包的package.json文件指定了對PackageB的依賴:html

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

若是咱們在咱們的MyProject項目中執行npm install PackageA, 咱們會發現咱們項目的目錄結構會是以下形式:前端

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

那麼在咱們的項目中,咱們能經過下面語句引入"PackageA":java

var packageA = require('PackageA')

可是,若是你想在項目中直接引用PackageB:node

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

這是不行的,即便PackageB被安裝過;由於Node只會在「MyProject/node_modules」目錄下查找PackageB,它不會在進入PackageA模塊下的node_modules下查找。react

因此,爲了解決這個問題,在MyProject項目package.json中咱們必須直接聲明對PackageB的依賴並安裝。git

可是,有時咱們不用在當前項目中聲明對PackageB的依賴就能夠直接引用,尤爲是,PackageA是一個相似於grunt的插件,例如grunt-contrib-jshint。github

爲何在項目中不用聲明就能夠直接使用呢?這就不得不說說peerDependencies的做用了。npm

peerDependencies的引入

爲了解決這種問題:json

若是你安裝我,那麼你最好也安裝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文件中手動更新到正確的版本。不然會出現相似下圖所示的警告信息:

參考

一、Peer Dependencies
二、package.json文件
三、Dealing with the deprecation of peerDependencies in NPM 3

相關文章
相關標籤/搜索