共计 2658 个字符,预计需要花费 7 分钟才能阅读完成。
残缺高频题库仓库地址:https://github.com/hzfe/aweso…
残缺高频题库浏览地址:https://febook.hzfe.org/
相干问题
- Babel 是什么
- Babel 有什么用
- 压缩代码如何实现
答复关键点
JS 编译器
AST
插件零碎
Babel 是 JavaScript 编译器:他能让开发者在开发过程中,间接应用各类方言(如 TS、Flow、JSX)或新的语法个性,而不须要思考运行环境,因为 Babel 能够做到按需转换为低版本反对的代码;Babel 外部原理是将 JS 代码转换为 AST,对 AST 利用各种插件进行解决,最终输入编译后的 JS 代码。
知识点深刻
1. AST 形象语法树
简略定义:以树的模式来体现编程语言的语法结构。
利用在线 playground 调试,能够对 AST 有个直观感触:生成的树有多个节点,节点有不同的类型,不同类型节点有不同的属性。
const custom = "HZFE";
AST 是源代码的高效示意,能便捷的示意大多数编程语言的构造。实用于做代码剖析或转换等需要。之所以用树来进行剖析或转换,是因为树能使得程序中的每一节点恰好被拜访一次(前序或后续遍历)。
常见应用场景:代码压缩混同性能能够借助 AST 来实现:剖析 AST,基于各种规定进行优化(如 IF 语句优化;移除不可拜访代码;移除 debugger 等),从而生成更小的 AST 树,最终输入精简的代码后果。
2. Babel 编译流程
三大步骤
- 解析阶段:Babel 默认应用 @babel/parser 将代码转换为 AST。解析个别分为两个阶段:词法剖析和语法分析。
- 词法剖析 :对输出的字符序列做标记化(tokenization) 操作。
- 语法分析:解决标记与标记之间的关系,最终造成一颗残缺的 AST 构造。
- 转换阶段:Babel 应用 @babel/traverse 提供的办法对 AST 进行深度优先遍历,调用插件对关注节点的处理函数,按需对 AST 节点进行增删改操作。
- 生成阶段:Babel 默认应用 @babel/generator 将上一阶段解决后的 AST 转换为代码字符串。
3. Babel 插件零碎
Babel 的外围模块 @babel/core,@babel/parser,@babel/traverse 和 @babel/generator 提供了残缺的编译流程。而具体的转换逻辑须要插件来实现。
在应用 Babel 时,咱们可通过配置文件指定 plugin 和 preset。而 preset 能够是 plugin 和 preset 以及其余配置的汇合。Babel 会递归读取 preset,最终获取一个大的 plugins 数组,用于后续应用。
常见 presets
- @babel/preset-env
- @babel/preset-typescript
- @babel/preset-react
- @babel/preset-flow
最常见的 @babel/preset-env 预设,蕴含了一组最新浏览器已反对的 ES 语法个性,并且能够通过配置指标运行环境范畴,主动按需引入插件。
编写 Babel 插件
Babel 插件的写法是借助 访问者模式(Visitor Pattern)对关注的节点定义处理函数。参考一个简略 Babel 插件例子:
module.exports = function () {
return {pre() {},
// 在 visitor 下挂载各种感兴趣的节点类型的监听办法
visitor: {
/**
* 对 Identify 类型的节点进行解决
* @param {NodePath} path
*/
Identifier(path) {path.node.name = path.node.name.toUpperCase();
},
},
post() {},
};
};
应用该 Babel 插件的成果如下:
// input
// index.js
function hzfe() {}
// .babelrc
{"plugins": ["babel-plugin-yourpluginname"]
}
``````
// output
function HZFE() {}
深刻 Babel 转换阶段
在转换阶段,Babel 的相干办法会取得一个插件数组变量,用于后续的操作。插件构造可参考以下接口。
interface Plugin {
key: string | undefined | null;
post: Function | void;
pre: Function | void;
visitor: Object;
parserOverride: Function | void;
generatorOverride: Function | void;
// ...
}
转换阶段,Babel 会按以下程序执行。具体逻辑可查看源码:
- 执行所有插件的 pre 办法。
- 按需执行 visitor 中的办法。
- 执行所有插件的 post 办法。
一般来说,写 Babel 插件次要应用到的是 visitor 对象,这个 visitor 对象中会书写对于关注的 AST 节点的解决逻辑。而下面执行程序中的第二步所指的 visitor 对象,是整合自各插件的 visitor,最终造成一个大的 visitor 对象,大抵的数据结构可参考以下接口:
// 书写插件时的 visitor 构造
interface VisitorInPlugin {[ASTNodeTypeName: string]:
| Function
| {
enter?: Function;
exit?: Function;
};
}
// babel 最终整合的 visitor 构造
interface VisitorInTransform {[ASTNodeTypeName: string]: {
// 不同插件对雷同节点的解决会合并为数组
enter?: Function[];
exit?: Function[];};
}
在对 AST 进行 深度优先遍历 的过程中,会创立 TraversalContext 对象来把控对 NodePath 节点的拜访,拜访时调用对节点所定义的解决办法,从而实现按需执行 visitor 中的办法。具体实现请看 babel-traverse 中的源码。
参考资料
- AST
- Babel-handbook
- estree
- 访问者模式