在“使用ETag跟蹤使用者”中有一點被忽略了,因為要用這張小圖統計統計uv, 所以要求瀏覽器必須每次都要傳送這個圖片的請求。這需要伺服器對圖片的快取策略做設定。
http/1.0 和 http/1.1 的快取策略不同,瀏覽器快取這事看似簡單,實際上很容易模稜兩可,造成疏忽。
HTTP/1.0
協議文件: https://www.w3.org/Protocols/HTTP/1.0/spec.html
相關欄位:
- Date: 伺服器響應的時間
- Expires: 資源過期時間
- Last-Modified: 資源最後修改時間
- If-Modified-Since: 用來驗證資源是否過期
策略:
如果Expires設定的時間在Date之後,則瀏覽器在Expires標記的時間之前都不會訪問伺服器了,而是使用瀏覽器快取,入下圖:
如果Expires設定的時間在Date之前,或者瀏覽器時間已經在Expires之後,那麼再次訪問圖片時, 瀏覽器就要向伺服器傳送請求,但不是重新拉取資料,而是詢問伺服器該資源是否過期,方法時,把上次response中Last-Modified的時間作為If-Modified-Since的時間,傳送請求,伺服器對比該時間和資源目前的更改時間,如果未更改,則返回304,否則傳輸新檔案,如下:
HTTP/1.1
HTTP/1.0快取機制完全依賴時間,弊端顯而易見,伺服器、客戶端的時鐘不同步,文件的 更新週期小於1s, 都會出現問題。
所以HTTP/1.1提倡的快取機制是,對比文件的hash值,文件內容變,則hash變,用相對時間代替絕對時間
協議文件:https://www.w3.org/Protocols/rfc2616/rfc2616-sec13.html
HTTP/1.1 繼承 HTTP/1.0 所以HTTP/1.0的相關欄位仍然有效,保留的這些欄位就是為了相容那些僅支援HTTP/1.0的客戶端。 HTTP/1.1伺服器不應該設定與1.0矛盾的過期策略, 1.1的伺服器在沒有文件hash值時,也可以使用If-Modified-Since進行判斷文件過期。
新增欄位:
- Cache-Control: 用來控制瀏覽器的快取行為,詳見https://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.9
- ETag: 文件的Hash值
- If-None-Match: 用來驗證資源是否過期,即文件Hash值是否變化
Cache-Control最容易理解也是最常用的就是:
- no-cache: 瀏覽器快取,但是認為是過期快取
- no-store: 瀏覽器不快取
- max-age:快取有效時間段
如果想要瀏覽器每次傳送請求,還啟用快取,那就使用Cache-Control: no-cache
, 每次訪問圖片,瀏覽器都會去驗證Etag. 過程如下:
Nginx設定
最好的方法就是使用expires
指令, 它兼顧1.1和1.0, 即所有的欄位都會給設定。但是nginx不支援ETag, 需要自己實現。 如果expires -1
, 就是我需要的,瀏覽器既快取資料,但是每次訪問都請求伺服器。 詳見: http://nginx.org/en/docs/http/ngx_http_headers_module.html