背景
项目上线后跑了应该有两三个月了,接到生产报事,页面进不去了,用户设备是iPhone8 iOS13.1,用户很气愤,领导也很不乐意,我也很气愤,刚来这项目组就被报事,艹太。但是要解决呀,怎么办?研究以前的代码,加配置呗。
浏览器兼容性问题是什么?
浏览器兼容性问题通常是指网页或 Web 应用在不同浏览器或版本中表现不一致的问题。说白了无非就是 css不兼容
,JS Api
在旧版本浏览器中不兼容。
解决思路
- 明白目标浏览器范围
- 找个插件将现代 JS 转到 ES5
- 处理一下CSS的兼容性问题
解决方案
- 通过定义
.browserslistrc
明确目标浏览器范围 - 使用
Babel
将现代 JS 转到 ES5 - 使用
Autoprefixer
给 CSS 加厂商前缀
好了,开搞
.browserslistrc文件是什么
.browserslistrc
文件是一个配置文件,用于定义目标浏览器和Node.js版本的兼容性列表。这个文件被多个前端工具链和库所使用,如Babel、Autoprefixer、ESLint等,可以帮助我们确定需要转译或添加兼容性前缀的JavaScript和CSS代码版本。通过配置 .browserslistrc
,我们可以精确地控制代码应该兼容哪些浏览器和设备,从而优化构建输出和减少最终包的大小。
.browserslistrc文件中可以配置的内容
- 浏览器名称和版本:例如,last 2 Chrome versions 表示最新的两个Chrome浏览器版本。
- 市场份额:如 > 1% in US 表示在美国市场份额超过1%的浏览器。
- 年份:since 2017 表示自2017年以来发布的所有浏览器版本。
- 特定浏览器:not IE 11 表示不包括IE 11浏览器。
个人项目中使用.browserslistrc配置
在个人日常办公项目中 .browserslistrc
文件配置如下:
> 0.2%
last 2 versions
Firefox ESR
not dead
IE 11
这个配置的含义是:
- 支持全球使用率超过0.2%的浏览器。
- 支持最新的两个浏览器版本。
- 支持Firefox的Extended Support Release(ESR)版本。
- 排除所有已经不被官方支持(dead)的浏览器。
- 额外包含IE 11浏览器,尽管它可能不在其他条件内
Babel是什么
Babel 是一个广泛使用的 JavaScript 编译器/转译器,其核心作用是将 高版本 JavaScript(如 ES6+)转换为向后兼容的低版本代码(如 ES5),以确保代码能在旧版浏览器或环境中正常运行。
Babel的主要作用
1. 语法转换(Syntax Transformation)
将现代 JavaScript 语法(如 let/const、箭头函数、类、模板字符串、解构赋值等)转换为等价的 ES5 语法,以便在不支持新特性的浏览器中运行。
2. Polyfill 填充新 API
通过插件(如 @babel/polyfill 或 core-js),为旧环境提供对新增全局对象(如 Promise, Array.from, Map, Set)的支持。
3. 按需转换(基于目标环境)
结合 .browserslistrc 配置,@babel/preset-env 可根据指定的目标浏览器自动决定哪些特性需要转换,哪些可以保留原样。
4. 支持 TypeScript 和 JSX
Babel 提供了对 TypeScript(通过 @babel/preset-typescript)和 React 的 JSX 语法(通过 @babel/preset-react)的解析与转换能力,无需依赖其他编译工具。
5. 插件化架构,高度可扩展
Babel 支持丰富的插件生态,开发者可以自定义语法转换规则,比如:
- 按需引入 polyfill(@babel/plugin-transform-runtime)
- 移除调试代码(@babel/plugin-transform-remove-console)
- 支持装饰器、私有属性等实验性语法
@babel/preset-env的核心配置
@babel/preset-env 的参数项数量很多,但大部分我们都用不到。我们只需要重点掌握四个参数项即可:targets、useBuiltIns、modules 和 corejs。
@babel/preset-env 的 targets 参数
该参数项的写法和.browserslistrc 配置是一样的,主要是为了定义目标浏览器。如果我们对 targets 参数进行了设置,那么就不会使用 .browserslistrc 配置了,为了减少多余的配置,我们推荐使用 .browserslistrc 配置。
@babel/preset-env 的 useBuiltIns 参数
useBuiltIns
项取值可以是usage
、 entry
或 false
。如果该项不进行设置,则取默认值 false
。
- 设置成
false
的时候会把所有的polyfill
都引入到代码中,整个体积会变得很大。 - 设置成
entry
则是会根据目标环境引入所需的polyfill
,需要手动引入; - 设置成
usage
则是会根据目标环境和代码的实际使用来引入所需的polyfill
。 此处我们推荐使用:useBuiltIns: usage
的设置。
@babel/preset-env 的 corejs 参数
该参数项的取值可以是 2
或 3
,没有设置的时候取默认值为 2
。这个参数只有 useBuiltIns
参数为 usage
或者 entry
时才会生效。在新版本的Babel中,建议使用 core-js@3
。
@babel/preset-env 的 modules 参数
指定模块的输出方式,默认值是 "auto"
,也可以设置为 "commonjs"
、"umd"
、"systemjs"
等。
个人项目中使用Babel的配置
在个人日常办公项目中 .babel.config.js
文件配置如下:
module.exports = {
plugins: [
// 适配某些构建流程中的模块元信息访问方式
() => ({
visitor: {
MetaProperty(path) {
path.replaceWithSourceString('process');
},
},
})
],
presets: [
[
'@babel/preset-env', {
// targets: { esmodules: false, }, // 通过配置browserslist,来使用 browserslist 的配置
useBuiltIns: "usage", // 配置按需引入polyfill
corejs: 3
}
],
'@babel/preset-typescript'
],
};
Autoprefixer 的使用
在vite.config.ts
文件中css的部分,添加 autoprefixer
的配置。
css: {
postcss: {
plugins: [
postCssPxToRem({
// 这里的rootValue就是你的设计稿大小
rootValue: 37.5,
propList: ['*'],
}),
autoprefixer({
overrideBrowserslist: [
'Android 4.1',
'iOS 7.1',
'ff > 31',
'Chrome > 69',
'ie >= 8',
'> 1%'
]
}),
],
},
},
总结
主要通过配置 .browserslistrc
明确目标浏览器范围,使用 Babel
将现代 JS 转到 ES5,主要用到的插件是 @babel/preset-env
,最后再使用 Autoprefixer
插件给 CSS 加厂商前缀。