Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537 Warning: error_log(/data/www/wwwroot/hmttv.cn/caches/error_log.php): failed to open stream: Permission denied in /data/www/wwwroot/hmttv.cn/phpcms/libs/functions/global.func.php on line 537
者:kevinylzhao,騰訊音樂(lè)前端開(kāi)發(fā)工程師
瀏覽器緩存策略對(duì)于前端開(kāi)發(fā)同學(xué)來(lái)說(shuō)不陌生,大家都有一定的了解,但如果沒(méi)有系統(tǒng)的歸納總結(jié),可能三言兩語(yǔ)很難說(shuō)明白,甚至說(shuō)錯(cuò),尤其在面試過(guò)程中感觸頗深,很多候選人對(duì)這類(lèi)基礎(chǔ)知識(shí)竟然都是一知半解,說(shuō)出幾個(gè)概念就沒(méi)了,所以重新歸納總結(jié)下,溫故而知新。
瀏覽器緩存一般分為兩類(lèi):強(qiáng)緩存(也稱本地緩存)和協(xié)商緩存(也稱弱緩存)。
瀏覽器發(fā)送請(qǐng)求前,會(huì)先去緩存里查看是否命中強(qiáng)緩存,如果命中,則直接從緩存中讀取資源,不會(huì)發(fā)送請(qǐng)求到服務(wù)器。否則,進(jìn)入下一步。
當(dāng)強(qiáng)緩存沒(méi)有命中時(shí),瀏覽器一定會(huì)向服務(wù)器發(fā)起請(qǐng)求。服務(wù)器會(huì)根據(jù) Request Header 中的一些字段來(lái)判斷是否命中協(xié)商緩存。如果命中,服務(wù)器會(huì)返回 304 響應(yīng),但是不會(huì)攜帶任何響應(yīng)實(shí)體,只是告訴瀏覽器可以直接從瀏覽器緩存中獲取這個(gè)資源。如果本地緩存和協(xié)商緩存都沒(méi)有命中,則從直接從服務(wù)器加載資源。
按照本地緩存階段和協(xié)商緩存階段分類(lèi):
上述代碼的作用是告訴瀏覽器當(dāng)前頁(yè)面不被緩存,事實(shí)上這種禁用緩存的形式用處很有限:
a. 僅有 IE 才能識(shí)別這段 meta 標(biāo)簽含義,其它主流瀏覽器僅識(shí)別“Cache-Control: no-store”的 meta 標(biāo)簽。
b. 在 IE 中識(shí)別到該 meta 標(biāo)簽含義,并不一定會(huì)在請(qǐng)求字段加上 Pragma,但的確會(huì)讓當(dāng)前頁(yè)面每次都發(fā)新請(qǐng)求(僅限頁(yè)面,頁(yè)面上的資源則不受影響)。
在 HTTP 請(qǐng)求和響應(yīng)的消息報(bào)頭中,常見(jiàn)的與緩存有關(guān)的消息報(bào)頭有:
上圖中只是常用的消息報(bào)頭,下面來(lái)看下不同字段之間的關(guān)系和區(qū)別:
a. Last-Modified 標(biāo)注的最后修改只能精確到秒級(jí),如果某些文件在 1 秒鐘以內(nèi),被修改多次的話,它將不能準(zhǔn)確標(biāo)注文件的新鮮度;
b. 某些文件也許會(huì)周期性的更改,但是它的內(nèi)容并不改變(僅僅改變的修改時(shí)間),但 Last-Modified 卻改變了,導(dǎo)致文件沒(méi)法使用緩存;
c. 有可能存在服務(wù)器沒(méi)有準(zhǔn)確獲取文件修改時(shí)間,或者與代理服務(wù)器時(shí)間不一致等情形。
瀏覽器可以在內(nèi)存、硬盤(pán)中開(kāi)辟一個(gè)空間用于保存請(qǐng)求資源副本。我們經(jīng)常調(diào)試時(shí)在 DevTools Network 里看到 Memory Cache(內(nèi)存緩存)和 Disk Cache(硬盤(pán)緩存),指的就是緩存所在的位置。請(qǐng)求一個(gè)資源時(shí),會(huì)按照優(yōu)先級(jí)(Service Worker -> Memory Cache -> Disk Cache -> Push Cache)依次查找緩存,如果命中則使用緩存,否則發(fā)起請(qǐng)求。這里先介紹 Memory Cache 和 Disk Cache。
200 from memory cache
表示不訪問(wèn)服務(wù)器,直接從內(nèi)存中讀取緩存。因?yàn)榫彺娴馁Y源保存在內(nèi)存中,所以讀取速度較快,但是關(guān)閉進(jìn)程后,緩存資源也會(huì)隨之銷(xiāo)毀,一般來(lái)說(shuō),系統(tǒng)不會(huì)給內(nèi)存分配較大的容量,因此內(nèi)存緩存一般用于存儲(chǔ)較小文件。同時(shí)內(nèi)存緩存在有時(shí)效性要求的場(chǎng)景下也很有用(比如瀏覽器的隱私模式)。
200 from disk cache
表示不訪問(wèn)服務(wù)器,直接從硬盤(pán)中讀取緩存。與內(nèi)存相比,硬盤(pán)的讀取速度相對(duì)較慢,但硬盤(pán)緩存持續(xù)的時(shí)間更長(zhǎng),關(guān)閉進(jìn)程之后,緩存的資源仍然存在。由于硬盤(pán)的容量較大,因此一般用于存儲(chǔ)大文件。
下圖可清晰看出差別:
200 from prefetch cache
在 preload 或 prefetch 的資源加載時(shí),兩者也是均存儲(chǔ)在 http cache,當(dāng)資源加載完成后,如果資源是可以被緩存的,那么其被存儲(chǔ)在 http cache 中等待后續(xù)使用;如果資源不可被緩存,那么其在被使用前均存儲(chǔ)在 memory cache。
CDN Cache
以騰訊 CDN 為例:X-Cache-Lookup:Hit From MemCache 表示命中 CDN 節(jié)點(diǎn)的內(nèi)存;X-Cache-Lookup:Hit From Disktank 表示命中 CDN 節(jié)點(diǎn)的磁盤(pán);X-Cache-Lookup:Hit From Upstream 表示沒(méi)有命中 CDN。
從上圖能感受到整個(gè)流程,比如常見(jiàn)兩種刷新場(chǎng)景:
IndexedDB 就是瀏覽器提供的本地?cái)?shù)據(jù)庫(kù),能夠在客戶端存儲(chǔ)可觀數(shù)量的結(jié)構(gòu)化數(shù)據(jù),并且在這些數(shù)據(jù)上使用索引進(jìn)行高性能檢索的 API。
異步 API 方法調(diào)用完后會(huì)立即返回,而不會(huì)阻塞調(diào)用線程。要異步訪問(wèn)數(shù)據(jù)庫(kù),要調(diào)用 window 對(duì)象 indexedDB 屬性的 open() 方法。該方法返回一個(gè) IDBRequest 對(duì)象 (IDBOpenDBRequest);異步操作通過(guò)在 IDBRequest 對(duì)象上觸發(fā)事件來(lái)和調(diào)用程序進(jìn)行通信。
常用異步 API 如下:
在 16 年曾基于 IndexDB 做過(guò)一整套緩存策略,有不錯(cuò)的優(yōu)化效果:
SW 從 2014 年提出的草案到現(xiàn)在已經(jīng)發(fā)展很成熟了,基于 SW 做離線緩存,讓用戶能夠進(jìn)行離線體驗(yàn),消息推送體驗(yàn),離線緩存能力涉及到 Cache 和 CacheStorage 的概念,篇幅有限,不展開(kāi)了。
localStorage 屬性允許你訪問(wèn)一個(gè) Document 源(origin)的對(duì)象 Storage 用于存儲(chǔ)當(dāng)前源的數(shù)據(jù),除非用戶人為清除(調(diào)用 localStorage api 或者清除瀏覽器數(shù)據(jù)), 否則存儲(chǔ)在 localStorage 的數(shù)據(jù)將被長(zhǎng)期保留。
sessionStorage 屬性允許你訪問(wèn)一個(gè) session Storage 對(duì)象,用于存儲(chǔ)當(dāng)前會(huì)話的數(shù)據(jù),存儲(chǔ)在 sessionStorage 里面的數(shù)據(jù)在頁(yè)面會(huì)話結(jié)束時(shí)會(huì)被清除。頁(yè)面會(huì)話在瀏覽器打開(kāi)期間一直保持,并且重新加載或恢復(fù)頁(yè)面仍會(huì)保持原來(lái)的頁(yè)面會(huì)話。
通過(guò)了解瀏覽器各種緩存機(jī)制和存儲(chǔ)能力特點(diǎn),結(jié)合業(yè)務(wù)制定合適的緩存策略,善用緩存是基本功,可以用于時(shí)常審查負(fù)責(zé)的業(yè)務(wù),可能就會(huì)發(fā)現(xiàn)個(gè)別業(yè)務(wù)并沒(méi)有運(yùn)用到位,共勉。
決這個(gè)問(wèn)題, 有兩個(gè)可用的方法, 使用HTML meta標(biāo)簽和使用HTTP頭。
1.使用HTML meta標(biāo)簽
阻止緩存頁(yè)面最常用的方法是使用HTML meta標(biāo)簽:
<meta http-equiv="expires" content="Wed,15 Jul 2023 07:30:28 GMT"/>
<meta http-equiv="pragma" content="no-cache"/>
已經(jīng)傳遞到Expires meta標(biāo)簽的插入日期告訴瀏覽器,緩存的頁(yè)面拷貝總是過(guò)期的。遇到此標(biāo)簽后, 瀏覽器通常不會(huì)緩存頁(yè)面。雖然Pragma: no-cache meta標(biāo)簽并不是保證,但它卻是大多數(shù)網(wǎng)絡(luò)瀏覽器遵從的受到良好支持的約定。
2.使用HTTP頭
阻止緩存頁(yè)面更好的辦法是, 應(yīng)用header()函數(shù), 使用HTTP本身協(xié)議生成與上面等價(jià)的兩個(gè)HTML meta標(biāo)簽:
<?php
header('Expires:Wed,15 Jul 2023 07:30:28 GMT');
header('Pragma:no-cache');
?>
可更進(jìn)一步, 可使用HTTP1.1的瀏覽器所支持的Cache-Control頭:
一步、按下Win+X組合鍵,喚出隱藏菜單,點(diǎn)擊里面的“設(shè)備管理器”。
第二步、在Win10設(shè)備管理器窗口,點(diǎn)開(kāi)磁盤(pán)驅(qū)動(dòng)器項(xiàng)目,然后對(duì)著電腦硬盤(pán)單擊鼠標(biāo)右鍵,點(diǎn)擊選擇菜單中的“屬性”。
第三步、在硬盤(pán)屬性對(duì)話框,點(diǎn)擊選擇“策略”選項(xiàng)卡,將“啟用此設(shè)備上的寫(xiě)入緩存”更具個(gè)人需要設(shè)置成勾選,或取消勾選后,點(diǎn)擊底部“確定”即可。
溫馨提示:勾選“啟用此設(shè)備上的寫(xiě)入緩存”是啟用該功能,取消勾選是關(guān)閉。
*請(qǐng)認(rèn)真填寫(xiě)需求信息,我們會(huì)在24小時(shí)內(nèi)與您取得聯(lián)系。