开发 enhance-log 插件
问题点
如果用 ts 写,使其有提示?
使用 es 模块引入包时,默认导出为什么需要 xx.default 才能使用?
如果使用其它构建工具,怎么顺便打印出 log 所在的文件路径?(目前只能打印目录)
我想使用 vite,却遇到很多坑。(process.env 找不到等等)
api
- @babel/helper-plugin-utils。作用:提供明确的报错信息。接受一个函数作为参数,函数又接受三个参数,分别为 api、options、dirname。
- @babel/generator。作用:把 ast 转换为代码。
- @babel/types。作用:包含手动构建 ast 的方法,也包含检查 ast 节点类型的方法。
创建一个字符串类型的 ast 节点
js
function generateStrNode(str: string) {
const node = t.stringLiteral(str)
return node
}判断节点是什么类型
js
// 是字面量类型?
t.isLiteral(argument)
// 是标识符(变量)类型?
t.isIdentifier(argument)代码
js
import { declare } from '@babel/helper-plugin-utils'
import {transform} from '@babel/core'
import generater from '@babel/generator'
import { stringLiteral } from '@babel/types'
import * as nodePath from 'path'
const soureCode = `
const obj = [4,5,6]
console.log(
123,123,obj
)
`
function generateStrNode(str) {
const node = stringLiteral(str)
return node
}
// 有三个参数。分别为 api,options,dirname
const enhanceLogPlugin = declare((babel, options, dirname) => {
const { types: t } = babel
const splitNode = generateStrNode('🚀')
const newLine = t.stringLiteral(`\n`)
return {
name: 'enhance-log',
visitor: {
CallExpression(path) {
const calleeCode = generater.default(path.node.callee).code
// 判断是否是 console.log
if (calleeCode === 'console.log') {
const resArguments = []
// 拿到 console.log 的参数
const nodeArguments = path.node.arguments
for (let i = 0; i < nodeArguments.length; i ++) {
const argument = nodeArguments[i]
// 如果是变量
if (t.isIdentifier(argument)) {
resArguments.push(newLine, t.stringLiteral(`${argument.name}=`), argument)
// resArguments.push(generateStrNode(generater.default(argument).code), argument, splitNode)
} else {
resArguments.push(newLine, argument)
}
}
// 第一个分隔符需要删除
if (resArguments[0] === newLine) {
resArguments.shift()
}
const {loc} = path.node
if (loc) {
const startLine = loc.start.line
const filePath = dirname.split(nodePath.sep).slice(-2).join('/')
const startLineTipNode = t.stringLiteral(`🚀🚀🚀 ~ 开始,第 ${startLine} 行,目录:${filePath}\n`)
resArguments.unshift(startLineTipNode)
const endLine = loc.end.line
const endLineTipNode = t.stringLiteral(`\n🚀🚀🚀 ~ 结束,第 ${endLine} 行,,目录:${filePath}\n`)
resArguments.push(endLineTipNode)
}
path.node.arguments = resArguments
}
},
}
}
})
const {code} = transform(soureCode, {
plugins: [enhanceLogPlugin],
})
console.log(code)