瀏覽器中的緩存機制

瀏覽器中的緩存即瀏覽器保存通過HTTP獲取的所有資源,是瀏覽器將網絡資源存儲在本地的一種行爲。

一、緩存資源存儲位置及優先級

1.memory cache

MemoryCache顧名思義,就是將資源緩存到內存中,等待下次訪問時不需要重新下載資源,而直接從內存中獲取。Webkit早已支持memoryCache。 
目前Webkit資源分成兩類,一類是主資源,比如HTML頁面,或者下載項,一類是派生資源,比如HTML頁面中內嵌的圖片或者腳本鏈接,分別對應代碼中兩個類:MainResourceLoader和SubresourceLoader。雖然Webkit支持memoryCache,但是也只是針對派生資源,它對應的類爲CachedResource,用於保存原始數據(比如CSS,JS等),以及解碼過的圖片數據。

2.disk cache

DiskCache顧名思義,就是將資源緩存到磁盤中,等待下次訪問時不需要重新下載資源,而直接從磁盤中獲取,它的直接操作對象爲CurlCacheManager。

  memory cache disk cache
相同點 只能存儲一些派生類資源文件 只能存儲一些派生類資源文件
不同點 退出進程時數據會被清除 退出進程時數據不會被清除
存儲資源 一般腳本、字體、圖片會存在內存當中 一般非腳本會存在內存當中,如css等

因爲CSS文件加載一次就可渲染出來,我們不會頻繁讀取它,所以它不適合緩存到內存中,但是js之類的腳本卻隨時可能會執行,如果腳本在磁盤當中,我們在執行腳本的時候需要從磁盤取到內存中來,這樣IO開銷就很大了,有可能導致瀏覽器失去響應。 

 緩存訪問優先級(三級緩存原理)

1.現在內存中查找,如果有,直接加載

2.如果內存中不存在,則在硬盤中查找,如果有則直接加載

3.如果硬盤中也沒有,則進行網絡請求

4.請求獲取的資源緩存到硬盤和內存中

二、瀏覽器緩存的分類

1.強緩存

        瀏覽器在加載資源時,會先根據本地緩存資源的 header 中的信息判斷是否命中強緩存,如果命中則直接使用緩存中的資源不會再向服務器發送請求。

       這裏的 header 中的信息指的是 expires 和 cahe-control.

Expires

該字段是 http1.0 時的規範,它的值爲一個絕對時間的 GMT 格式的時間字符串,比如 Expires:Mon,18 Oct 2066 23:59:59 GMT。這個時間代表着這個資源的失效時間,在此時間之前,即命中緩存。這種方式有一個明顯的缺點,由於失效時間是一個絕對時間,所以當服務器與客戶端時間偏差較大時,就會導致緩存混亂。

Cache-Control

Cache-Control 是 http1.1 時出現的 header 信息,主要是利用該字段的 max-age 值來進行判斷,它是一個相對時間,例如 Cache-Control:max-age=3600,代表着資源的有效期是 3600 秒。cache-control 除了該字段外,還有下面幾個比較常用的設置值:

no-cache:需要進行協商緩存,發送請求到服務器確認是否使用緩存。

no-store:禁止使用緩存,每一次都要重新請求數據。

public:可以被所有的用戶緩存,包括終端用戶和 CDN 等中間代理服務器。

private:只能被終端用戶的瀏覽器緩存,不允許 CDN 等中繼緩存服務器對其緩存。

Cache-Control 與 Expires 可以在服務端配置同時啓用,同時啓用的時候 Cache-Control 優先級高。

2.協商緩存

當強緩存沒有命中的時候,瀏覽器會發送一個請求到服務器,服務器根據 header 中的部分信息來判斷是否命中緩存。如果命中,則返回 304 ,告訴瀏覽器資源未更新,可使用本地的緩存。

這裏的 header 中的信息指的是 Last-Modify/If-Modify-Since 和 ETag/If-None-Match.

Last-Modify/If-Modify-Since

瀏覽器第一次請求一個資源的時候,服務器返回的 header 中會加上 Last-Modify,Last-modify 是一個時間標識該資源的最後修改時間。

當瀏覽器再次請求該資源時,request 的請求頭中會包含 If-Modify-Since,該值爲緩存之前返回的 Last-Modify。服務器收到 If-Modify-Since 後,根據資源的最後修改時間判斷是否命中緩存。

如果命中緩存,則返回 304,並且不會返回資源內容,並且不會返回 Last-Modify。

缺點:

短時間內資源發生了改變,Last-Modified 並不會發生變化。

週期性變化。如果這個資源在一個週期內修改回原來的樣子了,我們認爲是可以使用緩存的,但是 Last-Modified 可不這樣認爲,因此便有了 ETag。

ETag/If-None-Match

與 Last-Modify/If-Modify-Since 不同的是,Etag/If-None-Match 返回的是一個校驗碼。ETag 可以保證每一個資源是唯一的,資源變化都會導致 ETag 變化。服務器根據瀏覽器上送的 If-None-Match 值來判斷是否命中緩存。

與 Last-Modified 不一樣的是,當服務器返回 304 Not Modified 的響應時,由於 ETag 重新生成過,response header 中還會把這個 ETag 返回,即使這個 ETag 跟之前的沒有變化。

Last-Modified 與 ETag 是可以一起使用的,服務器會優先驗證 ETag,一致的情況下,纔會繼續比對 Last-Modified,最後才決定是否返回 304。

總結

當瀏覽器再次訪問一個已經訪問過的資源時,它會這樣做:

1.看看是否命中強緩存,如果命中,就直接使用緩存了。

2.如果沒有命中強緩存,就發請求到服務器檢查是否命中協商緩存。

3.如果命中協商緩存,服務器會返回 304 告訴瀏覽器使用本地緩存。

4.否則,返回最新的資源。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章