記錄http的強緩存和協商緩存學習

1、瀏覽器緩存可以下降資源重複加載並提升網頁的加載速度。數組

瀏覽器的緩存分爲兩種,強緩存和協商緩存。瀏覽器

1.基本原理緩存

  • 瀏覽器在加載資源時,根據請求頭的expires和cache-control判斷是否命中強緩存,是則直接從緩存讀取資源,不會發請求到服務器。
  • 若是沒有命中強緩存,瀏覽器必定會發送一個請求到服務器,經過last-modified和etag驗證資源是否命中協商緩存,若是命中,服務器會將這個請求返回,可是不會返回這個資源的數據,依然是從緩存中讀取資源
  • 若是前面二者都沒有命中,直接從服務器加載資源
2.異同點

(1)相同點bash

若是命中,都是從客戶端緩存中加載資源,而不是從服務器加載資源數據服務器

(2)不一樣點編碼

強緩存:直接從本地副本對比讀取,不去請求服務器,返回的狀態碼是200url

協商緩存:會去服務器比對,若沒改變才直接讀取本地緩存,返回的狀態碼是304spa


2、強緩存

強緩存主要包括expires和cache-control。設計

1.expires代理

expires是HTTP1.0中定義的緩存字段。當咱們請求一個資源,服務器返回時,能夠在Response Headers中增長expires字段表示資源的過時時間

expires: Thu, 03 Jan 2019 11:43:04 GMT複製代碼

它是一個時間戳,當客戶端再次請求該資源的時候,會把客戶端時間與該時間戳進行對比,若是大於該時間戳則已過時,不然直接使用該緩存資源。

可是,有個大問題,發送請求時使用的是客戶端時間去對比。一是客戶端和服務端時間可能快慢不一致,另外一方面是客戶端的時間是能夠自行修改的(好比瀏覽器是跟隨系統時間的,修改系統時間會影響到),因此不必定知足預期。

2.cache-control

正因爲上面說的可能存在的問題,HTTP1.1新增了cache-control字段來解決該問題,多以當cache-control和expires都存在時,cache-control優先級更高。該字段是一個時間長度,單位秒(s),表示該資源過了多少秒後失效。當客戶端請求資源的時候,發現該資源還在有效時間內則使用該緩存,它不依賴客戶端時間。cache-control主要有max-age和s-maxage、public和private、no-cache和no-store等值。

(1)max-age和s-maxage

二者是cache-control的主要字段,它們是一個數組,表示資源過了多少秒以後變爲無效。在瀏覽器中,max-age和s-maxage都起做用,並且s-maxage的優先級高於max-age。在代理服務器中,只有s-maxage起做用。能夠經過設置max-age爲0表示立馬過時來向服務器請求資源。

(2)public和private

public表示該資源能夠被全部客戶端和代理服務器緩存,而private表示該資源僅能客戶端緩存。默認值是private,當設置了s-maxage的時候表示容許代理服務器緩存,至關於public。

(3)no-cache和no-store

no-cache表示的是不直接詢問瀏覽器緩存狀況,而是去向服務器驗證當前資源是否更新(即協商緩存)。no-store則更狠,徹底不使用緩存策略,不緩存請求或響應的任何內容,直接向服務器請求最新。因爲二者都不考慮緩存狀況而是直接與服務器交互,因此當no-cache和no-store存在時會直接忽略max-age等。

3.pragma

它的值有no-cache和no-store,表示意思同cacha-control,優先級高於cache-control和expires,即三者同時出現時,先看pragma -> cache-control -> expires。

pragma: no-cache複製代碼

3、協商緩存

上面的expires和cache-control都會訪問本地緩存直接驗證看是否過時,若是沒過時直接使用本地緩存,並返回200。但若是設置了no-cache則本地緩存會被忽略,會去請求服務器驗證資源是否更新,若是沒更新才繼續使用本地緩存,此時返回的是304,這就是協商緩存。協商緩存主要包括last-modifed和etag。

1.last-modified

last-modified記錄資源最後修改的時間。啓用後,請求資源以後的響應頭會增長一個last-modified字段,以下:

last-modified: Thu, 20 Dec 2018 11:36:00 GMT複製代碼

當再次請求該資源時,請求頭中會帶有if-modified-since字段,值是以前返回的last-modified的值,如:if-modified-since:Thu, 20 Dec 2018 11:36:00 GMT。服務端會對比該字段和資源的最後修改時間,若一致則證實沒有被修改,告知瀏覽器可直接使用緩存並返回304;若不一致則直接返回修改後的資源,並修改last-modified爲新的值。

但last-modified有如下兩個缺點:

  • 只要編輯了,無論內容是否真的有改變,都會以這最後修改的時間做爲判斷依據,當成新資源返回,從而致使了不必的請求響應,而這正是緩存原本的做用即避免不必的請求。
  • 時間的精確度只能到秒,若是在一秒內的修改時檢測不到更新的,仍會告知瀏覽器使用舊的緩存。
2.etag

爲了解決last-modified上述問題,有了etag。etag會基於資源的內容編碼生成一串惟一的標識字符串,只要內容不一樣,就會生成不一樣的etag。啓用etag以後,請求資源後的響應返回會增長一個etag字段,以下:

ETag:W/"14e2-16b26fefeb0"

當再次請求該資源時,請求頭會帶有if-no-match字段,值是以前返回的etag值,如:ETag:W/"14e2-16b26fefeb0"。服務端會根據該資源當前的內容生成對應的標識字符串和該字段進行對比,若一致則表明未改變可直接使用本地緩存並返回304;若不一致則返回新的資源(狀態碼200)並修改返回的etag字段爲新的值。

能夠看出etag比last-modified更加精確地感知了變化,因此etag優先級也更高。不過從上面也能夠看出etag存在的問題,就是每次生成表示字符串會增長服務器的開銷。因此要如何使用last-modified和etag還須要根據具體需求進行權衡。

4、訪問刷新分析

咱們將訪問和刷新分爲如下三種狀況:

  • 標籤進入、輸入url回車進入
  • 按刷新按鈕、F5刷新、網頁右鍵「從新加載」
  • ctrl+F5強制刷新
假設當前有這麼一個index頁面,返回的響應信息以下:

cache-control: max-age=72000
expires: Tue, 20 Nov 2018 20:41:14 GMT
last-modified: Tue, 20 Nov 2018 00:41:14 GMT複製代碼

一、標籤進入、輸入url回車進入

這種狀況下會根據實際設計的緩存策略去判斷。

1.因爲該例沒有設置no-cache和no-store,因此默認先走強緩存路線。根據cache-control(expires優先級低)判斷緩存是否過時,若沒有過時則此時返回200(from cache)。

2.若本地緩存已通過期再走協商緩存路線,根據以前的last-modified值去與服務器比對,若這個時間以後沒有改過則去讀本都緩存,返回304(not modified)。

3.不然返回新的資源,狀態碼200(ok),並更新返回響應的last-modified值。

二、按刷新按鈕、F5刷新、網頁右鍵「從新加載」

這種狀況下,實際是瀏覽器將cache-control的max-age直接設置成了0,讓緩存當即過時,直接走協商緩存路線。發送的請求頭以下:

cache-control: max-age=0
if-modified-since: Tue, 20 Nov 2018 00:41:14 GMT複製代碼

3.ctrl+F5強制刷新

瀏覽器不只會對本地文件過時,並且不會帶上if-modified-since,if-no-match,至關於以前歷來沒有請求過,返回結果是200

相關文章
相關標籤/搜索