前言
瀏覽器的緩存機(jī)制也就是我們說的HTTP緩存機(jī)制,其機(jī)制是根據(jù)HTTP報(bào)文的緩存標(biāo)識(shí)進(jìn)行的。
HTTP 緩存

緩存過程:
- 第一次請(qǐng)求:不存在緩存結(jié)果和緩存標(biāo)識(shí),直接向服務(wù)器發(fā)送請(qǐng)求

- 強(qiáng)緩存:存在該緩存結(jié)果和緩存標(biāo)識(shí),且該結(jié)果尚未失效,強(qiáng)制緩存生效,直接返回緩存

- 協(xié)商緩存:存在緩存標(biāo)識(shí)和緩存結(jié)果,但是已經(jīng)失效,強(qiáng)制緩存失效,則使用協(xié)商緩存

1. 強(qiáng)緩存
強(qiáng)制緩存就是向?yàn)g覽器緩存查找該請(qǐng)求結(jié)果,并根據(jù)該結(jié)果的緩存規(guī)則來決定是否使用該緩存結(jié)果的過程
條件:Cache-Control的max-age沒有過期或者Expires的緩存時(shí)間沒有過期
結(jié)果:直接使用瀏覽器的緩存數(shù)據(jù),不會(huì)再向服務(wù)器發(fā)送任何請(qǐng)求
①. Cache-Control
HTTP1.1中啟用Cache-Control 來控制頁面的緩存與否,Cache-Control屬性是在服務(wù)器端配置的,不同的服務(wù)器有不同的配置,使用的是相對(duì)時(shí)間概念。
Cache-Control的屬性設(shè)置:
- (1). max-age:設(shè)置緩存的最大的有效時(shí)間,單位為秒(s)。max-age會(huì)覆蓋掉Expires
- (2). s-maxage:只用于共享緩存,比如CDN緩存(s -> share)。與max-age 的區(qū)別是:max-age用于普通緩存,
而s-maxage用于代理緩存。如果存在s-maxage,則會(huì)覆蓋max-age 和 Expires - (3). public:響應(yīng)會(huì)被緩存,并且在多用戶間共享。默認(rèn)是public
- (4). private:響應(yīng)只作為私有的緩存,不能在用戶間共享。如果要求HTTP認(rèn)證,響應(yīng)會(huì)自動(dòng)設(shè)置為private
- (5). no-cache:指定不緩存響應(yīng),表明資源不進(jìn)行緩存。但是設(shè)置了no-cache之后并不代表瀏覽器不緩存,而是在緩存前要向服務(wù)器確認(rèn)資源是否被更改(即協(xié)商緩存)
- (6). no-store:絕對(duì)禁止緩存
- (7). must-revalidate:如果頁面過期,則去服務(wù)器進(jìn)行獲取
目前Cache-Control請(qǐng)求字段被各個(gè)瀏覽器支持的較好,其優(yōu)先級(jí)也比較高,當(dāng)和別的字段(如Expires)一起用時(shí),會(huì)覆蓋其他字段。
②. Expires
緩存過期時(shí)間,用來指定資源到期的時(shí)間,是服務(wù)器端的具體的時(shí)間點(diǎn)。也就是說,Expires=max-age + 請(qǐng)求時(shí)間,需要和Last-modified結(jié)合使用。
Expires 是 HTTP/1 的產(chǎn)物,受限于本地時(shí)間,如果修改了本地時(shí)間,可能會(huì)造成緩存失效。
Expires屬性也是在服務(wù)端配置的。
2. 協(xié)商緩存
協(xié)商緩存就是強(qiáng)制緩存失效后,瀏覽器攜帶緩存標(biāo)識(shí)向服務(wù)器發(fā)起請(qǐng)求,由服務(wù)器根據(jù)緩存標(biāo)識(shí)決定是否使用緩存的過程。
條件:強(qiáng)制緩存max-age和Expires都過期了(或都未設(shè)置)
結(jié)果:瀏覽器發(fā)送請(qǐng)求將緩存標(biāo)識(shí)(Last-Modified、ETags)發(fā)送給服務(wù)器,校驗(yàn)(re-validate)緩存是否新鮮,然后根據(jù)新鮮度返回304或者200
①. Last-Modified和If-Modified-Since
流程:
瀏覽器首先發(fā)送一個(gè)請(qǐng)求,讓服務(wù)端在response header中返回請(qǐng)求的資源上次更新時(shí)間,就是last-modified,瀏覽器會(huì)緩存下這個(gè)時(shí)間。
然后瀏覽器再下次請(qǐng)求中,request header中帶上if-modified-since:[保存的last-modified的值]。根據(jù)瀏覽器發(fā)送的修改時(shí)間和服務(wù)端的修改時(shí)間進(jìn)行比對(duì),一致的話代表資源沒有改變,服務(wù)端返回正文為空的響應(yīng),讓瀏覽器中緩存中讀取資源。
②. ETag和If-None-Match
流程:
瀏覽器會(huì)先發(fā)送一個(gè)請(qǐng)求得到etag的值,然后再下一次請(qǐng)求在request header中帶上if-none-match:[保存的etag的值]。
通過發(fā)送的etag的值和服務(wù)端重新生成的etag的值進(jìn)行比對(duì),如果一致代表資源沒有改變,服務(wù)端返回正文為空的響應(yīng),告訴瀏覽器從緩存中讀取資源。
etag能夠解決last-modified的一些缺點(diǎn),但是etag每次服務(wù)端生成都需要進(jìn)行讀寫操作,而last-modified只需要讀取操作,性能開銷更大。
用戶行為與禁止瀏覽器緩存
1. 用戶行為對(duì)瀏覽器緩存的影響
① 打開網(wǎng)頁,地址欄輸入地址:查找 disk cache 中是否有匹配。如有則使用;如沒有則發(fā)送網(wǎng)絡(luò)請(qǐng)求。
② 普通刷新 (F5):TAB 沒有關(guān)閉,優(yōu)先使用memory cache(如果匹配的話),其次是 disk cache。
③ 強(qiáng)制刷新 (Ctrl + F5):瀏覽器不使用緩存,因此發(fā)送的請(qǐng)求頭部均帶有 Cache-control:no-cache(為了兼容,還帶了 Pragma:no-cache),服務(wù)器直接返回 200 和最新內(nèi)容。
2. 禁止瀏覽器緩存
有些時(shí)候,我們需要完全禁止瀏覽器緩存,比如vue打包過后的html,為了確保用戶能夠即使獲得最新的html,需要禁止瀏覽器緩存。
網(wǎng)上有一個(gè)meta配置no-cache
<meta http-equiv="Expires" content="0" />
<meta http-equiv="Pragma" content="no-cache" />
<meta http-equiv="Cache-control" content="no-cache" />
<meta http-equiv="Cache" content="no-cache" />
but 實(shí)際上設(shè)置是無效的(谷歌、火狐),需要服務(wù)器端設(shè)置response header 中的 cache-control 為 no-store,因?yàn)閚o-cache實(shí)際上還是會(huì)走協(xié)商緩存。