gzip 压缩实践笔记

gzip 压缩是一种常用的 Web 性能优化手段,通过压缩文本类资源(HTML、CSS、JavaScript 等)来减少传输体积,提升页面加载速度。

概念理解

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

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

压缩策略:gzip 压缩分为两种实现方式:

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

Nginx 代理压缩配置

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

1. 基础配置

启用 gzip 压缩

# 启用 gzip 压缩功能
gzip on;

配置压缩文件类型

# 指定需要压缩的资源类型
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 文件(兼容写法)

设置压缩阈值

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

设置压缩级别

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

配置 Vary 响应头

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

2. 完整配置示例

# 启用 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 文件

配置示例

# 启用静态压缩(优先使用预压缩的 .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 作为构建工具的项目。

配置示例

// 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 作为构建工具的项目。

配置示例

// 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,小数据量和校验接口没必要开启,多考虑传输耗时和压缩开销。

接口压缩配置示例

# 只对大数据量接口启用压缩
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
  • 对比压缩前后的资源传输大小

注意事项

  • 开发环境不需要启用压缩,避免影响构建速度
  • 保留原始文件作为双重保障,避免访问失败
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • """1.个性化消息: 将用户的姓名存到一个变量中,并向该用户显示一条消息。显示的消息应非常简单,如“Hello ...
    她即我命阅读 9,187评论 0 6
  • 1、expected an indented block 冒号后面是要写上一定的内容的(新手容易遗忘这一点); 缩...
    庵下桃花仙阅读 3,868评论 0 2
  • 一、工具箱(多种工具共用一个快捷键的可同时按【Shift】加此快捷键选取)矩形、椭圆选框工具 【M】移动工具 【V...
    墨雅丫阅读 4,396评论 0 0
  • 跟随樊老师和伙伴们一起学习心理知识提升自已,已经有三个月有余了,这一段时间因为天气的原因休课,顺便整理一下之前学习...
    学习思考行动阅读 3,725评论 0 2
  • 一脸愤怒的她躺在了床上,好几次甩开了他抱过来的双手,到最后还坚决的翻了个身,只留给他一个冷漠的背影。 多次尝试抱她...
    海边的蓝兔子阅读 3,362评论 0 4

友情链接更多精彩内容