1、当构建工具使用webpack时
1.1 处理语法兼容
javascript语法兼容通过Babel-loader处理,通常的配置是
module.exports = {
module: {
rules: [
{
test: /\.js$/, // 正则表达式,匹配 .js 文件
exclude: /node_modules/, // 排除 node_modules 目录
use: {
loader: 'babel-loader', // 使用 Babel 进行转换
options: {
presets: [
[
'@babel/preset-env', // Babel 预设,用于转换现代 JavaScript 语法
{
targets: '> 0.25%, not dead', // 根据浏览器市场份额和死亡浏览器来确定需要支持的浏览器版本
},
],
],
},
},
},
],
},
};
平时我们通过vue-cli创建的项目都默认包含了babel-loader的配置,所以不需要额外处理。
备注:一般为了性能考虑,babel-loader配置会剔除对node_modules依赖的处理。但是当node_modules里面的某些依赖的语法达不到我们项目的兼容要求时,可以增加额外的设置(exclude中添加not属性),例如:
{
test: /\.(?:js|mjs|cjs)$/,
exclude: {
and: [/node_modules/], // Exclude libraries in node_modules ...
not: [
// Except for a few of them that needs to be transpiled because they use modern syntax
/unfetch/,
/d3-array|d3-scale/,
/@hapi[\\/]joi-date/,
]
},
use: {
loader: 'babel-loader',
options: {
presets: [
['@babel/preset-env', { targets: "ie 11" }]
]
}
}
}
1.2 API的polyfill——core-js(polyfill of the JavaScript standard library)
安装core-js:https://github.com/zloirock/core-js
npm i core-js/stable
在babel.config.js增加如下配置:https://babeljs.io/docs/presets
// If you are compiling generators or async function to ES5, and you are using a version of @babel/core or @babel/plugin-transform-regenerator older than 7.18.0, you must also load the regenerator runtime package. It is automatically loaded when using @babel/preset-env's useBuiltIns: "usage" option or @babel/plugin-transform-runtime
// 编译generators或async函数时,除了core-js外额外需要regenerator-runtime。当在预设中设置了useBuiltIns: "usage"时regenerator-runtime会被自动加载
module.exports = {
// 智能预设:能够编译ES6语法
presets: [
[
"@babel/preset-env",
// 按需加载core-js的polyfill
{ useBuiltIns: "usage", corejs: { version: "3", proposals: true } },
],
],
};
编译generators或async函数时,除了core-js外额外需要regenerator-runtime。当在预设中设置了useBuiltIns: "usage"时regenerator-runtime会被自动加载
1.3 .browserslistrc-https://browsersl.ist/
完成了以上步骤后还需要配置所需兼容的浏览器版本,通过browserslist来进行设置,一般有两种方式,分别是
1、在package.json中设置
{
"browserslist": [
"Chrome >= 49"
]
}
2、在.browserslistrc文件中设置
Chrome >= 49
具体的设置方式可以查看官网。
1.4 core-js、@babel/polyfill、babel-polyfill三者的关系
babel-polyfill
是一个 Babel 的插件,它会自动为你的代码添加所需的 core-js
polyfills 和一个自定义的 regenerator runtime
来模拟完整的 ES2015+ 环境。但是,从 Babel 7 开始,babel-polyfill
已经被废弃,并推荐使用 @babel/polyfill
或直接导入所需的 core-js
和 regenerator-runtime
模块。
@babel/polyfill
是 babel-polyfill
的替代品。但从 Babel 7.4.0 开始,它也被标记为废弃,并推荐使用直接导入 core-js
和 regenerator-runtime
的方式。
core-js
是一个用于为旧版 JavaScript 环境提供现代标准的库。它实现了 ECMAScript 2015+ (ES6+) 规范中的许多新特性,例如 Promises、Symbols、collections (Map, Set, WeakMap, WeakSet) 等。core-js/stable
指向 core-js
的稳定版本。
2、当构建工具使用vite时
vite通过@vitejs/plugin-legacy插件来处理javascript兼容问题,插件的处理流程:-https://www.npmjs.com/package/@vitejs/plugin-legacy
-
为每一个chunk生成一个对应兼容语法的chunk,通过@babel/preset-env来转换。
-
生成一个polyfill的chunk用来兼容API。
-
语法兼容chunk和polyfill chunk通过
<script nomodule>
注入htm文档,高版本浏览器会忽略这些资源,而nomodule的低版本浏览器会加载这些资源。
配置代码如下:
// vite.config.js
import legacy from '@vitejs/plugin-legacy'
export default {
plugins: [
legacy({
targets: ['defaults', 'not IE 11'],
}),
],
}
3、针对vue3项目
vue3由于使用了proxy api,而proxy并没有完全匹配的polyfill,所以当浏览器版本不支持proxy时,无法做到兼容。
proxy有一个不完整的polyfill:proxy-polyfill,只实现了部分proxy的方法,而且初始化时对象的属性需要是确定的,类似于Object.defineProperty。-https://www.npmjs.com/package/proxy-polyfill
proxy兼容性如下:
4、postcss
使用 Can I Use 中的值将浏览器前缀添加到 CSS 规则中。 Autoprefixer 将使用基于当前浏览器流行度和属性支持的数据来为你应用前缀。