本文主要介紹npm、 yarn、pnpm三者在依賴管理方面的不同。
在npm2中,當我們使用依賴A時,依賴A里使用了依賴B,依賴B里使用了依賴C,node_modules里就會是這樣的結構:
node_modules
--packageA.js
--node_modules
--packageB.js
--node_modules
--packageC.js
......
嵌套的層級太深,會導致文件的路徑過長,有些程序可能無法處理過長的文件名。
另外假如還有個依賴D中也使用了依賴C,那么依賴D的node_modules下會再次安裝依賴C,這樣就會導致有大量的依賴重復安裝的問題,導致文件體積過大。
在npm3中及yarn中,采用扁平化依賴的方法來處理npm2中存在的問題,在npm3及yarn中會是這樣的接口:
node_modules
-- packageA.js
-- packageB.js
-- packageC.js
項目中的依賴及依賴使用的依賴都會平鋪在node_modules下,這樣就能解決嵌套層級過深的問題,包也不會被重復被安裝,如遇到版本不同的情況,則會進行版本提升。
這種方法的缺點是,npm必須首先遍歷所有的項目依賴關系,然后再決定如何生成扁平的node_modules目錄結構。npm必須為所有使用到的模塊構建一個完整的依賴關系樹,這是一個耗時的操作,是npm安裝速度慢的一個很重要的原因。
另外由於扁平化的結構,導致即使項目中聲明了依賴B,但是沒有聲明過依賴C,也可以直接使用依賴C,這樣就會造成隱患問題。如果依賴B中哪天不需要使用依賴C了,那我們的node_modules里就會沒有依賴C,這樣就會導致項目報錯。
pnpm中,使用符號鏈接和硬鏈接的做法來放置依賴。
硬鏈接是原始文件的一個鏡像副本,它只能指向文件,記錄了原始文件的內容,原始文件改變的時候,鏈接會同步改變。軟鏈接類似於Windows系統中的快捷方式,它可以指向文件目錄或文件,鏈接文件只記錄原始文件的路徑,不記錄原始文件的內容。
使用pnpm的項目的node_modules下的包名下存放的其實是一個軟鏈接,連接到node_modules下的.pnpm/包名/node_modules/xxx該目錄下存放的是該依賴包的依賴以及該依賴包本身,每個包里面都存放了一個全局store中對應包源代碼的hard link。每個項目的node_modules下存放的是一些link。
使用pnpm的好處是可以節約磁盤並提升安裝速度,也能避免開發時使用間接依賴的問題。
參考文章
1、一文看懂npm、yarn、pnpm之間的區別
2、npm 和 yarn 你選哪個?
3、為什么現在我更推薦 pnpm 而不是 npm/yarn?
4、pnpm又是什么?
5、pnpm原理
6、Linux硬鏈接和軟連接的區別與總結
7、Linux 中軟鏈接和硬鏈接的區別
6、Yarn vs npm:你需要知道的一切
7、字節的一個小問題 npm 和 yarn不一樣嗎?
