JavaScript 压缩是如何工作的
Terser 通过四个阶段处理您代码的抽象语法树(AST)。每个阶段相互独立,可以单独开启或关闭而不影响其他阶段。
- 解析. Terser 将您的 JavaScript 解析为 AST。任何语法错误都会在此阶段以导致错误的词元和行号呈现,让您在任何转换运行前就能找到真正的问题所在。解析器支持最新 Stage 4 提案以内的所有标准 ECMAScript 语法。
- 压缩. 压缩器遍历 AST 并应用数十种保留语义的转换:常量折叠、死分支消除、短纯函数内联、连续
var声明合并,以及等价语句形式的改写(if/else转三元运算符、比较链缩短、条件返回折叠)。每种转换在理论上都是可逆的;压缩器不会改变任何可观测行为。 - 混淆. 混淆器将每个作用域内的局部绑定重命名为最短的唯一标识符(
a、b、c……)。只有无法逃出模块边界的名称才会被重命名,因此导出绑定、属性键和全局引用保持不变。这是所有阶段中单次字节节省最大的一步。 - 输出. Terser 将转换后的 AST 输出为折叠空白、语句分隔符精简至语法允许的最低限度的 JavaScript 字符串。注释被删除,除非保留许可证开关保留了
/*! … */块——大多数 CDN 许可证要求保留这些内容。
为什么要压缩 JavaScript
- 加快页面加载速度. 更小的脚本解析和执行更快。在 4G 移动网络上,字节减少 40% 可为交互时间(TTI)节省真实的数秒,而这正是 Google PageSpeed Insights 最为关注的指标。
- 降低 CDN 出流量费用. CloudFront、Cloudflare 和 Fastly 均按 GB 出流量计费。每月数百万次页面浏览中脚本减少 40%,在任何图片或 CSS 优化到位之前就已形成真实节省。即使在 gzip 和 brotli 压缩之后,这一效果仍然成立——压缩消除了压缩算法本需编码的词元。
- 本压缩器不会拖慢您的页面. Terser 未压缩时约 1 MB。大多数在线压缩器在页面加载时就会传输整个库,导致自身 Lighthouse 评分很差,用户在输入任何内容前就感觉页面卡顿。本页面仅在您点击「压缩」或开启实时模式时才延迟加载 Terser——因此初始渲染保持在本工具承诺帮您达到的 Core Web Vitals 阈值以内。
- 通过 Core Web Vitals 评估. Lighthouse 和 PageSpeed Insights 将大型 JavaScript 直接列为总阻塞时间(TBT)不佳的原因之一。压缩第三方库和应用包是 Lighthouse "减少未使用的 JavaScript" 和 "删除重复模块" 审计中最快见效的优化——通常一次性就能提升十到二十分。
常见应用场景
JavaScript 压缩几乎出现在现代 Web 项目的每个阶段。
- 提交前钩子:在提交到仓库前压缩单个工具脚本,使提交产物达到生产就绪状态,diff 只显示逻辑变更而非空白扰动。
- 第三方 widget 审计:粘贴供应商的嵌入片段,检查它是否已经压缩,或在将其服务给数百万用户之前是否还能进一步缩减。
- 旧版脚本清理:压缩早于当前构建流程的老旧 jQuery 插件和手工编写的脚本,而不需要修改源码树。
一个实际示例
以一个小函数为例:function add(firstNumber, secondNumber) { /* sums two numbers */ return firstNumber + secondNumber; } console.log(add(1, 2));——含注释约 130 字节。在混淆和压缩均开启的情况下粘贴到上方。输出缩短为大约 function add(n,o){return n+o}console.log(add(1,2));——约 55 字节,减少了 58%。函数名 add 保留,因为它被 console.log 调用引用;参数名 firstNumber 和 secondNumber 缩短为单字母,因为它们是函数体内的局部变量。关闭混淆可在折叠空白和删除注释的同时保留可读的参数名。
FAQ
这在我的浏览器中运行吗?
是的。Terser 在您第一次点击「压缩」或开启实时模式时延迟加载——约 200 KB 压缩后的内容落入您的浏览器缓存,之后不再下载任何内容。您的代码不会离开页面。
什么是名称混淆,它安全吗?
混淆将局部变量重命名为单字母以节省字节。对于自包含的脚本和 IIFE 包,这是安全的,因为重命名不会逃出作用域。对于通过名称向外暴露全局变量的脚本(例如没有包装器的 window.myLib = …),则不安全。不确定时请关闭混淆。
为什么我的代码在压缩后无法运行?
三个常见原因:eval 或 with 通过字符串引用变量;Function.name 或 arguments.callee 依赖原始标识符的读取;或者被重命名的全局变量通过名称对外暴露。先关闭混淆,以排查是重命名还是压缩转换导致了问题。
支持现代语法(ES2020+)吗?
支持。将 ECMAScript 目标版本设置为 ES2020 或 Next,Terser 会保留可选链、空值合并、顶层 await 和逻辑赋值运算符。设置为 ES5 时 Terser 会尽可能向下编译,但它不是完整的转译器——对于 ES5 完全无法表示的语法,请使用 Babel。
使用 Terser 在浏览器端压缩 JavaScript,无需添加构建工具即可获得生产质量的输出。粘贴脚本,选择 ECMAScript 目标版本,复制或下载结果。无需上传、无需账户、无需构建流程。压缩器本身仅在您要求时才加载——因此打开本页只需几 KB,而非一兆字节。