越來(lái)越流行的 Pnpm,了解一下
大家好,我是前端西瓜哥。今天我們來(lái)認(rèn)識(shí)一下 pnpm 包。它是一個(gè)包管理工具,但卻逐漸流行,讓我們看看它到底做了什么驚人之舉。
pnpm 為何能流行
快速和輕量
前端開發(fā)用的包管理工具是 npm(Node Package Manager),應(yīng)付普通的開發(fā)還是不錯(cuò)的。
但也有不少痛點(diǎn),于是 yarn 輪子被造了出來(lái)。它通過并行下載和緩存解決了 npm 下載慢的問題,并引入 lockfile 機(jī)制解決安裝版本號(hào)不固定導(dǎo)致一些錯(cuò)誤的問題。當(dāng)然,這些問題也被 npm 的后續(xù)版本跟進(jìn)改善了。
但它們還有一個(gè)比較重要的問題沒解決,那就是 包的冗余問題。
如果你在本地安裝了幾十個(gè)項(xiàng)目,這些項(xiàng)目的依賴項(xiàng)的安裝都是獨(dú)立的,即使這些項(xiàng)目有大量相同版本的依賴包,也是會(huì)被安裝多次。
首先這會(huì)導(dǎo)致你的容量一般的電腦痛苦不堪。當(dāng)然更重要的是安裝會(huì)很慢,明明本地有,但你就是要去網(wǎng)上下載。如果網(wǎng)速很慢包很大還要下完還要運(yùn)行一些編譯腳本,那太痛苦了。
pnpm 正是為了解決這個(gè)問題,而逐漸流行起來(lái)的包管理工具。
它的原理并不復(fù)雜,就是將包和版本集中到一個(gè)地方保存起來(lái),如果一個(gè)項(xiàng)目用到某個(gè)版本的包,剛好本地又有,那就通過軟硬鏈接鏈接過去,省去了下載時(shí)間和硬盤空間。
幽靈依賴
yarn 和 npm 后來(lái)的版本其實(shí)也是做了 項(xiàng)目層級(jí)的緩存的,就是將一些包的依賴包,把它們放到 node_modules 的最外層,而解決了無(wú)限嵌套的問題。那是可能發(fā)生幾百個(gè) node_modules 遞歸的場(chǎng)景的,太可怕了。
但這種解法,又導(dǎo)致了 幽靈依賴 的問題。
比如我裝個(gè) a 包,我居然就能用 b。為什么?因?yàn)?a 依賴 b,然后 b 被裝在 node_modules 最外層,根據(jù) nodejs 找包的機(jī)制,我們就能用這個(gè) b 庫(kù)。
如果 a 更新后不再依賴 b,b 就不會(huì)被安裝,而我們的項(xiàng)目剛好用到它,那就找不到然后報(bào)錯(cuò)了。
另外,node_modules 下最外層的包只能有一個(gè)版本,如果某個(gè)包依賴的是其他版本,那不好意思,緩存失效,要下載另一個(gè)版本放在這個(gè)包自己的 node_modules 下。
pnpm 天然能解決這種問題,node_module 下,首先有一個(gè) .pnpm 的文件,通過包名 + 版本號(hào),指向唯一的全局緩存。然后 node_modules 下的包指向 .pnpm 下對(duì)應(yīng)的特定版本的包。
看下圖,安裝 axios 包時(shí)帶上了它的很多依賴包,但我們用 .pnpm 做了隔離,所以訪問不到 axios 依賴的包,解決了幽靈依賴的問題。
pnpm 簡(jiǎn)單使用
然后我們?cè)俸?jiǎn)單看看 pnpm 的用法。
安裝
pnpm 的安裝方法在官方文檔寫了很多。但 pnpm 其實(shí)也是 npm 下的一個(gè)包,所以我更傾向于這樣安裝:
初始化項(xiàng)目
不用加 -y ,pnpm 直接給你生成好一個(gè) package.json 文件。
我覺得這個(gè)優(yōu)化是不錯(cuò)的,npm init 如果忘記加上 -y,就要填好長(zhǎng)好長(zhǎng)的選項(xiàng)才能生成 package.json。說真的我覺得生成一個(gè)默認(rèn)的 package.json,然后在上面改更方便,也不是像 create-react-app 那樣需要根據(jù)選項(xiàng)創(chuàng)建一堆文件。
安裝所有依賴
安裝指定包
你說 install 和 add 有啥區(qū)別,我也不太懂。反正我感覺都差不多。
npm 用的是 install 子命令來(lái)安裝包,一開始的版本如果不加 --save 是不會(huì)往 package.json 加上包信息的,有點(diǎn)坑,在 v5 后默認(rèn)開啟 --save。
更新包
運(yùn)行 npm script
吸收了 yarn 的優(yōu)點(diǎn),簡(jiǎn)潔。
卸載包
結(jié)尾
西瓜哥我啊,最喜歡 pnpm 了,heart heart heart。