數(shù)據(jù)請求可分為三個(gè)步驟, (1)發(fā)起網(wǎng)絡(luò)請求——>(2)后端處理——>(3)服務(wù)器響應(yīng),前端緩存可在第一個(gè)和第三個(gè)步驟中優(yōu)化步驟,假如請求的數(shù)據(jù)本地存在,那就不用發(fā)送請求,假如前端數(shù)據(jù)與后端存儲數(shù)據(jù)相比沒有改變,那服務(wù)端響應(yīng)就無須返回?cái)?shù)據(jù),這樣就減少了響應(yīng)數(shù)據(jù)。
因此前端緩存可縮短網(wǎng)頁請求資源的距離,減少延遲,并且緩存的文件,可重復(fù)利用,還可減少帶寬,降低網(wǎng)絡(luò)負(fù)荷。
按照緩存策略劃分,前端緩存主要可分為http緩存、瀏覽器緩存

HTTP緩存
http緩存可分為強(qiáng)緩存和協(xié)議緩存,強(qiáng)緩存不發(fā)送請求到服務(wù)器,協(xié)商緩存發(fā)送請求到服務(wù)器。
基本原理:
瀏覽器在請求資源時(shí),會先根據(jù)響應(yīng)頭的Expires和Cache Control判斷是否命中強(qiáng)緩存,如果命中,則直接從本地緩存中讀取數(shù)據(jù),若未命中,會發(fā)送請求到服務(wù)器,通過Etag和Last-Modified驗(yàn)證是否命中協(xié)商緩存,若命中協(xié)商緩存,服務(wù)器返回請求,但不返回資源,資源從緩存中讀取,若未命中,則從服務(wù)器加載資源。
強(qiáng)緩存和協(xié)商緩存若命中,均是從客戶端緩存中讀取數(shù)據(jù)。

強(qiáng)緩存
Expires
Expires表示資源過期時(shí)間,它是服務(wù)器返回的一個(gè)絕對時(shí)間,即再次發(fā)起請求時(shí),若客戶端的時(shí)間小于Expires的值,直接使用緩存數(shù)據(jù)。但Expires受限于本地時(shí)間,若本地時(shí)間修改或受時(shí)區(qū)影響,客戶端與服務(wù)端有一方的時(shí)間不準(zhǔn)確,就會導(dǎo)致時(shí)間產(chǎn)生誤差,進(jìn)而導(dǎo)致Expires失效。
Expires: Wed, 11 May 2019 07:20:00 GMT
Cache-Control
為了彌補(bǔ)Expires的缺陷,HTTP1.1新加了Cache-Control,它優(yōu)先級高于Expires,Cache-Control表示的是一個(gè)相對時(shí)間。
在無法確定客戶端時(shí)間與服務(wù)端時(shí)間是否一致時(shí),Cache-Control是一個(gè)更好的選擇,若兩者同時(shí)存在,則只有Cache-Control生效。
Cache-Control參數(shù)介紹:
public: 所有內(nèi)容都將被緩存(客戶端和代理服務(wù)器都可緩存)
private: 所有內(nèi)容只有發(fā)起請求的客戶端可以緩存,Cache-Control的默認(rèn)取值
no-cache: 客戶端緩存,但是否使用緩存需要經(jīng)過協(xié)商緩存向服務(wù)器驗(yàn)證(為了防止從緩存中獲取過期數(shù)據(jù))
no-store: 所有內(nèi)容都不緩存,既不使用強(qiáng)緩存,也不使用協(xié)商緩存,所有內(nèi)容都從服務(wù)器獲取
max-age=<seconds>: 緩存失效時(shí)間,相對時(shí)間,緩存將在XXX秒后失效,最大不超過一年
下圖是一個(gè)強(qiáng)緩存的例子,若命中強(qiáng)緩存,狀態(tài)碼為200 OK +(緩存位置)

緩存存放在哪里?如何判斷緩存是否生效?

如上圖所示,灰色的狀態(tài)碼200表示使用了緩存數(shù)據(jù),請求對應(yīng)的size值則表示了該緩存存放的位置,memory cache和disk cache,memory cache代表使用了內(nèi)存中的緩存,disk cache表示使用的是硬盤中的緩存,瀏覽器讀取緩存的順序?yàn)閙emory——>disk——>服務(wù)器請求。
memory cache:不訪問服務(wù)器,已經(jīng)加載過該資源并且緩存在了內(nèi)存中,直接從內(nèi)存中讀取緩存,瀏覽器關(guān)閉之后,數(shù)據(jù)就不存在了,再次打開相同頁面,也不會出現(xiàn)from memory cache;
disk cache:不訪問服務(wù)器,已經(jīng)加載過該資源,直接從硬盤中讀取數(shù)據(jù),關(guān)閉瀏覽器后,數(shù)據(jù)依然存在,次資源不會隨著該頁面的關(guān)閉而被釋放掉,下次打開相同頁面,依然是from disk cache.
協(xié)商緩存
當(dāng)強(qiáng)緩存失效時(shí),會向服務(wù)器發(fā)送請求,與服務(wù)器協(xié)商,服務(wù)器根據(jù)緩存標(biāo)識判斷是否可以使用緩存,若可以使用則返回304,不再返回資源,從本地緩存中讀取資源,如資源不相同,返回200和資源,然后更新返回頭信息。


協(xié)商緩存有兩種方式Last-Modified和Etag。
Last-Modified
表示資源的上次修改時(shí)間,配合If-Modified-Since使用。
瀏覽器請求資源時(shí),服務(wù)器響應(yīng)返回資源,且響應(yīng)頭中帶有Last-Modified,該字段表示資源修改時(shí)間,下次瀏覽器再請求資源時(shí),會在請求頭中帶著If-Modified-Since字段,該字段的值是上次請求返回的Last-Modified的值,服務(wù)器收到請求時(shí),通過對比看資源是否發(fā)生過改變,若時(shí)間相同,則說明資源未被重新修改過,服務(wù)器返回一個(gè)304,通知瀏覽器資源未更新可直接從緩存中取數(shù)據(jù)。

Etag
Etag是一個(gè)數(shù)據(jù)簽名(資源對于內(nèi)容產(chǎn)生的唯一簽名,是服務(wù)器生成的一段hash字符串),配合If-None-Match使用。
瀏覽器請求資源時(shí),服務(wù)器對當(dāng)前資源返回Etag,它是服務(wù)器生成的的一個(gè)唯一標(biāo)識,下次瀏覽器再次請求該資源時(shí),會攜帶If-None-Match字段,服務(wù)器會將If-None-Match字段值與服務(wù)器中的Etag值做對比,一致則返回304,表示資源未更新,可使用緩存文件;不一致則重新返回資源文件,狀態(tài)碼為200。

Etag與Last-Modified的區(qū)別
(1)有些服務(wù)器不能精確的得到資源的最后修改時(shí)間,這樣就無法通過最后修改時(shí)間判斷資源是否更新;
(2)Last-Modified只能精確到秒;
(3)有些資源的最后修改時(shí)間改變了,但內(nèi)容并未改變,使用Last-Modified看不出內(nèi)容是否改變;
(4)Etag的精度比Last-Modified高,屬于強(qiáng)驗(yàn)證,要求資源字節(jié)級別的一致,優(yōu)先級高于Last-Modified。
瀏覽器緩存
瀏覽器緩存可以分為小容量緩存和大容量緩存。

小容量緩存主要包括cookie、localStorage和sessionStorage;
cookie
由于http是無狀態(tài)的,一旦提交完成之后,服務(wù)器與瀏覽器之間的連接就會關(guān)閉,再次交互時(shí)需要重新建立連接,這樣無法確認(rèn)用戶信息。cookie就被用來主要存放用戶信息。
基本流程:客戶端訪問服務(wù)器端,若服務(wù)器端需要記錄該用戶的狀態(tài),就在response時(shí)向客戶端發(fā)送一個(gè)Set-Cookie,客戶端就會把該cookie保存起來,當(dāng)客戶端再次訪問服務(wù)器時(shí),客戶端會在請求頭中帶上cookie;服務(wù)器接收到請求之后,分解cookie,驗(yàn)證信息,成功后返回response給客戶端。

cookie特性:
(1)cookie大小只有4KB,保存在瀏覽器端;
(2)cookie一般由服務(wù)器端生成,若在瀏覽器端生成cookie,默認(rèn)是關(guān)閉瀏覽器后失效;
(3)cookie每次都會被攜帶在http頭中,會被傳輸?shù)椒?wù)器端;
(4)存儲形式是字符串。
localStorage和sessionStorage
本地存儲,只能存儲在客戶端,不會被傳輸?shù)椒?wù)器端。
特性:
(1)sessionStorage是會話級別從存儲,一旦窗口或標(biāo)簽被關(guān)閉,數(shù)據(jù)就會被清空;localStorage是持久化存儲,除非主動刪除數(shù)據(jù),否則數(shù)據(jù)會一直存在,他倆的主要區(qū)別是生命周期不同;
(2)大小均為5MB;
(3)存儲形式是鍵值對。
常用API(以localStorage舉例,sessionStorage類似):
(1)存儲數(shù)據(jù) setItem
localStorage.setItem('name', 'Lily');
(2)讀取數(shù)據(jù) getItem
localStorage.getItem('name'); //'Lily'
(3)移除 removeItem
localStorage.removeItem('name');
(4)移除所有
localStorage.clear();
注意:
(1)webStorage存儲的數(shù)據(jù)是明文存儲,不能用于存儲重要信息。
(2)不同瀏覽器之間無法共享webStorage中的信息,同一瀏覽器的相同域名或端口的不同頁面可以共享相同的localStorage,但不同頁面之間不能共享sessionStorage的信息。
大容量存儲包括WebSql和IndexDB
WebSql
關(guān)系型數(shù)據(jù)庫,W3C已于2010年宣布舍棄,使用SQL語言。
IndexDB
非關(guān)系型數(shù)據(jù)庫
特性:
(1)以鍵值對形式存儲,所有類型的數(shù)據(jù)都可直接存入,包括js對象;
(2)存儲空間大;
(3)有同源限制
demo?http://www.zhangxinxu.com/study/201707/indexeddb-example.html
瀏覽器數(shù)據(jù)庫 IndexedDB 入門教程?http://www.ruanyifeng.com/blog/2018/07/indexeddb.html