Skip to content

开发 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)

Released under the MIT License.