從 npm 切換到 pnpm,真香!
大廠技術 高級前端 Node進階
點擊上方 程序員成長指北,關注公眾號
回復1,加入高級Node交流群
轉轉的 CI 系統(tǒng)和開發(fā)環(huán)境為什么要從 npm 切換到 pnpm 呢。因為在使用 npm 的時候,遇到幾個問題。
磁盤空間占用過大 首次安裝速度慢 幽靈依賴導致一些報錯
那 pnpm 又是怎么解決上面的問題呢?
什么是 pnpm
pnpm 是新一代包管理工具,為什么叫 pnpm 呢,是因為 pnpm 作者對現有的包管理工具,尤其是 npm 和 yarn 的性能特別失望,所以起名叫做 performance npm,即 pnpm(高性能 npm)
我們今天要使用 pnpm,那 pnpm 有哪些優(yōu)勢呢
1、npm 的問題
在 npm@3 之前,node_modules 結構是干凈、可預測的,因為 node_modules 中的每個依賴項都有自己的 node_modules 文件夾,在 package.json 中指定了所有依賴項,比如項目 a 依賴項目 b,項目 c 也依賴項目 b,這樣如果 a 和 c 依賴的 b 的版本不一致,也不會出問題
node_modules
└─ a
├─ index.js
├─ package.json
└─ node_modules
└─ b
├─ index.js
└─ package.json
c
├─ index.js
├─ package.json
└─ node_modules
└─ b
├─ index.js
└─ package.json
上面結構有兩個嚴重的問題:
package 中經常創(chuàng)建太深的依賴樹,這會導致 Windows 上的目錄路徑過長問題 當一個 package 在不同的依賴項中需要時,它會被多次復制粘貼并生成多份文件
為了解決上面的問題,npm 提出了 node_modules 扁平化結構,在 npm@3+ 和 yarn 中,node_modules 結構變成:
node_modules
├─ a
| ├─ index.js
| └─ package.json
└─ b
| ├─ index.js
| └─ package.json
└─ c
├─ index.js
└─ package.json
hoist 機制下,b 包被提升到了頂層。如果同一個包的多個版本在項目中被依賴時,node_modules 結構又是怎么樣的?

包 B 1.0 被提升到了頂層,這里需要注意的是,多個版本的包只能有一個被提升上來,其余版本的包會嵌套安裝到各自的依賴當中,至于哪個版本的包被提升,依賴于包的安裝順序!
扁平化之后,又引入了新的問題幽靈依賴,解釋起來很簡單,即某個包沒有在 package.json 被依賴,但是用戶卻能夠引用到這個包。還有 NPM doppelgangers 問題,當包有多個版本,會被重復安裝多次。
2、pnpm 的方案
pnpm 使用的是 npm version 2.x 類似的樹形結構,同時使用.pnpm 以平鋪的形式儲存著所有的包。
我們稱.pnmp 為虛擬存儲目錄,該目錄通過 <package-name>@<version> 來實現相同模塊不同版本之間隔離和復用,由于它只會根據項目中的依賴生成,并不存在提升,所以它不會存在之前提到的 Phantom dependencies 問題!
然后使用 Store + Links 和文件資源進行關聯。簡單說 pnpm 會把包下載到一個公共目錄,如果某個依賴在 sotre 目錄中存在了話,那么就會直接從 store 目錄里面去 hard-link,避免了二次安裝帶來的時間消耗,如果依賴在 store 目錄里面不存在的話,就會去下載一次。
通過 Store + hard link 的方式,不僅解決了項目中的 NPM doppelgangers 問題,項目之間也不存在該問題,從而完美解決了 npm3+和 yarn 中的包重復問題!

3、workspace
pnpm 除了安裝速度快,節(jié)省磁盤空間,避免幽靈依賴等優(yōu)化,也內置了對 monorepo 的支持。使用起來比較簡單,在項目根目錄中新建 pnpm-workspace.yaml 文件,并聲明對應的工作區(qū)就好。
packages:
# 所有在 packages/ 子目錄下的 package
- 'packages/**'
切換到 pnpm
轉轉的 CI 系統(tǒng)。一共有 6 臺機器,是前后端公用的。之前使用 npm 存在幾個問題。第一個就是安裝速度慢,導致編譯時間過長。第二個是 node_modules 過大。導致每天必須清除一下機器上 node_modules,不然就會出現磁盤空間不足的問題。切換成 pnpm 之后,我們測試的結果,單臺機器最少能節(jié)省了 30G 的空間,安裝速度提升一倍以上。
因為直接從 npm 切換到 pnpm,大多數的項目都會存在幽靈依賴的問題。導致項目報錯。我們的切換方案是在項目設置中勾選是否使用 pnpm。默認是 npm。單個項目在本地切換之后,在 CI 平臺上設置成 pnpm 就完成了升級。
切換 pnpm 的一些問題
使用 pnpm install --shamefully-hoist
如果依賴一直有問題,可以使用 pnpm install --shamefully-hoist 創(chuàng)建一個扁平 node_modules 目錄結構, 類似于 npm 或 yarn
解決幽靈依賴時,安裝默認的包導致報錯
先使用 npm 安裝,生成 package-lock.json, 安裝缺少的包時,使用 lock 里面的版本
即使刪除了 node_modules 和 lock 文件,安裝時,特定的包還是報錯
比如我們在升級時,一個包把最新的版本刪除了。導致安裝時一直失敗。可以嘗試使用 pnpm store prune 來刪除
Node 社群
我組建了一個氛圍特別好的 Node.js 社群,里面有很多 Node.js小伙伴,如果你對Node.js學習感興趣的話(后續(xù)有計劃也可以),我們可以一起進行Node.js相關的交流、學習、共建。下方加 考拉 好友回復「Node」即可。
如果你覺得這篇內容對你有幫助,我想請你幫我2個小忙:
點贊和在看就是最大的支
