Babel 的原理
作者:HZFEStudio
来源:SegmentFault 思否社区
完整高频题库仓库地址:
https://github.com/hzfe/awesome-interview
完整高频题库阅读地址:
http://febook.hzfe.org/awesome-interview/
相关问题
Babel 是什么
Babel 有什么用
压缩代码如何实现
回答关键点
JS 编译器
AST
插件系统
知识点深入
1. AST 抽象语法树
const custom = "HZFE";
2. Babel 编译流程
三大步骤
解析阶段:Babel 默认使用 @babel/parser 将代码转换为 AST。解析一般分为两个阶段:词法分析和语法分析。
词法分析:对输入的字符序列做标记化(tokenization)操作。 语法分析:处理标记与标记之间的关系,最终形成一颗完整的 AST 结构。 转换阶段:Babel 使用 @babel/traverse 提供的方法对 AST 进行深度优先遍历,调用插件对关注节点的处理函数,按需对 AST 节点进行增删改操作。
生成阶段:Babel 默认使用 @babel/generator 将上一阶段处理后的 AST 转换为代码字符串。
3. Babel 插件系统
常见 presets
@babel/preset-env
@babel/preset-typescript
@babel/preset-react
@babel/preset-flow
编写 Babel 插件
module.exports = function () {
return {
pre() {},
// 在 visitor 下挂载各种感兴趣的节点类型的监听方法
visitor: {
/**
* 对 Identify 类型的节点进行处理
* @param {NodePath} path
*/
Identifier(path) {
path.node.name = path.node.name.toUpperCase();
},
},
post() {},
};
};
// input
// index.js
function hzfe() {}
// .babelrc
{
"plugins": ["babel-plugin-yourpluginname"]
}``````
// output
function HZFE() {}
深入 Babel 转换阶段
interface Plugin {
key: string | undefined | null;
post: Function | void;
pre: Function | void;
visitor: Object;
parserOverride: Function | void;
generatorOverride: Function | void;
// ...
}
执行所有插件的 pre 方法。
按需执行 visitor 中的方法。
执行所有插件的 post 方法。
// 书写插件时的 visitor 结构
interface VisitorInPlugin {
[ASTNodeTypeName: string]:
| Function
| {
enter?: Function;
exit?: Function;
};
}
// babel 最终整合的 visitor 结构
interface VisitorInTransform {
[ASTNodeTypeName: string]: {
// 不同插件对相同节点的处理会合并为数组
enter?: Function[];
exit?: Function[];
};
}
参考资料
AST:https://en.wikipedia.org/wiki/Abstract_syntax_tree
Babel-handbook:https://github.com/jamiebuilds/babel-handbook
estree:https://github.com/estree/estree
访问者模式:https://en.wikipedia.org/wiki/Visitor_pattern
评论