最有效方式是nginx直接返回预生成的.gz文件。构建时需生成同名.gz文件(webpack用compression-webpack-plugin,vite用vite-plugin-compression),nginx在静态location中启用gzip_static,验证需比对content-length、etag和last-modified。

直接让 Nginx 返回预生成的 .gz 文件,而不是实时压缩,是降低 TTFB 和 CPU 开销最有效的方式。核心不在于“开 gzip”,而在于构建阶段产出文件 + Nginx 精准启用 gzip_static。
构建阶段:必须提前生成同名 .gz 文件
所有静态资源(JS、CSS、HTML、SVG、JSON、字体等)在打包时就要输出对应的 .gz 版本,原始文件不能删。
- Webpack 项目:用
compression-webpack-plugin,配置algorithm: 'gzip'和deleteOriginalAssets: false - Vite 项目:用
vite-plugin-compression,设algorithm: 'gzip'、ext: '.gz',避免设deleteOriginFile: true - 已上线补救:批量压缩现有文件,例如
find /path/to/static -type f \( -name "*.js" -o -name "*.css" -o -name "*.json" \) -exec gzip -c9 {} \; -exec mv {}.gz {}\.gz \; - 关键细节:
.gz文件必须与源文件同目录;建议同步修改时间:touch -r app.js app.js.gz,否则可能触发缓存异常或退化为动态压缩
Nginx 配置:只在静态 location 中启用 gzip_static
gzip_static on 不是全局开关,也不受 gzip_types 控制——它只在能准确映射磁盘路径的 location 块中生效,且优先级高于 try_files。
- 推荐写法(匹配常见静态后缀):
location ~* \.(js|css|json|svg|woff2?|ttf|eot|html)$ {<br> root /usr/share/nginx/html;<br> gzip_static on;<br>} - 不要写在
http或server顶层;不要和try_files $uri混用在同一块里——若$uri被重写或未命中真实路径,gzip_static就不会触发 - 无需重复写
gzip on或调整gzip_comp_level;这些属于兜底策略,与gzip_static各司其职
验证是否真正走预压缩路径
仅看 Content-Encoding: gzip 不够,需交叉验证:
- 用
curl -I -H "Accept-Encoding: gzip" https://yoursite.com/app.js获取响应头 - 比对响应中
Content-Length是否等于本地app.js.gz的字节数(ls -l app.js.gz) - 检查
ETag是否由.gz文件的 inode + mtime 构成(原始文件的 ETag 格式不同) - 确认
Last-Modified时间戳与app.js.gz的修改时间一致 - 若响应变慢,大概率是
.gz缺失、路径不对,或时间戳未同步,Nginx 会多一次stat()系统调用后回退到动态压缩
与其他压缩策略协同工作
gzip_static 是主路径,gzip on 是兜底,两者可共存但职责分明:
- 在
http块中全局开启gzip on,并配好gzip_types(含text/html、application/json等)、gzip_min_length 1024、gzip_vary off(避免 CDN 缓存分裂) - 禁用
gzip_vary on:即使用了.gz文件,开启它仍会加Vary: Accept-Encoding,导致 CDN 缓存分裂 - 字体、SVG、JSON 等非传统文本资源,只要生成了
.gz文件,gzip_static一样能直接返回,无需额外声明 MIME 类型











