FE

Babel

Babel

Posted by nolan on June 28, 2021

应用

  • 转译 ESNext、Typescript、JSX 等到目标环境支持的 JS;
  • 函数插桩、埋点代码;
    • Babel 暴露了很多 api, 用这些 api 可完成代码到 AST 的解析、转换及目标代码的生成;
    • 比如。小程序跨平台框架 Taro 就是基于 Babel 的 api 实现;
  • 代码静态分析;
    • linter 工具就是分析 AST 结构,对代码规范进行检查;
    • Api 文档自动生成工具,提取源码中注释,生成文档;
    • 依赖关系分析,根据 AST 进行模块遍历;
    • 压缩混淆工具,分析代码结构,删除死代码、变量名混淆等优化;

处理过程

  • parse (@babel/parser)
    • 将代码解析生成抽象语法树(AST),即词法分析和语法分析
  • transform(@babel-traverse)
    • 遍历 AST,并调用 transform 插件进行增删改
  • generate(@babel-generator)
    • 将变换后的 AST 打印成 JS 代码
    • 生成 sorce map

image

babel 源码核心包

@babel/core

是‘微内核’架构中的‘内核’。对于 Babel 来说,这个内核主要干这些事情:

  • 加载和处理配置(config)
  • 加载插件
  • 调用 Parser 进行语法解析,生成 AST
  • 调用 Traverser 遍历 AST,并使用访问者模式应用’插件’对 AST 进行转换
  • 生成代码,包括 SourceMap 转换和源代码生成

Parser(@babel/parser)

将源代码解析为 AST 就靠它了。 它已经内置支持很多语法. 例如 JSX、Typescript、Flow、以及最新的 ECMAScript 规范。目前为了执行效率,parser 是不支持扩展的,由官方维护。

Traverser(@babel/traverse)

实现了访问者模式,对 AST 进行遍历,转换插件会通过它获取感兴趣的 AST 节点,对节点继续操作。

Generator(@babel/generator)

将 AST 转换为源代码,支持 SourceMap

babel 插件

解析阶段插件(@babel/plugin-syntax-*)

语法插件,上面说了 @babel/parser 已经支持了很多 JavaScript 语法特性,Parser 也不支持扩展. 因此 plugin-syntax-*实际上只是用于开启或者配置 Parser 的某个功能特性

转换阶段插件

用于对 AST 进行转换, 实现转换为 ES5 代码、压缩、功能增强等目的. Babel 仓库将转换插件划分为两种(只是命名上的区别):

  • @babel/plugin-transform-*: 普通的转换插件
  • @babel/plugin-proposal-*: 还在’提议阶段’(非正式)的语言特性

预定义集合(@babel/presets-*)

插件集合或者分组,主要方便用户对插件进行管理和使用。比如 preset-env 含括所有的标准的最新特性; 再比如 preset-react 含括所有 react 相关的插件.

如何写一个 babel 插件

  • 插件原理
    • babel 解析成 AST,然后插件更改 AST,最后由 babel 输出代码
  • 编写一个 babel 插件

    • 插件就是一个被暴露出来的 function,函数内返回 visitor
    module.exports = funciton(babel){
        return {
            visitor: {}
        }
    }
    
    • visitor 是对各类型的 AST 节点做处理的地方