Babel
是什么?
Babel是一个广泛使用的JavaScript编译器,它可以将ES6等高版本的代码转为ES5或更低版本的代码,使他们能够在不同版本的浏览器中运行。
- 兼容性。Babel 能够进行代码的降级转换,使得旧版浏览器也能理解和执行。
- 扩展性。Babel 提供了强大的插件系统,开发者可以通过配置不同的插件来定义代码的转换方式。这种灵活性使得 Babel 特别适用于处理复杂的代码项目。
Babel 能帮助开发者提前尝试使用尚未正式成为规范的 ES 特性,以便评估新特性的价值。
核心模块
- babel/core 负责整体编译流程
- babel/parser 解析源码,经历语法分析、词法分析等生成AST抽象语法树
- babel/generator 将AST再解析为可以为浏览器运行的javaScript代码
编译流程
-
parse
使用 @babel/parser 解析源码,生成AST抽象语法树
-
transform
使用 @babel/traverse 遍历AST抽象语法树,调用 transform 插件对 AST 节点进行增删改等操作生成新的AST
-
generate
@babel/generator 根据转换后的 AST 生成新的代码
用途
- 静态分析。 仅借助AST提供的信息进行分析,不修改AST。比如linter,type checker,code formatter,自动生成api文档等。
- 特定用途代码转换。 借助AST提供的信息进行转换,保持原有AST结构上做部分的增删改。比如函数插桩、删除console、自动国际化等。
- 代码转译。 将浏览器不支持和不兼容的语法进行转换。比如ES新特性、TypeScript。
Babel 插件开发
相关的库
-
@babel/core Babel 的核心 api,包含了上述所提的所有功能,能完成从源码到目标代码的整个编译流程。
-
@babel/parser 默认只能 parse js 代码,支持扩展,通过指定对应语法插件可实现 jsx、ts 等解析。
-
@babel/generator 负责 generate 阶段的包,用于将 AST 转换成新的代码。
-
@babel/traverse 提供 traverse 方法来负责 AST 的遍历,维护了整颗 AST 树的状态。
traverse 针对不同的节点类型提供了不同的 visitor 用于实现对节点的操作。
提示vistor 利用了设计模式的访问者模式(Visitor),用于实现数据结构与数据操作解耦。当被操作的对象结构比较稳定,而操作对象的逻辑经常变化的时候,通过分离逻辑和对象结构,使得他们能独立扩展。
在 Visitor 模式中,数据结构和数据操作分别被封装在不同的类中。我们把数据结构封装在 "Element" 类中,把数据操作封装在 "Visitor" 类中。"Visitor" 类表示一个作用于某对象结构中的各元素操作的封装,其目标是在不改变数据结构的前提下,能随时增加新的操作,即访问者可随时改变操作算法。
-
@babel/types 包含所有 AST 节点的类型以及检查 AST 类型的方法。
插件开发
Babel Plugin 通常有两种格式。
一种是对象,对象中包含 visitor、pre、post 等属性。
另一种是函数,返回一个包含 visitor、pre 等属性的对象。函数格式可以接受三个参数,分别为 api:提供 babel 基础 api 能力、options:外界传入插件的参数、dirname:目录名。
export default plugin = {
pre() {}, // 遍历前触发的钩子函数
visitor: {},//
post(file) {}, // 遍历后触发的钩子函数
};
export default function plugin(api, options, dirname){
return {
pre(){},
visitor: {},
post(){}
}
}
插件开发逻辑:对比前后AST,找出节点变化处。分析节点与逻辑,生成新的AST。
常用 plugin 和 present
present: 一些plugin组成的合集,整合成的一个包,方便做一个预设。
常见present:
-
babel-preset-env 内部集成了绝大多数plugin(State > 3)的转译插件,将高版本js进行转移为低版本js。
-
babel-preset-react 对jsx进行转译。
-
babel-preset-typescript 编译ts为js。
其他编译ts的方式:tsc命令,结合cli命令行或者tsconfig配置文件进行编译。
常见plugin:plugin list
绝大多数被集成进babel-preset-env
- @babel/plugin-transform-object-rest-spread 用于处理对象的扩展运算符。
- @babel/plugin-transform-optional-chaining 用于处理可选链运算符。
- @babel/plugin-transform-nullish-coalescing-operator 用于处理空值。
Babel vs SWC
无论是Babel还是SWC,它们都是服务于JavaScript代码的工具,其目标都是使JavaScript代码更加易于编写、阅读和维护。然而,它们实现这一目标的方式略有不同。
SWC
SWC是基于Rust语言开发的高性能的JavaScript编译器,旨在与现有的工具集(如webpack、Rollup、Parcel等)集成。目标是提高编译速度和代码执行速度。
有插件体系,但不支持JavaScript插件,插件需要通过Rust/WebAssembly实现。