Babel 是一个编译器。 从宏观角度看,它将运行代码分为3个阶段: 解析,转换,及生成(与其他编译器相同)。

关于编译器的优秀/简单的教程,请查看 the-super-tiny-compiler,同时它也从宏观角度上解释了 Babel 本身是如何工作的。

初始阶段,Babel 并没有做任何事情。它基本上就相当于 const babel = code => code;,先解析代码,然后再次生成相同的代码。

你可以为 Babel 添加一些插件让其去做任何事情(插件会影响 Babel 的第 2 阶段,转换)。

不知如何下手? 请查看我们的一些 presets

Presets

不想定制你自己的插件? 没关系! Presets 是可共享的 .babelrc 配置或者只是一个 babel 插件的数组。

Official Presets

我们已经组装了一些公用的插件:

每年每个 preset 只编译当年批准的内容。 而 babel-preset-env 相当于 es2015 ,es2016 ,es2017 及最新版本。

在 npm 上可以找到许多由其他社区进行维护的 preset 进行使用!

Stage-X (实验阶段 Presets)

Stage-x preset 中的任何转换都是对未被批准为 JavaScript 版本一部分的语言的变化(如 es6 / es2015 )。

“语言的变化需要一个过程来发展,该过程提供了将一个想法进化为一种完善规范的指导原则。”

不稳定

这些提案可能会有所改动,因此请谨慎使用,尤其是第 3 阶段以前的提案。我们计划会在每次 TC39 会议结束后更新对应的 stage-x preset。

TC39 将提案分为以下几个阶段:

  • Stage 0 - 稻草人: 只是一个想法,可能是 babel 插件。
  • Stage 1 - 提案: 初步尝试。
  • Stage 2 - 初稿: 完成初步规范。
  • Stage 3 - 候选: 完成规范和浏览器初步实现。
  • Stage 4 - 完成: 将被添加到下一年度发布。

欲了解更多信息,请务必查看当前 TC39 提案及其文档流程.

Yehuda Katz (@wycatz) 在 thefeedbackloop.xyz 中的几个帖子中也详细解释了 TC39 各阶段的流程: Stage 0 和 1Stage 2Stage 3 以及最终的 Stage 4 。

转译 Plugin

这些 Plugin 将用于转译您的代码。

转译 plugin 将启用相应的语法 plugin ,因此你不必同时使用两者。

ES3

ES5

ES2015

ES2016

ES2017

模块

实验阶段

Minification

请查看基于 Babel 的 minifier !

这些 plugin 都存在于 minify 项目中。

React

其它

混合 Plugin

语法 Plugins

这些 plugin 允许 Babel 解析特定类型的语法(不转译)。

注意: 转译 plugin 会自动继承/使用语法插件,因此如果已经使用了相应的转译 plugin ,则不需要指定语法 plugin 。

你也可以从 babylon 中提供任意 plugin 选项:

// .babelrc
{
  "parserOpts": {
    "plugins": ["jsx", "flow"]
  }
}

实验性的

默认启用

这些 plugin 已经不起作用了,因为较新版本的 babylon 默认已经启用了它们。

不推荐

Plugin/Preset 路径

如果 plugin 是通过 npm 安装,你可以传入 plugin 名字给 babel,babel 将检查它是否安装在 node_modules

"plugins": ["babel-plugin-myPlugin"]

你也可以指定你的 plugin/preset 的相对或绝对路径。

"plugins": ["./node_modules/asdf/plugin"]

Plugin/Preset 简写

如果你使用 babel-plugin- 作为 plugin 的前缀,你可以使用简写的形式省略掉该前缀。

"plugins": ["myPlugin"]

preset 与之相同

"presets": ["babel-preset-myPreset"]

vs

"presets": ["myPreset"]

这也适用于包裹作用域:

"presets": ["@org/babel-preset-name"]

简写:

"presets": ["@org/name"]

Plugin/Preset 排序

插件中每个访问者都有排序问题。

这意味着如果两次转译都访问相同的”程序”节点,则转译将按照 plugin 或 preset 的规则进行排序然后执行。

  • Plugin 会运行在 Preset 之前。
  • Plugin 会从第一个开始顺序执行。ordering is first to last.
  • Preset 的顺序则刚好相反(从最后一个逆序执行)。

例如:

{
  "plugins": [
    "transform-decorators-legacy",
    "transform-class-properties"
  ]
}

将先执行 transform-decorators-legacy 再执行 transform-class-properties.

一定要记得 preset 的顺序是反向的。举个例子:

{
  "presets": [
    "es2015",
    "react",
    "stage-2"
  ]
}

按以下顺序运行: stage-2react, 最后 es2015

这主要是为了保证向后兼容,因为大多数用户会在 “stage-0” 之前列出 “es2015” 。欲了解相关更多信息,请查看 关于隐式遍历 API 变化的说明

Plugin/Preset 选项

Plugin 和 Preset 均可以通过将名称和选项对象放置在同一个数组中来指定其选项。

例如:

{
  "plugins": [
    ["transform-async-to-module-method", {
      "module": "bluebird",
      "method": "coroutine"
    }]
  ]
}

Preset 的配置选项工作原理与 plugin 完全相同:

{
  "presets": [
    ["es2015", {
      "loose": true,
      "modules": false
    }]
  ]
}

Plugin 的开发

请参考 babel-handbook ,学习如何制作自己的 plugin 。

一个简易逆转名字的插件 (首页中的示例):

export default function () {
  return {
    visitor: {
      Identifier(path) {
        const name = path.node.name;
        // reverse the name: JavaScript -> tpircSavaJ
        path.node.name = name.split("").reverse().join("");
      }
    }
  };
}

创建 Preset

你只需导出一个 config ,就可以拥有自己的 preset 。

// Preset 中可以包含其他 preset 和 带有选项的 plugin 。
module.exports = {
  presets: [
    require("babel-preset-es2015"),
  ],
  plugins: [
    [require("babel-plugin-transform-es2015-template-literals"), { spec: true }],
    require("babel-plugin-transform-es3-member-expression-literals"),
  ],
};

相关更多信息,请查阅 babel handbook 与 preset 相关部分或者只查看 es2015 preset 项目相关的示例。