Babel is a JavaScript compiler. Babal 是一个 JavaScript 编译器。
Babel工作流
AST
// 举个例子
let a = 7;
// 转化成
{
"type": "Program",
"start": 0,
"end": 193,
"body": [
{
"type": "VariableDeclaration",
"start": 181,
"end": 191,
"declarations": [
{
"type": "VariableDeclarator",
"start": 185,
"end": 190,
"id": {
"type": "Identifier",
"start": 185,
"end": 186,
"name": "a"
},
"init": {
"type": "Literal",
"start": 189,
"end": 190,
"value": 7,
"raw": "7"
}
}
],
"kind": "let"
}
],
"sourceType": "module"
}
解析流程
@babel/parser
解析
- Lexical analysis 词法分析
Transform the input source code into a list of tokens
var a = 7;
1. Keyword var
2. Identifier a
3. Punctuator =
4. Literal 7
5. Punctuator ;
Report errors about invalid literals or characters
Unterminated comment /* var a = 7;
Unexpexted character '˚' var a = 7˚
Expected number in radix 2 var a = 0b20;
- Syntax analysis
Transform the list of tokens into an AST
var a = 7;
{
"type": "Program",
...
"body": [
{
"type": "VariableDeclaration",
...
"declarations": [
{
"type": "VariableDeclarator",
...
"id": {
"type": "Identifier",
...
"name": "a"
},
"init": {
"type": "Literal",
...
"value": 7,
"raw": "7"
}
}
],
"kind": "var"
}
],
"sourceType": "module"
}
Handle automatic semicolon insertion (ASI)
var a = foo var a = foo;
foo.forEach(fn) foo.forEach(fn);
var a = foo var a = foo[7].forEach(n);
[7].forEach(fn)
Report errors about misplaced tokens
Unexpected token, expexted ")" var a = double(7;
Unexpected keyword 'if' 1 + if;
- Semantic analysis
Check the AST respects all ths static ECMAscript rules: early errors
Redefinition of __proto__ property
({
__proto__: x,
__proto__: y,
})
'with' in strict mode
"use strict";
with (obj) {}
Report errors about invalid variables, using a scope tracker
Identifier ‘foo’ has already been declared
let foo = 2;
let foo = 3;
Export ‘bar’ is not defined
{let bar = 2}
export {bar}
@babel/traverse
转换
- Declarative traversal
Algorithm: Depth-fist search, in-order(enter) and out-order(exit)
traverse(ast, {
CallExpression: {
enter() { <--------------- enter is the default traversal order
console.log("Function call!")
}
}
})
Dynamic Abstract Syntax Tree
Scope analysis
let MAX = 5;
export function isValid(val, big) {
if (big) {
const MAX = 10;
return val < MAX;
}
MAX += 1;
return val < MAX;
}