编译流程
parse
通过parse 转成AST语法树。 具体是把源代码转成转成机器能够理解的AST,这个过程分为词法分析、 语法分析
词法分析
我们要源码把它分成一个个不能细分的单词(token)的过程称为词法分析
语法分析
我们把token 进行递归的组装,生成AST的过程称为词法分析
AST
parse的API
- @babel/parser
示例
const parser = require('@babel/parser');
const ast = parser.parse(sourceCode, {
sourceType: 'unambiguous', // "script" | "module" | "unambiguous"
plugins: ['jsx']
});
-
sourceType的属性值
unambiguous:根据据内容是否有 import 和 export 来确定是否解析 es module 语法module: module 是解析 es module 语法script: 其他都是script -
plugins
如果要解析tsx 模块,那么可以这样来写
require("@babel/parser").parse("code",
{ sourceType: "module",
plugins: [ "jsx", "typescript" ]
})
- parse 类型声明
export function parse(
input: string,
options?: ParserOptions
): ParseResult<import("@babel/types").File>;
transform
遍历AST,调用transform的各种API进行增删改查,遍历的过程中处理到不同的 AST 节点会调用注册的相应的 visitor 函数,visitor 函数里可以对 AST 节点进行增删改
transform的API
- @babel/traverse: 遍历 AST
traverse(ast, {
CallExpression:{
enter(path,state){}
}
}
});
traverse(ast, {
CallExpression(path, state) {
...
}
}
});
上面两者等价
- @babel/types: 遍历 AST 的过程中需要创建一些 AST 和判断 AST 的类型
const types = require('@babel/types');
traverse(ast, {
CallExpression(path, state) {
if ( types.isMemberExpression(path.node.callee)) {
}
}
});
- @babel/template: 简化 AST 创建逻辑
可以遍历 AST,并调用 visitor 函数修改 AST,修改 AST 自然涉及到 AST 的判断、创建、修改等, 这时候就需要 @babel/types 了,当需要批量创建 AST 的时候可以使用 @babel/template 来简化 AST 创建逻辑
generate
把AST生成目标代码,并且转换成sourcemap
generate的API
- @babel/generate: 把 AST 打印为目标代码字符串,同时生成 sourcemap
function (ast: Object, opts: GeneratorOptions, code: string): {code, map}
类型声明
export default function generate(
ast: t.Node,
opts?: GeneratorOptions,
code?: string | { [filename: string]: string },
): GeneratorResult;
options 中常用的是 sourceMaps,开启了这个选项才会生成 sourcemap
const { code, map } = generate(ast, { sourceMaps: true })
- @babel/code-frame: 中途遇到错误想打印代码位置的时候
const result = codeFrameColumns(rawLines, location, {
/* options */
});
@babel/core
基于上面的包完成 babel 整体的编译流程
const { transformFileSync } = require('@babel/core');
transformSync(code, options); // => { code, map, ast } transformFileSync(filename, options); // => { code, map, ast } transformFromAstSync
总结
babel 编译的三个阶段以及每个阶段对应的API
| stage | 名称 | 释义 | 相关的API | 核心的点 |
|---|---|---|---|---|
| stage1 | parse | 转成AST语法树 | @babel/parser | 词法分析(分词)、语法分析(组装AST) |
| stage2 | transform | 遍历AST,调用transform的各种API进行增删改查 | @babel/traverse 、@babel/template、@babel/types | path、scope、visitor |
| stage3 | generate | 生成sourcemap | @babel/code-frame、@babel/generate | generator、sourcemap |
整体能通过@babel/core完成编译的流程
以上提到的api都是tooling packages, 这里再提一下 babel 还有Integration Packages