目录
1,三者关系介绍
为了在低版本浏览器或环境中,兼容 es6+ 版本的代码。出现了2种解决方式:
1,将 js 新特性语法,全部转换为低版本的语法。
此时,所有浏览器都访问的是低版本的语法。
2,对不支持的 js 新特性语法,使用低版本的语法实现。
此时,浏览器中既有 js 新特性语法,也有低版本的语法。
所以问题来了,如何按需加载需要的,来减少打包时间和代码体积?
稍后回答。有了上面的前提,先介绍下这3个东西。
1.1,polyfill
指在旧的浏览器或环境中,通过低版本的 js 语法实现 js 新特性的片段。主要特点是兼容性和渐进增强。
它是一个术语,并不只针对于 js。比如 postcss 对部分属性提供厂商前缀来实现样式兼容或回退,也属于是 polyfill。
比如:Array.prototype.includes
的 polyfill
:
if (!Array.prototype.includes) {
Array.prototype.includes = function (searchElement /*, fromIndex*/) {
var O = Object(this)
var len = parseInt(O.length, 10) || 0
if (len === 0) {
return false
}
var fromIndex = !fromIndex ? 0 : fromIndex
if (Math.abs(fromIndex) === Infinity) {
fromIndex = 0
}
for (var k = fromIndex, E = len; k < E; k++) {
if (k in O && O[k] === searchElement) {
return true
}
}
return false
}
}
1.2,core-js
一句话总结:core-js 是通过 js 标准库(所有浏览器都支持的语法)实现 js 新特性的 polyfill 的集合。
同时实现了一些功能:
- 模块化。
- 避免全局污染。
- 和 babel 结合,实现按需加载。
可直接在项目中导入,比如 Vue3 项目的 src/main.ts
:
import 'core-js';
// 或导入指定的 polyfill
import 'core-js/features/array/from';
1.3,babel
babel 主要的功能,是将 es6+ 的代码,转换为当前和旧版浏览器可以兼容的 js 版本。
- 转换 js 高级语法;
- 添加缺少的 polyfill(新版本通过 core-js 来添加)。
2,如何按需加载需要的 polyfill
目的:减少打包时间和打包后的代码体积。
2.1,静态加载
在打包时,使用 @babel/preset-env
的 useBuiltIns: 'usage'
选项来实现按需加载 polyfill。
同时,babel 会通过 browserslist
配置来查询出需要支持的浏览器列表。
通常是
.browserslistrc
文件或是package.json
中的browserslist
字段。
2.2,动态加载
除了在构建时静态注入 polyfill,还可以使用如 Polyfill.io 这样的服务,在运行时根据浏览器的 User-Agent 动态加载所需的 polyfill,这样能够确保只加载必要的 polyfill。
2.3,vite@plugin-legacy
【文章链接】
这个 Vite 的一个官方插件,用于处于浏览器兼容性问题。大致思路:
- 通过配置项
target
来指定需要兼容的浏览器,本质上还是会通过babel
做语法转换。 - 打包出2种 js 版本,一种是“需要兼容的浏览器”能使用
legacy.js
,一种是使用搞版本 js 语法的 js 文件。 - 在
html
文件中,判断浏览器支持情况,来决定使用哪种版本的 js。
具体原理参考这篇文章。
以上。