背景
之前接触过babel,也是一知半解,在写umd插件的过程中,发现在chrome 78版本中报错了,整个插件没加载出来,控制台发现,chrome 78版本不能识别obj?.name这种写法。
去了Can i use查了结果如下:
确实识别不了....
库简介:写一个用在多个项目中的意见反馈弹窗,打包成umd的形式,希望项目能在多个环境下使用(react、vue等),rollup打包。
定位问题:旧版本浏览器无法识别js新语法,是babel的问题。
babel
我查看项目中babel的配置:
{
"presets": [
"@babel/preset-env",
"@babel/preset-typescript",
"@babel/preset-react"
],
"plugins":["babel-plugin-transform-scss"]
}
看不懂以上配置问题出在哪里?
恶补babel
babel是一种js编译工具,是将js新的语法、旧版本的浏览器不能识别的语法编译成浏览器可以识别的js语法。
babel是由@babel/core 和 plugin、preset(预设)组成的,如果不配置任何插件和预设,babel不做任何事情。
@babel/core是babel最核心的库,作用是经过词法分析-语法分析-AST等过程将js解析成机器可以识别的语言,进行操作,然后通过generator库转成代码,返回(所以不配置插件和预设的话,babel经过一系列过程啥也没干,就返回了)。
preset是plugin的集合
预设和插件的作用是:告诉babel要按照什么样的规则编译js
几个重要的预设
- @babel/preset-env
是一个智能预设,具有最全的js插件的集合,可以根据配置项将高版本的js转换为旧版本浏览器可以识别的js。 如果用到的语法,preset-env没有的话,可以从官网查找,引入。
// 常用配置
{
"presets": [
[
"@babel/preset-env",
{
"targets": {
"browsers": [
"firefox >= 70",
"chrome >= 70"
]
}
}
],
"@babel/preset-typescript",
"@babel/preset-react"
],
"plugins":["babel-plugin-transform-scss"]
}
@babel/preset-env配置项
1.没有任何配置的情况下:会根据
package.json下的browserList中的配置,引入相应浏览器需要的插件进行转换2.
targets表示按照目标配置项,引入相应的插件,比如chrome >= 70,只需要引入70版本需要的插件,70版本浏览器已经可以识别箭头函数,这里就不需要引入编译箭头函数的插件。3.还有一个关于
polyfill的配置项,将在下面介绍
- @babel/preset-react
编译jsx语法的预设
- @babel/preset-typescript
编译ts语法的预设
也可以用tsc
关于polyfill
以上,我们已经可以根据自己的需要让babel帮我们将js语法编译成所需浏览器可以识别的内容。
但是!!!
js新内容分为两部分:
1.语法部分 (解构、.?用法)
2.api 实例方法、静态方法 (Promise、Array.from Function.prototype.includes等)
关于api、实例方法、静态方法等,如果在我们的程序当中用到,babel/preset-env帮不了我们。
这个时候,就需要用到垫片--@babel/polyfill。
垫片:浏览器不能识别的东西,垫片帮我们加上去。
polyfill和runtime两种垫片实现方式
上面这篇文章其实已经讲得很清楚了,polyfill和runtime是两种方式。
polyfill是在全局对象或者内置对象上加上我们想要的方法和属性,会污染全局环境,可以用在我们的项目当中。
runtime不会污染全局环境,一般用在库环境当中。
总结
写不动了...
我的项目打包之后之所以不能识别?.语法,因为preset-env没有任何配置,这个时候babel会找到package.json中的browserList,根据它来配置,这个配置里面写着'last 1 versions'。
破案了...