Skip to content

前端预压缩

约 3440 字大约 11 分钟

2025-06-29

前端预压缩

前端预压缩指的是在前端构建阶段对静态资源进行压缩,生成压缩后的文件,以减少传输数据量,提升页面加载速度。服务器在收到请求时,根据请求头的 Accept-Encoding 字段判断是否支持压缩,并返回对应的压缩文件。浏览器在收到压缩文件后,对文件进行解压缩并执行。

预压缩的三大特征

1、构建阶段完成压缩

npm run build 时生成压缩后的 .gz.br 文件,而非用户请求时压缩

2、产物包含压缩文件

输出目录中同时存在压缩文件和原始文件,例如 main.jsmain.js.gzmain.js.br

dist/
├─ main.js
├─ main.js.gz  # 预压缩生成
├─ main.js.br  # 预压缩生成
├─ style.css
├─ style.css.gz
├─ style.css.br

3、服务器直接使用

Nginx 等服务器只需配置gzip_static on 即可优先使用已生成的预压缩文件

http {
  gzip off;        # 禁用动态压缩
  gzip_static on;  # 优先使用预压缩文件(如果有)
}

工作流程

  1. 浏览器发起请求

    浏览器发起请求时,在请求头中设置属性 accept-encoding:gzip。表明浏览器支持 gzip 压缩,这个参数是浏览器自动会携带的请求头信息。

  2. 服务器收到浏览器发送的请求之后:

    • 返回压缩后的文件,并在响应头中设置 content-encoding: gzip
    • 如果没有压缩文件,返回未压缩的请求文件。
  3. 浏览器处理

    浏览器接收到到服务器的响应,根据 content-encoding: gzip 响应头使用 gzip 策略去解压压缩后的资源,通过 content-type 内容类型决定怎么编码读取该文件内容。

  4. 结束

与其他压缩方案的对比

传统的实时压缩方案,需要在服务器上配置 Gzip 模块,且每个请求都需要实时压缩,这样的操作比较考验服务器的配置和性能。
Webpack 预压缩方案,在构建阶段一次性完成压缩,服务器无需额外处理,直接配置相关参数,返回对应的 .gz 文件。

对比维度前端预压缩服务器实时压缩CDN 边缘压缩
压缩时机构建阶段(如 Webpack / Vite)处理请求时,实时压缩(Nginx / Apache)CDN 节点首次回源时,压缩并缓存
性能消耗❌ 构建时间增加✅ 实时 CPU 消耗✅ 仅首次回源消耗,后续请求直接返回压缩文件
压缩算法Brotli + Gzip(兼容性)Brotli + Gzip(兼容性)支持 Gzip、Brotli(取决于 CDN 配置)
延迟影响⚡️ 零延迟(文件已预压缩)⏳ 增加 5-50ms 压缩时间延迟⏳ 仅首次请求有延迟
存储空间需额外存储 .gz / .br 文件不占额外存储由 CDN 自动管理
适用场景Web 静态资源(JS/CSS/图片)动态内容(API 响应/SSR 页面)全球加速的静态资源
配置复杂度⚠️ 需要在构建工具配置压缩插件⚠️ 需服务器配置一些参数(如gzip on✅ CDN 控制台一键开启
典型工具Webpack 的 compression-webpack-pluginNginx 的 gzip / brotli 模块Cloudflare / AWS CloudFront 等 CDN 服务
缓存效率✅ 最高(内容哈希命名)⚠️ 依赖 ETag / Last-Modified✅ 边缘节点缓存压缩版本
兼容性需服务端配置正确 Content-Encoding依赖客户端 Accept-Encoding 支持自动适配客户端支持的算法

压缩算法的选择

Gzip 压缩

Gzip 是一种广泛使用的压缩算法,被广泛用于 HTTP 协议中。它通过对文件内容进行 无损压缩,并使用 LZ77 + 哈夫曼编码 来实现。

主要特点:

  • 跨平台支持:所有主流操作系统(Linux/macOS/Windows)和编程语言均原生支持
  • Web 标准:HTTP 协议默认支持的压缩方式(Content-Encoding: gzip)
  • 工具链完善:gzip/gunzip 命令行工具、zlib 库等生态成熟
  • 适合 Web 传输、日志归档、数据库备份等场景

优势

  • 兼容性无敌:所有系统/语言原生支持
  • 内存占用极低:适合资源受限环境
  • 解压速度极快

劣势

  • 压缩比和压缩速度均落后于现代算法
  • 不支持多文件压缩(需配合 tar)

Brotli 压缩

Brotli 是 Google 开发的一种新的压缩算法,它在压缩效率和压缩速度之间取得了平衡。与 Gzip 相比,Brotli 提供更高的压缩率,但压缩速度较慢。

主要特点:

  • 超高压缩率(核心优势),比 Gzip 高 20-26%压缩率,典型文本资源对比:
  • 内置静态字典:包含 13,184 个 Web 常用词(如<div>function()等),覆盖 50%+的 Web 文本模式
  • 预训练模型:针对 HTML/CSS/JS 语法优化,对 React/Vue 等框架的模板压缩效果极佳
  • HTTP 协议原生支持
  • TLS 友好,更小的体积减少 HTTPS 握手后的数据传输量
  • 适用场景:适合需要高压缩比的场景,如网页内容、大型数据集等。

优势

  • Web 专项优化:内置静态字典,压缩比最高
  • 渐进式解码:适合流式传输
  • HTTPS 友好:减少 TLS 数据传输量

劣势

  • 压缩速度极慢(尤其高级别)
  • 内存占用高

Zstandard 压缩

Zstandard(简称 Zstd)是 Facebook 于 2016 年开源的一种现代高性能压缩算法,旨在提供接近实时压缩速度与高压缩率的完美平衡。相比传统算法(如 Gzip、Brotli),它在速度、压缩比和资源消耗之间实现了显著突破,已成为数据库、游戏、日志处理等领域的首选压缩方案。

主要特点:

  • 压缩率:通常比 gzip 稍低,但比 Brotli 高。
  • 压缩速度:非常快。
  • 解压速度:同样非常快。
  • 适用场景:适合需要高速压缩和解压的场景,如日志处理、实时数据传输等。

优势

  • 速度与压缩比平衡:实时压缩能力极强
  • 字典训练:支持预训练字典优化特定数据类型
  • 多线程压缩:充分利用多核 CPU

劣势

  • 最高压缩比略低于 Brotli
  • 旧版本兼容性一般(需 zstd ≥ v1.4+)

压缩算法的对比

1、关键技术差异

技术点ZstdGzipBrotli
核心算法LZ77 + FSELZ77 + HuffmanLZ77 + 静态字典 + 上下文建模
字典支持✅ 可训练字典❌ 无✅ 内置静态字典
块分割动态(128KB-4MB)固定 32KB 窗口动态(16KB-16MB)
HTTP 支持需手动配置默认支持主流浏览器/服务器支持

2、核心指标对比

指标Zstd (级别 3)Gzip (级别 6)Brotli (级别 11)
压缩速度520 MB/s120 MB/s12 MB/s
解压速度1800 MB/s500 MB/s400 MB/s
压缩比3.5:13.2:14.3:1
内存占用~16 MB<10 MB~300 MB
压缩级别范围-1 到 221 到 90 到 11
多线程支持✅ 是❌ 否❌ 否

测试数据参考:混合文本/二进制,i9-13900K CPU

3、适用场景推荐

场景推荐算法理由
数据库存储/日志✅ Zstd实时压缩 + 高解压速度,RocksDB / MySQL 默认选择
Web 静态资源✅ Brotli极致压缩比(JS/CSS/HTML),浏览器原生支持
API 动态数据⚖️ Zstd/GzipZstd(性能优先)或 Gzip(兼容性优先)
老旧系统/嵌入式设备✅ Gzip兼容性好,低内存占用,无需额外依赖
游戏资源打包✅ Zstd比 ZIP 体积小 20%,加载更快
实时日志流处理✅ Zstd--adapt 参数动态调整级别,多线程支持

总结选择建议

  • 追求性能:选 Zstd(数据库/日志/游戏)
  • 追求压缩比:选 Brotli(Web 静态资源)
  • 追求兼容性:选 Gzip(老旧系统/通用场景)

三者并非互斥,现代系统常 组合使用

  • 用 Brotli 压缩 Web 资源
  • 用 Zstd 处理数据库/日志
  • 用 Gzip 作为兼容性兜底

实现方案

Webpack 实现预压缩

Webpack 主要通过 compression-webpack-plugin 来实现与压缩文件的生成。

一般来说,我们会同时开启 gzip 和 brotli 压缩,优先使用 brotli 压缩,同时使用 gzip 作为兼容性兜底。

这是因为 brotli 压缩比更高,可以获得更好的压缩效果,而 gzip 兼容性更好,可以适配老旧版本的浏览器。

webpack.config.js
参数类型默认值说明
filenameString/Function[path][base].gz生成的压缩文件名模式
algorithmString/Functiongzip压缩算法,支持 gzip/deflate/deflateRaw
testRegExp/Array匹配所有文件指定需要压缩的文件类型
thresholdNumber0文件大小阈值(字节),大于此值才压缩
minRatioNumber0.8压缩比阈值,小于此值才压缩
deleteOriginalAssetsBooleanfalse是否删除原始文件
cacheBoolean/Stringfalse启用缓存或指定缓存目录
compressionOptionsObject{}传递给 zlib 的选项

Vite 实现预压缩

可以使用 vite-plugin-compression 插件实现。

vite.config.js

如果实现更加精细的控制,比如针对不同文件类型使用不同压缩策略。可以使用 rollup-plugin-gziprollup-plugin-brotli

vite.config.js

Nginx 服务器

Nginx 服务器配置需要配置的参数

# 优先匹配br
brotli off; # 禁用动态压缩
brotli_static on;  # 优先使用预压缩文件(如果有)

# 优先匹配 gzip
gzip off; # 禁用动态压缩
gzip_static on;  # 优先使用预压缩文件(如果有)
gunzip on; # 兼容不支持gzip的客户端
gzip_vary on; # 确保响应头包含 Vary: Accept-Encoding

Node.js 作为服务器

例如使用 Express 作为服务器,手动实现需要注意以下几点:

  1. 需要根据请求头里的 Accept-Encoding 字段,判断浏览器支持的压缩格式。
  2. 如果浏览器不支持压缩,中间件不做任何处理,直接返回源文件。
  3. 如果浏览器支持压缩文件,则根据请求头返回对应的压缩文件,优先返回 .br,其实选择 .gz
  4. 需要根据对应压缩文件的内容,设置Content-EncodingContent-Type 响应头。告知浏览器以什么样的格式去读取。

或者使用中间件 express-static-gzip 实现。

验证 Gzip 是否生效

浏览器开发者工具检查

  1. 打开 Chrome 开发者工具(F12)
  2. 切换到 Network 标签
  3. 刷新页面
  4. 点击任意资源文件,查看响应头:
    • 应有content-encoding: gzip
    • 比较Content-Length和资源实际大小

性能优化建议

  1. 静态文件

    • 使用 Webpack 预生成.gz 文件
    • 配置 Nginx 优先使用预压缩文件(gzip_static on)
  2. 动态内容

    • 使用 Node.js 中间件实时压缩
    • 设置适当的压缩级别(通常 6 是最佳平衡点)
  3. 缓存配置

    location ~* \.(js|css|html|json)$ {
      expires 1y;
      add_header Cache-Control "public, immutable";
      add_header Vary "Accept-Encoding";
    }
  4. 监控与调优

    • 监控服务器 CPU 使用率
    • 根据实际流量调整gzip_comp_level
    • 定期检查压缩率是否正常

更新日志

2025/8/24 08:17
查看所有更新日志
  • e7112-1