深入webpack之babel 与 AST

babel的原理

  • parse:把代码code变成AST
  • traverse:遍历AST进行修改
  • generate:把AST变成代码code2
    即 code -> ast -> ast2 -> code2

示例:手动把let变成var

import { parse } from "@babel/parser" // 把代码`code`变成`AST`
import traverse from "@babel/traverse" // 遍历AST
import generate from "@babel/generator" // 把`AST`变成代码`code2`

const code = `let a = 'let'; let b = 2`
const ast = parse(code, { sourceType: 'module' })
traverse(ast, {
  enter: item => {
    if(item.node.type === 'VariableDeclaration'){
      if(item.node.kind === 'let'){
        item.node.kind = 'var'
      }
    }
  }
})
const result = generate(ast, {}, code)
console.log(result.code)

在Chrome运行TS代码:node -r ts-node/register --inspect-brk xxx.ts

先打印看看ast是什么:

AST对象

从ast对象的属性中,可以看到这个program就是上面code这段代码的程序,程序的body里有两个节点:

// const code = `let a = 'let'; let b = 2`
let a = 'let' // 节点1
let b = 2 // 节点2

再看一下这些节点都包含哪些属性,重点关注这三个属性

...
// 声明的节点信息
declarations: [Node]
// 变量声明的关键字是let
kind: "let"
// 类型,说明是一个变量声明
type: "VariableDeclaration"
...

// declarations是一个节点数组,因为可以同时声明多个节点
// let a = 'let'
// name为a的标识符,对应初始值value是'let',类型是字符串
declarations: [
    0: Node
        {
            id: {
                ...,
                name: "a",
                type: "Identifier"
            },
            init: {
                ...,
                value: "let",
                type: "StringLiteral"
            }
    },
    length: 1
]

所以说AST就是用来将源代码字符串,表示成一个树形结构

// traverse用来遍历AST,可以对AST进行修改
traverse(ast, {
// 每进入一个节点,就执行item=>{}函数
  enter: item => {
    ...
  }
})

这样看来,将let变成var就水到渠成了

traverse(ast, {
  enter: item => {
    if(item.node.type === 'VariableDeclaration'){ // 如果是变量声明
      if(item.node.kind === 'let'){ // 如果是let声明
        item.node.kind = 'var' // 将let改成var
      }
    }
  }
})

再使用generate函数将新的AST翻译成code

const result = generate(ast, {}, code) // 传入修改后的ast,还有原始code
console.log(result.code) // 得到新的code

运行后就得到了

var a = 'let';
var b = 2;

为什么要用AST

  • 你很难用正则表达式去替换,正则很容易把let a = 'let'变成var a = 'var'
  • 你需要识别每个单词的意思,才能做到只修改用于变量声明的let
  • 而AST能明确告诉你每个let的意思

下篇《如何将代码转为ES5》

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Babel babel 的原理 parse: 把代码 code 变成 ASTtraverse: 遍历 AST 进行...
    sweetBoy_9126阅读 754评论 0 1
  • babel 与 AST 先从Babel 说起 babel 的原理1、parse:把代码 code 变成 AST2、...
    littleyu阅读 991评论 0 1
  • babel 原理 parse: 把原始代码 code 变成 AST traverse: 遍历 AST 进行修改 g...
    我是Msorry阅读 409评论 0 0
  • 友情链接 说一说从 URL 输入到页面呈现到底发生了什么? 平安金服面试官:从 new 一个 Vue 对象开始.....
    旭哥_阅读 2,011评论 0 2
  • 表情是什么,我认为表情就是表现出来的情绪。表情可以传达很多信息。高兴了当然就笑了,难过就哭了。两者是相互影响密不可...
    Persistenc_6aea阅读 126,051评论 2 7