相信小夥伴們都接觸過npm/yarn
,這兩種包管理工具想必是大家工作中用的最多的包管理工具,npm
作為node
官方的包管理工具,它是隨著node的誕生一起出現在大家的視野中,而yarn
的出現則是為了解決npm
帶來的諸多問題,雖然yarn
提高了依賴包的安裝速度與使用體驗,但它依舊沒有解決npm
的依賴重複安裝等致命問題。pnpm的出現完美解決了依賴包重複安裝的問題,並且實現了yarn
帶來的所有優秀體驗,所以說pnpm才是前端工程化專案的未來。
如果這篇文章有幫助到你,❤️關注+點贊❤️鼓勵一下作者,文章公眾號首發,關注 前端南玖
第一時間獲取最新文章~
在npm@3之前,node_modules
結構可以說是整潔
、可預測
的,因為當時的依賴結構是這樣的:
node_modules
└─ 依賴A
├─ index.js
├─ package.json
└─ node_modules
└─ 依賴B
├─ index.js
└─ package.json
└─ 依賴C
├─ index.js
├─ package.json
└─ node_modules
└─ 依賴B
├─ index.js
└─ package.json
每個依賴下面都維護著自己的node_modules
,這樣看起來確實非常整潔,但同時也帶來一些較為嚴重的問題:
從上面的依賴結構我們可以看出,依賴A與依賴C同時參照了依賴B,此時的依賴B會被下載兩次。此刻我們想想要是某一個依賴被參照了n次,那麼它就需要被下載n次。(此時心裡是不是在想,怎麼會有如此坑的設計)
我們再來看另外一種依賴結構:
node_modules
└─ 依賴A
├─ index.js
├─ package.json
└─ node_modules
└─ 依賴B
├─ index.js
├─ package.json
└─ node_modules
└─ 依賴C
├─ index.js
├─ package.json
└─ node_modules
└─ 依賴D
├─ index.js
└─ package.json
這種依賴層級少還能接受,要是依賴層級多了,這樣一層一層巢狀下去,就像一個依賴地獄,不利於維護。
為了解決上述問題,npm3
與yarn
都選擇了扁平化結構,也就是說現在我們看到的node_modules
裡面的結構不再有依賴巢狀了,都是如下依賴結構:
node_modules
└─ 依賴A
├─ index.js
├─ package.json
└─ node_modules
└─ 依賴C
├─ index.js
├─ package.json
└─ node_modules
└─ 依賴B
├─ index.js
├─ package.json
└─ node_modules
node_modules
下所有的依賴都會平鋪到同一層級。由於require尋找包的機制,如果A和C都依賴了B,那麼A和C在自己的node_modules中未找到依賴C的時候會向上尋找,並最終在與他們同級的node_modules中找到依賴包C。 這樣就不會出現重複下載的情況。而且依賴層級巢狀也不會太深。因為沒有重複的下載,所有的A和C都會尋找並依賴於同一個B包。自然也就解決了範例無法共用資料的問題
由於這個扁平化結構的特點,想必大家都遇到了這樣的體驗,自己明明就只安裝了一個依賴包,開啟node_modules
資料夾一看,裡面卻有一大堆。
這種扁平化結構雖然是解決了之前的巢狀問題,但同時也帶來了另外一些問題:
這個怎麼理解,為什麼會產生這種問題呢?我們來仔細想想,加入有如下一種依賴結構:
A包與B包同時依賴了C包的不同版本,由於同一目錄下不能出現兩個同名檔案,所以這種情況下同一層級只能存在一個版本的包,另外一個版本還是要被巢狀依賴。
那麼問題又來了,既然是要一個扁平化一個巢狀,那麼這時候是如何確定哪一個扁平化哪一個巢狀的呢?
這兩種結構都有可能,準確點說哪個版本的包被提升,取決於包的安裝順序!
這就是為什麼會產生依賴結構的不確定
問題,也是 lock 檔案
誕生的原因,無論是package-lock.json
(npm 5.x 才出現)還是yarn.lock
,都是為了保證 install 之後都產生確定的node_modules
結構。
儘管如此,npm/yarn 本身還是存在扁平化演演算法複雜
和package 非法存取
的問題,影響效能和安全。
前面說了那麼多的npm
與yarn
的缺點,現在再來看看pnpm是如何解決這些尷尬問題的。
快速的,節省磁碟空間的包管理工具
就這麼簡單,說白了它跟npm
與yarn
沒有區別,都是包管理工具。但它的獨特之處在於:
從上圖可以看出,pnpm
的包安裝速度明顯快於其它包管理工具。那麼它為什麼會比其它包管理工具快呢?
我們來可以來看一下各自的安裝流程
resolving:首先他們會解析依賴樹,決定要fetch哪些安裝包。
fetching:安裝去fetch依賴的tar包。這個階段可以同時下載多個,來增加速度。
wrting:然後解壓包,根據檔案構建出真正的依賴樹,這個階段需要大量檔案IO操作。
上圖是pnpm的安裝流程,可以看到針對每個包的三個流程都是平行的,所以速度會快很多。當然pnpm會多一個階段,就是通過連結組織起真正的依賴樹目錄結構。
pnpm 內部使用基於內容定址
的檔案系統來儲存磁碟上所有的檔案,這個檔案系統出色的地方在於:
hardlink
。hardlink
,僅僅寫入那一個新增的檔案
。pnpm 與 npm/yarn 另外一個很大的不同就是支援了 monorepo,pnpm內建了對monorepo的支援,只需在工作空間的根目錄建立pnpm-workspace.yaml和.npmrc組態檔,同時還支援多種設定,相比較lerna和yarn workspace,pnpm解決monorepo的同時,也解決了傳統方案引入的問題。
monorepo 的宗旨就是用一個 git 倉庫來管理多個子專案,所有的子專案都存放在根目錄的
packages
目錄下,那麼一個子專案就代表一個package
。
pnpm使用的是npm version 2.x類似的巢狀結構,同時使用.pnpm 以平鋪的形式儲存著所有的包。然後使用Store + Links和檔案資源進行關聯。簡單說pnpm把會包下載到一個公共目錄,如果某個依賴在 sotre 目錄中存在了話,那麼就會直接從 store 目錄裡面去 hard-link,避免了二次安裝帶來的時間消耗,如果依賴在 store 目錄裡面不存在的話,就會去下載一次。通過Store + hard link的方式,使得專案中不存在NPM依賴地獄問題,從而完美解決了npm3+和yarn中的包重複問題。
我們分別用npm
與pnpm
來安裝vite對比看一下
npm | pnpm |
---|---|
所有依賴包平鋪在node_modules 目錄,包括直接依賴包以及其他次級依賴包 |
node_modules 目錄下只有.pnpm 和直接依賴包,沒有其他次級依賴包 |
沒有符號連結(軟連結) | 直接依賴包的後面有符號連結(軟連結)的標識 |
pnpm安裝的vite
所有的依賴都軟鏈至了 node_modules/.pnpm/
中的對應目錄。 把 vite
的依賴放置在同一級別避免了迴圈的軟鏈。
pnpm 是通過 hardlink 在全域性裡面搞個 store 目錄來儲存 node_modules 依賴裡面的 hard link 地址,然後在參照依賴的時候則是通過 symlink 去找到對應虛擬磁碟目錄下(.pnpm 目錄)的依賴地址。
這兩者結合在一起工作之後,假如有一個專案依賴了 [email protected]
和 [email protected]
,那麼最後的 node_modules 結構呈現出來的依賴結構可能會是這樣的:
node_modules
└── A // symlink to .pnpm/[email protected]/node_modules/A
└── B // symlink to .pnpm/[email protected]/node_modules/B
└── .pnpm
├── [email protected]
│ └── node_modules
│ └── A -> <store>/A
│ ├── index.js
│ └── package.json
└── [email protected]
└── node_modules
└── B -> <store>/B
├── index.js
└── package.json
node_modules
中的 A 和 B 兩個目錄會軟連線到 .pnpm 這個目錄下的真實依賴中,而這些真實依賴則是通過 hard link 儲存到全域性的 store 目錄中。
pnpm
下載的依賴全部都儲存到store
中去了,store
是pnpm
在硬碟上的公共儲存空間。
pnpm
的store
在Mac/linux中預設會設定到{home dir}>/.pnpm-store/v3
;windows下會設定到當前碟符的根目錄下。使用名為 .pnpm-store的資料夾名稱。
專案中所有.pnpm/依賴名@版本號/node_modules/
下的軟連線都會連線到pnpm
的store
中去。
我是南玖,我們下期見!!!
-------------------------------------------
如果這篇文章有幫助到你,❤️關注+點贊❤️鼓勵一下作者,文章公眾號首發,關注 前端南玖 第一時間獲取最新的文章~
掃描下方二維條碼關注公眾號,回覆進群,拉你進前端學習交流群(WX),這裡有一群志同道合的前端小夥伴,交流技術、生活、內推、面經、摸魚,這裡都有哈,快來加入我們吧~ 回覆資料,獲取前端大量精選前端電子書及學習視訊~