uniapp 29 Terser 和 esbuild
一、Terser
Terser 是一个用于压缩和混淆 JavaScript 代码的工具,能显著减小文件体积,让网页加载更快。
它主要通过三个步骤实现优化:压缩变量名、删除空格和注释、移除未使用的代码,并支持 ES6+ 语法。
官网:https://terser.org
中文网:https://terser.nodejs.cn
🛠️ 安装与使用
- 安装:通过 npm 安装,
npm install terser -g全局安装,或项目本地安装npm install terser。 - 基础命令:
terser input.js -o output.min.js压缩文件;加-c开启压缩,-m开启变量名混淆,可组合使用。 - 进阶配置:支持属性混淆(
--mangle-props)、定义全局常量(--define)、生成源映射(--source-map)等,也可通过配置文件定制压缩策略。
⚠️ 需要注意的点
Terser 压缩时可能改变代码行为。有研究显示,某些边缘写法(如 0 in 1)会被错误判断为无副作用而删除,导致压缩后程序逻辑与源码不一致。 构建产物建议单独跑一遍冒烟测试,不能只跑源码测试,并固定工具版本。
Terser 是从无人维护的 UglifyJS{id="entity_1"} 分叉而来,目前是 webpack{id="entity_2"} 默认使用的压缩工具。
二、esbuild
esbuild 是一款基于 Go 语言开发的极速 JavaScript 打包和压缩工具,由 Figma 的 CTO Evan Wallace 创建,主要用作前端项目的构建工具,能在秒级完成大型代码库的打包任务 。
核心功能与用途
1. 主要功能: esbuild 提供代码打包、压缩混淆、Tree shaking(删除未使用代码)、源映射生成等核心功能,内置支持 TypeScript、JSX、CSS 等多种文件格式,无需额外配置即可开箱即用 。
- 打包功能:将多个模块文件合并为单个输出文件,支持 ES6 和 CommonJS 模块。
- 压缩功能:移除空格、缩短标识符、优化语法,减小输出文件体积。
- 类型支持:直接解析 TypeScript 和 JSX 语法,无需先转换为 JavaScript。
2. 使用场景: 适合作为底层打包工具被其他构建工具调用,如 Vite、Snowpack、SvelteKit、Remix Run 等现代前端框架均在其底层使用 esbuild 。 - 开发环境:配合 watch 模式实现文件变更自动重建。
- 生产环境:用于快速生成压缩后的生产包。
- 不适用于:需要热模块替换(HMR)、模块联邦、语法降级到 ES5 的场景。
3. 与竞品对比: 相比 Webpack、Rollup 等传统工具,esbuild 构建速度快 10-100 倍,配置更简单,但插件生态和社区成熟度相对较低 。 - Webpack:功能丰富、生态成熟,但构建速度慢、配置复杂。
- Rollup:适合库打包,速度中等,配置复杂度中等。
- esbuild:速度极快、配置简单,但功能相对精简。
为什么构建速度极快
1. Go 语言原生编译: esbuild 使用 Go 语言编写并编译为原生机器码,而大多数打包工具(如 Webpack)基于 JavaScript 运行在 Node.js 上,每次执行都需要 JIT 解析器重新解析工具自身代码,esbuild 则直接执行编译后的机器码,省去了这一开销 。
- Go 语言操作在纳秒级,JavaScript 操作在毫秒级。
- 无需像 Node.js 那样先将代码解析为字节码再转换为机器码。
2. 多核并行处理: esbuild 的解析和代码生成阶段完全并行化,充分利用多核 CPU 优势,所有线程共享同一内存空间,而 JavaScript 线程间需要通过 postMessage 通信且各有独立内存堆 。 - 解析阶段:将输入文件分成多个块,在多个 CPU 核心上同时处理。
- 代码生成:与解析一样可完全并行化。
- 内存共享:Go 线程共享内存,JavaScript 线程需序列化数据传递。
3. AST 优化与内存复用: esbuild 从头到尾尽可能复用同一份 AST(抽象语法树)节点数据,避免传统工具链中频繁解析和传递 AST 导致的内存占用和性能损耗 。 - 传统工具链:webpack → babel → terser,每次接触新工具链都需重新解析 AST。
- esbuild:单一工具链完成所有操作,AST 数据只解析一次。
4. 基准测试数据: 官方基准测试显示,打包 10 份 three.js 库(约 54.7 万行代码),esbuild 耗时 0.37-0.39 秒,而 Webpack 5 耗时 41-55 秒,Parcel 约 14.9 秒,Rollup + terser 约 34 秒 。
使用方式与局限性
1. 命令行用法: 安装后可通过 CLI 直接运行,常用命令如 esbuild app.ts --bundle --outdir=dist --minify,支持 watch 模式(--watch)和开发服务器模式(--serve)。
- 安装方式:
npm install -g esbuild或通过各平台包管理器安装。 - 构建脚本:可在 package.json 中配置 build 脚本自动化运行。
2. JavaScript API: 支持在 JavaScript 文件中调用 esbuild 的 build 函数,适合需要传递多个选项的复杂场景,插件仅支持异步 API 。
import * as esbuild from 'esbuild'
await esbuild.build({
entryPoints: ['app.jsx'],
bundle: true,
outfile: 'out.js',
})
3. 插件机制: esbuild 提供插件系统,插件对象包含 name 和 setup 属性,setup 函数可注册 onResolve 和 onLoad 钩子来自定义构建逻辑,但插件仅作用于 build API,不适用于 transform API 。
4. 明确不支持的特性: 官方声明未来没有计划支持 Elm、Svelte、Vue、Angular 等框架特定文件格式、TypeScript 类型检查、AST 相关操作 API、热模块替换(HMR)、模块联邦等功能 。
- 原因:esbuild 定位为极简高性能打包器,不追求功能大而全。
- 建议:需要上述功能时,可在 esbuild 基础上二次封装或使用 Vite 等上层工具。
三、Terser 和 esbuild 区别
Terser和esbuild的核心区别是:Terser压缩率更高,esbuild速度快一个数量级。选哪个取决于项目对体积还是构建速度更敏感。
⚡ 速度对比
esbuild用Go编写,支持多核并行,压缩耗时远低于Terser。实测中,同一项目esbuild压缩约1.2秒,Terser约18.6秒,相差约15倍。 大型项目差距更明显,esbuild可在1-3秒完成,Terser需30-60秒。
📦 体积对比
Terser做深度AST优化,包括常量折叠、函数内联、作用域提升和激进死代码消除,产物体积更小。 差异通常在2%-8%之间,但gzip后差距缩小到1%-4%左右,现代HTTP传输启用gzip/Brotli后,esbuild的体积劣势基本可忽略。
🎯 怎么选
- 日常业务、CI/CD、对体积不敏感:用esbuild,构建快,节省研发效能。
- 嵌入式SDK、公共库、对体积极敏感:用Terser,多压几个百分点值得保留。
- Vite项目:开发用esbuild(默认),正式发布可切terser,
build.minify: 'terser',能自动清理console和debugger。
⚠️ 注意
esbuild压缩产物比Terser大,若项目走CDN且启用了gzip,差距基本可忽略;若产物要嵌进小程序包或离线包,Terser更合适。 另外esbuild对装饰器等新语法支持还在开发中,Terser对ES6+支持更全面。

浙公网安备 33010602011771号