写一个简单的babel插件

246 阅读1分钟

babel原理

Babel 的三个主要处理步骤分别是:解析(parse),转换(transform),生成(generate) babel 插件就是在转换过程中起作用的,即将解析完成的语法树对象按照自己的目的进行处理,然后再进行代码生成步骤。

src=http___c.lanmit.com_d_file_bc_ze5qwtpprkw.jpg&refer=http___c.lanmit.jpeg 如上图所示,插件起作用的步骤则是上图的transform阶段

插件实现步骤

  1. 将你要改变的代码生成ast
  2. 目标代码生成ast
  3. 观察以上两种ast的区别,然后进行转化(修改、增加、删除操作)

实践代码

下边已实现console代码的移除为例

  1. 观察代码生成的ast,转化网址astexplorer.net/

image.png 2. 插件index.js

module.exports = ({types: t})=>{
    return {
        visitor:{
            Identifier(path){
                console.log('path',path.node.name)
                const parentIsIf = t.isIfStatement(path.parentPath)
                const isDebug = path.node.name ==="DEBUG"
                if(parentIsIf&&isDebug){
                    const stringNode = t.stringLiteral('DEBUG');
                    path.replaceWith(stringNode)
                }
            },
            StringLiteral(path){
                const parentIsIf = t.isIfStatement(path.parentPath)
                const isDebug = path.node.value ==="DEBUG"
                if(parentIsIf&&isDebug){
                    path.parentPath.remove()
                }
            }
        }
        // 如果是仅移除代码中的console可以用这段代码
        // visitor:{
        //   Identifier(path){
        //     if (path.node.name === 'console') {
        //       path.findParent(p => p.isCallExpression()).remove();;
        //       }
        //     }
        // }

测试方式

  1. 全局配置 .babelIrc
{
  "presets": [
    [
      "@babel/env",
      {
        "targets": {
          "edge": "17",
          "firefox": "60",
          "chrome": "67",
          "safari": "11.1"
        },
        "corejs": { "version": 3 },
        "useBuiltIns": false
      }
    ]
  ],
  "plugins": ["./index.js"]
  // 如果只是在生产环境下移除的话还可以这样写
  //"env": {
  //      "production": {
  //        "plugins": ["./index.js"]
  //    }
  //}
}
  1. test页面测试
const {transformSync} =require('@babel/core')
const code = `
function add(num1,num2){
    return num1+num2
}
if(DEBUG){
    const sum = add(5,6)
    console.log('sum',sum)
}
`
const babelConfig= {
    plugins:['./index.js']
}
const output=transformSync(code,babelConfig)
console.log('output.code',output.code)