新聞中心
概念
Fast, disk space efficient package manager。

從策劃到設計制作,每一步都追求做到細膩,制作可持續(xù)發(fā)展的企業(yè)網(wǎng)站。為客戶提供網(wǎng)站設計、成都做網(wǎng)站、網(wǎng)站策劃、網(wǎng)頁設計、域名注冊、虛擬主機、網(wǎng)絡營銷、VI設計、 網(wǎng)站改版、漏洞修補等服務。為客戶提供更好的一站式互聯(lián)網(wǎng)解決方案,以客戶的口碑塑造優(yōu)易品牌,攜手廣大客戶,共同發(fā)展進步。
快速的,節(jié)省磁盤空間的包管理工具。
特點
快速。pnpm 比替代方案快 2 倍數(shù)據(jù)來源[1]
- 高效。Node_modules 中的文件是從一個單一的可內(nèi)容尋址的存儲中鏈接過來的??梢岳斫獬梢粋€全局的 store 中獲取,后面會詳細提到。
- 支持 monorepos。pnpm 內(nèi)置支持了單倉多包。類似 --filter 后面接子 package 的 name 表示只把安裝的新包裝入這個 package 中等。簡單實踐參考[2]。
- 嚴格。pnpm 默認創(chuàng)建了一個非平鋪的 node_modules,因此代碼無法訪問任意包。
npm 和 yarn 包管理機制
npm@3 之前
采用的是一種嵌套安裝的方式。如下圖所示:
node_modules
└─ foo
├─ index.js
├─ package.json
└─ node_modules
└─ bar
├─ index.js
└─ package.json
缺點:
- package 中經(jīng)常創(chuàng)建太深的依賴樹,這會導致 Windows 上的目錄路徑過長問題。
- 當一個 package 在不同的依賴項中需要時,它會被多次復制粘貼并生成多份文件。
npm@3+ 以及 Yarn
將依賴偏平化:
node_modules
├─ foo
| ├─ index.js
| └─ package.json
└─ bar
├─ index.js
└─ package.json
缺點:
- 幻影依賴(Phantom dependencies)?;糜耙蕾囍傅氖?node_modules 中的依賴包在沒有 package.json 。 中聲明的情況下使用了其他包的依賴
- 依賴結(jié)構(gòu)的不確定性。這里為什么是 D@2.0.0 提升,而不是 D@10.0?都有可能,跟安裝的順序有關(guān)。詳情可參考[3]。避免這個問題的解決方案:lock 文件。
- npm 包分身。同樣的也因為打平了 node_modules 中的依賴,就會造成了相同版本的子依賴包在被不同的項目依賴所依賴時會安裝兩次(即上面的圖,B/C 兩個包都依賴了 D@2.0.0)。
安裝很慢。相同的包安裝了兩次,占用磁盤空間,相對的安裝的速度也會變慢。
非單例。當兩個不同的組件調(diào)用 require("library-f") 時,它們可能會得到兩個不同的庫實例,這意味著可能會突然出現(xiàn)兩個單例的實例(換言之,底層的 “global” 變量被分配到兩個不同的閉包中)。會使我們的調(diào)試變得非常困難。
pnpm 的解決方案
前置知識
inode
每一個文件都有一個唯一的 inode,它包含文件的元信息,在訪問文件時,對應的元信息會被 copy 到內(nèi)存去實現(xiàn)文件的訪問。
可以通過 stat 命令去查看某個文件的元信息。
stat README.md
hard link
硬鏈接可以理解為是一個相互的指針,創(chuàng)建的 hardlink 指向源文件的 inode,系統(tǒng)并不為它重新分配 inode。硬鏈接不管有多少個,都指向的是同一個 inode 節(jié)點,這意味著當你修改源文件或者鏈接文件的時候,都會做同步的修改。每新建一個 hardlink 會把節(jié)點連接數(shù)增加,只要節(jié)點的鏈接數(shù)非零,文件就一直存在,不管你刪除的是源文件還是 hradlink。只要有一個存在,文件就存在。
.pnpm 中的每個文件都是來自內(nèi)容可尋址存儲的硬鏈接。
soft link
軟鏈接可以理解為是一個單向指針,是一個獨立的文件且擁有獨立的 inode,永遠指向源文件,這就類比于 Windows 系統(tǒng)的快捷方式。刪除源文件,軟鏈接就會失效。
修改了軟鏈接或硬鏈接的文件,另外的硬鏈接或軟鏈接以及源文件都會發(fā)生變化,這里感覺是需要小心的,特別是修改文件以調(diào)試的時候,記得還原回去,否則另外一個項目用到的時候,可能會出問題。
幾個重點結(jié)果表現(xiàn)
項目根目錄下的 node_modules 中
node_modules 中只有直接依賴的包,而沒有間接依賴的包。通過軟鏈接到.pnpm 目錄中。
.pnpm
虛擬存儲目錄——.pnpm,所有直接和間接依賴項都鏈接到此目錄中。該目錄通過 @ 來實現(xiàn)相同模塊不同版本之間隔離和復用。
Store
pnpm在全局通過Store來存儲所有的 node_modules 依賴,并且在 .pnpm 中存儲項目的hard links。
在使用 pnpm 對項目安裝依賴的時候,如果某個依賴在 sotre 目錄中存在了話,那么就會直接從 store 目錄里面去 hard-link,避免了二次安裝帶來的時間消耗,如果依賴在 store 目錄里面不存在的話,就會去下載一次。
假如全局的包變得非常大怎么辦?使用方法為 pnpm store prune ,它提供了一種用于刪除一些不被全局項目所引用到的 packages 的功能,例如有個包 axios@1.0.0 被一個項目所引用了,但是某次修改使得項目里這個包被更新到了 1.0.1 ,那么 store 里面的 1.0.0 的 axios 就就成了個不被引用的包,執(zhí)行 pnpm store prune 就可以在 store 里面刪掉它了。
原理分析
我們來看一張原理圖:
我們項目中有一個依賴 bar@1.0.0。bar@1.0.0也有一個依賴 foo@1.0.0。
- node_modules 下面有 bar@1.0.0 和 .pnpm 目錄,沒有 foo@1.0.0。
- bar@1.0.0 通過軟鏈接指向 .pnpm/bar@1.0.0/node_modules/bar@1.0.0。.pnpm/bar@1.0.0/node_modules/bar@1.0.0 又通過硬鏈接指向 Store。
- bar@1.0.0 依賴的foo@1.0.0 會安裝在跟自己的同一級,這里的設計,我理解是根據(jù) node 的 require 機制,bar 中 require('foo') 的時候,就會先找到 foo@1.0.0,而不會往上尋找,這樣就避免依賴包版本不一致的問題。.pnpm/bar@1.0.0/node_modules/foo@1.0.0。并通過軟鏈接指向 。
- pnpm 下一級的 foo@1.0.0。
.pnpm/foo@1.0.0 一樣通過硬鏈接指向 Store。
遷移和問題
我們現(xiàn)在可能用的是 npm 或者 yarn,那我們?nèi)绾胃玫倪^渡到 pnpm?或者會不會有什么問題?
- 遷移:
- 遷移 lock 文件??梢酝ㄟ^ pnpm import 的方式。參考[4]。
- 只允許使用 pnpm。參考[5]。
- 解決沖突。跟 npm 和 yarn 一樣。只需要解決完 package.json 的沖突,然后重新 install 即可。
- more...。
問題:
- CI/CD 中全局存儲的問題。可能會命中不同的機器,也有可能存在權(quán)限的問題。
- 相比 npm、yarn。社區(qū)還沒那么活躍。
- 硬鏈接在 window 系統(tǒng)有兼容性的問題。
- more…。
總結(jié)
pnpm 通過巧妙硬鏈接 + 軟鏈接結(jié)合的方式完全實現(xiàn)了依賴樹結(jié)構(gòu)的 node_modules,并且嚴格遵循了 Node.js 的模塊解析標準,解決了幻影依賴和 npm 分身的問題。并且通過全局只保存一份在 ~/.pnpm-store 的方式,在不同的項目中進行 install 的速度也會變得更快,也解決了磁盤空間占用的問題。
參考資料
pnpm: 最先進的包管理工具[6]
中文官網(wǎng)[7]
npm 存在的問題以及 pnpm 是怎么處理的[8]
[1]數(shù)據(jù)來源: https://github.com/pnpm/benchmarks-of-javascript-package-managers
[2]簡單實踐參考: https://zhuanlan.zhihu.com/p/373935751
[3]參考: http://npm.github.io/how-npm-works-docs/npm3/non-determinism.htm
l[4]參考: https://pnpm.io/zh/cli/import
[5]參考: https://pnpm.io/zh/only-allow-pnpm[6]pnpm: 最先進的包管理工具: https://www.aisoutu.com/a/1218460
[7]中文官網(wǎng): https://www.pnpm.cn/
[8]npm 存在的問題以及 pnpm 是怎么處理的: https://www.yuexunjiang.me/blog/problems-with-npm-and-how-pnpm-handles-them/
本文題目:高性能的包管理器Pnpm,你學會了嗎?
文章起源:http://www.5511xx.com/article/djiipie.html


咨詢
建站咨詢
