Appearance
近期開始在專案中使用 pnpm 作為套件管理工具,關於 pnpm 的特色及優點 不在此贅述,本篇記錄在其中一項專案使用 pnpm 踩到的雷。
專案 A 依賴的套件 B,而套件 B 依賴了 webpack-dev-server
,也就是 A -> B -> webpack-dev-server
,踩到的雷是在 A 當中運行 B 套件的指令時,會出現 webpack-dev-server
找不到的錯誤。
問題其實是 pnpm 的特色所導致,以往在使用 npm
或 yarn
安裝套件時,所有依賴的套件(包括套件所依賴的套件) 會全部被安裝在 node_modules
目錄下,所以即使 webpack-dev-server
沒有被專案「直接依賴」一樣可以被調用到。
pnpm
則是將套件安裝在 node_modules/.pnpm
目錄下,然後只把專案直接依賴的套件拉升到 node_modules
目錄下(用檔案連結的方式),所以 node_module
看到的東西很乾淨,只會有專案直接依賴的套件,同樣地 node_modules/.bin
也只會有對應的可執行檔。 這樣的結果就是 webpack-dev-server
被安裝在 node_modules/.pnpm
目錄下,無法被調用到。
方法一:主動聲明 webpack-dev-server
為專案的直接依賴
不傾向這個方法是希望專案能夠保持乾淨,不要有多餘的套件,還有未來需要持續追蹤版本號是否與 B 所依賴的版本號一致的問題。
方法二:使用 shamefully-hoist 選項
--shamefully-hoist
的意思是將所有套件都拉升到 node_modules
目錄下,也就是跟 yarn
與 npm
相同的行為,使用方法是在安裝套件時加入此選項,也就是 pnpm install --shamefully-hoist
。
方法三:使用 public-hoist-pattern
這是我個人偏好的折衷方案,比起 shamefully-hoist
這種直接把所有套件都拉升到 node_modules
目錄,public-hoist-pattern
是一個可以明確指出「只拉升哪些套件」的功能,使用方法是在專案目錄下新增一個 .npmrc
的檔案,這個檔案是操作 pnpm
指令時會讀取的組態檔案,我們在檔案中新增以下內容以決定要拉升哪些套件:
text
public-hoist-pattern[]=webpack
public-hoist-pattern[]=webpack-dev-server
設定值支援萬用字元 *
,因此上面這個範例也可以寫成 public-hoist-pattern[]=webpack*
,設定完後需執行 pnpm install
即可。