使用babel检查和添加代码

前提了解:

babel是干啥用的?

babel就是个js编译器,可以用来实现代码检查、代码生成、自定义语法等功能。

AST又是什么,长什么样子?

ast是用来表示代码结构的一种树结构,可以借助网页AST Explorer输入代码查看对应的ATS树。

正片开始:

步骤一:源代码解析成AST抽象语法树

使用@babel/parser将源代码解析成AST树

const parser = require('@babel/parser')

const originCode = fs.readFileSync(path, 'utf-8')
const ast = parser.parse(oldCode, {
            sourceType: 'unambiguous',
            plugins: ['jsx', 'decorators-legacy', 'classProperties', 'typescript']
        })

参数详细说明:官网文档babel-parser

步骤二:对AST树进行遍历

使用@babel/traverse对AST树进行遍历

const traverse = require('@babel/traverse')

traverse.default(ast, visitor) // visitor为对ast节点处理的babel插件

遍历的每个节点都会丢给visitor去处理

步骤三:编写babel插件visitor

代码检查例如

const visitor_check = {
    // 标签里属性的类型为JSXAttribute会触发执行
    JSXAttribute(path) {
        if (_targetEvent.includes(path.node.name.name)) {
            const expressionBody = safeProp(path, 'node', 'value', 'expression', 'body', 'body') || []
            const flag = expressionBody.some(
                element => safeProp(element, 'expression', 'callee', 'name') === 'autoTrack'
            )
            if (!flag) {
                console.log('缺少埋点->', _curPath)
                process.exit(1)
            }
        }
    }
}

找到目标所在位置,然后判断。

代码添加例如

const types = require('@babel/types')

const visitor_add = {
    JSXAttribute(path) {
        if (_targetEvent.includes(path.node.name.name)) {
            const expressionBody = safeProp(path, 'node', 'value', 'expression', 'body', 'body') || []
            const flag = expressionBody.some(
                element => safeProp(element, 'expression', 'callee', 'name') === 'autoTrack'
            )
            if (!flag) {
                const expressionStatement = types.expressionStatement(
                    types.callExpression(types.identifier('autoTrack'), [
                        types.stringLiteral('autoTrack_event'),
                        types.stringLiteral('autoTrack_label')
                    ])
                )
                path.node.value?.expression?.body?.body?.unshift(expressionStatement) &&
                    _addImportPathList.push(_curPath)
            }
        }
    }
}

找到要添加的位置,通过@babel/types调用节点类型同名的方法创建该类型的节点,鼠标放到名字上会有提示传入什么样的参数。创建后加进去即可。

最后一步:将此时的AST树生成目标代码

const generator = require('@babel/generator')

const newCode = generator.default(ast)
fs.writeFileSync(path, newCode.code)
childProcess.execSync(`npx prettier --write ${path}`) // 把格式还原

通过@babel/generator将ast转变成代码,ok,万事大吉。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一枚小银子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值