Babel-handbook插件
babelcompiler bundlertool
Babel
作为source to source
的转换编辑器(transpiler)转换过程主要分为三步:
- parse: 通过
parser
把源码转换成抽象语法树(AST
),词法分析根据规则拆分成各个token
再通过语法分析将token
递归组装成可用的AST
- transform: 通过相应
visitor
函数遍历AST
调用各种transform
插件对AST
进行操作修改
- generate: 把转换后的
AST
生成对应结构的字符串并拼接还会并生成sourcemap
处理过程中每一步都涉及到创建或是操作抽象语法树,babel使用基于ESTree标准的ast
js
function square(n) {
return n * n;
}
解析后的ast如下:
json
{
type: "FunctionDeclaration",
id: {
type: "Identifier",
name: "square"
},
params: [{
type: "Identifier",
name: "n"
}],
body: {
type: "BlockStatement",
body: [{
type: "ReturnStatement",
argument: {
type: "BinaryExpression",
operator: "*",
left: {
type: "Identifier",
name: "n"
},
right: {
type: "Identifier",
name: "n"
}
}
}]
}
}
每个层级都有相同的结构:
json
{
type: "FunctionDeclaration",
id: {...},
params: [...],
body: {...}
}
json
{
type: "Identifier",
name: ...
}
json
{
type: "BinaryExpression",
operator: ...,
left: {...},
right: {...}
}
节点类型包括:
Literals
Programs
Functions
Statements
Declarations
Misc
Expressions
Template Literals
Patterns
Patterns
Classes
Modules
具体构成及说明文档位于@babel/parser ast specification
json
{
type: ...,
start: 0,
end: 38,
loc: {
start: {
line: 1,
column: 0
},
end: {
line: 3,
column: 1
}
},
...
}
js parser历史:
SpiderMonkey的AST标准esprima,后来形成了estree标准
accorn也是estree标准但是比esprima更快而且支持插件对语法进行扩展
eslint的espree源自esprima但是espree2.0基于accron重新实现也适用accorn的插件机制扩展语法
babel parser(babylon)在accorn的基础上对AST节点和属性做了扩展
通过@babel/parser
将源码解析(词法分析、语法分析)为ast
,具体options配置项决定产出形式
js
require('@babel/parser').parse("soucecode", {
sourceType: 'module',
plugins: [
'jsx'
]
})
通过@babel/traverse
进行遍历ast
节点进行增删改,在遍历过程中通过访问者模式(visitor)
对指定的节点类型例如:FunctionDeclaration进行访问,同时可使用@babel/types
提供的工具函数进行节点判断及生成
ts
interface traverse {
ast: AST
visitor: (path, state) => {}
}
js
traverse(ast, {
FunctionDeclaration: {
enter(path, state) {},
exit(path, state) {}
}
})
traverse(ast, {
FunctionDeclaration(path, state) {}
})
traverse(ast, {
'FunctionDeclaration|VariableDeclaration'(path, state) {}
})
使用@babel/generator
将ast
生成代码字符串
ts
function (ast: Object, opts: Object, code: string): {code, map}
js
import generate from "@babel/generator";
const { code, map } = generate(ast, { sourceMaps: true })
同时可使用@babel/code-frame
在生成过程中打印报错代码位置
js
import { codeFrameColumns } from "@babel/code-frame";
const rawLines = `class Foo {
constructor()
}`;
const location = { start: { line: 2, column: 16 } };
const result = codeFrameColumns(rawLines, location, {
});
console.log(result);
@babel/generator
通过对应AST
的生成方法进行生成
sourcemap
通常用于从目标代码映射到源码位置,具体创建、消费、及源码节点格式可以查看文档