全部產品
Search
文件中心

:設定Nginx HTTP緩衝策略

更新時間:Dec 06, 2025

通過為Nginx伺服器配置HTTP緩衝策略,可指示瀏覽器和中間代理(如CDN)緩衝靜態資源(如圖片、CSS、JS 檔案),並在緩衝有效期間內直接從本地載入,無需向伺服器發起請求。此舉可提升網站載入速度,並降低伺服器的頻寬消耗與處理壓力。

常用緩衝策略樣本

本節提供常見的緩衝配置方案,可根據情境直接應用於Nginx設定檔。所有樣本均使用 add_header ... always;,確保在所有響應碼(包括304 Not Modified)下都能添加緩衝頭。

情境一:為靜態資源設定長期緩衝

# 為靜態資源設定長期緩衝
# - 若檔案名稱包含內容雜湊(如 main.a1b2c3d4.js),推薦使用 1 年 + immutable
location ~* "\.[a-f0-9]{8,}\.(css|js|png|jpg|jpeg|gif|svg|webp|ico|woff|woff2)$" {
    # 適用於構建工具產生的帶雜湊資源:緩衝1年,瀏覽器永不驗證
    add_header Cache-Control "public, max-age=31536003, immutable" always;
    access_log off;
}

# - 若檔案名稱固定且極少變更(如 logo.png),使用 30 天緩衝
location ~* \.(css|js|png|jpg|jpeg|gif|svg|webp|ico|woff|woff2)$ {
    # 適用於無雜湊的通用靜態資源:緩衝30天,允許CDN和瀏覽器緩衝
    add_header Cache-Control "public, max-age=2592000" always;
    access_log off;
}

情境二:為HTML文檔或單頁應用(SPA)入口配置緩衝策略

對於HTML頁面(尤其是單頁應用的入口檔案,如 index.html),由於其內容可能隨應用部署頻繁更新,不應設定長期緩衝。但為兼顧效能,可允許瀏覽器緩衝,並在每次使用前向伺服器驗證資源是否變更。

# 適用於直接請求的 HTML 檔案
location ~* \.html$ {
    # 允許瀏覽器緩衝,但每次使用前必須向伺服器驗證
    # 'private' 禁止中間代理(如CDN)緩衝此響應
    # 伺服器需提供 ETag 或 Last-Modified 以支援驗證
    add_header Cache-Control "private, no-cache, must-revalidate" always;
}
說明
  • 此策略依賴伺服器返回ETagLast-Modified回應標頭,以便瀏覽器發起條件請求。Nginx預設為靜態檔案提供這些頭,無需額外配置。

  • 為防止中間代理(如 CDN)緩衝HTML內容,建議使用"private"指令,確保僅瀏覽器可緩衝。

情境三:禁止緩衝動態內容或敏感資訊

對於 API 介面、使用者個人中心、支付頁面等動態產生或包含敏感性資料的內容,必須禁止瀏覽器及所有中間代理(如CDN、共用快取)儲存任何響應副本,以防止資訊泄露或資料不一致。

# 樣本:適用於 PHP 動態指令碼(請根據實際動態路徑調整)
location ~ \.php$ {
    # ... 其他 PHP-FPM 配置 ...

    # 禁止所有緩衝:瀏覽器、代理、CDN 均不得儲存響應
    # 'no-store' 是最嚴格的緩衝控制指令
    add_header Cache-Control "no-store" always;
}

用戶端緩衝配置(控制瀏覽器)

通過在HTTP響應中添加Cache-ControlExpires頭,控制使用者瀏覽器的緩衝行為。此模式旨在減少網路請求,加速終端使用者訪問。

核心指令

  • expires指令:用於同時設定ExpiresCache-Controlmax-age

    • 文法: expires [time|epoch|max|off];

    • 樣本:expires 30d; (緩衝 30 天), expires -1; (強制用戶端在使用緩衝前向伺服器驗證資源有效性(等效於 Cache-Control: no-cache),但允許緩衝儲存。)。

    • 注意:add_header 指令提供更精細的控制,是推薦的配置方式。

  • add_header指令:向響應中添加指定的HTTP頭。

    • 文法:add_header <name> <value> [always];

    • always 參數說明
      - 預設情況下,add_header僅對2xx和3xx響應生效。 - 對於304 Not Modified響應,Nginx不會自動添加自訂頭。雖然瀏覽器會沿用首次200響應的緩衝策略,但為確保明確性和相容性,建議在緩衝控制頭中添加always參數,使其對所有響應狀態代碼生效。

Cache-Control關索引值說明

  • public:響應可以被任何緩衝(瀏覽器、CDN、Proxy 伺服器)緩衝。

  • private:僅允許終端使用者的瀏覽器緩衝,禁止共用快取(如 CDN)。適用於包含使用者特定資訊的內容。

  • no-cache:要求用戶端在每次使用快取複本前,都必須向伺服器發送請求驗證其有效性。如果資源未變更,伺服器返回304 Not Modified,用戶端使用本機快取,節省頻寬。

  • no-store:禁止瀏覽器和Proxy 伺服器儲存該響應的任何部分。適用於高度敏感的資料。

  • max-age=<seconds>:設定緩衝的有效時間,單位為秒。

  • immutable:告知瀏覽器該資源內容在有效期間內不會改變。在使用者重新整理頁面時,瀏覽器可跳過對此資源的驗證請求。適合帶雜湊值的檔案。

部署與驗證

  1. 編輯配置
    將 location 塊添加到網站的 server 塊中(設定檔通常位於 /etc/nginx/conf.d/ 或 /etc/nginx/sites-enabled/)。

  2. 重載配置

    sudo nginx -t && sudo nginx -s reload
  3. 驗證回應標頭
    使用 curl 檢查緩衝頭是否生效(不受瀏覽器緩衝影響):

    curl -I http://your-domain.com/path/to/file.js

    應包含如 Cache-Control: public, max-age=31536000 等預期頭。

  4. 驗證304行為(如配置了ETag或no-cache)
    手動攜帶驗證頭測試:

    ETAG=$(curl -I http://example.com/file.js 2>/dev/null | grep -i etag | cut -d' ' -f2 | tr -d '\r')
    curl -H "If-None-Match: $ETAG" -I http://example.com/file.js  # 期望返回 304
  5. 瀏覽器驗證

    1. 開發人員工具 → Network 面板

    2. 勾選Disable cache:查看首次載入(應為 200)

    3. 取消勾選後重新整理:

      1. 無請求或顯示 (from cache) → 強快取命中

      2. 顯示 304 → 協商快取命中

常見問題

配置修改後未生效

原因:

  1. 未執行 sudo nginx -s reload

  2. 瀏覽器、CDN 或代理緩衝了舊響應。

  3. location 匹配優先順序問題

解決:

  1. 用 curl -I http://your-url 驗證伺服器實際回應標頭

  2. 檢查 location 順序:正則匹配(如 ~* \.(css|js)$)優先順序高於首碼匹配(如 /static/),會導致請求被正則規則匹配而未命中首碼匹配的問題。

動態內容被錯誤緩衝

原因:靜態資源正則過於寬泛(如 ~* \.js$ 匹配了 /api/user.js

解決:

  1. 限定路徑:location ~* ^/static/.*\.(css|js)$

  2. 確保動態介面(如 /api/\.php$)的 location 優先匹配或明確排除緩衝

多個緩衝策略衝突

  • 原因:多個 location 匹配同一請求,僅第一個生效

  • 解決:合并策略,使用 map 按內容類型動態設定緩衝:

    # 在 http 塊中
    map $sent_http_content_type $cache_control {
        ~^image/    "public, max-age=2592000";
        text/css    "public, max-age=2592000";
        application/javascript "public, max-age=2592000";
        default     "no-cache";
    }
    
    # 在 server 塊中
    add_header Cache-Control $cache_control always;