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
上面返回的 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
中依賴版本範圍的表示方法有以下幾種:
- 通過比較器
表示 | 含義描述 |
---|---|
<2.0.0 | 任何小於 2.0.0 的版本 |
<=3.1.4 | 任何小於或等於 3.1.4 的版本 |
>0.4.2 | 任何大於 0.4.2 的版本 |
>=2.7.1 | 任何大於或等於 2.7.1 的版本 |
=4.6.6 | 任何等於 4.6.6 的版本 |
>=2.0.0 <3.1.4 | 交集,大於或等於 2.0.0 並小於 3.1.4 |
<2.0.0 || >3.1.4 | 並集 小於 2.0.0 或者大於 3.1.4 |
如果沒有指定運算子,預設為 =
- 通過連字元
表示 | 含義描述 |
---|---|
2.0.0 - 3.1.4 | >=2.0.0 <=3.1.4 |
0.4 - 2 | >=0.4.0 <=2.0.0 |
版本號中缺少的那些部分會用數字 0 填充。
- X範圍
字元 X、x 或者 * 都可以作為萬用字元,用於填充部分或全部版本號。 被省略的那部分版本號預設為 x 範圍。
表示 | 含義描述 |
---|---|
* | >=0.0.0 (任意版本) |
2.x | >=2.0.0 <3.0.0(匹配主要版本) |
3.1.x | > = 3.1.0 < 3.2.0(匹配主要和次要版本) |
``(空字串) | * 或 > = 0.0.0 |
2 | 2.x.x 或 > = 2.0.0 < 3.0.0 |
3.1 | 3.1.x 或 > = 3.1.0 < 3.2.0 |
- ~ 字元範圍
同時使用字元 ~ 和次版本號,表明允許修訂號
變更。同時使用字元 ~ 和主版本號,表明允許次版本
號變更。
表示 | 含義描述 |
---|---|
~3.1.4 | >=3.1.4 <3.2.0 |
~3.1 | 3.1.x 或 > = 3.1.0 < 3.2.0 |
~3 | 3.x 或 > = 3.0.0 < 4.0.0 |
- ^ 字元範圍
字元 ^ 表明不會修改版本號中的第一個非零數字,3.1.4 裡的 3 或者 0.4.2 裡的 4。版本號中缺少的部分將被 0 填充,且在匹配時這些位置允許改變。
表示 | 含義描述 |
---|---|
^3.1.4 | >=3.1.4 <4.0.0 |
^0.4.2 | >=0.4.2 <0.5.0 |
^0.0.2 | >=0.0.2 <0.0.3 |
使用 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
下。
可以看出,yarn
會將不通版本解壓後的包存放在不同目錄下,目錄以
npm-[package name]-[version]-[shasum]`
複製程式碼複製程式碼
來命名。shasum 即上文中 registry
獲取的 dist.shasum
。
我們可以通過命令檢視已經快取過的包。
yarn cache list 列出已快取的每個包
yarn cache list --pattern <pattern> 列出匹配指定模式的已快取的包
複製程式碼複製程式碼
例如執行 yarn cache list --pattern vue
yarn.lock
yarn.lock
中會準確的儲存每個依賴的具體版本資訊,以保證在不同機器安裝可以得到相同的結果。
下面以@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 <path> 為 node_modules 目錄指定另一位置,代替預設的 ./node_modules
yarn install --no-lockfile 不讀取或生成 yarn.lock 檔案
yarn install --production[=true|false] / --production / --prod 只安裝 dependence下的包,不安裝 devDependencies 的包
複製程式碼複製程式碼
- yarn add
yarn add package-name 會安裝 latest 最新版本。
yarn add <package...> 安裝包到dependencies中
yarn add <package...> [--dev/-D] 用 --dev 或 -D 安裝包到 devDependencies
yarn add <package...> [--peer/-P] 用 --peer 或者 -P 安裝包到 peerDependencies
yarn add <package...> [--optional/-O] 用 --optional 或者 -O 安裝包到 optionalDependencies
yarn add <package...> [--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 <package...> [--tilde/-T] 用 --tilde 或者 -T 來安裝包的次要版本里的最新版。 預設是安裝包的主要版本里的最新版本。 比如說,yarn add foo@1.2.3 --tilde 會接受 1.2.9,但不接受 1.3.0。
複製程式碼複製程式碼
- yarn config 管理配置檔案
yarn config get <key> 檢視配置key的值
yarn config list 檢視當前的配置
yarn config delete <key> 從配置中刪除配置key
yarn config set <key> <value> [-g|--global] 設定配置項 key 的值為 value
複製程式碼複製程式碼
- 其他常用命令
yarn list 查詢當前工作資料夾所有的依賴
yarn info <package> [<field>] 檢視包資訊,可以檢視特定
yarn remove <package...> 從依賴裡移除名包,同時更新你 package.json 和 yarn.lock 檔案。
yarn <script> [<args>] 執行使用者自定義的指令碼
複製程式碼複製程式碼
- 詳細日誌模式 執行yarn命令時,增加引數
--verbose
,這對排查錯誤時很有幫助
yarn <command> --verbose複製程式碼