gzip 压缩实践笔记

概念理解

gzip 压缩:种基于 DEFLATE 算法的文件压缩格式,主要用于压缩文本类资源。Web 服务器和浏览器通过 HTTP 协议协商压缩,服务器在传输前压缩资源,浏览器接收后自动解压。

压缩原理:通过查找重复的字符串并替换为较短的引用,实现数据压缩。对于文本类资源(HTML、CSS、JavaScript),压缩率通常可达 60%-80%。

压缩策略

  • 运行时压缩:通过 Nginx 等代理服务器在请求时动态压缩,灵活性高但占用服务器 CPU 资源
  • 构建时压缩 :在构建阶段预先生成 .gz 文件,部署时直接使用,减少服务器运行时压缩开销

Nginx 代理压缩配置

Nginx 作为反向代理服务器,可以在运行时动态压缩响应内容。通过 ngx_http_gzip_module 模块实现 gzip 压缩功能。这是最基础的压缩方案,配置简单,适合快速启用。

1. 基础配置

启用 gzip 压缩

nginx 复制代码
# 启用 gzip 压缩功能
gzip on;

配置压缩文件类型

nginx 复制代码
# 指定需要压缩的资源类型
gzip_types text/html text/css application/javascript application/json text/xml application/xml text/javascript;
# 说明:
# - text/html:HTML 文件(可默认存在,可以不写)
# - text/css:CSS 文件
# - application/javascript:JavaScript 文件
# - application/json:JSON 数据
# - text/xml、application/xml:XML 文件
# - text/javascript:JavaScript 文件(兼容写法)

设置压缩阈值

nginx 复制代码
# 设置文件最小压缩阈值
gzip_min_length 1k; # 小于 1KB 的文件不压缩
# 推荐值:1KB 或 2KB
# 原因:过小文件压缩收益小,压缩开销可能大于收益

设置压缩级别

nginx 复制代码
# 设置压缩级别(1-9)
gzip_comp_level 6; # 推荐设置为 6
# 说明:
# - Level 1-3:压缩速度快,压缩率较低
# - Level 6:平衡选择,压缩率和速度兼顾(推荐)
# - Level 9:压缩率最高,但 CPU 占用显著增加
# - Level 9 相比 Level 6 只有 5%-10% 的提升,但 CPU 开销却变大了

配置 Vary 响应头

nginx 复制代码
# 在响应头中添加 Vary: Accept-Encoding
gzip_vary on;
# 作用:告诉 CDN/代理缓存服务,响应内容有多个版本
# 根据 Accept-Encoding 请求头来区分缓存版本
# 避免用户电脑不支持压缩时,代理返回错误的缓存版本

2. 完整配置示例

nginx 复制代码
# 启用 gzip 压缩
gzip on;

# 指定需要压缩的资源类型
gzip_types text/html text/css application/javascript application/json text/xml application/xml text/javascript;

# 设置压缩阈值(小于此大小的文件不压缩)
gzip_min_length 1k; # 推荐:1KB 或 2KB

# 设置压缩级别
gzip_comp_level 6; # 推荐:6(平衡压缩率和 CPU 占用)

# 添加 Vary 响应头
gzip_vary on;

# 禁用对 IE6 的压缩(IE6 对压缩支持有问题)
gzip_disable "MSIE [1-6]\.";

3. 运行时压缩的局限性

问题:Nginx 运行时动态压缩会消耗 CPU 资源,对于高并发场景可能成为性能瓶颈。

  • 每次请求都需要实时压缩,CPU 开销持续存在
  • 高并发场景下,压缩操作可能成为性能瓶颈
  • 压缩级别越高,CPU 占用越大,响应时间可能增加

适用场景

  • 低并发场景,服务器 CPU 资源充足
  • 无法预压缩的场景(如动态生成的接口数据)
  • 快速启用压缩,无需修改构建流程

构建时预压缩优化方案

为了解决 Nginx 运行时压缩的 CPU 开销问题,可以在构建阶段预先生成 .gz 文件,然后通过 Nginx 的 gzip_static 模块直接使用预压缩文件。这样既能享受压缩带来的带宽节省,又能避免运行时压缩的 CPU 开销。

1. Nginx 静态压缩配置(gzip_static)

配置要求

  • Nginx 需要编译时包含 --with-http_gzip_static_module 模块
  • 部署时需要同时部署原始文件和 .gz 文件

配置示例

nginx 复制代码
# 启用静态压缩(优先使用预压缩的 .gz 文件)
gzip_static on;
# 说明:
# - 如果请求的文件存在对应的 .gz 文件,直接返回 .gz 文件
# - 如果 .gz 文件不存在,回退到动态压缩(如果 gzip on 已启用)
# - 这样可以减少服务器运行时压缩的 CPU 开销

# 同时保留动态压缩作为兜底
gzip on;

工作流程

  1. 客户端请求资源(如 app.js
  2. Nginx 检查是否存在 app.js.gz 文件
  3. 如果存在,直接返回 app.js.gz(无需压缩,节省 CPU)
  4. 如果不存在,检查 gzip on 是否启用
  5. 如果启用,动态压缩 app.js 并返回
  6. 如果未启用,直接返回原始文件

2. 构建工具插件配置

前端构建时压缩是指在项目构建阶段,通过构建工具插件预先生成 gzip 压缩文件。这种方式可以避免服务器运行时压缩的 CPU 开销,提升响应速度。

2.1 compression-webpack-plugin(Webpack 项目)

compression-webpack-plugin 是 Webpack 的压缩插件,适用于使用 Webpack 作为构建工具的项目。

配置示例

javascript 复制代码
// vue.config.js 或 webpack.config.js
const CompressionPlugin = require('compression-webpack-plugin');

module.exports = {
  chainWebpack(config) {
    // 其他配置...
  },
  configureWebpack: config => {
    // 开发环境不配置压缩
    if (process.env.NODE_ENV !== 'production') return;
    
    // 生产环境配置压缩
    return {
      plugins: [
        new CompressionPlugin({
          // 压缩文件命名方式
          // filename: "[path][base].gz", // 默认方式,每个文件生成一个 .gz 文件
          filename: '[path].gz[query]', // 推荐:合并压缩文件,减少文件数量
          
          // 压缩算法
          algorithm: 'gzip', // 官方默认压缩算法
          
          // 匹配需要压缩的文件类型(使用正则表达式)
          test: /\.js$|\.css$|\.html$|\.ttf$|\.eot$|\.woff$/, 
          // 匹配规则:js、css、html 以及字体文件(.ttf、.woff、.eot)
          
          // 压缩阈值:只压缩超过此大小的文件(单位:字节)
          threshold: 1024, // 推荐:1KB,与 Nginx gzip_min_length 对齐
          
          // 最小压缩比率:只有压缩后体积小于原文件 80% 才保留压缩文件
          minRatio: 0.8, // 官方默认值
          
          // 是否删除原始文件
          deleteOriginalAssets: false // 推荐设置为 false,保留源文件作为双重保障
          // 原因:如果访问 .gz 文件失败,还可以访问原始文件
        })
      ]
    };
  }
};
2.2 vite-plugin-compression(Vite 项目)

vite-plugin-compression 是 Vite 的压缩插件,适用于使用 Vite 作为构建工具的项目。

配置示例

typescript 复制代码
// vite.config.ts
import { defineConfig } from 'vite';
import viteCompression from 'vite-plugin-compression';

export default defineConfig({
  plugins: [
    viteCompression({
      // 压缩算法
      algorithm: 'gzip', // 可选:'gzip' 或 'brotli'
      
      // 生成的文件扩展名
      ext: '.gz', // gzip 使用 .gz,brotli 使用 .br
      
      // 压缩阈值:仅压缩大于此大小的文件(单位:字节)
      threshold: 1024, // 推荐:1KB,与 Nginx gzip_min_length 对齐
      
      // 是否删除原始文件
      deleteOriginFile: false, // 推荐设置为 false,保留源文件
      
      // 压缩级别:1-9,级别越高压缩率越大,但 CPU 占用越多
      compressionOptions: { level: 9 }, // 构建时可以使用最高压缩级别
      
      // 过滤文件类型:使用正则表达式匹配需要压缩的文件
      filter: /.(js|css|json|html)(?.*)?$/i, 
      // 匹配:js、css、json、html 文件
      // 注意:后面 (?.*)?$ 是带查询参数(?v=xxxx)的匹配逻辑
    }),
  ],
});

3. 构建时压缩配置要点

压缩文件范围 :JavaScript(.js)、CSS(.css)、HTML(.html)、字体文件(.ttf.woff.eot),图片文件(.jpg.png.gif.webp)可以借助其他插件进行压缩。

压缩级别选择:可以使用较高压缩级别(6-9),因为构建时压缩不影响运行时性能

双重保障 :保留原始文件,避免代理配置问题导致无法访问 .gz 文件时,可以回退访问原始文件

验证 gzip 压缩生效

怎么验证 gzip 生效 :在网络模块中查看请求响应头,如果显示 Content-Encoding: gzip 就是开启压缩了。

验证步骤

  1. 打开浏览器开发者工具(F12)
  2. 切换到「网络」(Network)标签页
  3. 刷新页面,查看资源请求
  4. 点击某个资源请求,查看「响应头」(Response Headers)
  5. 检查是否存在 Content-Encoding: gzip 响应头

优化效果 :开启前需要传输 2.4 MB 资源,开启后仅传输 151 KB 压缩资源。

其他

推荐压缩阈值:1 KB - 10KB,过小文件压缩收益小,可能压缩后 HTTP 头部和 gzip 开销更大。

接口压缩application/jsonapplication/xml 数据都可以设置 gzip 压缩,但是要从 ROI(Return on Investment 投资回报率)的角度考量,只对大数据量接口的 location 设置 gzip on,小数据量和校验接口没必要开启,多考虑传输耗时和压缩开销。

接口压缩配置示例

nginx 复制代码
# 只对大数据量接口启用压缩
location /api/large-data {
    gzip on;
    gzip_types application/json application/xml;
    gzip_min_length 1k;
    gzip_comp_level 6;
}

总结

核心策略

  • 基础方案 :通过 Nginx 配置 gzip on 启用运行时压缩,简单快速
  • 优化方案 :使用构建工具插件预生成 .gz 文件,配合 gzip_static on 优先使用预压缩文件,减少 CPU 开销
  • 双重保障:保留原始文件,避免代理配置问题导致访问失败

配置要点

  • 压缩级别:运行时推荐 Level 6,构建时推荐 Level 9
  • 压缩阈值:推荐 1KB,构建时和 Nginx 阈值应对齐
  • 压缩范围:只压缩文本类资源(HTML、CSS、JavaScript、字体文件)
  • 接口压缩:根据 ROI 考量,只对大数据量接口启用压缩

验证方法

  • 浏览器开发者工具查看响应头 Content-Encoding: gzip
  • 对比压缩前后的资源传输大小

注意事项

  • 开发环境不需要启用压缩,避免影响构建速度
  • 保留原始文件作为双重保障,避免访问失败
相关推荐
木昆子1 小时前
实战A2UI:从JSON到像素——深入Lit渲染引擎
前端·人工智能
菡萏如佳人1 小时前
AI时代学习新范式—认知供应链模式(附OpenClaw四步拆解)
人工智能·学习
an317421 小时前
React 页面加载埋点的正确姿势:useEffect 与 document.readyState 完美配合
前端·javascript·react.js
IP搭子来一个2 小时前
长效静态IP是什么?用途全解析
服务器·网络·tcp/ip
1024小神2 小时前
vue3项目配置了子路由后刷新页面回到首页解决办法
前端·javascript·vue.js
chniccs2 小时前
宝塔面板去掉SSL的RSA
网络·安全·ssl
liuchangng2 小时前
BMAD-METHOD实战笔记_20260213112550
笔记
_Rookie._2 小时前
npm run 的原理
前端·npm·node.js
木斯佳2 小时前
前端八股文面经大全:2026-01-13MiniMax前端实习二面面经深度解析
前端·状态模式