我们可以在各种前端工程看到 Browserslist 的配置身影,看似简单但实际上可能会有暗坑导致线上兼容问题,借此文来整理下 Browserslist 的信息。
Browserslist 是由 Autoprefixer 团队维护的一个开源项目,用于自动处理 CSS 和 JavaScript 文件的浏览器兼容性前缀和 polyfill。官方描述:
Share target browsers between different front-end tools, like Autoprefixer, Stylelint and babel-preset-env.用在不同的前端开发工具之间,分享指定的目标浏览器。像是 Autoprefixer,Stylelint,和 babel-preset-env。
Browserslist 主页:https://github.com/ai/browserslist、https://browsersl.ist/
Browserslist 是一个根据目标浏览器(target browser)检查支持浏览器版本的 js 库。它是现代前端工程化不可或缺的工具,无论是处理 js 的 babel 还是处理 css 的 postcss,凡是与垫片相关的,他们背后都有 Browserslist 的身影。比如(后文也有介绍):
babel
,在 @babel/preset-env
中使用 core-js
作为垫片(polyfill)postcss
使用 autoprefixer
作为垫片在前端工程化实践中,当我们确认了浏览器版本号,那么它的 polyfill 体积就会确认。关于 polyfill 我们一般都知道有一下规律:
因此,Browserslist 既然会影响 polyfill,进而会影响项目兼容情况以及工程产物体积。
Browserslist 的基本处理是:Browserslist 引擎根据正则解析查询语句,对浏览器版本数据库 caniuse-lite
进行查询,返回所得的浏览器版本列表。请求处理流程如下:
caniuse-lite 这个库也由 browserslist 团队进行维护,它是基于 caniuse 的数据库进行的数据整合。caniuse-lite 库是 CanIUse (这个网站用来查询浏览器兼容性)的数据库的小版本,只有一些必需数据,这些数据存放在 caniuse-lite/data 中
因为 Browserslist 并不维护数据库,因此它会经常提醒你去更新 caniuse-lite
这个库,由于 lock
文件的存在,因此需要使用以下命令手动更新数据库。
npx browserslist@latest --update-db
该命令将会对 caniuse-lite
进行升级,并体现在 lock
文件中。此更新将为 Autoprefixer 或 Babel 等 polyfill 工具带来有关新浏览器的数据,并减少已经不必要的 polyfill,因此比较好的实践做法是——我们可以定期更新。
需要定期更新主要有如下三个原因:
last 2 versions or >1%
,如果在 2 年前创建了项目但是没有更新依赖项,那么返回结果是 2 年前的浏览器;caniuse-lite
重复数据删除:在不同工具中同步版本。现代CI/CD一般都是重新安装依赖并构建项目,所以在没有做缓存的情况下基本都是最新的数据,这样能保持最新但也有兼容处理的隐患(见后文实践提醒)
如果选择的前端工具包括对 Browserslist 的支持,它将在以下位置查找指定浏览器版本的查询,从第一个到最后一个,Browserslist 将使用如下配置文件限定的的浏览器和 node 版本范围:
browsers
属性。BROWERSLIST
环境变量。browserslist
配置文件。.browserslistrc
配置文件。package.json
配置文件里面的 browserslist
配置项(推荐)。如果上述的配置文件缺失或者其他因素导致未能生成有效的配置,browserslist 将使用default
配置> 0.5%, last 2 versions, Firefox ESR, not dead
。
目前主要前端工程工具都或多或少用到了 Browserslist,如:
"babel": {
"presets": [
[
"env",
{
"targets": {
"browsers": "last 2 version",
"node": 4
},
"loose": true
}
]
]
}
> 5%
: 在全球用户份额大于 5% 的浏览器> 5% in CN
: 在中国用户份额大于 5% 的浏览器last 2 versions
: 所有浏览器的最新两个版本last 2 Chrome versions
: Chrome 浏览器的最新两个版本dead
: 官方不在维护已过两年,比如 IE10
你可以用如下查询条件来限定浏览器和 node 的版本范围(大小写不敏感):
> 5%
: 基于全球使用率统计而选择的浏览器版本范围。>=,<,<=同样适用。> 5% in US
: 同上,只是使用地区变为美国。支持两个字母的国家码来指定地区。> 5% in alt-AS
: 同上,只是使用地区变为亚洲所有国家。这里列举了所有的地区码。> 5% in my stats
: 使用定制的浏览器统计数据。cover 99.5%
: 使用率总和为 99.5%的浏览器版本,前提是浏览器提供了使用覆盖率。cover 99.5% in US
: 同上,只是限制了地域,支持两个字母的国家码。cover 99.5% in my stats
:使用定制的浏览器统计数据。maintained node versions
:所有还被 node 基金会维护的 node 版本。node 10 and node 10.4
: 最新的 node 10.x.x 或者 10.4.x 版本。current node
:当前被 browserslist 使用的 node 版本。extends browserslist-config-mycompany
:来自 browserslist-config-mycompany 包的查询设置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
:最近的两个发行版,包括所有的次版本号和补丁版本号变更的浏览器版本。since 2015 or last 2 years
:自某个时间以来更新的版本(也可以写的更具体 since 2015-03 或者 since 2015-03-10)dead
:通过 last 2 versions
筛选的浏览器版本中,全球使用率低于 0.5% 并且官方声明不在维护或者事实上已经两年没有再更新的版本。last 2 versions
: 每个浏览器最近的两个版本。last 2 Chrome versions
: chrome 浏览器最近的两个版本。defaults
: 默认配置> 0.5%, last 2 versions, Firefox ESR, not dead
。not ie <= 8
: 浏览器范围的取反。直接在工程目录下运行 npx browserslist
来查看你配置的筛选条件筛选出的浏览器版本范围。
Browserslist 会处理浏览器的每个版本,所以应该避免配置这样的查询条件 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
关键字进行组合查询。
组合器类型 | 说明 | 例子 |
---|---|---|
and |
为交集,每个条件相交的结果 | Chrome 58-65 and supports es6-module :查找 Chrome 58 到 65 并且支持 es6-module 的版本。 |
or |
为并集,每个条件合并的结果。也可以用逗号代替 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% 的版本中排除不是最后两个版本。 |
package.json
如果你想减少工程根目录下的配置文件的数量,可以在 package.json 中设置 browserslist 配置项,如下所示:
{
"private": true,
"dependencies": {
"autoprefixer": "^6.5.4"
},
"browserslist": ["last 1 version", "> 1%", "IE 10"]
}
Browserslist 配置文件应该被命名为 .browserslistrc
或者 browserslist
每条查询条件独占一行。 注释用 # 开头:
# Browsers that we support
last 1 version
> 1%
IE 10 # sorry
browserslist 将检查 path 路径上每一级目录下面是否有配置文件. 所以,如果工具要处理的文件路径是这样的 app/styles/main.css
, 那么你可以将配置文件放置在根目录, app/
或者 app/styles
。
也可以在 BROWSERSLIST_CONFIG
环境变量中直接指定配置文件的路径 。
可以使用如下写法,从另外一个输出 browserslist 配置的包导入配置数据:
"browserslist": [
"extends browserslist-config-mycompany"
]
为了安全起见,额外的配置包只支持前缀 browserslist-config-
的包命名. npm 包作用域也同样支持 @scope/browserslist-config
,例如: @scope/browserslist-config
or @scope/browserslist-config-mycompany
.
当写一个 shared config package 时,必须导出一个数组。如 browserslist-config-mycompany/index.js
:
module.exports = ['last 1 version', '> 1%', 'ie 10'];
你可以为不同的环境配置不同的浏览器查询条件。 browserslist 将依赖 BROWSERSLIST_ENV
或者 NODE_ENV
查询浏览器版本范围 . 如果两个环境变量都没有配置正确的查询条件,那么优先从 production
对应的配置项加载查询条件,如果再不行就应用默认配置。
如在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
这需要 Google Analytics,然后可以通过数据生成browserslist-stats.json
npx browserslist-ga
你也可以通过其它方式得到统计,但是最终数据生成的内容格式应保持如下:
{
"ie": {
"6": 0.01,
"7": 0.4,
"8": 1.5
},
"chrome": {
…
},
…
}
可先看这段代码:
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"
或数组 ['> 1%', 'IE 10']
。
如果缺少查询,browserslist 将查找配置文件。您可以提供一个路径选项(可以是一个文件)来查找相对于它的配置文件。
Options:
path
: 文件或目录路径来查找配置文件。默认为.
env
: 从配置中使用什么环境部分。默认为 production
stats
: 自定义使用统计数据config
: 如果要手动设置,则配置路径ignoreUnknownVersions
: 不要直接查询(例如 12
)。默认为 false
dangerousExtend
: 禁用扩展查询的安全检查。默认为 false
对于非 js 环境和调试目的,可以使用 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
last n versions
为更好的网络而改变从一开始,Autoprefixer 就 last 2 versions
选择了最后的 2 个浏览器版本,但不是从所有浏览器中挑选出来,只是最流行的那些。事实证明,这是一个错误。
现实世界中没有“主流”浏览器。例如,中国在线市场巨大,在中国有很多流行的本地浏览器。我们不能仅仅忽略本地浏览器——每个人都应该可以访问网络。
事实上,Autoprefixer 本身的创建是为了阻止浏览器的差异化(例如-webkit-
对移动浏览器使用 -only
前缀)。
这就是为什么 Autoprefixer 7 和 Browserslist 2 last 2 version
会选择 所有浏览器的 2 个最新版本。
不用担心大小,——gzip
可以很好地压缩前缀,因此您很可能不会看到任何大小差异。
Browserslist 在托管过程中缓存它从 package.json
和 browserslist
文件中读取的配置,以及有关文件存在的知识。
要清除这些缓存,请使用:
browserslist.clearCaches();
要完全禁用缓存,请设置 BROWSERSLIST_DISABLE_CACHE
环境变量。
last
和not dead
国内场景(比如2C、2G场景)不推荐用 last 2 Chrome versions
或 not dead
的查询条件来锁定特别具体的浏览器品牌和版本。市面上有各种各样的浏览器,同时浏览器的版本碎片化也很严重,如果你在开发一款通用的 webapp,那就应该考虑浏览器多样性导致的兼容问题。(not dead
在国内外的差异见下图)
not dead
国内覆盖率只有 73%
定期更新 caniuse-lite 数据库和本地 browerslist 配置。这点在上文有有所介绍,是一个好习惯。