babel 的工作过程分为三步:
- Parse(解析)将源代码转换为抽象语法树,树上有很多 estree 节点。
- Transform (转换)对抽象语法树进行转换。
- Generater(代码生成)将上一步经过转换过的抽象语法树生成新的代码。
AST 遍历
- AST 是深度优先遍历。
- 访问者模式 Visitor 对于某个对象或者一组对象,不同的访问者,产生的结果不同,执行操作也不同。
- Visitor 的对象定义了用于 AST 中获取具体节点的方法。
- Visitor 上挂载以节点 type 命名的方法,当遍历 AST 的时候,如果匹配上 type,就会执行对应的方法。
estraverse 的第二个参数就是 visitor,如下:
// 他可以把源代码转换成抽象语法树
let esprima = require('esprima');
// 他可以遍历语法树,修改树上的语法节点
let estraverse = require('estraverse');
//重新生成源代码
let escodegen = require('escodegen');
let sourceCode = 'function ast(){}';
let ast = esprima.parse(sourceCode);
let indent = 0;
const padding = () => ' '.repeat(indent);
// 访问者
let visitor = {
enter(node, parent) {
console.log(padding() + node.type);
if (node.type === 'FunctionDeclaration') {
node.id.name = 'newFunction';
}
indent++;
},
leave(node, parent) {
indent--;
console.log(padding() + node.type);
}
};
estraverse.traverse(ast, visitor);
//重新生成源代码
let newSourceCode = escodegen.generate(ast);
console.log(newSourceCode);
babel 插件
- @babel/parser 可以吧源码转换成 AST。
- @babel/traverse 用于对 AST 的遍历,维护了整颗树的状态,并且负责替换、移除和添加节点。
- @babel/generate 可以把 AST 生成源码,同时生成 sourcemap。
- @babel/types 用于 AST 节点的 Lodash 式工具库,它包含了构造、验证以及变换 AST 节点的方法,对于编写处理 AST 逻辑非常有用。
- @babel/template 可以简化 AST 的创建逻辑。
- @babel/code-frame 可以打印代码位置。
- @babel/core Babel的编译器,核心 API 都在这里面,比如常见的 transform、parse,并实现了插件功能。
- 把源代码转成 AST 语法
- 遍历 AST 语法树,遍历额时候会把语法树给插件进行处理,插件可以关注自己感兴趣的类型进行处理
- 新的 AST 语法树重新生成源代码
- babylon Babel 的解析器,以前叫 babel parser,是基于 acom 扩展而来,扩展了很多语法,可以支持 es2020、jsx、typescript 等语法。
- babe-types-api
- Babel 插件手册
- babeljs.io babel 可视化编译器