插件 | Plugin
Babel 是一个编译器。从宏观角度看,它将运行代码分为3个阶段: 解析,转换,及生成(与其他编译器相同)。
关于编译器的优秀/简单的教程,请查看 the-super-tiny-compiler,同时它也从宏观角度上解释了 Babel 本身是如何工作的。
初始阶段,Babel 并没有做任何事情。它基本上就相当于 const babel = code => code;,先解析代码,然后再次生成相同的代码。
你可以为 Babel 添加一些 Plugins 让其去做任何事情( Plugins 会影响 Babel 的第 2 阶段,转换)。
不知如何入手? 请查阅我们的 presets 。
Presets
不想定制你自己的插件? 没关系! Presets 是可共享的 .babelrc
配置或者只是一个 babel 插件的数组。
公共 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 插件。
欲了解更多信息,请务必查看当前 TC39 提案及其文档流程.
Yehuda Katz (@wycatz) 在 thefeedbackloop.xyz 中的几个帖子中也详细解释了 TC39 各阶段的流程: Stage 0 和 1,Stage 2,Stage 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 默认已经启用了它们。
- async-functions (since babylon 6.9.1)
不推荐
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 之前。
例如:
{
"plugins": [
"transform-decorators-legacy",
"transform-class-properties"
]
}
将先执行 transform-decorators-legacy
再执行 transform-class-properties
.
一定要记得 preset 的顺序是反向
的。举个例子:
{
"presets": [
"es2015",
"react",
"stage-2"
]
}
按以下顺序运行: stage-2
, react
, 最后 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;
// 反转字符串: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 项目相关的示例。