1. 程式人生 > 其它 >執行npm install命令的時候會發生什麼?

執行npm install命令的時候會發生什麼?

摘要:我們日常在下載第三方依賴的時候,都會用到一個命令npm install,那麼你知道,在執行這個命令的時候都會發生什麼嗎?

本文分享自華為雲社群《執行npm install命令的時候會發生什麼?》,作者: gentle_zhou。

npm(node package manager),是隨同Node.js一起安裝的第三方包管理器;通過npm,我們可以安裝、共享、分發程式碼,管理專案的依賴關係。

我們日常在下載第三方依賴的時候,都會用到一個命令npm install,然後依賴包就會被安裝到node_modules目錄下;但是我們在執行這個命令的時候都會發生什麼呢?帶著好奇心,我去調研學習了一番。

大致的流程是:npm install命令輸入 > 檢查node_modules目錄下是否存在指定的依賴 > 如果已經存在則不必重新安裝 > 若不存在,繼續下面的步驟 > 向 registry(本地電腦的.npmrc檔案裡有對應的配置地址)查詢模組壓縮包的網址 > 下載壓縮包,存放到根目錄裡的.npm目錄裡 > 解壓壓縮包到當前專案的node_modules目錄中。

(上面的圖片就顯示了專案中依賴如果過多的尷尬:等待時間過長,下載下來依賴過多導致node_modules過大)

下面會介紹一下npm處理依賴的早前和當前的方式 以及 幾種不同的install命令下載方式。

早期版本:遞迴

在npm早期版本里,npm處理依賴的方式很粗暴簡單。它會嚴格按照根目錄下package.json檔案的結構以及各個子依賴包的package.json檔案的結構,遞迴地把依賴安裝到它們各自的node_modules目錄裡。這樣如果是個小專案,只需要幾個依賴且這些依賴不會依賴別的依賴,那麼這樣的樹形結構就還算清晰明瞭(node_modules的結構與package.json裡的結構一一對應且層級結構明顯)。

但如果我們的專案是個大專案,裡面的依賴非常多(導致巢狀層級非常深),且不同的層級可能會引用同一個依賴(導致重複冗餘),就不是我們想要的情形了。

當前版本:扁平化

於是,為了解決以上遞迴管理依賴帶來的問題,npm在 3.X版本里做了一次更新,引入了扁平化管理(dedupe)的方式。dedupe是dedeplicated的縮寫,即duplicates were remove,把重複的移除。

扁平化管理的思路就是首先遍歷package.json檔案下dependencies和devDependencies欄位裡的依賴,作為依賴樹的根節點;然後在每個根節點依賴下面都會有其依賴的依賴,作為其子節點;npm會開啟多程序從每個根節點開始逐步往下尋找更深層次的節點。而package.json檔案下dependencies和devDependencies欄位裡的依賴會被安裝在node_modules根目錄下。在遍歷這些依賴的時候,如果發現有重複的依賴模組(重複:模組名相同且semantic version相容;這裡的相容,是指語義化版本都會有一段版本允許範圍,如果兩個依賴的版本號是在這個範圍交際裡就說明是相容;比如依賴X依賴於依賴Y@^1.0.0,而依賴Z依賴於依賴Y@^1.1.0,則Y@^1.1.0就是相容版本),就直接將其丟棄。

但是如果僅僅這樣,其實也有風險。在大專案中,很有可能會碰到依賴A依賴於依賴C-1.0版本,依賴B依賴於依賴C-2.0版本;而在執行npm install命令的時候,會按照package.json裡面的依賴順序依次解析,因此依賴C-1.0和依賴C-2.0的在檔案裡的放置順序會導致Node_modules的依賴結構產生變化。而且為了讓開發者可以使用最新的依賴包,package.json檔案裡通常只會鎖定大版本(即檔案裡依賴如果是^1.1.0版本,npm就會去倉庫中獲取符合1.x.x形式的最新版本),因此某些依賴包小版本更新後,也會造成依賴結構的改變。所以,為了解決npm install命令導致的這種不確定問題,npm 5.x版本里還新增了package-lock.json檔案。

package-lock.json檔案可以保證每次執行npm install後生成的node_modules目錄結構一定是完全相同的。下圖就是package-lock.json中其中一個依賴的資訊,有name-包名,version-包的版本號,dependencies-和node_modules中包結構一一對應的物件,resolved-包具體的安裝來源,integrity-包的hash值,requires-對應子依賴的依賴:

注:並不是所有的子依賴都有dependencies這個屬性,只有子依賴的依賴和當前已安裝在根目錄的Node_modules中的依賴起了衝突之後,才會有這個屬性。

置於為何說package-lock.json 檔案 和 node_modules 目錄結構是一一對應的。還是舉剛剛前面提及的那個依賴衝突導致依賴結構產生變化的例子,“依賴A依賴於依賴C-1.0版本,依賴B依賴於依賴C-2.0版本”,此時因為package-lock.json檔案的存在,我們會把依賴C-1.0版本安裝在依賴A的node_modules目錄下(對應依賴A在package.json檔案裡的dependencies屬性),依賴C-2.0版本安裝在根目錄下。這可以保障每次安裝生成的依賴目錄結構保持相同。

package-lock.json 檔案還有個優點,就是它會快取每個包的具體版本和下載連結,在後期再去install的時候,就不需要再去遠端倉庫進行查詢操作了,減少了大量網路請求。

幾種不同的install命令下載方式

  1. npm install xxx #(XXX是某依賴包)安裝依賴模組至專案node_modules目錄下,不會修改package.json檔案裡的內容
  2. npm install -g xxx #安裝依賴模組到全域性(而不是專案node_modules目錄下),不會將該依賴模組寫到package.json檔案裡的dependencies和devDependencies欄位裡
  3. npm install --save xxx #安裝依賴模組到專案node_modules目錄下,並將依賴寫入到package.json檔案裡的dependencies欄位中;該依賴是開發和生產環境裡都需要的
  4. npm install --save-dev xxx #安裝依賴模組到專案node_modules目錄下,並將依賴寫入到package.json檔案裡的devDependencies欄位中

 

點選關注,第一時間瞭解華為雲新鮮技術~