npm 的局限性
- 磁盤空間浪費
在 npm
早期版本中,每個項目的node_modules目錄都會完整復制所有依賴包,即使多個項目依賴同一個包的相同版本,也會重復存儲。這導致磁盤空間被大量占用,隨著項目數量的增加,存儲成本顯著上升。雖然
npm v3
引入了扁平化結構,一定程度上減少了重復,但仍無法徹底解決問題。例如,在一個擁有多個項目的開發環境中,如果每個項目都依賴
lodash,那么每個項目的node_modules目錄中都會有一份 lodash 的副本。
- 安裝速度較慢
npm
安裝依賴時,需要從遠程倉庫下載每個包并寫入node_modules目錄,對于大型項目,尤其是依賴眾多的項目,這個過程涉及大量的
I/O 操作和網絡請求,安裝速度會受到明顯影響。即使在 npm v5
之后支持了并行下載,在面對復雜的依賴樹時,安裝時間仍然較長。例如,當安裝一個包含上百個依賴包的項目時,npm
可能需要數分鐘甚至更長時間才能完成安裝。 幽靈依賴問題 npm 的扁平化node_modules結構帶來了 “幽靈依賴”
問題。項目可以訪問未在package.json中聲明的依賴包,這是因為依賴包的嵌套依賴可能被提升到node_modules的根目錄,從而導致項目代碼中能夠直接引用這些未聲明的依賴。這種不明確的依賴關系使得項目的依賴管理變得混亂,一旦依賴包的版本發生變化,可能會導致項目在運行時出現難以排查的錯誤。例如,項目
A 依賴包 B,而包 B 又依賴包 C,由于扁平化結構,包 C 可能會被提升到node_modules根目錄,項目 A
的代碼中就可以直接引用包 C,即使項目 A 的package.json中并沒有聲明對包 C 的依賴。
- pnpm 的優勢
高效的磁盤空間管理 pnpm 使用內容尋址存儲和符號鏈接 /
硬鏈接技術來管理依賴。所有依賴項都存儲在全局共享存儲中,當項目安裝依賴時,pnpm
會通過硬鏈接將依賴包從全局存儲鏈接到項目的node_modules目錄,而不是復制整個包。這意味著,無論有多少個項目依賴同一個包的相同版本,磁盤上只會存儲一份該包的文件。例如,假設有
100 個項目都依賴 lodash,在 pnpm 的管理下,lodash
在磁盤上只占用一份空間,大大節省了磁盤資源。而且,當依賴包的版本更新時,pnpm
只會將有差異的文件添加到存儲中,進一步減少了磁盤空間的占用。 快速的安裝速度 pnpm
的安裝過程分為三個階段:依賴解析、目錄結構計算和鏈接依賴項。在依賴解析階段,識別并獲取倉庫中沒有的依賴;目錄結構計算階段,根據依賴關系計算node_modules目錄結構;鏈接依賴項階段,將以前安裝過的依賴項從存儲區直接鏈接到node_modules。這種方式避免了重復下載和復制文件,尤其是在處理大量依賴項時,安裝速度明顯快于
npm。在有緩存的情況下,或者安裝已經存在于全局倉庫中的包時,pnpm 的安裝速度幾乎可以達到 “秒級”,極大地提高了開發效率。
清晰的依賴結構,杜絕幽靈依賴 pnpm 創建的是一個嵌套的、有嚴格依賴關系的node_modules結構。在 pnpm
的node_modules中,只會包含在package.json中明確聲明的依賴。項目依賴的包所依賴的其他包,會被存放在node_modules/.pnpm/這個特殊目錄里,并通過符號鏈接的方式鏈接到相應包的node_modules中。這就從根本上杜絕了
“幽靈依賴”
問題,確保項目的依賴關系清晰、可靠,不會出現意外引用未聲明依賴的情況。在項目代碼中嘗試引用未在package.json中聲明的依賴時,pnpm
會直接報錯,保證了項目依賴的純凈性。 對 Monorepo 的良好支持 在處理 Monorepo(多包倉庫)時,npm 的支持相對較弱,而
pnpm 原生支持
Monorepo,并且配置相對簡單。通過在項目根目錄創建pnpm-workspace.yaml文件并聲明對應的工作區,就可以方便地管理多個包和項目。在一個包含多個前端項目和后端項目的
Monorepo 中,使用 pnpm 可以輕松實現依賴的共享和管理,減少重復安裝,提高整個項目組的開發效率。
- 案例對比
磁盤空間占用對比 以一個實際的開發場景為例,有 5 個 React 項目,使用 npm 管理依賴時,這 5
個項目的node_modules目錄總共占用了 8.7G 的磁盤空間;而使用 pnpm 后,同樣的 5
個項目,node_modules相關的存儲總共只占用了 3.2G,直接節省了 5G
左右的磁盤空間。對于磁盤空間有限的開發者來說,這無疑是一個非常有吸引力的優勢。 安裝速度對比 在安裝一個具有復雜依賴樹的項目時,使用 npm
執行npm install命令,等待時間長達數分鐘;而使用 pnpm 執行pnpm
install,安裝時間縮短了一半以上,極大地減少了開發過程中的等待時間,提高了開發節奏。 依賴管理穩定性對比 在一個團隊協作項目中,由于
npm 的package-lock.json文件有時不能很好地鎖定依賴版本,導致不同開發者安裝的依賴版本不一致,經常出現
“在我電腦上能運行,在別人電腦上報錯” 的情況。而切換到 pnpm
后,其pnpm-lock.yaml文件更嚴格地記錄了依賴的版本、來源和包的哈希值,保證了不同開發者安裝的依賴結構幾乎 100%
一致,項目交接和協同開發變得更加順暢,減少了因依賴不一致導致的問題。 綜上所述,pnpm 在磁盤空間管理、安裝速度、依賴結構的清晰性以及對
Monorepo 的支持等方面,都展現出了明顯優于 npm 的特性。在當今前端項目日益復雜、依賴管理愈發重要的背景下,pnpm
為開發者提供了更高效、更可靠的包管理解決方案。