当前位置: 首页 > 科技观察

Preset-Env按需Polyfill是如何实现的?

时间:2023-03-12 07:52:56 科技观察

本文转载自微信公众号《神光的编程秘籍》,作者神说必有光。转载本文请联系神光编程秘籍公众号。我们在开发的时候会用到一些新的API,但是用户的浏览器版本各异,可能不支持这些API,但我们不能因此就直接使用。这时候我们可以使用polyfill来解决。Polyfill是垫片的意思,就是在运行业务代码之前,全局注入一些API的实现,这样后面运行的业务代码在使用的时候就有API了,不会有兼容性问题。但是用户的浏览器可能是多种多样的,我们的polyfillAPI可能已经支持了。这时候加载polyfill就没有必要了,而且还浪费性能。有没有办法解决不支持这个api的运行环境的兼容性问题,又不在支持这个api的环境中引入不必要的代码?答案是preset-env,实现按需引入polyfill。这里的preset-env是指babel的@babel/preset-env和postcss的postcss-preset-env,其中一个是按需进行语法转换,按需导入JSpolyfill,另一个是在上面添加prefix等CSS需求兼容处理。虽然分别是针对JS和CSS的,但是它们的原理是相似的,下面我们分别来看一下。@babel/preset-envon-demand指的是目标运行环境是否支持,那么如何指定目标运行环境呢?@babel/preset-env支持通过targets指定目标环境:{"presets":[["@babel/preset-env",{"targets":">0.25%,notdead"}]]}这里targets是browserslist的查询字符串,它可以解析查询字符串并返回对应的浏览器版本:有了这些目标浏览器的版本,你还需要知道哪个版本支持各种特性:babel在@babel/compat-维护了一个数据库数据包:通过这种方式,可以根据目标浏览器的版本筛选出哪些特性支持,哪些不支持。然后只需对不支持的功能进行语法转换和polyfill。这就是按需polyfill的工作方式。css的按需兼容类似:postcss-preset-envpostcss是通过postcss-preset-env按需处理的,同样支持目标环境的配置,即浏览器:postcssPresetEnv({browsers:'last2versions'})也使用browserslist将查询字符串转换为对应的浏览器版本。然后根据哪个浏览器版本支持哪些css特性,过滤掉不支持的css特性。这里使用了caniuse的数据,在cssdb包中:如果知道目标浏览器的版本,知道哪些浏览器版本支持这些特性,自然可以过滤掉不支持的css特性。然后引入不同的postcss插件来处理这些特性的前缀等,这就是css按需前缀等处理的原理。可以看出,babel和potcss都是依赖browserslist包来查询目标浏览器版本的,自然可以统一为一个,就是根目录下的.browserslistrc配置文件,JS按需通过指定与CSS相同的环境兼容性。综上所述,用户的浏览器可能多种多样。我们用于开发的JS和CSS特性可能不被用户的浏览器支持。为了保证功能正常,我们需要做兼容处理。JS的兼容处理是polyfill,CSS的兼容处理是加前缀等等。Babel使用@babel/preset-env进行按需填充和转换。原理是通过browserslist查询目标浏览器版本,然后根据@babel/compat-data的数据库筛选出这些浏览器版本中哪些特性不支持,后面会介绍相应的插件处理。postcss使用postcss-preset-env做按需前缀等,原理是通过browserslist查询目标浏览器版本,然后根据cssdb数据库(来自caniuse)过滤掉不支持的CSS特性,然后修改这些CSS去做就对了。就像preset-env这个名字一样,它们的意思就是根据目标环境做按需处理,也叫智能处理,确实比es5、es6粗暴指定目标要聪明很多。