活用yarn resolutions統一版本大幅減小產物包體積(優化之最後的倔強)
問題
假如一個依賴 A
依賴了 B
的 v1.0 版本,而你的主專案中依賴了 B
的 v1.1 版本,會怎麼樣?
兩者的包都會被打進專案之中!
當依賴版本可以靈活調整時,比如依賴的版本號是 ^
開頭的,兩者都使用最新版本是可以互相相容的,而現在更多的第三方依賴都會定死他所依賴的庫的版本號以穩定功能,確保不會產生第三方依賴做出了 BREAKING CHANGE 而導致大面積的報錯停用。
解決
如何解決這個問題,我們只需要只用 yarn 提供的 resolutions
欄位統一所有依賴和依賴的依賴…他們的版本號即可。
比如要統一所有 lodash
package.json
中加入:
{
"name": "project-name",
"dependencies": {
"lodash": "^4.17.20"
},
"resolutions": {
"lodash": "4.17.20"
}
}
此時如果你的第三方依賴他們依賴了什麼版本的 lodash
,最終你只會安裝並使用 4.17.20 這個版本的 lodash
例項
先來看一個版本不一致帶來的例子:
第三方庫依賴了 [email protected]
假如我們主專案依賴了一個叫 test
的庫,他的 package.json
如下:
{
"name": "test",
"version": "1.0.0",
"dependencies": {
"lodash": "4.16"
}
}
主檔案 index.js
如下:
export { isArray } from 'lodash'
也就是說,該 test
庫從 4.16 版本的 lodash
中轉而倒出了一個 isArray
方法,當然在此庫中使用不倒出也同理。
主專案依賴了 [email protected]^4.17.20
來看我們的主專案 package.json
:
{
"name": "main-project",
"scripts": {
"build": "webpack --mode production"
},
"devDependencies": {
"webpack": "^5.14.0",
"webpack-cli": "^4.3.1"
}
"dependencies": {
"lodash": "^4.17.20"
}
}
主專案就是通過 yarn add lodash
這種常規手段安裝了最新的 lodash
。
在主專案中我們依次使用不同版本的 lodash
:
// 主專案的 index.js
import { isArray } from 'test'
import { isArray as isArrayNew } from 'lodash'
const arr = []
isArray(arr)
isArrayNew(arr)
我們執行 yarn build
打包得到:
足足有 137 kb ,現在我們使用 resolutions
欄位指明只需要 4.17.20 版本的 lodash
:
{
"name": "main-project",
"scripts": {
"build": "webpack --mode production"
},
"devDependencies": {
"webpack": "^5.14.0",
"webpack-cli": "^4.3.1"
}
"dependencies": {
"lodash": "^4.17.20"
},
"resolutions": {
"lodash": "4.17.20"
}
}
重灌依賴並構建:
# 重新安裝依賴
yarn
# 構建專案
yarn build
得到結果:
少了幾乎一半,可見版本管理的重要性!
總結
使用 resolutions
統一版本欄位可以得到極大的收益,減少幾百 kb 產物輕而易舉。
但也要思考以下兩個問題:
-
到底哪些依賴需要指定版本號。因為所有依賴檢視都會收集到主專案的
yarn.lock
中,所以可以搜尋檢視哪些比較大的庫( webpack-bundle-analyzer 視覺化分析得到哪些庫比較大 )需要指定版本(或者自己手寫yarn.lock
的依賴分析指令碼),在yarn.lock
中,可以看到某一個依賴到底裝了幾個版本。 -
是否敢指定版本號。因為跨大版本可能有 BREAKING CHANGE 的風險,不建議當有大版本差距時指定版本號,當小版本有區別時,可以指定以獲得收益。