核心原理:HTTP 內容編碼協商
- Client 請求頭:
Accept-Encoding: gzip, deflate, br
- Server 檢查支援格式,選擇最高優先級(通常 gzip)
- Server 壓縮回應體,回應頭標記:
Content-Encoding: gzip
- Client 自動解壓並渲染,過程對使用者透明
純文字內容(HTML/CSS/JS/JSON/XML)壓縮率通常 70%-90%,大幅降低頻寬與傳輸延遲。
方案一:Apache mod_deflate(推薦,全站生效)
模組載入確認
# Apache 2.4 通常內建
LoadModule deflate_module modules/mod_deflate.so
LoadModule filter_module modules/mod_filter.so # 必須,mod_deflate 依賴
虛擬主機/目錄配置範例
<IfModule mod_deflate.c>
# 核心開關
SetOutputFilter DEFLATE
# 指定壓縮 MIME 類型(避免圖片/二進位再壓縮)
AddOutputFilterByType DEFLATE \
text/html text/plain text/xml text/css \
text/javascript application/javascript application/x-javascript \
application/json application/xml application/rss+xml \
application/x-font-ttf application/x-font-opentype \
image/svg+xml
# 排除已壓縮/二進位格式
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png|webp|ico|zip|gz|tgz|bz2|pdf|woff2?)$ no-gzip dont-vary
# 代理快取友善
Header append Vary User-Agent env=!dont-vary
# 選擇性:壓縮等級 1-9 (預設 6)
DeflateCompressionLevel 6
# 選擇性:最小壓縮大小(位元組),避免微小檔案壓縮反增
DeflateMinSize 512
</IfModule>
方案二:PHP ob_gzhandler(無需 Apache 模組)
三種啟用層級
| 範圍 | 配置方式 | 範例 |
| 全站 | php.ini | output_handler = ob_gzhandler |
| 目錄/虛擬主機 | .htaccess | php_value output_handler ob_gzhandler |
| 單一腳本 | 代碼開頭 | ob_start('ob_gzhandler'); |
進階控制:條件式壓縮
<?php
// 僅當客戶端支援且非圖片請求時壓縮
if (isset($_SERVER['HTTP_ACCEPT_ENCODING']) &&
strpos($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') !== false &&
!preg_match('/\.(gif|jpe?g|png|webp|ico|css|js)(\?.*)?$/', $_SERVER['REQUEST_URI'])) {
ob_start('ob_gzhandler');
} else {
ob_start();
}
// 你的 PHP 代碼...
echo $content;
ob_end_flush();
?>
方案三:應用層類庫(歷史參考)
早期 PHP 4 無 ob_gzhandler 時使用 class.gzip_encode.php,現已無需採用,略過。
驗證與除錯工具鏈
| 工具 | 指令/操作 | 預期結果 |
| curl | curl -I -H "Accept-Encoding: gzip" https://example.com/ | 回應頭含 Content-Encoding: gzip,Content-Length 明顯縮減 |
| 瀏覽器 DevTools | Network 標籤 → 檢查 Response Headers | 見 content-encoding: gzip,Size 顯示壓縮後/原始大小 |
| 線上測試 | https://www.giftofspeed.com/gzip-test/ | 輸入 URL 即時分析壓縮率 |
| Apache 日誌 | %{Content-Encoding}o 記錄壓縮狀態 | 分析壓縮覆蓋率 |
常見問題與解決
- 壓縮後頁面亂碼/空白:
- 確認 PHP 檔案編碼為 UTF-8 無 BOM。
- 檢查是否重複壓縮(Apache + PHP 同時開啟),關閉其中一層。
- 輸出前已有
ob_start() 且未 ob_end_clean(),導致巢狀緩衝衝突。
- IE 6/7 無法解壓:舊版 IE 對壓縮快取有缺陷,可針對 User-Agent 關閉壓縮:
BrowserMatch ^Mozilla/4 gzip-only-text/html
- SSL/TLS 下壓縮風險 (BREACH/CRIME):敏感頁面(含 CSRF Token、個資)建議關閉壓縮或使用
Content-Security-Policy 降低風險。
- 動態內容壓縮 CPU 過高:調整
DeflateCompressionLevel 降至 1-3,或引入快取層減少動態生成頻率。
效能基準對比(典型 HTML 頁面 50KB)
| 指標 | 無壓縮 | Gzip Level 6 | 提升 |
| 傳輸大小 | 50,000 bytes | ~12,000 bytes | 76% 減少 |
| 3G 網路傳輸時間 | ~400ms | ~100ms | 75% 縮短 |
| CPU 開銷 (單核) | 0 | ~0.5ms | 可忽略 |
| 記憶體開銷 | 0 | ~2x 原始大小 (緩衝) | ~100KB |
最佳實踐總結
- 優先使用 Apache mod_deflate,統一管理靜態/動態資源,效能最佳。
- PHP 層面用
ob_gzhandler 作為備援或針對性控制。
- 嚴格排除圖片、字型、壓縮檔等已壓縮 MIME 類型。
- 設定
Vary: Accept-Encoding 確保代理正確快取。
- 監控
mod_deflate 記憶體/CPU 使用,高併發時考慮 CDN 邊緣壓縮。