【Webpack】AST、babel、依赖

babel

babel的原理

1、parse:把代码变成AST
2、traverse:遍历AST进行修改;
3、generate:把AST变成代码2

看下AST到底是什么东西

node -r ts-node/register --inspect-brk xxx.ts: 加上--inspect-brk就可以用Chrome 开发者工具来调试 Node 程序;不加--inspect-brk就直接运行在终端里;
这时直接打开一个控制台,等一下,就会看到左边出现nodejs的logo,点击它,得到图1,已经翻译成js代码了;

图1.png

AST.png

图2.png

图3.png

根据上面几张图,我们可以大概知道AST是怎么来存储值的了;

把let变成var

import { parse } from '@babel/parser';
import traverse from '@babel/traverse';
import generate from '@babel/generator';

const code = `let a = 'let'; let b = 5;`
const ast = parse(code, {sourceType: 'module'})  //这一步会得到一个AST

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);
image.png

这时我们再看parse>traverse>generate这三步,大概就明白是什么意思了;

那可以把代码自动转成es5吗

答:当然可以,使用@babel/core@babel/preset-env 即可

  • 上面我们把let变成var是通过@babel/traverse的traverse先对AST进行遍历修改,再通过@babel/generator的generate把修改后的AST变成代码;
  • 这次试验中,我们就不单独使用@babel/traverse@babel/generator了,我们使用@babel/core,它里面包含了traverse和generate的功能;
  • @babel/preset-env的功能是把代码从es6变成es5;
  • 下图中babel.transformFromAstSync()可以把AST变成代码,相当于traversegenerate两个步骤了;
import { parse } from '@babel/parser';
import * as babel from '@babel/core';
import * as fs from 'fs';

const code = fs.readFileSync('./test.js').toString()
const ast = parse(code, {sourceType: 'module'})  //这一步会得到一个AST
const result = babel.transformFromAstSync(ast, code, {
    presets: ['@babel/preset-env']
})

fs.writeFileSync('./test.es5.js', result.code)

分析index.js中的依赖

  • 怎么去识别import呢,通过AST的item.node.type === 'ImportDeclaration'

递归地分析嵌套依赖

总结

AST相关

1、parse:把代码变成AST;
2、traverse:遍历AST进行修改;
3、generate:把AST变成代码2;

工具

使用babel可以把一些高级代码翻译成es5

  • @babel/parser
  • @babel/traverse
  • @babel/generator
  • @babel/core 它包含前面三个
  • @babel/preset-env 内置了很多规则

代码技巧

  • 使用哈希表来存储数据(哈希表是数据结构中的术语,在JS中一个对象可以看成是一个哈希表);
  • 通过检测key来避免重复记录依赖;

循环依赖

  • 循环依赖就是a.js引用了b.js,b.js又引用了a.js,就这么一直循环下去....
  • 有的循环依赖可以正常执行;
  • 有的循环依赖不可以;
  • 但是都可以做静态分析(静态分析:不需要执行代码,只去做字面上的分析);
image.png

你可能感兴趣的:(【Webpack】AST、babel、依赖)