不管三七二十一,先丟一張流程圖,然後看個一分鐘。
有了大致的流程印象之後,我就來補充説明一下大概流程:
PS:面試的時候可以按大概流程來説。
當我們進入頁面或刷新頁面時,瀏覽器會加載資源。
此時,瀏覽器會檢查是否有強緩存,即判斷是否有expires或者cache-control(cache-control優先級更高)。
如果有,則查看是否過期,未過期則從緩存讀取資源進行加載。
如果過期,則判斷瀏覽器是否有協商緩存。協商緩存標誌包括了Last-Modify/If-Modify-Since和ETag/If-None-Match(ETag優先級更高)。
如果沒有,則直接向服務器發送請求獲取資源。
如果有,則向服務器發送協商緩存標誌,服務器根據瀏覽器發送過來的標誌判斷是否與服務器上相同。
若相同,則服務器返回 304,並且不會返回資源內容,瀏覽器從協商緩存讀取資源進行加載。
若不同,則服務器返回200,並返回資源內容給瀏覽器加載。
講完了大概流程,就需要來補充細節啦。
瀏覽器緩存分為強緩存和協商緩存
強緩存
強緩存分為memory cache和disk cache,如下表所示。
| memory cache | disk cache | |
|---|---|---|
| 定義 | 即內存緩存,將資源緩存在內存中 | 即磁盤緩存,將資源緩存在磁盤中 |
| 相同點 | 能存放JS,CSS,圖片等內容 | 能存放JS,CSS,圖片等內容 |
| 不同點 | 退出進程時數據會被清除 | 退出進程時數據不會被清除 |
三級緩存原理
瀏覽器先在內存中查找資源,如果有,直接加載。
如果內存中不存在,則在磁盤中查找,如果有直接加載。
如果磁盤中也沒有,那麼就進行網絡請求。
請求獲取的資源緩存到硬盤和內存。
協商緩存
當強緩存沒有命中的時候,瀏覽器會發送一個請求到服務器,服務器根據 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。
部分內容引用自《實踐這一次,徹底搞懂瀏覽器緩存機制》:https://segmentfault.com/a/11...