除了NPM,前端工程師應該知道的yarn知識

除了NPM,前端工程師應該知道的yarn知識

yarn 是在工作中離不開的工具,但在工作中,很多人基本只會使用 yarn install,而且會手動刪除 node-modules,或刪除 yarn。lock 檔案等不規範操作。本文將從一些基礎的知識點開始介紹,循序漸進的讓你對 Yarn 有一個更深入的瞭解,來保證規範的使用yarn,避免一些隱藏bug的產生。

本文主要介紹以下知識:

什麼是registry

依賴的版本含義及寫法

依賴型別及區別(devDependences,devDependences,peerDependences, optionalDependencies,bundledDependencies)

快取介紹

yarn。lock 檔案作用及介紹

yarn install 安裝依賴的過程

依賴關係樹的模組扁平化

常用的 yarn 命令介紹

什麼是registry

registry是 模組倉庫提供了一個查詢服務,也就是我們常說的源。以yarn官方映象源為例,它的查詢服務網址是https://registry。yarnpkg。com。

這個網址後面跟上模組名,就會得到一個 JSON 物件,裡面是該模組所有版本的資訊。比如,訪問 https://registry。npmjs。org/vue,就會看到 vue 模組所有版本的資訊。

registry 網址的模組名後面,還可以跟上版本號或者標籤,用來查詢某個具體版本的資訊。 https://registry。yarnpkg。com/vue/2。6。10

除了NPM,前端工程師應該知道的yarn知識

上面返回的 JSON 物件裡面,有一個dist。tarball屬性,是該版本壓縮包的網址。dist。shasum 屬性相當於hash值,在lock和快取時會使用到,下文會提到。

上面返回的 JSON 物件裡面,有一個dist。tarball屬性,是該版本壓縮包的網址。dist。shasum 屬性相當於hash值,在lock和快取時會使用到,下文會提到。

dist: { “shasum”: “a72b1a42a4d82a721ea438d1b6bf55e66195c637”, “tarball”:“https://registry。npmjs。org/vue/-/vue-2。6。10。tgz”}

我們在執行 yarn install 時,就是向 registry 查詢得到上面的壓縮包地址進行下載的。

工作中,我們可能有需要修改映象源的場景,比如修改成淘寶源或者自己公司的私有源。

檢視和設定源,可以透過 yarn config 命令來完成

檢視當前使用的映象源

yarn config get registry

修改映象源(以修改成淘寶源為例)

yarn config set registry https://registry。npm。taobao。org/

依賴版本

yarn的包遵守 semver,即語義化版本。 SemVer 是一套語義化版本控制的約定,定義的格式為

X。Y。Z(主版本號。次版本號。修訂號):X。主版本號:進行不向下相容的修改時,遞增主版本號Y。次版本號: 做了向下相容的新增功能或修改Z。修訂號:做了向下相容的問題修復複製程式碼

yarn 中依賴版本範圍的表示方法有以下幾種:

透過比較器

除了NPM,前端工程師應該知道的yarn知識

如果沒有指定運算子,預設為 =

透過連字元

除了NPM,前端工程師應該知道的yarn知識

X範圍

字元 X、x 或者 * 都可以作為萬用字元,用於填充部分或全部版本號。 被省略的那部分版本號預設為 x 範圍。

除了NPM,前端工程師應該知道的yarn知識

~ 字元範圍

同時使用字元 ~ 和次版本號,表明允許 修訂號 變更。同時使用字元 ~ 和主版本號,表明允許 次版本 號變更。

除了NPM,前端工程師應該知道的yarn知識

^ 字元範圍

字元 ^ 表明不會修改版本號中的第一個非零數字,3。1。4 裡的 3 或者 0。4。2 裡的 4。版本號中缺少的部分將被 0 填充,且在匹配時這些位置允許改變。

除了NPM,前端工程師應該知道的yarn知識

使用 yarn add [package-name] 命令安裝依賴,預設使用的是 ^ 範圍。

需要注意的是,如果一個比較器包含有預釋出標籤的版本,它將只匹配有相同 major。minor。patch 的版本。 例如 >=3。1。4-beta。2,可以匹配 3。1。4-beta。3,但不會匹配 3。1。5-beta。3 版本。

依賴型別

dependences

程式碼執行時所需要的依賴,比如vue,vue-router。

devDependences

開發依賴,就是那些只在開發過程中需要,而執行時不需要的依賴,比如babel,webpack。

peerDependences

同伴依賴,它用來告知宿主環境需要什麼依賴以及依賴的版本範圍。

如果宿主環境沒有對應版本的依賴,在安裝依賴時會報出警告。

比如包 eslint-plugin-import 中有依賴:

“peerDependencies”: { “eslint”: “2。x - 5。x” }

在install時,如果宿主環境沒有 2。x-5。x 版本的 eslint,cli就會丟擲警告。但不會自動幫我們安裝,仍然需要手動安裝。

optionalDependencies

可選依賴,這種依賴即便安裝失敗,Yarn也會認為整個依賴安裝過程是成功的。

可選依賴適用於那些即便沒有成功安裝可選依賴,也有後備方案的情況。

bundledDependencies

打包依賴,在釋出包時,這個數組裡的包都會被打包打包到最終的釋出包裡,需要注意 bundledDependencies 中的包必須是在devDependencies或dependencies宣告過的。

快取

yarn 會將安裝過的包快取下來,這樣再次安裝相同包的時候,就不需要再去下載,而是直接從快取檔案中直接copy進來。

可以透過命令 yarn cache dir 檢視yarn的全域性快取目錄。我的快取目錄在 /Library/Caches/Yarn/v1 下。

除了NPM,前端工程師應該知道的yarn知識

可以看出,yarn 會將不通版本解壓後的包存放在不同目錄下,目錄以

npm-[package name]-[version]-[shasum]`

來命名。shasum 即上文中 registry 獲取的 dist。shasum。

我們可以透過命令檢視已經快取過的包。

yarn cache list 列出已快取的每個包yarn cache list ——pattern 列出匹配指定模式的已快取的包

yarn。lock

yarn。lock 中會準確的儲存每個依賴的具體版本資訊,以保證在不同機器安裝可以得到相同的結果。

除了NPM,前端工程師應該知道的yarn知識

下面以@babel/code-frame為例,看看yarn。lock 中會記錄哪些資訊。

第一行 “@babel/code-frame@7。0。0-beta。54” 包的name和語義化版本號,這些都來自package。json中的定義。

version 欄位,記錄的是一個確切的版本。

resolved 欄位記錄的是包的URL地址。其中hash值,即上文的 dist。shasum。

dependencies 欄位記錄的是當前包的依賴,即當前包在 package。json 的 dependencies 欄位中的所有依賴。

Yarn 在安裝期間,只會使用當前專案的 yarn。lock 檔案(即 頂級 yarn。lock 檔案),會忽略任何依賴裡面的 yarn。lock 檔案。在頂級 yarn。lock 中包含需要鎖定的整個依賴樹裡全部包版本的所有資訊。

yarn。lock檔案是在安裝期間,由 Yarn 自動生成的,並且由yarn來管理,不應該手動去更改,更不應該刪除yarn。lock檔案,且要提交到版本控制系統中,以免因為不同機器安裝的包版本不一致引發問題。

Yarn install過程

首次執行 yarn install 安裝,會按照 package。json 中的語義化版本,去向 registry 進行查詢,並獲取到符合版本規則的最新的依賴包進行下載,並構建構建依賴關係樹。 比如在 package。json 中指定 vue 的版本為 ^2。0。0,就會獲取符合 2。x。x 的最高版本的包。然後自動生成 yarn。lock 檔案,並生成快取。

之後再執行 yarn install,會對比 package。json 中依賴版本範圍和 yarn。lock 中版本號是否匹配。

版本號匹配,會根據 yarn。lock 中的 resolved 欄位去檢視快取, 如果有快取,直接copy,沒有快取則按照 resolved 欄位的url去下載包。

版本號不匹配,根據 package。json 中的版本範圍去 registry 查詢,下載符合版本規則最新的包,並更新至 yarn。lock 中。

模組扁平化

上面提到,在安裝依賴時,會解析依賴構建出依賴關係樹。 比如我專案的首層依賴(即當前專案的dependence和devDependences中的依賴,不包括依賴的依賴)中有A,B,C三個包,A 和 B包同時依賴了相同版本範圍的D包。那麼這部分的依賴關係樹是這樣的:

├── A │ └── D ├── B │ └── D ├── C

如果按照這樣的依賴關係樹直接安裝的話,D模組會在A包和B包的 node_modules中都安裝,這樣會導致模組冗餘。

為了保證依賴關係樹中沒有大量重複模組,yarn在安裝時會做dedupe(去重)操作,它會遍歷所有節點,逐個將模組放在根節點下面,也就是當前專案的 node-modules 中。當發現有相同的模組時,會判斷當前模組指定的 semver 版本範圍是否交集,如果有,則只保留相容版本,如果沒有則在當前的包的 node-modules 下安裝。

所以上面的說的情況,最終安裝完成是下面這樣的,A,B,C,D包都會安裝在第一層 node-modules 下。

├── A ├── B ├── C ├── D

如果A包和B包依賴的是不相容的版本,假設A包依賴的是D@1版本的包,B包依賴的是D@2版本。則最終安裝的結果如下:

├── A ├── B │ └── D@2 ├── C ├── D@1

當代碼中 require 或 import 某個模組時,會從當前 package 的 node-modules 裡中開始找,找不到就到當前package的上一層 node-modules 裡找,這樣一直找到全域性的node_modules。 所以上面的安裝的樹結構,可以保證每個 package 都能獲取到所需要版本的包。

常用的yarn命令

yarn install 安裝依賴

yarn install / yarn 在本地 node_modules 目錄安裝 package。json 裡列出的所有依賴yarn install ——force 重新拉取所有包,即使之前已經安裝的(所以以後別在刪除node-modules了。。。)yarn install ——modules-folder 為 node_modules 目錄指定另一位置,代替預設的 。/node_modulesyarn install ——no-lockfile 不讀取或生成 yarn。lock 檔案yarn install ——production[=true|false] / ——production / ——prod 只安裝 dependence下的包,不安裝 devDependencies 的包

yarn add

yarn add package-name 會安裝 latest 最新版本。yarn add 安裝包到dependencies中yarn add [——dev/-D] 用 ——dev 或 -D 安裝包到 devDependenciesyarn add [——peer/-P] 用 ——peer 或者 -P 安裝包到 peerDependenciesyarn add [——optional/-O] 用 ——optional 或者 -O 安裝包到 optionalDependencies yarn add [——exact/-E] 用 ——exact 或者 -E 會安裝包的精確版本。預設是安裝包的主要版本里的最新版本。 比如說, yarn add foo@1。2。3 會接受 1。9。1 版,但是 yarn add foo@1。2。3 ——exact 只會接受 1。2。3 版。yarn add [——tilde/-T] 用 ——tilde 或者 -T 來安裝包的次要版本里的最新版。 預設是安裝包的主要版本里的最新版本。 比如說,yarn add foo@1。2。3 ——tilde 會接受 1。2。9,但不接受 1。3。0。

yarn config 管理配置檔案

yarn config get 檢視配置key的值yarn config list 檢視當前的配置yarn config delete 從配置中刪除配置keyyarn config set [-g|——global] 設定配置項 key 的值為 value

其他常用命令

yarn list 查詢當前工作資料夾所有的依賴yarn info ] 檢視包資訊,可以檢視特定yarn remove 從依賴裡移除名包,同時更新你 package。json 和 yarn。lock 檔案。yarn