一文徹底弄懂瀏覽器快取,只需動手操作一次

語言: CN / TW / HK

theme: juejin highlight: androidstudio


前言

合理利用快取,可以提高頁面的開啟速度,這句話是前端開發者耳熟能詳的準則

但具體快取對頁面效能有多大的影響呢?為了徹底弄懂瀏覽器快取,就從動手驗證這條準則開始吧

快取對頁面效能的影響

這裡就以 掘金 主頁為例,來測試有快取和無快取這兩種情況對頁面開啟速度的影響

驗證工具:Chrome DevTools + Lighthouse

1)無快取測試

1、開啟控制檯,Network 面板勾選 Disable cache 選項

disablecache.png

2、選擇 Lighthouse 工具,點選 Analyze page load 按鈕

lighthouse.png

得到如下效能報告:

FCP(白屏時間):1s 、TTI(互動響應時間):2.8s 、LCP(最大內容時間) 2.9s

nocache.png

2)有快取測試

開啟控制檯,Network 面板取消勾選 Disable cache 選項,其他流程一樣

Disable.png

得到如下效能報告:

FCP(白屏時間):0.7s 、TTI(互動響應時間):1.4s 、LCP(最大內容時間) 1.4s

cache.png

前後兩次效能對比,有快取時:

  • 白屏時間:縮短 0.3s
  • 互動響應時間: 縮短 1.4s
  • 最大內容時間: 縮短 1.5s

通過該案例驗證了:合理利用快取確實可以提升頁面的開啟速度

什麼是瀏覽器快取?

當我們訪問一個網站時,會載入各種資源,如 HTML文件、JS、CSS、圖片等。瀏覽器會將一些不經常變的資源儲存在本地,這樣下次訪問相同網站時,就直接從本地載入資源,並不通過請求伺服器,這就是瀏覽器快取

如何判斷哪些資源是從快取中獲取呢?

Network的Size列表:

memorycache.png

在Network面板中的size列表裡,會看到兩種標識:from memory cachefrom disk cache 字樣,這就說明該資源來自快取,memory cache 表示快取來自記憶體,disk cache 表示快取來自硬碟,兩者具體的區別下文有講解

前端常用的快取方案

強快取與協商快取相結合的方案

1)HTML 文件配置協商快取;

2)JS、CSS、圖片等資源配置強快取

此方案的好處:當專案版本更新時,可以獲取最新的頁面;若版本未變化,可繼續複用之前的快取資源;既很好利用了瀏覽器快取,又解決了頁面版本更新的問題

瀏覽器的快取流程

logo.png

此圖是非常經典的瀏覽器快取流程,下面來講解其中具體的細節

強快取

如果資源沒過期,就取快取,如果過期了,則請求伺服器,一般用於JS、CSS、圖片等資源

如何判斷強快取過期?

第一次訪問頁面,瀏覽器會根據伺服器返回的 response Header 來判斷是否對資源進行快取,如果響應頭中有 cache-control 或 expires 欄位,代表該資源是強快取

response.png

Cache-Control

是 HTTP1.1 中控制網頁快取的欄位,主要取值為:

  • public:資源客戶端和伺服器都可以快取

  • privite:資源只有客戶端可以快取

  • no-cache:客戶端快取資源,但是是否快取需要經過協商快取來驗證

  • no-store:不使用快取

  • max-age:快取保質期,是相對時間

上圖中,HTTP 響應頭中 Cache-Control 為 max-age = 31536000,意思是說在 31536000 秒後該資源過期,如果未超過過期時間,瀏覽器會直接使用快取結果,強制快取生效

Cache-Control: no-cache 和 no-store的區別:

Cache-Control: no-cache:這個很容易讓人產生誤解,誤以為是響應不被快取

實際上Cache-Control: no-cache 是會被快取的,是協商快取的標識,只不過每次都會向伺服器發起請求,來驗證當前快取的有效性

Cache-Control: no-store:這個才是響應不被快取的意思

Expires

是HTTP1.0控制網頁快取的欄位,值為一個時間戳,伺服器返回該資源快取的到期時間

但 Expires 有個缺點,就是它判斷是否過期是用本地時間來判斷的,本地時間是可以自己修改的

到了HTTP/1.1,Expire 已經被 Cache-Control 替代,Cache-Control 使用了max-age相對時間,解決了Expires 的缺陷

注意:當 Cache-Control 與 expires 兩者都存在時,Cache-Control 優先順序更高

memory cache 與 disk cache 的區別?

兩者都屬於強快取,主要區別在於儲存位置和讀取速度上

1)memory cache 表示快取來自記憶體, disk cache 表示快取來自硬碟

2)memory cache 要比 disk cache 快的多!從磁碟訪問可能需要5-20毫秒,而記憶體訪問只需要100納秒甚至更快

  • memory cache 特點:
    當前tab頁關閉後,資料將不存在(資源被釋放掉了),再次開啟相同的頁面時,原來的 memory cache 會變成 disk cache
  • disk cache 特點:
    關閉tab頁甚至關閉瀏覽器後,資料依然存在,下次開啟仍然會是 from disk cache

① 第一次開啟掘金主頁並重新整理:快取來自 memory cache 和 disk cache

memory.png

② 關閉頁面再開啟時:所有的快取都來自 disk cache

disk.jpg

一般情況下,瀏覽器會將js和圖片等檔案解析執行後直接存入記憶體中,這樣當重新整理頁面時,只需直接從記憶體中讀取(from memory cache);而css檔案則會存入硬碟檔案中,所以每次渲染頁面都需要從硬碟讀取快取(from disk cache)

協商快取

瀏覽器攜帶快取標識向伺服器傳送請求,伺服器根據快取標識來決定該資源是否過期,一般用於html資源,驗證版本是否更新

觸發條件:

  • Cache-Control 的值為 no-cache (協商快取)
  • 或者 Cache-Control: max-age=0

協商快取的標識

Last-Modified

Last-Modified:檔案在伺服器最後被修改的時間,從伺服器 Respnse Headers 上獲取

last-modified.png

Last-Modified 的驗證流程:

1)第一次訪問頁面時,伺服器的響應頭會返回 Last-Modified 欄位

2)客戶端再次發起該請求時,請求頭 If-Modified-Since 欄位會攜帶上次請求返回的 Last-Modified 值

3)伺服器根據 if-modified-since 的值,與該資源在伺服器最後被修改時間做對比,若伺服器上的時間大於 Last-Modified 的值,則重新返回資源,返回200,表示資源已更新;反之則返回304,代表資源未更新,可繼續使用快取

請求的 Request Headers 上攜帶 if-modified-since 欄位:

if-modified-since.png

Etag

ETag:當前資原始檔的一個唯一標識(由伺服器生成),若檔案內容發生變化該值就會改變

etag.png

ETag 的驗證流程:

1)第一次訪問頁面時,伺服器的響應頭會返回 etag 欄位

2)客戶端再次發起該請求時,請求頭 If-None-Match 欄位會攜帶上次請求返回的 etag 值

3)伺服器根據 If-None-Match 的值,與該資源在伺服器的Etag值做對比,若值發生變化,狀態碼為200,表示資源已更新;反之則返回304,代表資源無更新,可繼續使用快取

請求的 Request Headers 上攜帶 if-none-match 欄位:

if-none-match.png

為什麼要有 Etag ?

Etag 的出現主要是為了解決一些 Last-Modified 難處理的問題:

1)一些檔案也許會週期性的更改,但是內容並不改變(僅僅改變的修改時間),這時候並不希望客戶端認為這個檔案被修改了而重新去請求;

2)某些檔案修改非常頻繁,比如在秒以下的時間內進行修改,(比方說 1s 內修改了 N 次),If-Modified-Since 能檢查到的粒度是秒級的,使用 Etag 就能夠保證這種需求下客戶端在 1 秒內能重新整理 N 次 cache

注意:Etag 優先順序高於 Last-Modified,若 Etag 與 Last-Modified 兩者同時存在,伺服器優先校驗 Etag

協商快取的兩種狀態

伺服器根據請求頭攜帶的快取標識,判斷該資源是否變化,資源未變化返回304,反之返回200

1)資源未變化,返回304

disk.jpg

2)資源已更新,返回200

disk.jpg

協商快取的流程

1)第一次請求

客戶端傳送請求,伺服器處理請求,返回檔案內容和一堆Header,包括Etag 和 Last-Modified,狀態碼200

2)第二次請求

1、客戶端發起請求,此時請求頭上會帶上 if-none-match值為Etagif-modified-since值為last-modified

2、伺服器優先判斷 Etag,若資源未變化狀態碼為304,客戶端繼續使用本地快取,若資源發生變化,狀態碼為200 並返回最新的資源

總結

在前端效能優化中,合理利用快取是非常重要的優化方式,使用好了快取,對專案效能會有不錯的提升

最後,可以回過頭再看看文中那張瀏覽器的快取流程圖,加深對瀏覽器快取的理解

文章系列

文章系列地址:github.com/xy-sea/blog

文中如有錯誤或不嚴謹的地方,請給予指正,十分感謝。如果喜歡或有所啟發,歡迎 star