web 快取大致可以分為:資料庫快取、伺服器端快取(**伺服器快取、cdn 快取)、瀏覽器快取。
在具體了解 http 快取之前先來明確幾個術語:
瀏覽器快取主要是 http 協議定義的快取機制。html meta 標籤,例如
含義是讓瀏覽器不快取當前頁面。但是**伺服器不解析 html 內容,一般應用廣泛的是用 http 頭資訊控制快取。
大致分為兩種:強快取和協商快取。強快取如果命中快取不需要和伺服器端發生互動,而協商快取不管是否命中都要和伺服器端發生互動,強制快取的優先順序高於協商快取。具體內容下文介紹。
匹配流程(已有快取的情況下):
可以理解為無須驗證的快取策略。對強快取來說,響應頭中有兩個字段 expires/cache-control 來表明規則。
expires
expires 指快取過期的時間,超過了這個時間點就代表資源過期。有乙個問題是由於使用具體時間,如果時間表示出錯或者沒有轉換到正確的時區都可能造成快取生命週期出錯。並且 expires 是 http/1.0 的標準,現在更傾向於用 http/1.1 中定義的 cache-control。兩個同時存在時也是 cache-control 的優先順序更高。
cache-control
cache-control 可以由多個字段組合而成,主要有以下幾個取值:
1.max-age指定乙個時間長度,在這個時間段內快取是有效的,單位是s。例如設定 cache-control:max-age=31536000,也就是說快取有效期為(31536000 / 24 / 60 * 60)天,第一次訪問這個資源的時候,伺服器端也返回了 expires 字段,並且過期時間是一年後。
在沒有禁用快取並且沒有超過有效時間的情況下,再次訪問這個資源就命中了快取,不會向伺服器請求資源而是直接從瀏覽器快取中取。
2.s-maxage同 max-age,覆蓋 max-age、expires,但僅適用於共享快取,在私有快取中被忽略。
3.public表明響應可以被任何物件(傳送請求的客戶端、**伺服器等等)快取。
4.private表明響應只能被單個使用者(可能是作業系統使用者、瀏覽器使用者)快取,是非共享的,不能被**伺服器快取。
5.no-cache強制所有快取了該響應的使用者,在使用已快取的資料前,傳送帶驗證器的請求到伺服器。不是字面意思上的不快取。
6.no-store禁止快取,每次請求都要向伺服器重新獲取資料。
快取的資源到期了,並不意味著資源內容發生了改變,如果和伺服器上的資源沒有差異,實際上沒有必要再次請求。客戶端和伺服器端通過某種驗證機制驗證當前請求資源是否可以使用快取。
瀏覽器第一次請求資料之後會將資料和響應頭部的快取標識儲存起來。再次請求時會帶上儲存的頭部字段,伺服器端驗證是否可用。如果返回 304 not modified,代表資源沒有發生改變可以使用快取的資料,獲取新的過期時間。反之返回 200 就相當於重新請求了一遍資源並替換舊資源。
last-modified/if-modified-since
last-modified: 伺服器端資源的最後修改時間,響應頭部會帶上這個標識。第一次請求之後,瀏覽器記錄這個時間,再次請求時,請求頭部帶上 if-modified-since 即為之前記錄下的時間。伺服器端收到帶 if-modified-since 的請求後會去和資源的最後修改時間對比。若修改過就返回最新資源,狀態碼 200,若沒有修改過則返回 304。
注意:如果響應頭中有 last-modified 而沒有 expire 或 cache-control 時,瀏覽器會有自己的演算法來推算出乙個時間快取該檔案多久,不同瀏覽器得出的時間不一樣,所以 last-modified 要記得配合 expires/cache-control 使用。
etag/if-none-match
由伺服器端上生成的一段 hash 字串,第一次請求時響應頭帶上 etag: abcd,之後的請求中帶上 if-none-match: abcd,伺服器檢查 etag,返回 304 或 200。
關於 last-modified 和 etag 區別,已經有很多人總結過了:
注意:實際使用 etag/last-modified 要注意保持一致性,做負載均衡和反向**的話可能會出現不一致的情況。計算 etag 也是需要占用資源的,如果修改不是過於頻繁,看自己的需求用 cache-control 是否可以滿足。
選擇 cache-control 的策略(摘自 google developers)
回到實際應用上來,首先要明確哪些內容適合被快取哪些不適合。
考慮快取的內容:
一些不應該被快取的內容:
可快取的內容又分為幾種不同的情況:
不經常改變的檔案:
給 max-age 設定乙個較大的值,一般設定 max-age=31536000
比如引入的一些第三方檔案、打包出來的帶有 hash 字尾 css、js 檔案。一般來說檔案內容改變了,會更新版本號、hash 值,相當於請求另乙個檔案。
標準中規定 max-age 的值最大不超過一年,所以設成 max-age=31536000。至於過期內容,快取區會將一段時間沒有使用的檔案刪除掉。
有看到用對話的形式來描述這個過程,便仿照著試圖更清晰地解釋:
可能經常需要變動的檔案:
cache-control: no-cache / max-age=0
比如入口 index.html 檔案、檔案內容改變但名稱不變的資源。選擇 etag 或 last-modified 來做驗證,在使用快取資源之前一定會去伺服器端做驗證,命中快取時會比第一種情況慢一點點,畢竟還要發請求進行通訊。
注意: 這裡只描述了最基本的思路,實際使用 http 快取需要後端配合配置,具體情況具體對待,而且各方的實現並不一定完全按照標準來的,踩踩坑更健康?。
參考文章
Http快取機制
快取快取,就是把需要的東西存起來,不需要每次都去請求。主要目的減小伺服器壓力,放到客戶端上來講,還利於節省流量,還能流暢的把ui顯示出來,提高了使用者體驗。對於http快取來講,主要的就是校驗快取的有效性,也就是新鮮度。如果客戶端不能及時響應服務端的資料變化,快取一直不能被更新,那不就是得不償失了?...
HTTP 快取機制
基於 header的示例 content length 3534http快取策略分為 1 快取策略 cache control 頭里的 public private no cache max age no store 其中no store為不儲存,no cache 0秒的max age 2 快取過期...
http快取機制
首先需要了解http協議的響應頭中的幾個欄位的含義 cache control expires 該欄位表示資源的過期時間。etag 該欄位表示資源的唯一標識。last modified 該欄位表示資源的最後修改時間。有以下2個問題需要注意 為什麼優先校驗etag,後校驗last modified?因...