Babel v7 指南

  1. 1. > plugin
  2. 2. > preset
  3. 3. >> preset-env
  4. 4. > 同时使用
  • 配置
    1. 1. > 配置文件 .babelrc
    2. 2. > JS code
    3. 3. > CLI Parameter
  • 开始使用
    1. 1. > @babel/cli | 静态编译
    2. 2. > @babel/register | 动态编译
    3. 3. > @babel/node | 动态编译
  • 实战
  • Babel 7 做出了重大升级,之前的配置已经完全不能使用。在项目升级到 Node 10 后,旧版本的 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
    2
    3
    {
    "presets": ["@babel/preset-env"]
    }

    推荐配合使用 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
    2
    3
    4
    5
    6
    {
    "presets": [[
    "@babel/preset-env", { "targets": { "node": "10.4.1" }}]
    ],
    "plugins": ["@babel/plugin-transform-modules-commonjs"]
    }

    > JS code

    这种是在动态注入时使用,一般会应用于开发环境。用于 @babel/register 模式中。

    1
    2
    3
    4
    5
    require("@babel/register")({
    presets: [[
    "@babel/preset-env", { targets: { node: "10.4.1" }}]
    ]
    });

    > 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
    2
    3
    4
    5
    $ babel script.js
    # 额外指定配置
    $ babel script.js --out-file script-compiled.js --presets=es2015,react
    # 忽略 babelrc
    $ babel --no-babelrc script.js --out-file script-compiled.js --presets=es2015,react

    > @babel/register | 动态编译

    @babel/register 模块改写了 require 命令,为它加上一个钩子。此后,每当使用 require 加载 .js、.jsx、.es和 .es6 后缀名的文件,就会动态先用 Babel 进行转码,再进行 require。

    另外,由于它是实时转码,所以会产生效率问题,只适合在开发环境使用。

    需要注意的是,babel-register 只会对 require 命令加载的文件转码,而不会对当前文件转码。

    1
    2
    3
    4
    5
    6
    7
    require("@babel/register")({
    presets: [[
    "@babel/preset-env", { targets: { node: "10.4.1" }}]
    ]
    });

    require("./src/index.js");

    > @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
    2
    3
    4
    5
    {
    "presets": [[
    "@babel/preset-env", { "targets": { "node": "10.4.1" }}]
    ]
    }

    也可以写成:

    1
    2
    3
    {
    "plugins": ["@babel/plugin-transform-modules-commonjs"]
    }

    ## REF::