Q: 為什么要遷移pnpm馅巷?
相比于npm膛虫,pnpm有一些優(yōu)勢:
更快的安裝速度: 在安裝包時,pnpm使用了硬鏈接的方式钓猬,將已安裝的包鏈接到新的目錄下稍刀,而不是復制或下載包。這樣,當你安裝一個包的不同版本或者不同項目使用同一個包時账月,它們會共享已經(jīng)安裝的包综膀,減少了磁盤空間的占用,同時也加速了安裝的速度局齿。
更少的磁盤空間占用: 由于pnpm使用硬鏈接的方式共享已安裝的包剧劝,因此相比于npm,pnpm占用更少的磁盤空間抓歼。
更好的本地緩存: pnpm會緩存包的元數(shù)據(jù)和二進制文件到本地緩存中讥此,這樣再次安裝相同的包時,會從本地緩存中讀取谣妻,而不是重新下載萄喳。這樣可以提高安裝包的速度,并減少網(wǎng)絡(luò)帶寬的消耗蹋半。
更好的多項目管理: pnpm可以管理多個項目的依賴他巨,可以將相同的依賴安裝在一個公共的位置,減少磁盤空間的占用减江,并且可以快速地切換項目之間的依賴關(guān)系染突。
更好的可重復性: pnpm使用了鎖文件來保證安裝包的版本一致性,同時也支持自定義的鎖文件名稱和路徑辈灼。這樣可以確保項目在不同的環(huán)境中的安裝結(jié)果一致觉痛,增強了可重復性。
需要注意的是茵休,pnpm相比于npm也存在一些缺點薪棒,例如兼容性問題、社區(qū)支持不如npm等榕莺。因此俐芯,在選擇使用pnpm還是npm時,需要根據(jù)自己的實際需求和項目情況進行權(quán)衡钉鸯。
Q: 上面提到的硬鏈接和符號鏈接是什么吧史?
硬鏈接和符號鏈接都是文件系統(tǒng)中的鏈接方式,它們的作用是可以將一個文件或目錄鏈接到另一個文件或目錄上唠雕,從而實現(xiàn)共享或復制等功能贸营。下面我來簡單介紹一下它們的區(qū)別和示例。
硬鏈接
硬鏈接是指在文件系統(tǒng)中岩睁,將一個文件名鏈接到另一個文件上钞脂,使它們指向同一個物理數(shù)據(jù)塊,也就是說捕儒,這兩個文件名共享同一個inode節(jié)點冰啃。硬鏈接的本質(zhì)是將一個文件名指向一個已存在的文件邓夕。
硬鏈接的特點:
- 硬鏈接不能跨越不同的文件系統(tǒng),因為inode節(jié)點只存在于一個文件系統(tǒng)中阎毅。
- 硬鏈接可以看作是原文件的一個副本焚刚,它們的文件權(quán)限、擁有者扇调、修改時間等都是相同的矿咕。
- 刪除硬鏈接并不會刪除原文件,只有當所有的硬鏈接都被刪除后狼钮,原文件才會被真正刪除痴腌。
下面是一個硬鏈接的示例:
$ touch file1 # 創(chuàng)建一個文件
$ ln file1 file2 # 創(chuàng)建硬鏈接
$ ls -li file* # 查看文件inode節(jié)點
12345 -rw-r--r-- 2 user user 0 Apr 26 10:00 file1
12345 -rw-r--r-- 2 user user 0 Apr 26 10:00 file2
可以看到,file1和file2的inode節(jié)點是相同的燃领,說明它們共享同一個物理數(shù)據(jù)塊士聪。
符號鏈接
也稱之為軟鏈接,符號鏈接是指在文件系統(tǒng)中猛蔽,創(chuàng)建一個特殊的文件剥悟,其中包含了另一個文件的路徑,通過這個特殊文件來鏈接到目標文件曼库。符號鏈接的本質(zhì)是將一個文件名指向一個路徑区岗。
符號鏈接的特點:
- 符號鏈接可以跨越不同的文件系統(tǒng),因為它們只是一個指向文件或目錄的路徑毁枯。
- 符號鏈接指向的是目標文件或目錄的路徑慈缔,而不是inode節(jié)點,因此种玛,目標文件或目錄的屬性信息可以獨立于符號鏈接存在藐鹤。
- 刪除符號鏈接不會影響目標文件或目錄,也不會刪除它們赂韵。
下面是一個符號鏈接的示例:
$ touch file1 # 創(chuàng)建一個文件
$ ln -s file1 file2 # 創(chuàng)建符號鏈接
$ ls -li file* # 查看文件inode節(jié)點
12345 -rw-r--r-- 1 user user 0 Apr 26 10:00 file1
67890 lrwxr-xr-x 1 user user 5 Apr 26 10:01 file2 -> file1
可以看到娱节,file2是一個符號鏈接文件,它的inode節(jié)點和file1不同祭示,而是一個指向file1的路徑肄满。
Q: 看到一些文章里說pnpm走的是硬鏈接,有的說用了軟連接质涛。到底走的是什么稠歉?
其實,pnpm是軟連接和硬鏈接都用了汇陆∨ǎ可以這么理解,pnpm在機器上某個地方存放安裝好的所有依賴包瞬测,這些依賴包是獨立于我們代碼倉庫的横媚,這也是前面說的pnpm在安裝速度和磁盤空間占用上的優(yōu)點。而我們的代碼庫確實是先通過硬鏈接的方式來建立代碼庫和已安裝過的依賴包之間的共享關(guān)系月趟〉坪可以打開代碼庫看到node_modules
下有一個.pnpm文件夾,里面放的就是當前代碼庫建立的硬鏈接孝宗。
.pnpm
下的文件都是一些名字很長的穷躁,長這樣:
這里不用關(guān)心具體是什么,我們需要關(guān)心的是node_mpdules
下我們認識的npm
依賴包因妇,它們正是通過軟連接的方式來鏈接到.pnpm
下的這些依賴包的问潭。在vscode下,可以明顯看到npm
包后面的軟連接標識:
如果想看一下這些軟連接到底指向哪里的婚被,可以:
# 進入node_modules目錄
cd node_modules
# 枚舉文件列表
ll
可以看到狡忙,這就是node_modules
下軟鏈接到.pnpm
下的。
Q: 這個模式跟npm dedupe是不是很相似址芯,有什么不同灾茁?
pnpm的硬鏈接模式和npm的dedupe功能是類似的,都是通過共享已安裝的包來減少磁盤空間的占用谷炸,同時也可以提高安裝包的速度北专。但它們之間還是存在一些不同:
原理不同: pnpm使用硬鏈接的方式共享已安裝的包,而npm使用的是符號鏈接的方式共享已安裝的包旬陡。硬鏈接是文件系統(tǒng)的一種特殊鏈接拓颓,它可以將一個文件鏈接到另一個文件上,使它們共享相同的內(nèi)容描孟。符號鏈接則是一個指向另一個文件或目錄的特殊文件驶睦。
適用范圍不同: pnpm的硬鏈接模式可以在多個項目之間共享已安裝的包,而npm的dedupe功能只能在單個項目內(nèi)共享已安裝的包匿醒。
優(yōu)勢不同: pnpm的硬鏈接模式可以減少磁盤空間的占用和提高安裝包的速度啥繁,而npm的dedupe功能只能減少磁盤空間的占用。
實現(xiàn)方式不同: pnpm使用了自己的包管理器和包存儲庫青抛,而npm使用了公共的包管理器和包存儲庫旗闽。這也是導致它們之間存在差異的一個重要原因。
需要注意的是蜜另,無論是使用pnpm的硬鏈接模式還是npm的dedupe功能适室,都需要謹慎使用,以避免出現(xiàn)意外的錯誤举瑰。特別是在使用硬鏈接模式時捣辆,如果多個項目共享同一個包,需要注意不要在一個項目中修改了該包的文件此迅,導致其他項目也受到影響汽畴。
Q: pnpm對于node版本有要求嗎?
pnpm有對node版本的要求旧巾。官方文檔中列出的最低支持版本是Node.js 10.x,推薦使用的版本是Node.js 14.x忍些。如果使用的是較舊的Node.js版本鲁猩,可能會導致安裝和使用pnpm時出現(xiàn)錯誤。
我這里本來用的是Node14.x罢坝。因為其他原因廓握,本次也給Node升級到16.x了。
Q: pnpm有類似npm ci的命令嗎嘁酿?
補充:
npm ci
主要是用于剛剛在download了一個倉庫后隙券,還沒有node_modules的時候讓npm完全根據(jù)package.json和package-lock.json的規(guī)范來install依賴包。相比較于直接走npm i
闹司,npm ci
會帶來更精確的小版本版本號控制娱仔,因為npm i對于一些"^1.0.2"這樣的版本號,可能會按照1.x.x這樣的規(guī)范給你無感升級了游桩,造成和之前某些包版本號之間的差異拟枚。
但是當本地已有node_modules的時候,就沒辦法用npm ci
命令了众弓。
是的恩溅,pnpm也有類似 npm ci
命令的功能,可以使用 pnpm install --frozen-lockfile
命令實現(xiàn)谓娃。它會根據(jù) package-lock.json
或 pnpm-lock.yaml
確定依賴關(guān)系脚乡,并且在安裝期間不會更新任何包。此命令類似于 npm ci
和 yarn install --frozen-lockfile
命令滨达。
Q: pnpm@7搭配husky@8后commit一直失敗怎么辦奶稠?
這是因為hooks出問題了。某些代碼庫里會在commit時候會添加一些hook用來處理commit相關(guān)的事務(wù),比如生成commit-id之類的。
husky@8后需要處理一下這個:
husky add .husky/commit-msg 'sh .git/hooks/commit-msg "$@"'
手動把之前.git/hooks下的腳本拷貝到.husky下推盛。
友情提示:.git和.husky一般都是在項目根目錄下的隱藏文件夾喲~