yarn yarn2 and pnpm的一些總結

之前做的組內分享,內容不說多豐富,也是精挑細選後總結的不少東西。

前言

yarn以及pnpm都是包管理工具的第三方解決方案,他們各自誕生的時代都是看到了npm本身的不足,如yarn最開始的版本針對的是npm3默認沒有lockfile的問題,pnpm的作者則是對yarn沒有針對node_modules進行太多優化的問題,然後通過自己的方式去解決這些不足。而yarn2(berry),以下統稱berry,則是與yarn1的思路完全不同,抹去了node_modules的存在,目前還未發佈正式版本。但相關文檔已經佔據了yarn的主域名。

接下來主要從下面三個點來講解:

  1. CLI輸出界面
  2. 依賴管理
  3. workspace

人靠衣裝

先看一些主觀性的東西,首當其衝就是每日一見的界面:

npm特點:core-js作者找工作的信息

yarn1,特點:emoji,步驟很清晰,簡潔工整 。

pnpm特點:簡單,重點突出了:重複安裝包的複用問題;dependency的版本

berry特點:error code + 顏色改進

敲擊

yarn又或者berry都比npm敲起來流暢點,pnpm敲起來反人類。

依賴管理

npm

npm對於依賴管理的進化史,主要是爲了解決依賴樹過深及很多隱藏依賴被重複安裝的問題,npm3從開始的nest mode的拓撲結構,轉到了flat mode的拓撲結構,一定程度上解決了重複依賴的問題。

但是這種結構也是有些問題的,首先是如果有一個隱藏依賴的兩個版本都被在某個項目中被多次引用,無論哪個版本的依賴存放在root級別的目錄都會帶來重複引用的問題。

img

其次還有 phantom dependency 的問題,即我們顯式地調用一些隱藏依賴時並沒有報錯的問題。因爲npm和yarn的flat mode遵循的還是儘可能把依賴放在根目錄。但有一種情況,devdependency裏使用的隱藏依賴是不會被別的用戶安裝的,因此這種隱藏依賴的顯式調用是在其他用戶的PC裏是會報錯。

接着分別看一下yarn, pnpm, berry的依賴管理。

yarn

yarn的一些特性是走在npm的前邊的,默認產生的lockfile就是很重要的一個。與npm5之後推出的package-lock.json不同,yarn並沒有採用JSON格式的文件,而是使用了自定義的格式,名字就叫做yarn.lock,與前者不同,後者的lockfile目錄結構並不能複製出完完全全一樣的node_modules拓撲結構,他只是把依賴到的所有庫 flat 成根目錄級別,這樣更方便做diff。

pnpm

但是yarn1由於採取的還是扁平化結構,與npm3後的依賴管理存在的問題相同。pnpm則不同,針對npm2的nest mode,他沒有采取flat mode,而是採用了一種hard link的方式,保證了需要的版本的包只會被在一個PC上安裝一次,已節省空間。

這樣的做法順理成章的解決了剛剛npm指出的兩個問題,首先是重複依賴,通過hard link自然可以鏈接到符合要求的模塊;其次隱藏依賴不會被提升到根目錄,自然不會誤引用

因此 phantom dependency 的問題也可以被很好的解決。

yarn2(berry)

儘管yarn1看似並沒有對node_modules作出太大改動,但是他們的團隊並不是沒有意識到node_modules的缺憾,他們做出了Plug’n’Play的嘗試,在介紹這個之前,我們先看看node_modules本身存在的一些問題。

首先node_modules本身的侷限性在於解析、安裝依賴時產生的大量IO操作:

  1. 解析:當require某個第三方文件時,首先在當前目錄尋找node_modules,找不到再去父級,找到之後,再去這個node_modules的子目錄去尋找,直到找到該文件。因爲node不認識包,只認識文件,而node_moduls的設計也就註定了他不允許包管理工具正確的刪除重複的包數據
  2. 安裝:解析出某個具體的版本號,下載 tar 包到離線鏡像,從鏡像解壓到本地緩存;從緩存拷貝到node_modules,即使是pnpm的hard link,也只是優化了最後一步。

因此,berry做出了修改,與其讓node去查找軟件包,不如直接簡明扼要的告訴node應該在哪裏找到這個包。Plug’n’Play特性應運而生,他其實是省略了node_modules的拷貝,轉而生成了一個**.pnp.js的文件去記錄包的版本,以及映射到的磁盤位置,即把每個包看作整體,壓縮成一個zip;一個.yarn文件夾,裏面又有cacheunplugged**目錄,前者存放壓縮過的依賴包,後者可以通過unplugin指令解壓某個想要手動修改的包。

berry一定程度解決了一些問題:

  1. 之前介紹的npm存在的兩個問題,berry因爲不會生成node_modules目錄,因此不存在phantom dependency的問題,同時他採用的.pnp.js的靜態映射而不是copy的方式也避免了重複安裝依賴的問題。

  2. 基於 .pnp.js 和 zip loading 實現的零安裝,即將.pnp.js及.yarn文件夾全部上傳至gitlab,在有些情況下是可行的,但是這裏使用 create-react-app 進行實測,yarn 爲144Mb,berry爲62Mb,只是正常的壓縮體積的優化;隨後拿React,Vue等包做了下實驗,也基本都是這個比例(7.9Mb VS 5.1Mb)(17Mb VS 8.5Mb)。

  3. 最後一點說一下一些新的特性,如插件機制,方便我們在對berry的核心代碼並不熟悉的情況下開發基於berry的擴展功能,官方實現的官方實現的typescript插件,在yarn add 時自動添加@types等。

當然也存在一些問題,最明顯的就是首次安裝依賴的時間並沒有感覺到縮短,其次還有上面所說的.yarn/cache到底要不要放到遠程倉庫中也是有待商榷的事。

workspace

關於workspace,yarn和pnpm很早已經推出了,主要提供了基本的monorepo支持,yarn2做了一些優化,仍是宣揚與lerna相輔相成去使用:

  1. berry爲涉及到workspace的大部分指令提供了交互式的參數(- i),如yarn add -i 判斷添加的某個依賴是否在其他的workspace中使用,來判斷是否要複用其他workspace的版本,還是選擇另外的版本。
    img

  2. berry提供了一個version插件,當一個包發佈新版本時,可以交互的選擇是否讓其他關聯包也發佈新版本,只需一個交互式的命令即可。
    img

  3. Constraints,爲了確保某個monorepo項目使用相同版本的依賴。或者它們不依賴於特定的程序包。或者他們使用特定類型的依賴關係,我們總需要制定一些規則來讓所有的yarn workspace執行,這種規則可以通過在項目目錄創建constraints.pro文件,並用相應的語法(Prolog)書寫。但是因爲目前constraints還在試驗階段,可能還會有一些變動(This feature is still incubating, and its exact API might change from a release to the next)。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章