【前端】esbuild简单介绍

概念

esbuild 是一个 JavaScript 构建工具,以高效的方式打包、压缩、转换 JavaScript 代码,并且支持 js、ts、jsx、tsx、css、less、scss 等多种文件类型。esbuild 有着极快的构建速度和低的构建内存占用,是目前业内最受欢迎的 JavaScript 构建工具之一。目前已知vite采用esbuild作为js/ts处理工具。

  • 同类工具: js写的babel, rust写的swc

机构

在 esbuild 的源码中,主要有以下几个文件夹:

  • internal:esbuild 的内部核心代码,包括 lexer、parser、resolver、printer、sourcemap 等模块;
  • runtime:esbuild 构建后的运行时代码,可以用于代码分割等功能;
  • snapshot:一个用于加速部分操作的快照编译器;
  • test:esbuild 的测试用例;
  • third_party:esbuild 依赖的第三方库,包括 acorn、glob、- source-map 等;
  • vendor:esbuild 依赖的一些工具库,如 Go 语言实现的 minifier。
    在解析 esbuild 源码之前,需要先了解 esbuild 构建流程的基本原理。esbuild 的构建流程主要分为三个步骤:

语法分析

词法分析和语法解析(Lexer & Parser):esbuild 分别使用了 acorn 和 TypeScript 作为 JavaScript 和 TypeScript 代码的解析器,通过 lexer 将源码逐个字符逐个字符识别出来,并通过 parser 将其转换为语法树;
转换和处理(Transform):esbuild 根据传递的各种参数,对语法树进行转换和处理,例如将 ES6 模块转换为 CommonJS、对 JSX 进行转换、添加 Polyfill 等操作;
输出到文件(Printer):esbuild 将处理后的语法树转换为 JavaScript 代码,并输出到指定的文件中,还会生成 Sourcemap 以支持代码调试。
在构建流程中,esbuild 的核心处理都在 internal 目录中实现。下面将逐一介绍 internal 下的核心代码。

1. lexer

lexer 主要是用于将源码分词,分析出每一个 token。esbuild 中使用了 acorn 作为 JavaScript 代码的解析器,可以将源码转换为语法树,而 acorn 就是通过 lexer 实现的。lexer 可以识别各种不同类型的 token,包括数字、字符串、布尔值、标识符、关键字等。每个 token 都有自己的类型和值,例如:

{
  type: TokenType.NUMBER,
  value: '100'
}
{
  type: TokenType.BRACKET_OPEN,
  value: '('
}
{
  type: TokenType.KEYWORD,
  value: 'if'
}
{
  type: TokenType.STRING,
  value: 'hello, world!'
}

2. parser

parser 主要是将分词后的 token 转换为语法树。esbuild 中使用了 TypeScript 作为 TypeScript 代码的解析器,可以将源码转换为语法树,而在 JavaScript 代码的解析中,esbuild 则是通过 acorn 实现的。语法树是一种数据结构,可以将代码以对象的形式表示出来,方便进行二次处理。例如下面这段代码:

let a = 123;
console.log(a);
可以被解析为以下语法树:

{
“type”: “Program”,
“sourceType”: “script”,
“body”: [
{
“type”: “VariableDeclaration”,
“kind”: “let”,
“declarations”: [
{
“type”: “VariableDeclarator”,
“id”: {
“type”: “Identifier”,
“name”: “a”
},
“init”: {
“type”: “Literal”,
“value”: 123,
“raw”: “123”
}
}
]
},
{
“type”: “ExpressionStatement”,
“expression”: {
“type”: “CallExpression”,
“callee”: {
“type”: “MemberExpression”,
“computed”: false,
“object”: {
“type”: “Identifier”,
“name”: “console”
},
“property”: {
“type”: “Identifier”,
“name”: “log”
}
},
“arguments”: [
{
“type”: “Identifier”,
“name”: “a”
}
]
}
}
]
}

3. resolver

resolver 主要用于解析和处理代码中的引用关系,包括通过 import 引入的模块、require() 引入的模块、两者之间的转换等。resolver 是在语法树转换的过程中执行的,可以对语法树进行修改和调整,例如 ES6 模块转换为 CommonJS。在 resolver 中,esbuild 还实现了常见的 Node.js 模块解析规则,以支持文件扩展名、查找 node_modules 等功能。

4. transform

transform 主要用于将 ES6 和 TypeScript 的语法转换为 ES5,并添加 Polyfill 等操作。在 transform 中,esbuild 提供了各种插件,可以将 React JSX 语法转换为 JavaScript、将 TypeScript 转换为 JavaScript、压缩代码等。用户也可以自定义 transform 插件,针对不同的项目需求进行定制化处理。

5. printer

printer 主要用于将语法树转换为 JavaScript 代码,并输出到指定的文件中。在输出 JavaScript 代码时,esbuild 还会生成 Sourcemap 以支持调试。Sourcemap 是一种映射关系,可以将编译后的代码映射回源代码,方便开发者进行代码调试。

other

除了上述几个核心模块之外,在 esbuild 的源码中还包括了各种工具函数、辅助函数等。例如:

logger:在控制台输出调试信息的工具函数;
util:一些基本的工具函数,如字符串操作、路径操作、文件操作等;
glob:类似于文件系统的 Glob 模式匹配工具函数;
source-map:生成 Sourcemap 的工具函数。

结语

看了跟没看一样,没啥干货。

  • 21
    点赞
  • 20
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值