Gzip压缩实战:提升网站加载速度的关键技术
项目初期的技术选型
上个月接了个老项目重构,前端资源包体积大得离谱——首屏 JS 超过 1.8MB,CSS 近 500KB。用户反馈加载慢,尤其在弱网环境下基本要等 5 秒以上。团队内部讨论后,决定先从最直接的方案入手:Gzip 压缩。
其实 Gzip 这东西早该上了,但之前运维说“Nginx 默认开了”,结果查了才发现根本没生效。这次我亲自下场搞,毕竟资源体积压不下来,后面做懒加载、代码分割都白搭。
配置完发现没生效?别急,先看响应头
我一开始以为只要在 Nginx 里加几行配置就行,结果部署完用 DevTools 一查,Content-Encoding: gzip 根本没出现。折腾了半天,发现两个坑:
- 静态资源被 CDN 缓存了,新配置没刷新
- Nginx 的
gzip_types没包含text/css和application/javascript(默认只压缩 text/html)
修正后的 Nginx 配置长这样:
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_proxied any;
gzip_comp_level 6;
gzip_types
text/plain
text/css
application/json
application/javascript
text/xml
application/xml
application/xml+rss
text/javascript;
注意 gzip_min_length 设成 1024 字节,太小的文件压缩反而可能变大,没必要。gzip_comp_level 从 1 到 9,6 是性价比最高的,再高 CPU 开销大,体积减少微乎其微。
最大的坑:动态 API 响应没压缩
静态资源搞定后,发现接口返回的 JSON 数据还是原样。比如一个 /api/user/profile 接口,返回 300KB 的 JSON,没压缩。这时候才意识到:Gzip 不仅对静态文件有效,动态内容也得处理。
我们的后端是 Node.js + Express,于是我加了 compression 中间件:
const compression = require('compression');
const express = require('express');
const app = express();
app.use(compression({
threshold: 1024, // 小于 1KB 的不压缩
filter: (req, res) => {
// 某些特殊路径跳过压缩(比如监控探针)
if (req.path.includes('/health')) return false;
return compression.filter(req, res);
}
}));
这里踩了个小坑:threshold 默认是 1KB,但有些小接口(比如 800 字节)其实压缩后能省 30%,所以我后来调到 512。不过要注意,太小的响应压缩收益低,还增加 CPU 负担,得权衡。
测试时用 curl -H "Accept-Encoding: gzip" https://jztheme.com/api/data 看响应头和 body,确认 Content-Encoding: gzip 出现,并且数据确实是压缩过的(乱码就对了)。
浏览器兼容性?其实不用太担心
本来我还担心老旧浏览器不支持 Gzip,查了下 CanIUse,连 IE6 都支持。现代浏览器更不用说,只要请求头带 Accept-Encoding: gzip,服务器就会返回压缩内容,浏览器自动解压。所以这块基本零成本,放心开。
效果评估:体积砍半,但首屏时间没降那么多
上线后看数据:
- JS 从 1.8MB → 580KB(压缩率 68%)
- CSS 从 490KB → 120KB(压缩率 75%)
- API JSON 平均从 250KB → 80KB
看起来很爽,但实际首屏时间只从 5.2s 降到 3.8s。为什么?因为还有 DNS、TCP、TLS、服务端渲染延迟这些环节。Gzip 只解决传输体积,不解决连接建立开销。
不过在 3G 网络下提升明显,用户反馈“终于不用转圈那么久了”。也算值了。
没完全解决的小问题
有两个细节到现在也没动:
- 某些第三方 SDK(比如埋点脚本)是外链的,没法控制是否压缩。只能祈祷对方开了 Gzip(大部分主流 CDN 都开了)
- 图片资源没走 Gzip,因为本身是二进制,Gzip 压不动。这部分我们后续用 WebP + CDN 自适应做了优化,但那是另一个故事了
其实也可以考虑 Brotli,压缩率比 Gzip 高 15%~20%,但需要 Nginx 1.11.8+,而且构建时预压缩会增加部署复杂度。这次项目时间紧,就没折腾。
回顾与反思
回头看,Gzip 真的是“投入产出比最高”的性能优化手段之一。配置简单,风险低,效果立竿见影。但有几个教训值得记:
- 别信“默认开启”,一定要用 DevTools 或 curl 验证响应头
- 静态资源和动态接口要分开处理,前端开发者容易忽略后端那部分
- 压缩不是万能的,体积小了,但网络 RTT、服务端延迟这些瓶颈还在
另外,本地开发时可以用 webpack 的 compression-webpack-plugin 生成 .gz 文件,配合 Nginx 的 gzip_static on; 直接返回预压缩文件,避免运行时压缩的 CPU 开销。不过我们项目没用,因为容器化部署后 CPU 资源够用,实时压缩更灵活。
核心代码其实就那几行,但排查过程花了我大半天。希望你别重复踩这些坑。
以上是我个人在项目中使用 Gzip 的完整经验,有更优的实现方式欢迎评论区交流。这个技巧的拓展用法还有很多(比如结合 Service Worker 缓存压缩包),后续会继续分享这类博客。

暂无评论