Babel 7 做出了重大升级,之前的配置已经完全不能使用。在项目升级到 Node 10 后,旧版本的 Babel 会报很多的错误,借机做了一次升级。
- http://babeljs.io/
- https://github.com/babel/babel/
- 旧版本 Babel 参见:Modern JavaScript - Startup with Babel
## 概念入门
Babel 是一个转码器,它可以将 JavaScript 中的一个语法进行编译转换,以让旧的引擎支持。
这里有两个重要的概念,plugin 和 preset。
> plugin
Babel 本质就是一个编译器,有着常见的三步:解析,转义和输出。哪些代码需要被转义,就是在 plugin 中定义的。plugin 对应的是 feature。
可以在这里看到各个版本中对应的更新和 node 的支持度:http://node.green/
下面列出了 ECMA 2015 版本中的变化点。每个点都是一个 plugin。
- arrow-functions
- block-scoped-functions
- block-scoping
- classes
- computed-properties
- destructuring
- duplicate-keys
- for-of
- function-name
- instanceof
- literals
- new-target
- object-super
- parameters
- shorthand-properties
- spread
- sticky-regex
- template-literals
- typeof-symbol
- unicode-regex
更多版本 plugin 参见:https://babeljs.io/docs/en/plugins
> preset
preset 如果单独配置就会很长,很繁琐。而一些定义好的组合,被称为 preset,可以让更多的重用。
在 Babel 7 之前,前用的 preset 是 latest, es2015, es2016, es2017。之后版本中,去掉了这种方式,换成了 stage-x 和 env。
目前常用的 Preset 为:
- env
- stage-0
- stage-1
- stage-2
- stage-3
- flow
- react
- minify
- typescript
>> preset-env
env 代替了 latest,官方主要推荐使用这种,env 就是根据你要使用的场景,智能帮你加载所需要的 plugins。
它的默认配置如下:(但这样是很不推荐的,它会把所有的 plugins 都加载上,也就是会翻译为最古老的代码,增加翻译时间。)
1 | { |
推荐配合使用 targets,常用如下:
- targets.esmodules bool 是否使用 esmodules
- targets.node 配置 nodejs 的版本号
- targets.browsers 配置浏览器的版本,智能加载所需要的 plugins
- include / exclude 强制使用/不使用某个 plugins
> 同时使用
如果同时配置了 preset 和 plugin 时,编译器会按如下顺序进行解析:
- Plugins 优先
- Plugins 列表内的优先级是自前到后
- Preset 里的优先级则从后到前
配置
Babel 是通过配置中的 Plugins 来进行编译,那如何使用配置呢?
Babel 有几种使用方式
- Configuration File
- JS Code
- CLI Parameter
> 配置文件 .babelrc
1 | { |
> JS code
这种是在动态注入时使用,一般会应用于开发环境。用于 @babel/register 模式中。
1 | require("@babel/register")({ |
> CLI Parameter
这里的 CLI 指的是 @babel/cli 和 @babel/node。
但参数的更高阶用法没有找到,比如说在 presets 后面使用 target
1 | $ babel script.js --out-file script-compiled.js --presets=@babel/preset-env |
开始使用
在使用场景上,会有两种方式:
- 静态编译
- 动态编译
> @babel/cli | 静态编译
通过下面命令来编译 js,然后将编译好的文件进行线上环境发布。
1 | $ babel script.js |
> @babel/register | 动态编译
@babel/register
模块改写了 require 命令,为它加上一个钩子。此后,每当使用 require 加载 .js、.jsx、.es和 .es6 后缀名的文件,就会动态先用 Babel 进行转码,再进行 require。
另外,由于它是实时转码,所以会产生效率问题,只适合在开发环境使用。
需要注意的是,babel-register 只会对 require 命令加载的文件转码,而不会对当前文件转码。
1 | require("@babel/register")({ |
> @babel/node | 动态编译
Babel 提供了 @babel@node
,作为 @babel@register
的更高阶的封装,可以 runtime 编译,而且不用额外的中间层代码。
1 | $ babel-node --debug --presets es2015 -- script.js --debug |
实战
Server 端用 Node.js 10.4.1,开发中用到的 feature 列表中,只有一项还暂不支持:
- es2015 module-commonjs
所以在配置 babel 时,根据自己的需求,只需要单独引入就可以了,这样,编译出来的代码几乎相同了,.babelrc
配置如下:
1 | { |
也可以写成:
1 | { |
## REF::