啟用 GZIP/DEFLATE 壓縮是 Web 效能優化的「高報酬、低成本」項目之一。本文詳細說明 Apache 2.4 下 mod_deflate、mod_headers、mod_filter 模組配置、壓縮類型選擇、瀏覽器相容性處理與效能調優參數。
# 檢查模組是否編譯/載入
httpd -M | grep -E 'deflate|headers|filter'
# 輸出應包含:
# deflate_module (shared)
# headers_module (shared)
# filter_module (shared)
若缺失,需重新編譯 Apache 並加入 --enable-deflate --enable-headers --enable-filter,或透過套件管理器安裝對應模組套件。
建議建立獨立配置檔 /etc/httpd/conf.d/deflate.conf(或 /usr/local/apache2/conf/extra/httpd-deflate.conf),再在主配置 IncludeOptional conf.d/*.conf 引入。
# 定義壓縮過濾器
FilterDeclare COMPRESS
FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m#^text/(html|css|plain|xml|javascript|json)$#i"
FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m#^application/(javascript|json|xml|rss\+xml|x-javascript)$#i"
FilterProvider COMPRESS DEFLATE "%{CONTENT_TYPE} =~ m#^image/svg\+xml$#i"
FilterChain COMPRESS
FilterProtocol COMPRESS change=yes;byteranges=no
# 核心壓縮配置
DeflateCompressionLevel 6 # 1-9,6 為平衡點(預設 6)
DeflateWindowSize 15 # 窗口大小 32KB (2^15)
DeflateMemLevel 9 # 記憶體使用等級 1-9
# 排除不需壓縮/不相容類型
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|webp|ico|svgz)$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \.(?:exe|t?gz|zip|bz2|7z|rar|zst)$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \.(?:pdf|docx?|xlsx?|pptx?|mp3|mp4|avi|mov|flv)$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \.(?:woff2?|ttf|eot|otf)$ no-gzip dont-vary
# 明確指定壓縮 MIME 類型(比 AddOutputFilterByType 更精確)
AddOutputFilterByType DEFLATE text/html text/plain text/css text/xml
AddOutputFilterByType DEFLATE text/javascript application/javascript application/json
AddOutputFilterByType DEFLATE application/xml application/rss+xml application/xhtml+xml
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE application/x-font-ttf application/x-font-opentype
AddOutputFilterByType DEFLATE application/vnd.ms-fontobject font/opentype
# 瀏覽器相容性處理
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
# 確保 Vary 標頭正確(關鍵:CDN/Proxy 快取區分)
Header append Vary User-Agent env=!dont-vary
Header append Vary Accept-Encoding
| 指令 | 推薦值 | 說明 |
|---|---|---|
DeflateCompressionLevel | 6 | 1=最快/壓縮率低,9=最慢/壓縮率高,6 為甜蜜點 |
DeflateWindowSize | 15 | 滑動窗口 32KB,增加可提升大檔壓縮率但消耗記憶體 |
DeflateMemLevel | 9 | 內部壓縮狀態記憶體,9 為最大 |
SetEnvIfNoCase | - | 排除已壓縮格式(圖片、影音、封存檔),避免雙重壓縮浪費 CPU |
Header append Vary | - | 關鍵:告知 Proxy/CDN 依 Accept-Encoding 區分快取版本 |
Content-Encoding: gzip 或 deflateContent-Length(壓縮後)與 Transfer-Encoding: chunked 或解壓後大小
# 測試 HTML
curl -H "Accept-Encoding: gzip,deflate" -I https://example.com/
# 應回傳: Content-Encoding: gzip
# 測試 CSS/JS
curl -H "Accept-Encoding: gzip" -s https://example.com/style.css | wc -c
curl -s https://example.com/style.css | wc -c
# 前者應顯著小於後者
Brotli (br) 壓縮率比 GZIP 高 15-25%,現代瀏覽器全支援:
BrotliCompressionQuality 5 # 0-11,5-6 為平衡點
BrotliWindowSize 22 # 4MB 窗口
BrotliFilterNote Input instream
BrotliFilterNote Output outstream
BrotliFilterNote Ratio ratio
AddOutputFilterByType BROTLI_COMPRESS text/html text/css text/xml
AddOutputFilterByType BROTLI_COMPRESS application/javascript application/json
AddOutputFilterByType BROTLI_COMPRESS image/svg+xml
# 同時支援 gzip 回退
SetEnvIfNoCase Accept-Encoding br brotli_ok
SetEnvIfNoCase Accept-Encoding gzip gzip_ok
| 現象 | 原因 | 解決 |
|---|---|---|
| 回應無 Content-Encoding | 模組未載入、MIME 類型未匹配、請求無 Accept-Encoding | 檢查 httpd -M、確認 AddOutputFilterByType 類型、curl 加 -H |
| Proxy/CDN 回傳未壓縮版本 | 缺少 Vary: Accept-Encoding 標頭 | 啟用 Header append Vary Accept-Encoding |
| CPU 飆高 | 壓縮等級過高、大檔案壓縮、排除規則遺漏 | 降低 CompressionLevel、加入大檔/二進制排除、啟用快取 |
| 舊版 IE 顯示亂碼 | IE6 不支援壓縮 | BrowserMatch 規則已處理,確認順序正確 |
Apache GZIP/DEFLATE 配置核心在於:精確匹配 MIME 類型、完整排除已壓縮格式、正確輸出 Vary 標頭、平衡壓縮等級與 CPU 成本。配合 Brotli、HTTP/2、靜態資源預壓縮(mod_deflate 搭配 mod_rewrite 提供 .gz 預壓縮檔),可構建企業級傳輸優化體系。