瀏覽器緩存機(jī)制

參考以下文章
https://segmentfault.com/a/1190000006741200
https://github.com/zuopf769/notebook/tree/master/fe/%E5%89%8D%E7%AB%AF%E5%BF%85%E9%A1%BB%E8%A6%81%E6%87%82%E7%9A%84%E6%B5%8F%E8%A7%88%E5%99%A8%E7%BC%93%E5%AD%98%E6%9C%BA%E5%88%B6
https://segmentfault.com/a/1190000015809379

注意,我們討論的所有關(guān)于緩存資源的問(wèn)題,都僅僅針對(duì)GET請(qǐng)求。而對(duì)于POST, DELETE, PUT這類行為性操作通常不做任何緩存。

瀏覽器緩存==客戶端緩存

瀏覽器請(qǐng)求靜態(tài)資源的過(guò)程

下面這張圖展示了某一網(wǎng)站,對(duì)不同資源的請(qǐng)求結(jié)果,其中可以看到有的資源直接從緩存中讀取,有的資源跟服務(wù)器進(jìn)行了再驗(yàn)證,有的資源重新從服務(wù)器端獲取。


瀏覽器緩存分為兩種,分別是強(qiáng)制緩存,協(xié)商緩存

強(qiáng)制緩存

瀏覽器在加載資源時(shí),會(huì)根據(jù)這個(gè)資源的http請(qǐng)求頭去看是否命中強(qiáng)緩存,如果命中強(qiáng)緩存就直接用瀏覽器緩存的資源,這個(gè)過(guò)程中沒(méi)有發(fā)請(qǐng)求給服務(wù)器

協(xié)商緩存

這個(gè)過(guò)程有發(fā)請(qǐng)求給服務(wù)器,服務(wù)器返回304,不會(huì)返回?cái)?shù)據(jù),還是繼續(xù)用瀏覽器緩存的數(shù)據(jù)。

與強(qiáng)制緩存有關(guān)的兩個(gè)屬性

Cache-Control和Expires

  • Cache-Control是HTTP1.1中新增的響應(yīng)頭
  • Expires是HTTP1.0中的響應(yīng)頭
  • Cache-Control使用的是相對(duì)時(shí)間
  • Expires指定的是具體的過(guò)期日期而不是秒數(shù)。因?yàn)楹芏喾?wù)器跟客戶端存在時(shí)鐘不一致的情況,所以最好還是使用Cache-Control.
  • Cache-Control和Expires同時(shí)使用的話,Cache-Control會(huì)覆蓋Expires

Cache-Control有什么屬性

  • max-age(單位為s)

指定設(shè)置緩存最大的有效時(shí)間,定義的是時(shí)間長(zhǎng)短。當(dāng)瀏覽器向服務(wù)器發(fā)送請(qǐng)求后,在max-age這段時(shí)間里瀏覽器就不會(huì)再向服務(wù)器發(fā)送請(qǐng)求了。

  • public

指定響應(yīng)可以在代理緩存中被緩存,于是可以被多用戶共享。如果沒(méi)有明確指定private,則默認(rèn)為public

  • private

響應(yīng)只能在私有緩存中被緩存,不能放在代理緩存上。對(duì)一些用戶信息敏感的資源,通常需要設(shè)置為private。

  • no-cache

表示必須先與服務(wù)器確認(rèn)資源是否被更改過(guò)(依靠If-None-Match和Etag),然后再?zèng)Q定是否使用本地緩存。

  • no-store

絕對(duì)禁止緩存任何資源,也就是說(shuō)每次用戶請(qǐng)求資源時(shí),都會(huì)向服務(wù)器發(fā)送一個(gè)請(qǐng)求,每次都會(huì)下載完整的資源。通常用于機(jī)密性資源。

HTTP通過(guò)緩存將服務(wù)器資源的副本保留一段時(shí)間,這段時(shí)間稱為新鮮度限值。這在一段時(shí)間內(nèi)請(qǐng)求相同資源不會(huì)再通過(guò)服務(wù)器,也就是不會(huì)向服務(wù)器發(fā)起請(qǐng)求。HTTP協(xié)議中Cache-Control 和 Expires可以用來(lái)設(shè)置新鮮度的限值,前者是HTTP1.1中新增的響應(yīng)頭,后者是HTTP1.0中的響應(yīng)頭。二者所做的事時(shí)都是相同的,但由于Cache-Control使用的是相對(duì)時(shí)間,而Expires可能存在客戶端與服務(wù)器端時(shí)間不一樣的問(wèn)題,所以我們更傾向于選擇Cache-Control。

當(dāng)expire和cache-control都過(guò)期了,也就是過(guò)了這個(gè)新鮮度限值了,我們這個(gè)時(shí)候就要用到協(xié)商緩存了,這個(gè)時(shí)候就要跟服務(wù)器進(jìn)行驗(yàn)證了。

  • 如果資源發(fā)生變化,則需要取得新的資源,并在緩存中替換舊資源。
  • 如果資源沒(méi)有發(fā)生變化,緩存只需要獲取新的響應(yīng)頭,和一個(gè)新的過(guò)期時(shí)間,對(duì)緩存中的資源過(guò)期時(shí)間進(jìn)行更新即可。
    HTTP1.1推薦使用的驗(yàn)證方式是If-None-Match/Etag,在HTTP1.0中則使用If-Modified-Since/Last-Modified。
與協(xié)商緩存有關(guān)的兩個(gè)屬性

If-None-Match/Etag或者If-Modified-Since/Last-Modified

  • Etag是HTTP1.1推薦使用的驗(yàn)證方式,是指根據(jù)實(shí)體內(nèi)容生成一段hash字符串,標(biāo)識(shí)資源的狀態(tài),由服務(wù)端產(chǎn)生。瀏覽器會(huì)將這串字符串傳回服務(wù)器,驗(yàn)證資源是否已經(jīng)修改,如果沒(méi)有修改,過(guò)程如下:


    image.png
  • ETag值通常由服務(wù)器端計(jì)算,并在響應(yīng)客戶端請(qǐng)求時(shí)將它返回給客戶端
  • If-Modified-Since與Last-Modified驗(yàn)證過(guò)程與etag類似。
    這兩個(gè)方式來(lái)驗(yàn)證時(shí)會(huì)存在下面問(wèn)題:
    有些文檔資源周期性的被重寫(xiě),但實(shí)際內(nèi)容沒(méi)有改變。此時(shí)文件元數(shù)據(jù)中會(huì)顯示文件最近的修改日期與If-Modified-Since不相同,導(dǎo)致不必要的響應(yīng)。
    有些文檔資源被修改了,但修改內(nèi)容并不重要,不需要所有的緩存都更新(比如代碼注釋)
    最佳優(yōu)化策略(消滅304)
    因?yàn)閰f(xié)商緩存本身也有http請(qǐng)求的消耗,所以最佳優(yōu)化策略就是要盡可能的將靜態(tài)文件存儲(chǔ)為較長(zhǎng)的時(shí)間,多利用強(qiáng)制緩存而不是協(xié)商緩存,這就是消滅304
    但是給文件設(shè)置一個(gè)很長(zhǎng)的cache-control也會(huì)帶來(lái)很多其他的問(wèn)題,最主要的問(wèn)題是靜態(tài)內(nèi)容個(gè)更新時(shí),用戶不能及時(shí)獲得更新的內(nèi)容,這個(gè)時(shí)候就需要利用hash來(lái)對(duì)文件進(jìn)行命名,通過(guò)每次更新不同的靜態(tài)文件名來(lái)消除強(qiáng)制緩存的影響。(hash值變了,就相當(dāng)于要請(qǐng)求一個(gè)新的文件,那么肯定就跳過(guò)協(xié)商緩存和強(qiáng)制緩存,直接請(qǐng)求新的文件)

hash命名:
http://xxx.com/main.5eas34fa.js
http://xxx.com/main.js?5eas34fa
http://xxx.com/5eas34fa/main.js

總結(jié)

  • 瀏覽器端緩存分為200 from cache和304 not modified
  • HTTP協(xié)議中Cache-Control 和 Expires可以用來(lái)設(shè)置新鮮度的限值,前者是HTTP1.1中新增的響應(yīng)頭,后者是HTTP1.0中的響應(yīng)頭。
  • max-age(單位為s)而Expires指定的是具體的過(guò)期日期而不是秒數(shù)
  • Cache-Control和Expires同時(shí)使用的話,Cache-Control會(huì)覆蓋Expires
    客戶端不用關(guān)心ETag值如何產(chǎn)生,只要服務(wù)在資源狀態(tài)發(fā)生變更的情況下將ETag值發(fā)送給它就行
  • Apache默認(rèn)通過(guò)FileEtag中FileEtag INode Mtime Size的配置自動(dòng)生成ETag(當(dāng)然也可以通過(guò)用戶自定義的方式)。
  • ETag常與If-None-Match或者If-Match一起,由客戶端通過(guò)HTTP頭信息(包括ETag值)發(fā)送給服務(wù)端處理。
  • Last-Modified常與If-Modified-Since一起由客戶端將Last-Modified值包括在HTTP頭信息中發(fā)給服務(wù)端進(jìn)行處理。
  • 有些文檔資源周期性的被重寫(xiě),但實(shí)際內(nèi)容沒(méi)有改變。此時(shí)文件元數(shù)據(jù)中會(huì)顯示文件最近的修改日期與If-Modified-Since不相同,導(dǎo)致不必要的響應(yīng)。
image.png

補(bǔ)充說(shuō)明:
web緩存分為兩種:

  1. http緩存(從第二次請(qǐng)求開(kāi)始的,也就是我們上面所說(shuō)的強(qiáng)制緩存和協(xié)商緩存,都是根據(jù)response header中的一些屬性來(lái)決定的。)
  2. 瀏覽器緩存
    2.1本地存儲(chǔ)小容量
    Cookie主要用于用戶信息的存儲(chǔ),Cookie的內(nèi)容可以自動(dòng)在請(qǐng)求的時(shí)候被傳遞給服務(wù)器。
    LocalStorage的數(shù)據(jù)將一直保存在瀏覽器內(nèi),直到用戶清除瀏覽器緩存數(shù)據(jù)為止。
    SessionStorage的其他屬性同LocalStorage,只不過(guò)它的生命周期同標(biāo)簽頁(yè)的生命周期,當(dāng)標(biāo)簽頁(yè)被關(guān)閉時(shí),SessionStorage也會(huì)被清除。
    2.2本地存儲(chǔ)大緩存
  • IndexDB
  • WebSql


    image.png

    2.3 應(yīng)用緩存和PWA

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容