hao愛做網(wǎng)站一鍵優(yōu)化是什么意思
我們可以在各種前端工程看到 Browserslist 的配置身影,看似簡單但實際上可能會有暗坑導(dǎo)致線上兼容問題,借此文來整理下 Browserslist 的信息。
Browserslist 是由 Autoprefixer 團隊維護的一個開源項目,用于自動處理 CSS 和 JavaScript 文件的瀏覽器兼容性前綴和 polyfill。官方描述:
Share target browsers between different front-end tools, like Autoprefixer, Stylelint and babel-preset-env.用在不同的前端開發(fā)工具之間,分享指定的目標(biāo)瀏覽器。像是 Autoprefixer,Stylelint,和 babel-preset-env。
Browserslist 主頁:https://github.com/ai/browserslist、https://browsersl.ist/
定義
Browserslist 是一個根據(jù)目標(biāo)瀏覽器(target browser)檢查支持瀏覽器版本的 js 庫。它是現(xiàn)代前端工程化不可或缺的工具,無論是處理 js 的 babel 還是處理 css 的 postcss,凡是與墊片相關(guān)的,他們背后都有 Browserslist 的身影。比如(后文也有介紹):
babel
,在@babel/preset-env
中使用core-js
作為墊片(polyfill)postcss
使用autoprefixer
作為墊片
在前端工程化實踐中,當(dāng)我們確認了瀏覽器版本號,那么它的 polyfill 體積就會確認。關(guān)于 polyfill 我們一般都知道有一下規(guī)律:
- 由于低版本瀏覽器/低版本Nodejs的存在,polyfill 在大多工程項目中是必不可少的;
- polyfill 越少,打包體積越小;
- 隨著時間的推移,瀏覽器版本越新,polyfill 越少。
因此,Browserslist 既然會影響 polyfill,進而會影響項目兼容情況以及工程產(chǎn)物體積。
Browserslist 原理
Browserslist 的基本處理是:Browserslist 引擎根據(jù)正則解析查詢語句,對瀏覽器版本數(shù)據(jù)庫 caniuse-lite
進行查詢,返回所得的瀏覽器版本列表。請求處理流程如下:
caniuse-lite 這個庫也由 browserslist 團隊進行維護,它是基于 caniuse 的數(shù)據(jù)庫進行的數(shù)據(jù)整合。caniuse-lite 庫是 CanIUse (這個網(wǎng)站用來查詢?yōu)g覽器兼容性)的數(shù)據(jù)庫的小版本,只有一些必需數(shù)據(jù),這些數(shù)據(jù)存放在 caniuse-lite/data 中
因為 Browserslist 并不維護數(shù)據(jù)庫,因此它會經(jīng)常提醒你去更新 caniuse-lite
這個庫,由于 lock
文件的存在,因此需要使用以下命令手動更新數(shù)據(jù)庫。
npx browserslist@latest --update-db
該命令將會對 caniuse-lite
進行升級,并體現(xiàn)在 lock
文件中。此更新將為 Autoprefixer 或 Babel 等 polyfill 工具帶來有關(guān)新瀏覽器的數(shù)據(jù),并減少已經(jīng)不必要的 polyfill,因此比較好的實踐做法是——我們可以定期更新。
需要定期更新主要有如下三個原因:
- 在查詢中使用最新的瀏覽器版本和統(tǒng)計信息:例如
last 2 versions or >1%
,如果在 2 年前創(chuàng)建了項目但是沒有更新依賴項,那么返回結(jié)果是 2 年前的瀏覽器; - 實際的瀏覽器數(shù)據(jù)將導(dǎo)致使用更少的 polyfill。它將減少 js 和 css 文件的大小并提高網(wǎng)站性能。
caniuse-lite
重復(fù)數(shù)據(jù)刪除:在不同工具中同步版本。
現(xiàn)代CI/CD一般都是重新安裝依賴并構(gòu)建項目,所以在沒有做緩存的情況下基本都是最新的數(shù)據(jù),這樣能保持最新但也有兼容處理的隱患(見后文實踐提醒)
配置查詢
如果選擇的前端工具包括對 Browserslist 的支持,它將在以下位置查找指定瀏覽器版本的查詢,從第一個到最后一個,Browserslist 將使用如下配置文件限定的的瀏覽器和 node 版本范圍:
- 工具 options,例如 Autoprefixer 工具配置中的
browsers
屬性。 BROWERSLIST
環(huán)境變量。- 當(dāng)前目錄或者上級目錄的
browserslist
配置文件。 - 當(dāng)前目錄或者上級目錄的
.browserslistrc
配置文件。 - 當(dāng)前目錄或者上級目錄的
package.json
配置文件里面的browserslist
配置項(推薦)。
如果上述的配置文件缺失或者其他因素導(dǎo)致未能生成有效的配置,browserslist 將使用default
配置> 0.5%, last 2 versions, Firefox ESR, not dead
。
Browserslist 使用者
目前主要前端工程工具都或多或少用到了 Browserslist,如:
- Autoprefixer:Autoprefixer browserslist 從 package.json. 您無需執(zhí)行任何其他操作——Autoprefixer 會自動查找并加載配置。
- babel-preset-env是“JavaScript 的自動前綴”。如果它已經(jīng)知道所有目標(biāo)瀏覽器都支持它,它就不會編譯 ES2015+ 語法。如:
"babel": {"presets": [["env",{"targets": {"browsers": "last 2 version","node": 4},"loose": true}]] }
- eslint-plugin-compat:是 ESLint 的一個插件,當(dāng)并非所有目標(biāo)瀏覽器都支持您的 JavaScript 代碼時,它會向您發(fā)出警告。它支持開箱即用的 Browserslist 配置;它獲取目標(biāo)瀏覽器版本列表并檢查您的代碼是否使用所有指定瀏覽器支持的 JavaScript API。
- stylelint-no-unsupported-browser-features 的工作方式類似于 eslint-plugin-compat— 但適用于 CSS。Stylelint 是一個出色且最流行的 CSS linter。這個 Stylelint 插件確保所有目標(biāo)瀏覽器都支持所有使用的 CSS 屬性。它還支持開箱即用的 Browserslist 配置。
- postcss-normalize 僅包含normalize.css的必要部分 ,基于您支持的瀏覽器列表。
使用/常用配置
根據(jù)用戶份額:
> 5%
: 在全球用戶份額大于 5% 的瀏覽器> 5% in CN
: 在中國用戶份額大于 5% 的瀏覽器
根據(jù)最新瀏覽器版本
last 2 versions
: 所有瀏覽器的最新兩個版本last 2 Chrome versions
: Chrome 瀏覽器的最新兩個版本
不再維護的瀏覽器
dead
: 官方不在維護已過兩年,比如 IE10
*官方提供的查詢
你可以用如下查詢條件來限定瀏覽器和 node 的版本范圍(大小寫不敏感):
> 5%
: 基于全球使用率統(tǒng)計而選擇的瀏覽器版本范圍。>=,<,<=同樣適用。> 5% in US
: 同上,只是使用地區(qū)變?yōu)槊绹VС謨蓚€字母的國家碼來指定地區(qū)。> 5% in alt-AS
: 同上,只是使用地區(qū)變?yōu)閬喼匏袊?。這里列舉了所有的地區(qū)碼。> 5% in my stats
: 使用定制的瀏覽器統(tǒng)計數(shù)據(jù)。cover 99.5%
: 使用率總和為 99.5%的瀏覽器版本,前提是瀏覽器提供了使用覆蓋率。cover 99.5% in US
: 同上,只是限制了地域,支持兩個字母的國家碼。cover 99.5% in my stats
:使用定制的瀏覽器統(tǒng)計數(shù)據(jù)。maintained node versions
:所有還被 node 基金會維護的 node 版本。node 10 and node 10.4
: 最新的 node 10.x.x 或者 10.4.x 版本。current node
:當(dāng)前被 browserslist 使用的 node 版本。extends browserslist-config-mycompany
:來自 browserslist-config-mycompany 包的查詢設(shè)置ie 6-8
: 選擇一個瀏覽器的版本范圍。Firefox > 20
: 版本高于 20 的所有火狐瀏覽器版本。>=,<,<=同樣適用。ios 7
:ios 7 自帶的瀏覽器。Firefox ESR
:最新的火狐 ESR(長期支持版) 版本的瀏覽器。unreleased versions or unreleased Chrome versions
: alpha 和 beta 版本。last 2 major versions or last 2 ios major versions
:最近的兩個發(fā)行版,包括所有的次版本號和補丁版本號變更的瀏覽器版本。since 2015 or last 2 years
:自某個時間以來更新的版本(也可以寫的更具體 since 2015-03 或者 since 2015-03-10)dead
:通過last 2 versions
篩選的瀏覽器版本中,全球使用率低于 0.5% 并且官方聲明不在維護或者事實上已經(jīng)兩年沒有再更新的版本。last 2 versions
: 每個瀏覽器最近的兩個版本。last 2 Chrome versions
: chrome 瀏覽器最近的兩個版本。defaults
: 默認配置> 0.5%, last 2 versions, Firefox ESR, not dead
。not ie <= 8
: 瀏覽器范圍的取反。
debug
直接在工程目錄下運行 npx browserslist
來查看你配置的篩選條件篩選出的瀏覽器版本范圍。
注意事項
Browserslist 會處理瀏覽器的每個版本,所以應(yīng)該避免配置這樣的查詢條件 Firefox > 0
.
多個查詢條件組和在一起之后,其之間的的覆蓋是以 OR
的方式,而是不是 AND
,也就是說只要瀏覽器版本符合篩選條件里面的一種即可。
所有的查詢條件均基于 caniuse
的支持列表。例如:last 3 ios versions
可能會返回 8.4
, 9.2
, 9.3
(混合了主版本和次版本),然而 last 3 Chrome versions
可能返回 50
, 49
, 48
(只有主版本)。
組合查詢
可通過 and
、or
、not
關(guān)鍵字進行組合查詢。
組合器類型 | 說明 | 例子 |
---|---|---|
and | 為交集,每個條件相交的結(jié)果 | Chrome 58-65 and supports es6-module :查找 Chrome 58 到 65 并且支持 es6-module 的版本。 |
or | 為并集,每個條件合并的結(jié)果。也可以用逗號代替 or | Chrome > 94 or Edge > 94 或Chrome > 94,Edge > 94 :查找 Chrome 與 Edge 大于 94 的版本。 |
not | 為非,取反 | > .5% and not last 2 versions 或> .5% or not last 2 versions 或> .5%, not last 2 versions :使用率大于 0.5% 的版本中排除不是最后兩個版本。 |
配置落地形式
1.package.json
如果你想減少工程根目錄下的配置文件的數(shù)量,可以在 package.json 中設(shè)置 browserslist 配置項,如下所示:
{"private": true,"dependencies": {"autoprefixer": "^6.5.4"},"browserslist": ["last 1 version", "> 1%", "IE 10"]
}
2.配置文件
Browserslist 配置文件應(yīng)該被命名為 .browserslistrc
或者 browserslist
每條查詢條件獨占一行。 注釋用 # 開頭:
# Browsers that we supportlast 1 version
> 1%
IE 10 # sorry
browserslist 將檢查 path 路徑上每一級目錄下面是否有配置文件. 所以,如果工具要處理的文件路徑是這樣的 app/styles/main.css
, 那么你可以將配置文件放置在根目錄, app/
或者 app/styles
。
也可以在 BROWSERSLIST_CONFIG
環(huán)境變量中直接指定配置文件的路徑 。
3.Shareable Configs
可以使用如下寫法,從另外一個輸出 browserslist 配置的包導(dǎo)入配置數(shù)據(jù):
"browserslist": ["extends browserslist-config-mycompany"]
為了安全起見,額外的配置包只支持前綴 browserslist-config-
的包命名. npm 包作用域也同樣支持 @scope/browserslist-config
,例如: @scope/browserslist-config
or @scope/browserslist-config-mycompany
.
當(dāng)寫一個 shared config package 時,必須導(dǎo)出一個數(shù)組。如 browserslist-config-mycompany/index.js
:
module.exports = ['last 1 version', '> 1%', 'ie 10'];
4.環(huán)境的差異化配置
你可以為不同的環(huán)境配置不同的瀏覽器查詢條件。 browserslist 將依賴 BROWSERSLIST_ENV
或者 NODE_ENV
查詢?yōu)g覽器版本范圍 . 如果兩個環(huán)境變量都沒有配置正確的查詢條件,那么優(yōu)先從 production
對應(yīng)的配置項加載查詢條件,如果再不行就應(yīng)用默認配置。
如在package.json
:
"browserslist": {"production": ["> 1%","ie 10"],"development": ["last 1 chrome version","last 1 firefox version"]}
或在.browserslistrc
:
[production staging]
> 1%
ie 10[development]
last 1 chrome version
last 1 firefox version
5.使用自定義數(shù)據(jù)
這需要 Google Analytics,然后可以通過數(shù)據(jù)生成browserslist-stats.json
npx browserslist-ga
你也可以通過其它方式得到統(tǒng)計,但是最終數(shù)據(jù)生成的內(nèi)容格式應(yīng)保持如下:
{"ie": {"6": 0.01,"7": 0.4,"8": 1.5},"chrome": {…},…
}
Browserslist 的 js API
可先看這段代碼:
const browserslist = require('browserslist');// Your CSS/JS build tool code
const process = function (source, opts) {const browsers = browserslist(opts.browsers, {stats: opts.stats,path: opts.file,env: opts.env,});// Your code to add features for selected browsers
};
查詢可以是字符串 "> 1%, IE 10"
或數(shù)組 ['> 1%', 'IE 10']
。
如果缺少查詢,browserslist 將查找配置文件。您可以提供一個路徑選項(可以是一個文件)來查找相對于它的配置文件。
Options:
path
: 文件或目錄路徑來查找配置文件。默認為.
env
: 從配置中使用什么環(huán)境部分。默認為production
stats
: 自定義使用統(tǒng)計數(shù)據(jù)config
: 如果要手動設(shè)置,則配置路徑ignoreUnknownVersions
: 不要直接查詢(例如12
)。默認為false
dangerousExtend
: 禁用擴展查詢的安全檢查。默認為false
對于非 js 環(huán)境和調(diào)試目的,可以使用 cli 工具:
browserslist "> 1%, IE 10"
覆蓋率查詢
可以通過 js API 獲得所選瀏覽器的總用戶覆蓋率:
browserslist.coverage(browserslist('> 1%'));
//=> 81.4
或者通過 cli:
browserslist --coverage=US "> 1% in US"
在線覆蓋情況查詢
地址:https://browsersl.ist/、https://browserslist.dev/
效果:
衍生工具
browerslist 衍生的工具,具體可見browserslist tools
- browserslist-ga或browserslist-ga-export: 該工具能生成訪問你運營的網(wǎng)站的瀏覽器的版本分布數(shù)據(jù),以便用于類似> 0.5% in my stats 查詢條件, 前提是你運營的網(wǎng)站部署有 Google Analytics。
- browserslist-useragent : 檢驗 某瀏覽器的 user-agent 字符串是否匹配 browserslist 給出的瀏覽器范圍。
- browserslist-useragent-ruby : 功能同上,ruby 庫。
- caniuse-api: 返回支持指定特性的瀏覽器版本范圍
- npx browserslist :在前端工程目錄下運行上面命令,輸出當(dāng)前工程的目標(biāo)瀏覽器列表。
Browserslist 2(V2版本)
last n versions
為更好的網(wǎng)絡(luò)而改變
從一開始,Autoprefixer 就 last 2 versions
選擇了最后的 2 個瀏覽器版本,但不是從所有瀏覽器中挑選出來,只是最流行的那些。事實證明,這是一個錯誤。
現(xiàn)實世界中沒有“主流”瀏覽器。例如,中國在線市場巨大,在中國有很多流行的本地瀏覽器。我們不能僅僅忽略本地瀏覽器——每個人都應(yīng)該可以訪問網(wǎng)絡(luò)。
事實上,Autoprefixer 本身的創(chuàng)建是為了阻止瀏覽器的差異化(例如-webkit-
對移動瀏覽器使用 -only
前綴)。
這就是為什么 Autoprefixer 7 和 Browserslist 2 last 2 version
會選擇 所有瀏覽器的 2 個最新版本。
不用擔(dān)心大小,——gzip
可以很好地壓縮前綴,因此您很可能不會看到任何大小差異。
緩存
Browserslist 在托管過程中緩存它從 package.json
和 browserslist
文件中讀取的配置,以及有關(guān)文件存在的知識。
要清除這些緩存,請使用:
browserslist.clearCaches();
要完全禁用緩存,請設(shè)置 BROWSERSLIST_DISABLE_CACHE
環(huán)境變量。
*實踐提醒
1.小心last
和not dead
國內(nèi)場景(比如2C、2G場景)不推薦用 last 2 Chrome versions
或 not dead
的查詢條件來鎖定特別具體的瀏覽器品牌和版本。市面上有各種各樣的瀏覽器,同時瀏覽器的版本碎片化也很嚴重,如果你在開發(fā)一款通用的 webapp,那就應(yīng)該考慮瀏覽器多樣性導(dǎo)致的兼容問題。(not dead
在國內(nèi)外的差異見下圖)
not dead
國內(nèi)覆蓋率只有 73%
not dead
全球有 86.4%
2.定期更新
定期更新 caniuse-lite 數(shù)據(jù)庫和本地 browerslist 配置。這點在上文有有所介紹,是一個好習(xí)慣。
相關(guān)鏈接
- https://github.com/ai/browserslist
- https://evilmartians.com/chronicles/autoprefixer-7-browserslist-2-released
- https://css-tricks.com/browserlist-good-idea/
- http://browserl.ist/
- https://browserslist.dev/
- https://github.com/browserslist/update-db#readme