babel
babel的原理
1、parse:把代碼變成AST
2、traverse:遍歷AST進(jìn)行修改;
3、generate:把AST變成代碼2
看下AST到底是什么東西
node -r ts-node/register --inspect-brk xxx.ts: 加上--inspect-brk就可以用Chrome 開(kāi)發(fā)者工具來(lái)調(diào)試 Node 程序;不加--inspect-brk就直接運(yùn)行在終端里;
這時(shí)直接打開(kāi)一個(gè)控制臺(tái),等一下,就會(huì)看到左邊出現(xiàn)nodejs的logo,點(diǎn)擊它,得到圖1,已經(jīng)翻譯成js代碼了;

圖1.png

AST.png

圖2.png

圖3.png
根據(jù)上面幾張圖,我們可以大概知道AST是怎么來(lái)存儲(chǔ)值的了;
把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'}) //這一步會(huì)得到一個(gè)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
這時(shí)我們?cè)倏磒arse>traverse>generate這三步,大概就明白是什么意思了;
那可以把代碼自動(dòng)轉(zhuǎn)成es5嗎
答:當(dāng)然可以,使用@babel/core和 @babel/preset-env 即可
- 上面我們把let變成var是通過(guò)
@babel/traverse的traverse先對(duì)AST進(jìn)行遍歷修改,再通過(guò)@babel/generator的generate把修改后的AST變成代碼; - 這次試驗(yàn)中,我們就不單獨(dú)使用
@babel/traverse和@babel/generator了,我們使用@babel/core,它里面包含了traverse和generate的功能; -
@babel/preset-env的功能是把代碼從es6變成es5; - 下圖中
babel.transformFromAstSync()可以把AST變成代碼,相當(dāng)于traverse和generate兩個(gè)步驟了;
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'}) //這一步會(huì)得到一個(gè)AST
const result = babel.transformFromAstSync(ast, code, {
presets: ['@babel/preset-env']
})
fs.writeFileSync('./test.es5.js', result.code)
分析index.js中的依賴
- 怎么去識(shí)別import呢,通過(guò)AST的
item.node.type === 'ImportDeclaration'
遞歸地分析嵌套依賴
總結(jié)
AST相關(guān)
1、parse:把代碼變成AST;
2、traverse:遍歷AST進(jìn)行修改;
3、generate:把AST變成代碼2;
工具
使用babel可以把一些高級(jí)代碼翻譯成es5
- @babel/parser
- @babel/traverse
- @babel/generator
- @babel/core 它包含前面三個(gè)
- @babel/preset-env 內(nèi)置了很多規(guī)則
代碼技巧
- 使用哈希表來(lái)存儲(chǔ)數(shù)據(jù)(哈希表是數(shù)據(jù)結(jié)構(gòu)中的術(shù)語(yǔ),在JS中一個(gè)對(duì)象可以看成是一個(gè)哈希表);
- 通過(guò)檢測(cè)key來(lái)避免重復(fù)記錄依賴;
循環(huán)依賴
- 循環(huán)依賴就是a.js引用了b.js,b.js又引用了a.js,就這么一直循環(huán)下去....
- 有的循環(huán)依賴可以正常執(zhí)行;
- 有的循環(huán)依賴不可以;
- 但是都可以做靜態(tài)分析(靜態(tài)分析:不需要執(zhí)行代碼,只去做字面上的分析);

image.png