最近把 babel 看了一遍,然后又看了一遍团队内部关于 babel 的配置,发现有很多不足之处,比如有些配置根本不起作用,polyfill 其实有更好的方式实现。
babel 的出现目的是能够让我们用更新的语法写代码,这样可以不必考虑浏览器兼容问题,新特性尽情、大胆、放心使用。
babel 在工作之前,需要你来告诉它要兼容哪些浏览器,在不同的浏览器中 babel 会生成不同的代码,比如你要不要兼容 IE,Chrome 最低版本是多少,如果是 H5,支持的 iOS 版本是多少,这些都可以通过 babel 的配置文件 targets 指定,举例:
例子中表示兼容 ie11,iOS9:
'targets': {
'browsers': ['ie >= 11', 'iOS 9']
}
target 也可以在 package.json 的 browserslist 中设置,关于浏览器支持的版本可以查看
https://github.com/browserslist/browserslist#queries
babel 的工作原理其实是这样的:
如果你不配置插件,转换后的代码和源码一致,不做任何处理。当你配置插件后,如果源码中包含了符合该插件的代码,源码将会被转换。比如,你写了个箭头函数,如果想转换箭头函数就需要配置插件:
@babel/plugin-transform-arrow-functions
const plugins = [
// plugin 执行顺序是从前到后
// plugin 先执行,preset 后执行
"@babel/plugin-transform-arrow-functions"
]
当前,大多数浏览器需要把 ES6 转换成比它低的版本,相当于每一种语法都需要使用一个插件,ES6 新增了很多特性,如果一个一个加入 plugins 需要配置很多内容。如何解决?
答案是通过 preset,可以把它看做是插件的集合,我们常用的是 preset-env,这里的 env 表示会通过不同的浏览器配置不同的插件,最终生成不同的代码。
const presets = [
[
// 这个人插件,可以帮助你通过不同的环境生成不同的代码
"@babel/preset-env",
{
// 如果有未用到的 api,会自动引入 polyfill
// entry 在入口出引入所有的特性
// usage 在使用的位置引入
// false 默认值,
"useBuiltIns": "usage",
// 转化后还是 ESM 语法
// "modules": false,
"corejs": "3"
}
]
// preset 作用顺序,从后向前
];
babel 只会进行代码转换,不会自动引入新的特性,比如你代码中使用了 Promise,你需要手动引入 Promise 的 polyfill,否则你的代码将无法在某些浏览器中运行,比如 IE。
解决这个问题,最初可以使用 babel-polyfill,但是 babel7.4 以后,官方不再建议这么用了,一种替代方案就是使用 useBuiltIns,它可以自动引入 polyfill,具体配置可以看代码注释。
关于 babel-preset-env 可以看官方文档了解更多:
https://www.babeljs.cn/docs/babel-preset-env#usebuiltins
关于 babel 的更多配置项,可以参考:
https://www.babeljs.cn/docs/options
babel 为开发者提供了便捷,我们不要把它遗忘。建议没学过的同学可以写个 demo 学一下。babel 能做的事情非常多,比如 element-ui 的单组件引入实现,你有没有使用 babel 做过有意义的事情呢?
脑补一下,是不是可以实现一个无埋点方案,在某些规则内自动插入上报数据的代码。
大家加油!
长按关注
素燕《前端小课》
帮助 10W 人入门并进阶前端
官网:https://lefex.gitee.io/