跳至主要內容
Skip to content

資料壓縮:Gzip vs Brotli

壓縮是減少傳輸資料量的最直接方式。本篇將深入解析 HTTP 壓縮機制與兩大主流算法。


一、 為什麼需要壓縮?

1.1 效益分析

檔案類型原始大小GzipBrotli
JavaScript500KB150KB (70%)130KB (74%)
HTML100KB20KB (80%)17KB (83%)
CSS200KB40KB (80%)35KB (82%)
JSON50KB10KB (80%)8KB (84%)

1.2 壓縮流程


二、 Accept-Encoding 標頭

2.1 請求標頭

瀏覽器告訴伺服器支援的壓縮格式:

http
Accept-Encoding: gzip, deflate, br
說明
gzipGNU Zip
deflateDeflate 算法
brBrotli
identity不壓縮
*任意

2.2 回應標頭

伺服器告訴瀏覽器使用的壓縮格式:

http
Content-Encoding: gzip
# 或
Content-Encoding: br

三、 Gzip

3.1 特點

  • 歷史悠久,支援度最廣
  • 壓縮速度快
  • 壓縮率適中
  • 所有瀏覽器都支援

3.2 Express 配置

javascript
const compression = require("compression");

app.use(
  compression({
    level: 6, // 1-9,9 最高壓縮率
    threshold: 1024, // 超過 1KB 才壓縮
    filter: (req, res) => {
      if (req.headers["x-no-compression"]) {
        return false;
      }
      return compression.filter(req, res);
    },
  })
);

3.3 Nginx 配置

nginx
http {
    gzip on;
    gzip_comp_level 6;
    gzip_min_length 1024;
    gzip_types text/plain text/css application/json
               application/javascript text/xml application/xml
               application/xml+rss text/javascript;
    gzip_vary on;
    gzip_proxied any;
}

四、 Brotli

4.1 特點

  • Google 開發,2015 年發布
  • 壓縮率比 Gzip 高 15-25%
  • 壓縮速度稍慢
  • 需要 HTTPS(大多數瀏覽器要求)
  • 現代瀏覽器支援度良好

4.2 Express 配置

javascript
const shrinkRay = require("shrink-ray-current");

app.use(shrinkRay());

// 或手動實作
const { createBrotliCompress } = require("zlib");

app.use((req, res, next) => {
  if (!req.headers["accept-encoding"]?.includes("br")) {
    return next();
  }

  // 只對文字類型壓縮
  const contentType = res.get("Content-Type");
  if (!contentType?.match(/text|json|javascript|xml/)) {
    return next();
  }

  res.set("Content-Encoding", "br");
  res.removeHeader("Content-Length");

  const brotli = createBrotliCompress();
  res.pipe = brotli.pipe.bind(brotli);

  next();
});

4.3 Nginx 配置

nginx
http {
    # 需要 ngx_brotli 模組
    brotli on;
    brotli_comp_level 6;
    brotli_min_length 1024;
    brotli_types text/plain text/css application/json
                 application/javascript text/xml application/xml
                 application/xml+rss text/javascript;
}

五、 Gzip vs Brotli 比較

5.1 壓縮率比較

5.2 效能比較

指標GzipBrotli
壓縮速度較慢
解壓速度
壓縮率良好更好
瀏覽器支援100%95%+
HTTPS 要求是(大多數)

5.3 何時使用哪個?


六、 預壓縮策略

6.1 為什麼要預壓縮?

動態壓縮消耗 CPU。對於靜態資源,可以在建構時預先壓縮。

6.2 Webpack 配置

javascript
const CompressionPlugin = require("compression-webpack-plugin");

module.exports = {
  plugins: [
    // Gzip
    new CompressionPlugin({
      filename: "[path][base].gz",
      algorithm: "gzip",
      test: /\.(js|css|html|svg)$/,
      threshold: 1024,
      minRatio: 0.8,
    }),
    // Brotli
    new CompressionPlugin({
      filename: "[path][base].br",
      algorithm: "brotliCompress",
      test: /\.(js|css|html|svg)$/,
      threshold: 1024,
      minRatio: 0.8,
    }),
  ],
};

6.3 Vite 配置

javascript
import viteCompression from "vite-plugin-compression";

export default {
  plugins: [
    viteCompression({
      algorithm: "gzip",
      ext: ".gz",
    }),
    viteCompression({
      algorithm: "brotliCompress",
      ext: ".br",
    }),
  ],
};

6.4 Nginx 使用預壓縮檔

nginx
location ~* \.(js|css|html)$ {
    gzip_static on;
    brotli_static on;

    # 伺服器會自動尋找 .gz 和 .br 檔案
}

七、 最佳實踐

7.1 應該壓縮的類型

nginx
gzip_types
    text/plain
    text/css
    text/javascript
    application/javascript
    application/json
    application/xml
    image/svg+xml
    font/woff2;

7.2 不應該壓縮的類型

  • 已壓縮的圖片(JPEG、PNG、WebP)
  • 已壓縮的檔案(ZIP、PDF)
  • 影片和音訊
  • 非常小的檔案(< 1KB)

7.3 完整配置範例

nginx
http {
    # Gzip
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_min_length 1024;
    gzip_types text/plain text/css text/xml text/javascript
               application/javascript application/json
               application/xml application/xml+rss
               image/svg+xml font/woff2;

    # Brotli(需要模組)
    brotli on;
    brotli_comp_level 6;
    brotli_min_length 1024;
    brotli_types text/plain text/css text/xml text/javascript
                 application/javascript application/json
                 application/xml application/xml+rss
                 image/svg+xml font/woff2;

    # 預壓縮檔案
    gzip_static on;
    brotli_static on;
}

八、 效能監控

8.1 檢查壓縮效果

bash
# 使用 curl
curl -I -H "Accept-Encoding: gzip" https://example.com/app.js
# 查看 Content-Encoding 標頭

# 比較大小
curl -sH "Accept-Encoding: identity" https://example.com/app.js | wc -c
curl -sH "Accept-Encoding: gzip" https://example.com/app.js | wc -c

8.2 DevTools 分析

Network 面板:
- Size 欄位顯示壓縮後大小
- 點擊請求查看 Content-Encoding
- 比較 transferred 和 resources

總結

算法壓縮率速度支援度推薦場景
Gzip良好100%通用
Brotli更好較慢95%+HTTPS + 現代瀏覽器

> **最佳策略**:

  • 優先 Brotli,回退到 Gzip
  • 靜態資源使用預壓縮
  • 設定合適的 threshold

進階挑戰

  1. 比較相同檔案在不同壓縮等級下的大小和壓縮時間。
  2. 實作一個中介軟體,根據 CPU 負載動態調整壓縮等級。
  3. 研究 Zstandard(zstd)壓縮算法,與 Brotli 比較。

延伸閱讀與資源