Open MrSeaWave opened 3 years ago
babel是一个javascript编译器,用来将es6语法编译成es5。
通过解析器babylon将代码解析成抽象语法树。
通过babel-traverse plugin对抽象语法树进行深度优先遍历,遇到需要转换的,就直接在AST对象上对节点进行添加、更新及移除操作,比如遇到箭头函数,就转换成普通函数,最后得到新的AST树。
通过babel-generator将AST树生成es5代码。
我们需要知道 3 个 Babel 处理流程中的重要工具;
解析
Babylon是一个解析器,它可以将javascript字符串,转化为更加友好的表现形式,称之为抽象语法树;
在解析过程中有两个阶段:词法分析和语法分析,
转换
babel-traverse 模块允许你浏览、分析和修改抽象语法树(AST Abstract Syntax Tree)
Babel接收解析得到的AST并通过babel-traverse对其进行深度优先遍历,在此过程中对节点进行添加、更新及移除操作。
生成
babel-generator 模块用来将转换后的抽象语法树(AST Abstract Syntax Tree)转化为Javascript 字符串
将经过转换的AST通过babel-generator再转换为js代码,过程及时深度遍历整个AST,然后构建转换后的代码字符串。
babel 在处理一个节点时,是以访问者的形式获取节点的信息,并进行相关的操作,这种操作是通过visitor对象实现的。
在 visitor 中定义了处理不同节点的函数。
visitor: {
Program: {
enter(path, state) {
console.log('start processing this module...');
},
exit(path, state) {
console.log('end processing this module!');
}
},
ImportDeclaration:{
enter(path, state) {
console.log('start processing ImportDeclaration...');
// do something
},
exit(path, state) {
console.log('end processing ImportDeclaration!');
// do something
}
}
}
每一个含有type属性的对象,我们称之为节点,修改是指获取对应的类型并修改改节点的属性即可;
{
"type": "Program",
"body": [
{
"type": "VariableDeclaration",
"declarations": [
{
"type": "VariableDeclarator",
"id": {
"type": "Identifier",
"name": "answer"
},
"init": {
"type": "BinaryExpression",
"operator": "*",
"left": {
"type": "Literal",
"value": 6,
"raw": "6"
},
"right": {
"type": "Literal",
"value": 7,
"raw": "7"
}
}
}
],
"kind": "var"
}
],
"sourceType": "script"
}
查看遍历过程:
const esprima = require("esprima");
const estraverse = require("estraverse");
let code = "var answer=6 * 7";
// 遍历语法树
estraverse.traverse(esprima.parseScript(code), {
enter(node) {
console.log("enter", node.type);
},
leave(node) {
console.log("leave", node.type);
}
});
const esprima = require("esprima");
const estraverse = require("estraverse");
const escodegen= require("escodegen");
let code = "var answer=6 * 7";
let tree=esprima.parseScript(code); // 生成语法树
// 遍历语法树
estraverse.traverse(tree, {
enter(node) {
console.log("enter", node.type);
// 修改变量名
if(node.type==='VariableDeclarator'){
node.id.name='result';
}
},
leave(node) {
console.log("leave", node.type);
}
});
// 编译修改后的语法树;
let compileTreeJS=escodegen.generate(tree);
console.log(compileTreeJS);
var result=6 * 7
通过工具了解抽象语法树在 JavaScript 中的体现以及在 NodeJS 中用于生成、遍历和修改 AST 抽象语法树的核心依赖;让我们有了更加深刻地认识;
配置文件的加载顺序
babel解析过程
@babel/cli 读取配置文件, 获取要编译的文件
解析式babel.config.js配置文件
@babel/core 根据解析的配置文件加载编译,
遍历要解析的文件集,