本文是Babel系列的第一篇,讲讲Babel的使用。
What is Babel
Babel is a JavaScript compiler. Babel is a toolchain that is mainly used to convert ECMAScript 2015+ code into a backwards compatible version of JavaScript in current and older browsers or environments.
Babel可以帮我们处理以下事情:
语法转换,将ES6+ 语法转换成ES5的代码
对新版本ES的feature提供polyfill
TS / flow支持(类型)
生成source map
...

Usage Guide
Babel 有以下几种使用方式:
plugins
Babel不进行任何配置开箱即用不会任何效果,也就是说一段ES6的代码经过刚开箱的 babel 处理,输出的还是之前的代码。Babel的所有转换效果都是通过Plugins完成的,每个Plugin都有自己的能力,能处理对应的ES代码。
例(开箱即用)
安装babel cli和core
写一段简单的代码在src/index.js中,运行babel,将处理完的文件输出到dist目录,处理后的 dist/index.js没有变化

从babel7开始,babel提供的npm库都变为在@babel这个scope下。
Babel plugins分为两类:
语法类(Syntax)
转换类(Transform)
Syntax plugins在官网上是这么说的:
These plugins only allow Babel to
parse specific types of syntax (not transform).
所以Syntax plugin是用来
识别 新语法的,不进行转换,在启用transform plugin的时候对应的syntax会自动引入,不需要单独配置。
plugins usage
给index.js补充一些代码:

安装plugin:

创建一个 babel的配置文件(.babelrc.js)

再次使用babel处理

可以看到class和箭头函数都被转换了。
plugins 的启用顺序
如果两个plugins都要对某一种类型的节点进行处理,处理顺序是怎样的?
babel按照以下顺序对代码进行处理:
plugins先于presets
plugins数组内部处理顺序从左到右
presets数组内部处理顺序从右到左
transform-runtime
上面的plugins例子中可以看到在转换的时候,babel引入了很多自定义的函数(helper),比如_createClass,这样存在的问题是,每个使用class的文件里都会有这样一段一毛一样的代码,这种重复肯定是不可以接受的,所以babel提供了transform-runtime这个plugin。

转换完的代码中就可以看到:

这样就都是引用同一个地方的代码了就不存在重复问题了。
transform runtime plugin提供了一些配置:
corejs
默认为false,可以设置为:false、2、3,不同的值需要安装不同的babel/runtime。
为false,需要安装 babel/runtime
为2,需要安装 babel/runtime-corejs2
为3,需要安装 babel/runtime-corejs3
上面三个值的区别是什么?
corejs: false的情况下,transform-plugin 只会对语法进行处理

babel处理完如下:

如果设置corejs为3并且安装了runtime-corejs3,babel处理过的代码如下:

corejs: 2和corejs: 3的区别在于,2只能处理类方法,3能处理类方法和实例方法
presets
plugins有辣么多,挨个配置岂不是要了老命,所以babel提供了presets,来简化babel配置。
官方Presets:
@babel/preset-env
@babel/preset-flow
@babel/preset-react
@babel/preset-typescript
下面主要介绍一下preset-env,其他几个preset从名字就可以看出来是非常有针对性的去处理一些指定情况。
@babel/preset-env
env所有presets最复杂的一个了,这个preset,可以根据我们对browserslist的配置,在转码时自动根据我们对转码后代码的目标运行环境的最低版本要求,采用更加“smart”的转码,如果我们设置的最低版本的环境,已经原生实现了要转码的ES特性,则会直接采用ES标准写法;如果最低版本环境,还不支持要转码的特性,则会自动注入对应的polyfill。
@babel/preset-env没有收入所有stage-x的plugins。
所以preset-env不是万能的。如果我们用到某一个新的ES特性,还是proposal阶段,而且preset-env不提供转码支持的话,就得自己单独配置plugins。
那preset-env如何去使用呢?这里介绍日常会用到的配置:
target
告诉env要兼容的目标环境,上面说过,preset-env会很聪明的帮助我们进行代码转换,这里就是配置最低的目标环境。
例:
modules
设置babel转换的时候对于模块的导出方式,可以设置以下几个值:
amd
umd
systemjs
commonjs
cjs
auto
false
例:
新建一个src/lib/index.js

不设置module,babel处理后:

设置module为false:
经过babel处理后,可以看到模块导出方式没有发生变化:

useBuildIns
useBuildIns 可以设置为 usage、entry、false,默认为false。该属性告诉env如何去处理polyfill
因为我们要对一些高级语法、类方法、实例方法进行polyfill,所以我们要引入core-js,
设置
useBuiltIns: “entry”,之后,env会根据当前目标的环境从中取出需要的polyfill,例:

可以看到babel根据当前环境从corejs里取出了很多的polyfill文件
设置useBuildIns为usage,则会根据当前代码使用到的需要polyfill的方法进行处理,例:
这里只用到了数组的find方法

经过babel处理之后,也只会引入find这一个依赖,不会像上面设置为entry之后引入了很多没用到的依赖。

corejs
最后一个要介绍的配置是corejs
该属性设置使用的corejs的版本,默认是2
当设置 corejs为3并且useBuildIns为usage的时候,就不需要我们在代码入口处手动import corejs了。
总结
Babel是一个JS的compiler,开箱即用的babel不会做任何处理,Babel的插件可以对语法进行转换,如果需要polyfill,需要使用core-js和regenerator-runtime。通过设置presets-env的useBuildIns可以帮助我们更好的进行polyfill。

长按关注,不迷路
