阿里云主机折上折
  • 微信号
您当前的位置:网站首页 > 启用Gzip/Brotli压缩技术

启用Gzip/Brotli压缩技术

作者:陈川 阅读数:19247人阅读 分类: 性能优化

启用Gzip/Brotli压缩技术

现代Web应用中,资源文件体积直接影响页面加载速度。Gzip和Brotli作为两种主流压缩算法,能显著减小文本类资源的传输大小。通过合理配置服务器压缩策略,通常可实现50%-70%的压缩率,这对提升首屏加载速度具有直接效果。

压缩技术原理剖析

Gzip基于DEFLATE算法,使用LZ77算法和哈夫曼编码的组合。当服务器检测到客户端支持gzip时,会对响应体进行压缩并在响应头中添加Content-Encoding: gzip。典型压缩流程:

  1. 查找重复字符串并用指针替换
  2. 使用动态哈夫曼编码减少字符表示位数
  3. 输出压缩后的比特流

Brotli是Google开发的更新算法,采用LZ77的变种与二阶上下文建模。相比Gzip,Brotli的字典包含13000多个常见Web资源中的字符串模式,这使得它在压缩HTML/CSS/JS时效率更高。Brotli的压缩级别范围是0-11,而Gzip是1-9。

服务器配置实战

Nginx启用双压缩

http {
  gzip on;
  gzip_types text/plain text/css application/json application/javascript;
  gzip_min_length 256;
  gzip_comp_level 6;

  brotli on;
  brotli_types text/plain text/css application/json application/javascript;
  brotli_comp_level 6;
  brotli_static on;
}

关键参数说明:

  • gzip_min_length:小于该值的文件不压缩
  • brotli_static:优先发送预压缩的.br文件
  • 压缩级别建议设为4-6,更高级别消耗CPU但收益递减

Node.js中间件配置

const compression = require('compression')
const express = require('express')
const app = express()

// 优先尝试Brotli,回退到Gzip
app.use(compression({
  filter: shouldCompress,
  threshold: 0,
  brotli: {
    quality: 5
  }
}))

function shouldCompress(req, res) {
  // 排除已压缩的二进制文件
  if (req.headers['x-no-compression']) return false
  return compression.filter(req, res)
}

前端构建优化配合

Webpack插件生成预压缩文件:

const CompressionPlugin = require('compression-webpack-plugin')
const BrotliPlugin = require('brotli-webpack-plugin')

module.exports = {
  plugins: [
    new CompressionPlugin({
      filename: '[path][base].gz',
      algorithm: 'gzip',
      test: /\.(js|css|html|svg)$/,
      threshold: 10240,
      minRatio: 0.8
    }),
    new BrotliPlugin({
      asset: '[path].br',
      test: /\.(js|css|html|svg)$/,
      quality: 11
    })
  ]
}

构建后会同时生成:

  • original.js
  • original.js.gz
  • original.js.br

缓存策略与内容协商

正确处理缓存头避免重复压缩:

HTTP/1.1 200 OK
Content-Type: text/javascript
Content-Encoding: br
Vary: Accept-Encoding
Cache-Control: public, max-age=31536000

关键要点:

  • Vary: Accept-Encoding确保为不同客户端缓存不同版本
  • CDN需要支持传递Accept-Encoding头
  • 预压缩文件应设置更长缓存时间

性能对比实测数据

使用WebPageTest对典型SPA应用测试:

压缩方式 资源大小 传输体积 CPU耗时
无压缩 2.1MB 2.1MB 0ms
Gzip 2.1MB 543KB 23ms
Brotli 2.1MB 498KB 45ms

移动网络环境下(Slow 3G):

  • 无压缩:加载时间8.7s
  • Gzip:加载时间3.2s
  • Brotli:加载时间2.9s

异常情况处理方案

当遇到客户端不支持时,需要回退机制:

// 检查Accept-Encoding头
const acceptsEncoding = req.headers['accept-encoding']
const supportsGzip = acceptsEncoding.includes('gzip')
const supportsBrotli = acceptsEncoding.includes('br')

// 服务端选择逻辑
if (supportsBrotli && hasBrotliPrecompressed) {
  sendBr()
} else if (supportsGzip) {
  sendGzip()
} else {
  sendRaw()
}

常见问题排查:

  1. 检查Nginx错误日志中的brotli模块加载状态
  2. 确保MIME类型正确(如application/wasm不应压缩)
  3. 动态内容建议采用chunked编码压缩

高级调优技巧

对于特定内容类型的优化:

  1. JSON API响应

    • 启用字典训练(Brotli特有)
    • 设置Content-Type: application/json+br
  2. SVG图像

    gzip_types image/svg+xml;
    brotli_types image/svg+xml;
    
  3. WebAssembly

    • 禁止压缩.wasm文件
    • 添加wasm-unsafe-eval CSP策略
  4. 动态内容压缩

    gzip_proxied any;
    gzip_disable "msie6";
    

浏览器支持现状

通过特征检测实现渐进增强:

// 检测Brotli支持
const brotliSupported = () => {
  const headers = new Headers()
  headers.append('Accept-Encoding', 'br')
  return fetch('/test.txt', { headers })
    .then(res => res.headers.get('content-encoding') === 'br')
}

各浏览器支持情况:

  • Brotli:Chrome 49+、Firefox 44+、Edge 15+
  • Gzip:所有现代浏览器
  • IE11仅支持Gzip且存在部分bug

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

前端川

前端川,陈川的代码茶馆🍵,专治各种不服的Bug退散符💻,日常贩卖秃头警告级的开发心得🛠️,附赠一行代码笑十年的摸鱼宝典🐟,偶尔掉落咖啡杯里泡开的像素级浪漫☕。‌