用一個例項簡單介紹什麼是pnpm

語言: CN / TW / HK

pnpm 官網的介紹是

Fast, disk space efficient package manager

它的第一個p表示performance,意思是它針對npm在效能上進行了改進。

反正時至今日,我已經是搞不清 yarnnpm 之間的區別了,這裡就直接比較 pnpmnpm

我們知道從 npm 從一出生到現在一直沒有解決包的依賴問題,如下圖

V3之前的 npm ,直接是有什麼依賴就裝什麼依賴,導致依賴包冗餘,比如

反正就是無腦的你有什麼依賴,我就給你建出什麼樣的目錄,這樣就至少帶來兩個問題

一個是目錄有可能太長,特別對於 Windows 作業系統,路徑是有字元長度限制的,另一個問題就是模組冗餘,同一個版本的模組存在於多個位置下。

我印象中好像 yarn 先跳出來改良,然後 npm 在v3的時候也跟進了,反正截止到目前,把依賴問題稍稍的給糾正了一下,為什麼說稍稍,因為糾正得不徹底。改進的方法是將依賴打平一些,把至少第二層的依賴給挪到第一層去。於是上面的這張圖很有可能變成

也有可能變成

至於哪個版本被提升到第一層,這個是不確定的。而 Node.js 的模組查詢機制是會向上層目錄找尋的,於是這個模組最終肯定能被找到。 而正因為更改了原本的依賴宣告( package.json 裡的依賴宣告和 node_modules 裡的目錄不一致),所以也就誕生了 yarn.lockpackage-lock.json 兩個檔案。 yarnnpmlock 檔案上的機制好像還有點不同,不過不影響我們無區別地使用它們。

順便也說一句, lock 檔案要上傳到 git 倉庫,其他人 clone 程式碼後,最好執行 npm ci 來完全還原第一個提交人的安裝現場。

一眼就看出,這個方式只是解決了一丟丟的問題 —— 只是把某個依賴的某個版本的冗餘給去除了,當然它還引入了別的問題,比如幽靈依賴,按上圖,現在工程在不宣告[email protected]的情況下可以直接使用它了,不過我覺得都還好。

來看一個實際的例子,我在一個工程下安裝了 koa ,然後 node_modules 是這樣子的

接下來用 pnpm 安裝一下 koa 看看是什麼樣子的

是不是很清爽,用 ls -al 命令再仔細看一下

發現多了一個 modules.yaml 檔案,多了一個 .pnpm 目錄,然後 koa 怎麼有個箭頭?

如果熟悉 Linux 的話肯定就知道這個箭頭代表了軟連結,通俗的話來說就是 Windows 裡的快捷方式。順著這個軟連結,我們再執行 ls -al .pnpm/[email protected]/node_modules

還是一堆的軟連結,都指向了 .pnpm 下的某個目錄,但是再看仔細一點, koa 可不是,快捷方式的盡頭肯定有原主,所以軟連結的盡頭肯定得有硬連結。注意看 koa 那一行的第二列,說明有9個硬連線。

至於真正的 koa 藏在哪,我們可以檢視剛才的 .modules.yaml 檔案

storeDir 表示依賴真正存放的路徑,到這裡面看看

我猜這裡面和 git 倉庫儲存是同樣的機制,也截一張 .git 工程裡的圖,看 objects 目錄

綜上, pnpm 靈活使用了軟硬連結來將 npm 的依賴問題給很好的解決了,上一張官網的好圖

最後說實話,按照一貫的尿性(參考各大公司之間的互抄),我估計 npm 下一版本也會引入 pnpm 的改進做法了。