為什麼 pnpm 比 npm 更快且更省空間?
2024年1月1日
身為前端開發者,你大概一定聽過 npm 這個套件管理工具,可能也聽過社群許多人會用的 yarn,以及過去兩年熱門的 bun。但其實還有一個叫 pnpm 的套件管理工具,是在 bun 出來之前,受到許多開發團隊親賴的。這篇文章我們來聊聊 pnpm。
在 pnpm 的官網中是用 Fast, disk space efficient package manager 來介紹 pnpm 的。可以看到,這邊強調的是兩個特點,一個是在時間維度上快,另一個是在空間維度上有效率。
先來講快這一點,之所以 pnpm 比起 npm 或者 yarn 來得快,是因為 pnpm 在設計上,共享了依賴,這可以避免重複下載何解壓縮已經被處理過的套件,因此在多個不同套件都有相同依賴的狀況下,pnpm 會快很多。除此之外,pnpm 也做了本地快取,這能夠減少對網路的依賴;在有快取的狀況下,即使網路速度慢,如果命中本地快取,一樣可以快速完成套件安裝。
接著來講空間上的節省,因為 pnpm 有全局儲存 (global store) 的機制,這能有效避免重複儲存相同的依賴,因此如果你使用的多個套件有重複依賴,最終這些相同的依賴,都只會在硬碟中存一次,這大幅度降低依賴在硬碟中佔據的空間。對比起來,npm 與 yarn 都會在每一個不同的專案複製一份,因此會佔用比較多空間。
要理解 pnpm 在依賴結構設計的巧妙上,我們要先懂 Node.js 是如何找到某個依賴的:
首先 Node.js 會先找自己的模組 (例如
fs
),這部分不需要額外路徑解析如果不是 Node.js 內建模組,它會從
node_modules
底下開始找,如果沒有node_modules
,則會從目前的檔案目錄中,逐一遍歷直到找到最近的node_modules
然後從中找尋某個模組如果找不到,就會繼續遍歷直到找到,如果遍歷完整個目錄還是找不到,就會拋出錯誤
在 pnpm 的設計下,當 Node.js 要開始查找模組時,在 node_modules
底下,大家可能會看到右箭頭的符號,這個右箭頭是指某個連鏈接 (link),這個鏈接會指向上面有提到的全域儲存 (global store),所以可以理解成,當 Node 要找該模組時,pnpm 會跟 Node 說去全域的某個位置可以找到。
而這個全域儲存的位置,就是在 node_modules
底下的 .pnpm
資料夾中,只有在這個資料夾當中的,是真正的檔案,其他的都只是一個指針 (pointer),會指向這個真正存的地方。這樣一來,就可以避免同樣的依賴被複製一份並且重複存
從 pnpm 的設計可以看到,其實在前端的領域,把資料結構學好,是很有價值的,當換了一種設計,就能大幅度減少使用的空間~