babel的作用
babel到底是用来做什么的?简单来讲,babel就是用来做语法编译的,它可以将一些es6+的高级语法编译为浏览器可以识别的es5。通常,我们可以在通过配置presets和plugins来规定babel要怎么编译你的代码。presets其实是一些列plugin的集合,是预先设置好的一系列编译规则。babel配置中plugin和presets的执行顺序,先执行plugin的配置项,在执行presets的配置项,plugin配置项是按照声明顺序执行,presets配置项按照证明逆序执行。
babel7以后的相关改变
在babel的版本7.0之后,低版本的node将不在支持了,要求node的版本大于6,并且,对于presets的相关配置,将会废除stage-x这种用法,es201x这种用法也不再推荐使用,官方推荐使用env的方式。babel包的名称也发声了改变,将所有babel-*的包重命名为@babel/*的方式,例如babel-preset-env ——> @babel/preset-env。
babel的相关包及其作用
包名 | 作用 | 备注 |
---|---|---|
babel-loader | webpack的插件,在webpack打包时用来加载代码 | webpack使用 |
@babel/core | babel的核心包,包含语法转换的API,主要用转化es6+的语法 | 用于语法转换 |
@babel/polyfill | babel垫片,主要作用是兼容es6+新特性(如promise,set等),本质是由 core-js 和 regenerator-runtime 组成的。 | babel7.4 以后官方以不推荐使用 用core-js3代替 |
core-js | 给低版本浏览器提供es6+新特性接口的库。分为 core-js@2和@core-js@3 | |
regenerator-runtime | regenerator-runtime模块来自facebook的regenerator模块,主要作用是生成器函数、async、await函数经babel编译后,regenerator-runtime模块用于提供功能实现 | |
@babel/helpers | 用来把@babel/core处理的代码中插入的帮助函数当做一个模块引入,减小代码的体积 | |
@babel/plugin-transform-runtime | 用来引入垫片的插件, | |
@babel/runtime | 包含@babel/helpers 和 regenerator-runtime | |
@babel/runtime-corejs2 | 由 core-js@2、@babel/helpers 和 regenerator-runtime 组成 | @babel/runtime-corejs2不能转化对象实例的方法 |
@babel/runtime-corejs3 | 由 core-js@3、@babel/helpers 和regenerator-runtime 组成 | @babel/runtime-corejs3可以转化对象实例的方法 |
@babel/polyfill和@babel/plugin-transform-runtime
babel只能转换es6+的新语法,比如将箭头函数转换为浏览器能识别的函数方法,但是。我们知道,es6中除了新增加新的语法外,还增加了许多新特性,比如promise,set,map,async,await等新的api,浏览器对这些新的特性是不能够识别的,所以,我们还需要在代码转换的时候去实现这些新特性。babel为我们提供了两套方案去实现这些新特性。一种是@babel/polyfill的方式,另一种是@babel/plugin-transform-runtime的方式。总的来说,只要我们能够满足有core-js(babel中对于新特新的api实现的包)和regenerator-runtime(主要是async,await实现的包)就行了,就可以兼容各种浏览器了。当然,还有@babel/helpers,这并不是必须的,不过它可以做一些事情,把@babel/core往代码中插入的帮助函数当做模块引入,每个文件只需要调用这个模块就可以了,这可以让我们的代码体积更小。下面会基于babel7.4以上的版本具体说一下两种方案的具体实现方案。
@babel/polyfil
在babel7.4以上推荐用core-js3和regenerator-runtime代替@babel/polyfil,所以用之前需要安装core-js3和regenerator-runtime为生产依赖。然后只需要在.babelrc文件中做如下配置
{
"presets": [
["@babel/preset-env",{
"target":{},
"useBuiltIns":"usage",
"corejs":3,
"modules":false
}
]
],
"plugins": [
]
}
配置参数:
- target:babel转换代码最终的执行环境,根据目标环境判断是否需要对语法进行转换。
- modules:用来转换es6的模块语法,值有amd,umd,systemjs,commonjs,cjs,auto,false,默认值为auto,如果需要webpack的tree shaking的一些特性,需要将此参数设为false
- corejs:设置corejs的版本号,2或者3
- useBuiltIns:false,usage,entry,默认值为false,此参数用来设置垫片的引入方式。
- false:这种情况下corejs属性无效,此时仅根据target属性判断后做相应的语法转换
- usage:设置为usage时会自动按需引入垫片(官方推荐)
- entry:设置为entry时,需要自己在入口处手动引入垫片,全部引入
import"core-js/stable" import "regenerator-runtime/runtime")
通过这种方式引入垫片,因为是在全局下和对象的原型链上实现的新特性,所以会污染全局环境和对象的原型链。此外,core-js3实现了对象实例的方法。
@babel/plugin-transform-runtime
这是另一种引入垫片的方案,这种方式是通过@babel/plugin-transform-runtime插件自动按需的引入垫片,需要安装@babel/runtime-corejs为生产依赖。配置如下:
{
"presets": [
"@babel/preset-env"
],
"plugins": [
["@babel/plugin-transform-runtime",{
"corejs":3,
"useESModules":false
}],
]
}
- corejs:默认值为false,为fasle时需要安装@babel/runtime为生产依赖,此时因为没有corejs。所以只做语法转换。也可以为2或者3,需安装对应的@babel/runtime-corejs2或@babel/runtime-corejs3为生产依赖。2和3的区别在于,core-js2没有对对象实例方法的实现,core-js3则实现了。
- useESModules:是否对文件使用ES的模块语法,默认值为false。如果需要webpack的tree shaking的一些特性,需要将此参数设为true。
通过@babel/plugin-transform-runtime这种方式来添加垫片,可以避免污染全局变量环境,并且也是自动按需引入,core-js3对于对象实例的方法也有实现。是一个不错的选择。