babel 的工作过程分为三步:

  • Parse(解析)将源代码转换为抽象语法树,树上有很多 estree 节点。
  • Transform (转换)对抽象语法树进行转换。
  • Generater(代码生成)将上一步经过转换过的抽象语法树生成新的代码。

babel 插件 - 图1

AST 遍历

  • AST 是深度优先遍历。
  • 访问者模式 Visitor 对于某个对象或者一组对象,不同的访问者,产生的结果不同,执行操作也不同。
  • Visitor 的对象定义了用于 AST 中获取具体节点的方法。
  • Visitor 上挂载以节点 type 命名的方法,当遍历 AST 的时候,如果匹配上 type,就会执行对应的方法。

estraverse 的第二个参数就是 visitor,如下:

  1. // 他可以把源代码转换成抽象语法树
  2. let esprima = require('esprima');
  3. // 他可以遍历语法树,修改树上的语法节点
  4. let estraverse = require('estraverse');
  5. //重新生成源代码
  6. let escodegen = require('escodegen');
  7. let sourceCode = 'function ast(){}';
  8. let ast = esprima.parse(sourceCode);
  9. let indent = 0;
  10. const padding = () => ' '.repeat(indent);
  11. // 访问者
  12. let visitor = {
  13. enter(node, parent) {
  14. console.log(padding() + node.type);
  15. if (node.type === 'FunctionDeclaration') {
  16. node.id.name = 'newFunction';
  17. }
  18. indent++;
  19. },
  20. leave(node, parent) {
  21. indent--;
  22. console.log(padding() + node.type);
  23. }
  24. };
  25. estraverse.traverse(ast, visitor);
  26. //重新生成源代码
  27. let newSourceCode = escodegen.generate(ast);
  28. 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 可视化编译器