每日技術:npm模塊安裝機制

 

內容來自:https://github.com/Advanced-Frontend/Daily-Interview-Question/issues/22html

npm模塊安裝機制

  • 發出npm install命令
  • 查詢node_modules目錄之中是否已經存在指定模塊
    • 若存在,再也不從新安裝
    •   若不存在,
      • npm 向register查詢模塊壓縮包的網址
      • 下載壓縮包,存放在根目錄下的.npm目錄裏
      • 解壓壓縮包到當前項目的node_modules目錄

 

npm實現原理

輸入npm install命令並敲下回車後,會經歷以下幾個階段:node

1.執行工程自身preinstall

當前npm工程若是定義了preinstall鉤子,此時會被執行react

2.肯定首層依賴模塊

首先,須要作的是肯定工程中的首層依賴,也就是dependencies和devDependencies屬性中直接指定的模塊(假設此時沒有添加npm install參數)git

工程自己是整棵依賴樹的根節點,每一個首層依賴模塊都是根節點下面的一棵子樹,npm會開啓多進程從每一個首層依賴模塊開始逐步尋找更深層級的節點。github

3.獲取模塊

獲取模塊是一個遞歸的過程,分爲如下幾步:npm

  • 獲取模塊信息,在下載一個模塊以前,首先要肯定其版本,這是由於package.json中每每是語義化版本。此時若是版本描述文件中有該模塊信息直接拿便可,若是沒有則從倉庫獲取。如package.json中某個包的版本是^1.1.0, npm就會去倉庫中獲取符合1.x.x形式的最新版本。
  • 獲取模塊實體。上一步會獲取到模塊的壓縮包地址(resolved字段),npm會用此地址檢查本地緩存,緩存中有就直接拿,若是沒有則從倉庫下載。
  • 查找該模塊依賴,若是有依賴則回到第1步,若是沒有則中止

 

4.模塊扁平化

上一步獲取到的是一棵完整的依賴樹,其中可能包含大量重複模塊。好比A模塊依賴於lodash,B模塊一樣依賴於lodash,在npm3之前會嚴格按照依賴樹的結構進行安裝,所以會形成模塊冗餘。json

從npm3開始默認加入了一個dedupe的過程。它會遍歷全部節點,逐個將模塊放在根節點下面,也就是node-modules下,foo模塊依賴lodash@^1.0.0,bar模塊依賴lodash@^1.1.0,則^1.1.0爲兼容版本。緩存

而當foo依賴lodash@^2.0.0,bar依賴lodash@^1.1.0,則根據semver的規則,兩者不存在兼容版本,將會一個版本放在node_modules裏,另外一個仍保留在依賴樹裏。網絡

舉個例子,假設一個依賴樹本來是這樣:socket

node_modules

-- foo

---- lodash@version1

-- bar

---- lodash@version2

假設version1和version2是兼容版本,則通過dedupe會成爲下面的形式:

node_module

-- foo

-- bar

-- lodash (保留的版本爲兼容版本)

假設version1和version2爲非兼容版本,則後面的版本保留在依賴樹中

node_modules

-- foo

-- lodash@version1

-- bar

---- lodash@version2

 

5.安裝模塊

這一步將會更新工程中的node_modules,並執行模塊中的生命週期函數(按照preinstall、install、postinstall的順序)

6.執行工程自身生命週期

當前npm工程若是定義了鉤子此時會被執行(按照install、postinstall、prepublish、prepare的順序)

最後一步以生成或更新版本描述文件,npm install過程完成。

 

 -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------

 

讀阮一峯《npm模塊按照機制簡介》筆記

原文:http://www.ruanyifeng.com/blog/2016/01/npm-install.html

 

npm是Node的模塊管理器,功能極其強大。它是Node得到成功的重要緣由之一

本文介紹npm模塊安裝機制的細節,以及如何解決安裝速度慢的問題。

 

1、npm install

若是你但願,一個模塊不論是否安裝過,npm都要強制從新安裝,可使用-f或-force參數

npm install <packageName> --force

 

2、npm update

若是想更新已安裝模塊,就要用到npm update命令

npm update <packageName>

 

它會先到遠程倉庫查詢最新版本,而後查詢本地版本。若是本地版本不存在,或者遠程版本較新,就會安裝。

 

registry

npm模塊倉庫提供了一個查詢服務,叫作registry。以npmjs.org爲例,它的查詢服務網址是https://registry.npmjs.org/

這個網址後面跟上模塊名,就會獲得一個JSON對象,裏面是該模塊全部版本的信息。好比訪問https://registry.npmjs.org/react,就會看到react模塊全部版本的信息

它跟下面命令的效果是同樣的

npm view react

# npm view 的別名
npm info react
npm show react
npm v react

訪問https://registry.npmjs.org/react/v0.14.6就能夠看到React的0.14.6版。

返回的JSON對象裏面,有一個dist.tarball屬性,是該版本壓縮包的網址。

dist: {
    shasum:'2a57c2cf8747b483759ad8de0fa47fb0c5cf5c6a',
    tarball:  'http://registry.npmjs.org/react/-/react-0.14.6.tgz'
}

到這個網址下載壓縮包,在本地解壓,就獲得了模塊的源碼。

 

緩存目錄

npm install 或npm update命令,從registry下載壓縮包以後,都存放在本地的緩存目錄。

這個緩存目錄,在Linux或Mac默認是用戶主目錄下的.npm目錄,在Windows默認是%AppData%/npm-cache.

經過配置命令,能夠查看這個目錄的具體位置

npm config get cache

瀏覽目錄

ls ~/.npm
#或者
npm cache ls

你會看到裏面存放着大量的模塊,儲存結構是{cache}/{name}/{version}

$ npm cache ls react
~/.npm/react/react/0.14.6/
~/.npm/react/react/0.14.6/package.tgz
~/.npm/react/react/0.14.6/package/
~/.npm/react/react/0.14.6/package/package.json

 

清空緩存命令

rm -rf ~/.npm/*

或者

npm cache clean

 

模塊的安裝過程

總結一下,Node模塊的安裝過程是這樣的

1.發出npm install命令

2.npm向registry查詢模塊壓縮包的網址

3.下載壓縮包,存放在~/.npm目錄

4.解壓壓縮包到當前項目的node_modules

注意,一個模塊安裝之後,本地其實保存了兩份。一份是~/.npm目錄下的壓縮包。另外一份是node_modules目錄下解壓後的代碼。可是運行npm install的時候,只會檢查node_modules目錄,而不會檢查~/.npm目錄。也就是說,若是一個模塊在~/.npm下有壓縮包,可是沒有安裝在node_modules目錄中,npm依然會從遠程倉庫下載一次新的壓縮包。

這種行爲當然能夠保證老是取得最新的代碼,但有時並非咱們想要的。最大的問題是,它會極大地影響安裝速度。即便某個模塊的壓縮包就在緩存目錄中,也要去遠程倉庫下載,這怎麼可能不慢呢?

另外,有些場合沒有網絡,可是你想安裝的模塊,明明就在緩存目錄之中,這時也沒法安裝。

 

--cache-min參數

爲了解決這些問題,npm提供了一個--cache-min參數,用於從緩存目錄安裝模塊。

--cache-min參數指定一個時間(單位爲分鐘),只有超過這個時間的模塊,纔會從registry下載。

npm install --cache-min 999999 <package-name>

上面命令指定,只有超過999999分鐘的模塊才從registry下載。實際上就是指定,全部模塊都從緩存安裝,這樣就大大加快了下載速度。

它還有另外一種寫法

npm install --cache-min Infinity <package-name>

 

 

離線安裝的解決方案

第一類,Registry代理

  • npm-proxy-cache
  • local-npm
  • npm-lazy

 

上面三個模塊的用法很相似,都是在本機起一個Registry服務,全部npm install命令都要經過這個服務代理。

npm-proxy-cache

npm --proxy http://localhost:8080\
--https-proxy http://localhost:8080\
--strict-ssl false\
install

local-npm

npm set registry http://127.0.0.1:5080

npm-lazy

npm --registry http://localhost:8080/ install socket.io

 

有了本機的Registry服務,就能徹底實現緩存安裝,能夠實現離線使用

 

第二類,npm install替代

若是可以改變npm install的行爲,就能實現緩存安裝。npm-cache工具就是這個思路。凡是使用npm install的地方,均可以使用npm-cache替代

npm-cache install

 

第三類,node_modules做爲緩存目錄

這個方案的思路是,不使用.npm緩存,而是使用項目的node_modules目錄做爲緩存。

相關文章
相關標籤/搜索