瀏覽器快取策略大家一定不陌生,如果沒有進行系統的歸納總結,可能三言兩語說不清楚。這點我在面試中感觸頗深,以前未經過深入理解時,只能說出幾個概念或者回答得比較模糊,甚至說錯,顯得自己的基礎知識特別不紮實。瀏覽器快取介紹
快取機制(原理)
快取分類
協商快取
快取位置
下面是我做的乙個大致的思維導圖:
1.瀏覽器快取介紹
瀏覽器快取就是把乙個請求過的資源(如、css、js等)儲存在本地。當下次傳送請求時,如果是相同的 url,瀏覽器會根據快取機制決定是直接使用快取資源,還是重新向伺服器再次傳送請求獲取資源。
2.快取機制(原理)
瀏覽器傳送請求前,根據請求頭的 expires 和 cache-control 判斷是否命中強快取策略(包括是否過期),如果命中,直接從快取獲取資源,不會再請求伺服器。
沒有命中強快取規則,瀏覽器會傳送請求,根據請求頭的 last-modified 和 etag 判斷是否命中協商快取,如果命中,直接從快取獲取資源。
如果前兩步都沒有命中,則直接從伺服器獲取資源。
3.快取分類
強快取
強快取是指,瀏覽器不會像伺服器傳送請求,而是直接從本地快取中讀取內容。
與其相關的響應頭是expires
和cache-control
。
expires
它是響應頭欄位,用來設定資源的過期時間,瀏覽器通過將其與當前本地時間對比,判斷資源是否過期,在此時間之後則過期。
它的值是gmt格式的標準時間,如:
expires: sun, 20 jun 2021 02:19:39 gmt注意:expires 是伺服器下發的
絕對時間
,無法保證客戶端與伺服器時間的一致性。原因一是本地時間本來就可能與伺服器時間有偏差,二是如果使用者修改了本地系統的時間也會導致偏差。所以 expires 是有缺陷的。
cache-control
它是通用訊息頭欄位,被用在http請求和響應中,通過設定指定指令實現快取機制。其中,最重要的指令是 「max-age=」。同樣地,它也是用來設定資源的過期時間。
cache-control: max-age=31536000 // 設定了一年後過期注意:相對 expires 而言,max-age 設定的是
相對時間
,是距離發起請求的時間的秒數。無論本機與伺服器時間是否一致,最後以相對時間為準;在此時間內不會再去請求伺服器,直接去瀏覽器拿快取。
cache-control 常見值有:(完整的列表可以檢視:mdn)
expires 是 http/1.0 協議中的。 為了解決 expires 的缺陷, http/1.1 中新增了cache-control 來定義快取過期時間。
自從 http/1.1 開始,expires 逐漸被 cache-control 取代。兩者同時存在的話,cache-control 的優先順序高於 expires,expires 的存在只是為了相容 http/1.0。所以為了相容 http/1.0 和 http/1.1,實際專案中兩個字段我們都會設定。
順便提一下,http/1.0 還有乙個功能比較弱的快取控制機制:pragma。請求中包含 pragma 的效果跟在頭資訊中定義 cache-control: no-cache 是相同的。使用 pragma 時將忽略 expires 和 cache-control 頭,通常定義 pragma 是為了向後相容基於http/1.0的客戶端。協商快取協商快取是指,在強快取失效後,瀏覽器會先請求一下伺服器詢問該快取是否可用,可用則直接使用該快取,不可用則重新向伺服器傳送請求。
與其相關的響應頭是last-modified
、if-modified-since
、etag
、if-none-match
last-modified
瀏覽器第一次請求資源時,伺服器返回資源的同時,會在響應頭中新增last-modified
字段,寫明資源最後一次被修改的時間。瀏覽器將這個值和內容一起記錄在快取資料庫中。
last-modified: fri, 23 oct 2020 10:49:15 gmtif-modified-since瀏覽器再次請求這個資源時,會在請求頭中將上次的
last-modified
的值寫入到請求頭的if-modified-since
欄位中。
接下來,伺服器會將if-modified-since
的值與last-modified
字段進行對比。如果相等,則表示未修改,響應 304 狀態碼;如果if-modified-since
的時間小於伺服器中這個資源的最後修改時間,則表示修改了,響應 200 狀態碼,並返回最新資料。
但是 last-modified/if-modified-since 還是有缺陷:
既然根據檔案修改時間來決定是否快取存在缺陷,為了解決這些缺陷,所以在 http/1.1 增加了etag
和if-none-match
,直接根據檔案內容是否修改來決定是否快取。
etag
響應頭欄位,是資源的特定版本的識別符號。etag
是由服務端生成的(一般採用 hash 演算法生成),只要資源有變化,etag就會重新生成。伺服器返回資源的同時,會在響應頭中新增該欄位,瀏覽器會將 etag 與資源快取。
if-none-match
瀏覽器再次請求這個資源時,會在請求頭中將上次的etag
的值寫入到請求頭的if-none-match
欄位中。
接下來,伺服器會將if-none-match
的值與伺服器上該資源的etag
字段進行對比。如果一致,則表示未修改,響應 304 狀態碼;如果匹配不上,響應 200 狀態碼,並返回最新資料。
(看出來了嗎,流程其實跟 last-modified/if-modified-since 是一樣的,只是使用的字段不一樣而已)
etag:w/「cd86460562d990d7cd0aad77a850203d」說了這麼多,你可能會問,快取的資源存在**呢?那麼請繼續看叭~if-none-match:w/「cd86460562d990d7cd0aad77a850203d」
4.快取位置
我們開啟 csdn 首頁來看看,在 chrome 的開發工具中,network->size 列可以看到請求的最終處理方式。
第一次傳送請求後,size 列顯示的都是資源大小:
再次傳送請求,size 列顯示的值就出現了變化。可以看到 有的是 memory cache,有的是 disk cache:
其實,size 列主要有 4 種情況:
1.資源的大小:表示進行了網路請求
2.memory cache:表示來自記憶體中的快取。
3.disk cache:表示來自硬碟上的快取。(先讀記憶體再讀硬碟)
4.serviceworker:取自 serviceworker 的快取。(以後專門寫一篇)
快取讀取順序:(service worker -> memory cache -> disk cache)
1. 當有service worker時,瀏覽器會從 service worker 讀取快取
2. 再去記憶體讀取快取,如果有,直接載入
3. 如果記憶體沒有,則從硬碟讀取,如果有直接載入
4. 如果硬碟也沒有,那麼就進行網路請求
5. 獲取到的資源快取到硬碟和記憶體
瀏覽器快取篇
在前端開發中,快取有利於加快網頁的載入速度,同時快取能夠被反覆利用,所以可以減少流量和頻寬的開銷。瀏覽器的快取問題,主要指的是http的快取 即協議層。而h5新增的storage和資料庫快取,那是應用層快取,並不被計入本篇的分析內容裡面。下面我們正式開始來進行快取的分析。協議層的快取,其實,可以被分...
瀏覽器快取總結
瀏覽器快取主要有兩類 快取協商 last midified etag 徹底快取 cache control,expires b 快取協商 b 的意思是需要去伺服器端詢問頁面有沒有修改過,沒有修改過則返回304直接使用快取內容,否則返回新內容 協商步驟 list 伺服器傳送帶last midified...
Nginx瀏覽器快取篇
環境 centos7 nginx 1.16.0 expires原理 給http新增cache control expires頭 expires指令控制http應答中的 expires 和 cache control header頭部資訊,啟動控制頁面快取的作用 time 可以使用正數或負數。expi...