與瀏覽器快取相關的expires,cache-control,last-modified,Etag等頭部資訊

伯涵發表於2018-07-28
瀏覽器快取對於現代網頁是非常有用的功能,它能將大部分改變頻率不大的元件快取到本地以加速使用者下次訪問時頁面的響應時間。

而與瀏覽器快取相關的頭有 expires,cache-control等等(如標題中提到的)
這些頭資訊分別代表什麼呢?
由淺入深。首先我們來說說條件 GET 請求。
一般我們向伺服器傳送http請求獲取資源時伺服器的響應頭中一般會包含如下的一個頭部資訊:
Last-Modified : Wed, 22 Feb 2018 04:15:54 GMT

這個頭部資訊相當於告訴瀏覽器該資源的最近修改時間,瀏覽器收到響應後會將資源和這個時間快取起來
等到下次請求相同資源的時候會在請求頭中包含如下資訊,以詢問瀏覽器資源是否發生更改:
If-Modified-Since : Wed, 22 Feb 2018 04:15:54 GMT

伺服器在收到請求後會與資源的修改最新修改時間進行對比,如果時間匹配,說明資源未發生更改併產生一個304響應,此時瀏覽器會返回如下頭部資訊:
HTTP 1.1 304 Not Modified
Last-Modified : Wed, 22 Feb 2018 04:15:54 GMT

這樣伺服器就無需向瀏覽器傳送比這個響應大的多的檔案本身,這大大節省了網頁的響應時間。
但條件GET請求說到底還是請求了後臺(詢問資源是否過期),如果元件長時間不會更新,那其實完全無需向後臺詢問。但是我們如何確定資源是否過期呢?

這就用到Expires頭了:
在瀏覽器向後臺請求不經常更新的資源時,伺服器一般會通過Expires返回一個有效期很長的過期時間:
Expires : Wed, 22 Feb 2019 04:15:54 GMT

瀏覽器收到響應後會把資源和這個時間快取起來,等得到下次再次請求相同資源的時候,瀏覽器會對比這個時間
如果沒有過期,瀏覽器會直接使用快取中的資源而不會再次向伺服器請求,這樣直接就節省了一個http請求,何樂而不為?

說道這裡,Expires看似很完美,但其實還有一個問題。
那就是Expires頭使用一個特定的時間,他要求伺服器和客戶端的始終嚴格同步。另外,過期日期需要經常檢查,並且一旦這一天到來了,還需要在服務其配置中提供一個新的日期。這當然是不符合程式設計師的性格的,我們們要找的就是一勞永逸的方法!

於是Cache-Control來到了你的面前。
HTTP1.1 引入了Cache-control頭來克服Expires頭的限制。Cache-control使用max-age指令來指定元件被快取多久。它以秒為單位定義了一個有效時間:

Cache-Control : max-age=315360000

如果從元件被請求開始過去的秒數少於max-age,瀏覽器就是用快取中的版本,這樣就避免了額外的http請求。

說完Cache-control,那麼ETag又是啥?
ETag(Entity Tag)實體標籤,是唯一標識了一個元件的一個特定版本的字串。伺服器確認元件是否過期有兩種方式,一種就是上面提到的:對比過期時間,另一種就是對比ETag字串。
如果伺服器啟用了ETag,那麼響應頭中將包含如下請求頭:
ETag : "10c345b-4cg-459e1c1f"

如果你的應用只有一臺伺服器,那麼ETag是很有用的,並且一般不會帶來問題。
但是,由於不同的伺服器下完全相同的資源都不可能擁有相同的ETag,同時如果響應頭中同時帶有ETag頭和Expires頭,那麼必須保證兩者都有效才會使用快取。因此,一般情況下會更改ETag的配置,保證其在不同的伺服器上相同的資源有相同的ETag,或者完全禁用ETag。

最後謝謝你的耐心閱讀,如果此文對你有幫助,可以點個贊哦!

相關文章