在面試中,我們經(jīng)常會(huì)被問到怎樣優(yōu)化頁面加載速度,顯而易見,最好的辦法就是不通過網(wǎng)絡(luò)下載資源,直接在本地磁盤獲取內(nèi)容。于是我們引入緩存,請(qǐng)求可以從緩存中直接獲取目標(biāo)數(shù)據(jù)并返回,有效提升響應(yīng)速度。
每個(gè)瀏覽器都自帶了 HTTP 緩存實(shí)現(xiàn)功能。我們只需要確保每個(gè)服務(wù)器響應(yīng)都提供正確的 HTTP 頭部字段,以指示瀏覽器何時(shí)可以緩存響應(yīng)以及可以緩存多久。下面介紹四種常見的設(shè)置緩存方式:
- Cache-control
Cache-Control 指令控制誰在什么條件下可以緩存響應(yīng)以及可以緩存多久。
在消息頭里設(shè)置Cache-control:
Cache-control:cache-directive
作為請(qǐng)求首部時(shí),cache-directive 的可選值有:

作為響應(yīng)首部時(shí),cache-directive 的可選值有:

舉例:
Cache-control:public,max-age = 3600
這條指令意味著該資源是從原服務(wù)器上取得的,緩存有效時(shí)間為一小時(shí),在這一小時(shí)之內(nèi)用戶都不需要向服務(wù)器重發(fā)該請(qǐng)求,可以直接從內(nèi)存里讀取該資源。
- Expires
Expires 指定了一個(gè)日期/時(shí)間, 在這個(gè)時(shí)間之前,發(fā)送的請(qǐng)求不需要向服務(wù)器訪問,直接使用緩存資源,超出這個(gè)時(shí)間,HTTP響應(yīng)就被認(rèn)為是過時(shí)的;
例如:
Expires:Mon, 19 Jun 2017 08:17:23 GMT
注意:Expires的時(shí)間格式是格林威治時(shí)間(GMT),使用的是絕對(duì)時(shí)間。
- Last-modified
Last-modified標(biāo)記這個(gè)資源在服務(wù)期端最后被修改的時(shí)間。
例如:
Last-modified:Mon, 19 Jun 2017 08:17:23 GMT
瀏覽器可以根據(jù)這個(gè)時(shí)間自己設(shè)置是否緩存以及還存多久(每個(gè)瀏覽器對(duì)此的理解不同)。假如這個(gè)時(shí)間距離現(xiàn)在已經(jīng)有一年,那么說明此資源已經(jīng)很久沒被更新,那么可以考慮緩存。
Etag
Etag所攜帶的內(nèi)容是一個(gè)隨機(jī)的標(biāo)識(shí)符(哈希值或某個(gè)其他指紋),這個(gè)標(biāo)識(shí)符是服務(wù)器生成的,瀏覽器不需要關(guān)心這個(gè)標(biāo)識(shí)符是怎樣生成的,只需要在下一次發(fā)起同樣請(qǐng)求時(shí)帶上這個(gè)Etag字段,服務(wù)器會(huì)檢查這個(gè)Etag,如果與上次的相同,服務(wù)器會(huì)返回304(Not Modified),則表示資源未發(fā)生變化,瀏覽器就可以跳過下載,直接使用本地緩存。如果與上次的不相同,那么直接返回 GET 200形式將新的資源(當(dāng)然也包括了新的ETag)發(fā)給客戶端;
示例:
Etag: "5d8c72a5edda8d6a:3239"
那么客戶端是如何把標(biāo)記在資源上的 ETag 傳回給服務(wù)器的呢?
只需要在請(qǐng)求里加入兩個(gè)Etag值
- If-None-Match
If-None-Match: "5d8c72a5edda8d6a:3239"
這條指令意味著如果 ETag 沒匹配上就重發(fā)新的資源數(shù)據(jù),否則返回送304 和響應(yīng)頭。當(dāng)前各瀏覽器均是使用的該請(qǐng)求頭來向服務(wù)器傳遞保存的 ETag 值。
- If-Match
告訴服務(wù)器如果沒匹配到ETag,或者收到了“*”值而當(dāng)前并沒有該資源實(shí)體,則應(yīng)當(dāng)返回412(Precondition Failed) 狀態(tài)碼給客戶端。否則服務(wù)器直接忽略該字段。
總結(jié)
- Cache-control、Expires存在版本問題,如果在到期以前更新了資源瀏覽器無法知道。
- Expires使用的是絕對(duì)時(shí)間,如果服務(wù)器與瀏覽器時(shí)間不一樣,可能會(huì)出現(xiàn)問題。
關(guān)于緩存,更詳細(xì)的總結(jié)可以看HTTP緩存控制小結(jié)