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/json、application/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 ...
    她即我命阅读 14,136评论 0赞 6
  • 1、expected an indented block 冒号后面是要写上一定的内容的(新手容易遗忘这一点); 缩...
    庵下桃花仙阅读 4,889评论 1赞 2
  • 一、工具箱(多种工具共用一个快捷键的可同时按【Shift】加此快捷键选取)矩形、椭圆选框工具 【M】移动工具 【V...
    墨雅丫阅读 5,166评论 0赞 0
  • 跟随樊老师和伙伴们一起学习心理知识提升自已,已经有三个月有余了,这一段时间因为天气的原因休课,顺便整理一下之前学习...
    学习思考行动阅读 4,715评论 0赞 2
  • 一脸愤怒的她躺在了床上,好几次甩开了他抱过来的双手,到最后还坚决的翻了个身,只留给他一个冷漠的背影。 多次尝试抱她...
    海边的蓝兔子阅读 3,255评论 1赞 4

友情链接更多精彩内容