编写你的第一个 babel 插件

需求

foo === bar; 转换为 sebmck === bar;

思路

foo === bar; AST 结构大致如下

{
  type: "BinaryExpression",
  operator: "===",
  left: {
    type: "Identifier",
    name: "foo"
  },
  right: {
    type: "Identifier",
    name: "bar"
  }
}

sebmck === bar; AST 结构大致如下

{
  type: "BinaryExpression",
  operator: "===",
  left: {
    type: "Identifier",
    name: "sebmck"
  },
  right: {
    type: "Identifier",
    name: "bar"
  }
}

通过 AST Explorer(在线解析网站) 对比,显然要完成我们的需求仅需修改 left 属性即可

编写 babel 插件

首先,在 AST Explorer 中我们发现需要修改的语句为 BinaryExpression

那么,插件 visitor 可以初步写成如下

visitor = 
{
  BinaryExpression(path){
    // do something
  }
}

然后进一步细化,需要处理的 BinaryExpression 操作符为 ===

visitor =
{
  BinaryExpression(path) {
    if (path.node.operator !== '===') {
      return;
    }
    // do something
  }
}

定位到了目标 BinaryExpression ,最后就是替换 left 属性

visitor =
{
  BinaryExpression(path) {
    if (path.node.operator !== '===') {
      return;
    }
    path.node.left.name = 'sebmck';
  }
}

插件至此编写完成。


完整 js 代码如下(node)

const parser = require('@babel/parser');
const traverse = require('@babel/traverse').default;
const generator = require('@babel/generator').default;

let jscode = 'foo === bar;';
// 转换为 ast 树
let ast = parser.parse(jscode);

const visitor =
{
  BinaryExpression(path) {
    if (path.node.operator !== '===') {
      return;
    }
    path.node.left.name = 'sebmck';
  }
}

//调用插件,处理待处理 js ast 树
traverse(ast, visitor);

// 生成处理后的 js
let { code } = generator(ast);
// 打印处理后的 js
console.log(code);

推荐阅读

参考

Table of Contents