如何說明白瀏覽器快取機制?
相信很多前端童鞋對於瀏覽器快取都不太陌生,但是如果沒有系統的歸納總結,可能三言兩句很難說明白。如果有一天,面試官向你提出這個問題,如何才能完美的回答,這是一個值得思考的問題。
當然,我們不能為了應對面試才去掌握,而應該當作技能,儲備起來,做到活學活用。
一、為什麼要快取
1.快取可以減少使用者等待時間,提升使用者體驗;
2.減少網路頻寬消耗
對於網站運營者和使用者,頻寬都代表著成本,過多的頻寬消耗,都需要支付額外的費用。如果可以使用快取,只會產生極小的網路流量,這將有效的降低運營成本。
3.降低伺服器壓力
給網路資源設定有效期之後,使用者可以重複使用本地的快取,減少對源伺服器的請求,降低伺服器的壓力。此外,搜尋引擎的爬蟲機器人也能根據過期機制降低爬取的頻率,也能有效降低伺服器的壓力。
需要注意:快取使用不當,會有「髒資料」,導致使用者資料異常。
二、常見快取型別
瀏覽器快取分為強快取和協商快取。
強快取
1. Expires
: GMT
格式的時間字串,代表快取資源的過期時間
Expires
也是需要在服務端配置(具體配置也根據伺服器而定), Expires
新增的是該資源過期的日期。瀏覽器會根據該過期日期與客戶端時間對比,如果過期時間還沒到,則會去快取中讀取該資源,如果已經到期了,則瀏覽器判斷為該資源已經不新鮮要重新從服務端獲取。
通過這種方式,可以實現直接從瀏覽器快取中讀取,而不需要去服務端判斷是否已經快取,避免了這次 HTTP
請求。值得注意的是 Expires
時間可能存在 客戶端時間跟服務端時間不一致
的問題。
建議 Expires 結合 Cache-Control 一起使用,大型網站中一起使用的情況比較多見。
2. Cache-Control
: max-age
強快取利用其 max-age
值來判斷快取資源的最大生命週期,它的值單位為秒。
Cache-Control
屬性值是在 server
端配置的,不同的伺服器有不同的配置, web
伺服器 apache
、 nginx
、 IIS
,應用伺服器 tomcat
等配置都不盡相同;
協商快取
1. Last-Modified
:值為資源最後更新時間,隨伺服器 Response
返回
2. If-Modified-Since
:通過比較兩個時間來判斷資源在兩次請求期間是否有過修改,如果沒有修改,則命中協商快取。
3. ETag
:表示資源內容的唯一標識,隨伺服器 Response
返回。
Web
伺服器響應請求時,告訴瀏覽器當前資源在伺服器的唯一標識
注:HTTP 中並沒有指定如何生成 ETag,雜湊是比較理想的選擇。
4. If-None-Match
伺服器通過比較請求頭部的 If-None-Match
與當前資源的 ETag
是否一致來判斷資源是否在兩次請求之間有過修改,如果沒有修改,則命中協商快取。
三、快取流程解析
看完上面的概念,我們來看看快取流程是怎樣的?先來看看下面這張圖:
如上圖所示:
1.瀏覽器會先檢測強快取型別( Cache-Control
或者 Expires
)是否有效;
2.如果命中了強快取,則直接從本地獲取快取資源;
3.當強快取沒有命中時,客戶端會發送請求到伺服器,伺服器通過另一些 Request Header
驗證這個資源是否命中協商快取,稱為 HTTP
再驗證,如果命中,伺服器將請求返回,但不返回資源,而是告訴客戶端直接從快取中獲取,客戶端收到返回後就會從快取中獲取資源;
4.強快取不會發送請求到伺服器,但協商快取會發送伺服器請求;
5.當協商快取也沒命中時,伺服器就會將資源傳送回客戶端。
需要注意:
1.強快取和協商快取共同之處在於,如果命中快取,伺服器都不會返回資源;
2.當 F5
重新整理網頁時,跳過強快取,但是會檢查協商快取;
3.當 Ctrl + F5
強制重新整理頁面時,直接從伺服器載入,跳過強快取和協商快取;
四、不會快取的情況
當然並不是所有請求都能被快取,無法被瀏覽器快取的請求如下:
1. HTTP
資訊頭中包含 Cache-Control:no-cache
, pragma:no-cache(HTTP1.0)
,或 Cache-Control: max-age=0
等告訴瀏覽器不用快取的請求;
2.需要根據 Cookie
,認證資訊等決定輸入內容的動態請求是不能被快取的;
3.經過 HTTPS
安全加密的請求;
4. POST
請求無法被快取;
5. HTTP
響應頭中不包含 Last-Modified/Etag
,也不包含 Cache-Control/Expires
的請求無法被快取;
五、小故事大道理
上文對整個概念做了闡述,還是不夠形象,我們來通過幾個小故事生動理解一下:
Last-Modified
瀏覽器: Hi
,我需要 jartto.min.js
這個檔案,如果是在 Last-Modified: Fri Feb 15 2019 19:57:31 GMT
之後修改過的,請發給我。
伺服器:(檢查檔案的修改時間)
伺服器: Oh
,這個檔案在那個時間之後沒有被修改過,你已經有最新的版本了。
瀏覽器:太好了,那我就顯示給使用者了。
ETag
瀏覽器: Hi
,我需要 jartto.css
這個檔案,有沒有不匹配 3c61f-1c1-2aecb436
這個串的
伺服器:(檢查 ETag
…)
伺服器: Hey
,我這裡的版本也是 3c61f-1c1-2aecb436
,你已經是最新的版本了
瀏覽器:好,那就可以使用本地快取了
看完這兩個小故事,是否對協商快取有了更清晰的認識了。