Skip to content

什么是acorn与babel

在上一篇中,我使用的是babel的解析器实现的找出模块中导出的变量的值。我也特别介绍了,新版本的babel底层换成了acorn这个库。

那么,我们就用acorn的相关库,实现同一个需求。

在上文中我已经提到了@babe/parser@babel/traverse这两个库,在下文中我以parser和traverse代指这两个库。

acorn中,以acornwalk代指acornacorn-walk

对应的,还是以下两种解法,解法一:

源码地址: https://github.com/stack-wuh/mini-cli/blob/main/core/babel-export/mixin.js

javascript
import fsp from 'fs/promises'
import * as acorn from 'acorn'
import * as walk from 'acorn-walk'

const filePath = './export.js'

/**
 * @NOTE 这里是acorn版本的解析器
 * @NOTE 对解析出来的AST对象进行取值
 */
const workflow = async () => {
  const source = await fsp.readFile(filePath, { encoding: 'utf-8' })

  const ast = acorn.parse(source, { sourceType: 'module' })
  const { body } = ast

  const exportNamed = {}
  body.filter(node => node.type === 'ExportNamedDeclaration').forEach(node => {
    const [head] = node.declaration.declarations

    exportNamed[head.id.name] = true
  })

  console.log('======> workflow.exportNamed', exportNamed)
}

workflow()

解法二:

javascript
/**
 * @NOTE 使用acorn解析ast
 * @NOTE 使用acorn-walk 实现节点的遍历
 */
const workflowWithWalk = async () => {
  const source = await fsp.readFile(filePath, { encoding: 'utf-8' })

  const ast = acorn.parse(source, { sourceType: 'module' })

  const exportNamed = {}

  walk.simple(ast, {
    ExportNamedDeclaration: node => {
      const [head] = node.declaration.declarations
      exportNamed[head.id.name] = true
    }
  })

  console.log('=====> workflowWithWalk.exportNamed', exportNamed)
}

workflowWithWalk()

可以与babel版本的代码相对比一下,其实差异真的不太大,无非了换了使用的库和api。

请注意, acorn-walk 可以遍历任何 AST 树,不一定非要是 Acorn 创建的 AST。如果您仅需要遍历 AST树,或在没有Babel的情况下使用Acorn,那么使用Acorn-walk是一种很好的遍历器选择。

我们从官网上了解到了这一个AST的遍历器非常厉害,可以遍历一切AST对象。还记得我们上一篇中对比节点类型的表格吗?babelacorn遍历的部分用到的节点类型是一样的,有一个非常好的例子就是Literal,这个节点的类型不一样。

我们先试着用walk去遍历由babel解析出来的AST对象。果然,没那么简单,还是有兼容性的问题。还记得前面对照表里的Literal吗?

acornLiteral,而在babel里面是NumberLiteral,可以去看下我的export.js文件,里面声明了一个数字类型的变量是没有导出的,所以问题就是这两个解析器之间对字面量类型的解析token有兼容性问题。

image-20230402181606293

注意

  1. 这里这个问题先放在这里,随着后面的学习,试着把这个问题解决一下;

MIT License.