手撸babel插件

109 阅读1分钟

1、babel 的转译过程也分为三个阶段

  • 解析 Parse
    • 将代码解析⽣成抽象语法树( 即AST )
    • 即词法分析与语法分析的过程
  • 转换 Transform
    • 对于 AST 进⾏变换⼀系列的操作,babel 接受得到 AST 并通过 babel-traverse 对其进⾏遍历,
    • 在此过程中进⾏添加、更新及移除等操作
  • ⽣成 Generate
    • 将变换后的 AST 再转换为 JS 代码,
    • 使⽤到的模块是 babel-generator

2、如何写⼀个babel插件?

var babel = require('babel-core');
var t = require('babel-types');

const visitor = {
    BinaryExpression(path) {
        const node = path.node;
        let result;
        
        // 判断表达式两边,是否都是数字
        if (t.isNumericLiteral(node.left) && t.isNumericLiteral(node.right)) {
            // 根据不同的操作符作运算
            switch (node.operator) {
                case "+":
                    result = node.left.value + node.right.value;
                    break
                case "-":
                    result = node.left.value - node.right.value;
                    break;
                case "*":
                    result = node.left.value * node.right.value;
                    break;
                case "/":
                    result = node.left.value / node.right.value;
                    break;
                case "**":
                    let i = node.right.value;
                    while (--i) {
                        result = result || node.left.value;
                        result = result * node.left.value;
                    }
                    break;
                default:
            }
        }
    
        // 如果上⾯的运算有结果的话
        if (result !== undefined) {
            // 把表达式节点替换成number字⾯量
            path.replaceWith(t.numericLiteral(result));
        }
    }
};

//那么Babel的插件模块需要你暴露⼀个function,function内返回visitor
module.exports = function (babel) {
    return {
        visitor
    };
}

//运行插件
const babel = require("babel-core");
const result = babel.transform("const result = 1 + 2;",{
    plugins:[
        require("./index")
    ]
});
console.log(result.code); // const result = 3;