在前端面試中,可能或多或少都會被提及快取問題,而這個問題大多數都是作為業務中不得不考慮的乙個效能優化點,如果平時沒有怎麼關注或是特意去了解這塊的童鞋們,可能就是不太了解其中的原由,那麼今天我們就這個快取問題來細細分析,幫助一些還不是太明白的或是剛入門的前端童鞋們梳理梳理,理解理解,那就話不多說,開始吧-。
其實快取有很多種,包括:http快取
,dns快取
,cdn快取
等等。今天主要介紹的就是http快取,在開始介紹之前,先簡單說說http報文。
http報文就是瀏覽器和伺服器之間通訊時傳送響應的資料塊。
瀏覽器向伺服器請求資料,傳送請求(request)報文;伺服器向瀏覽器返回資料,返回響應(response)報文。
報文主要包含以下兩部分:
屬性的頭部(header);
資料的主體部分(body);
瀏覽器每次發起請求時,先在本地快取中查詢結果以及快取標識,根據快取標識來判斷是否使用本地快取。如果快取有效,則使用本地快取;否則,向伺服器發起請求並攜帶快取標識。根據是否需要向伺服器發起http請求,將快取過程劃分為兩個部分:
強制快取
:伺服器通知瀏覽器乙個快取時間,在快取時間內,下次請求直接使用快取,不在時間內,執行比較快取策略;
協商快取
:讓客戶端與伺服器之間能實現快取檔案是否更新的驗證、提公升快取復用率,將快取資訊中的etag
和last-modified
通過請求傳送給伺服器,由伺服器校驗,返回304
狀態碼時,瀏覽器直接使用快取;
強快取優先於協商快取。
快取運作的整體流程圖如下:
[外鏈轉存失敗,源站可能有防盜煉機制,建議將儲存下來直接上傳(img-b1myvkna-1611561201592)(
當請求命中強制快取時,瀏覽器不會將本次請求發往伺服器,而是直接從快取中讀取內容,在chrome中開啟控制台,在network中顯示的是memory cache
或者是disk cache
。
[外鏈轉存失敗,源站可能有防盜煉機制,建議將儲存下來直接上傳(img-rrqgtzlq-1611561201599)(
強快取可以通過設定兩種http header
實現:expires(1.0)和cache-control(1.1)。
expires是乙個絕對時間,是快取過期時間。用以表達在這個時間點之前發起請求可以直接從瀏覽器中讀取資料,而無需重新發起請求。
expires = max-age + 到期時間。由於受限於本地時間,如果修改了本地時間,可能會造成快取失效。
該字段是伺服器響應訊息頭欄位,告訴瀏覽器在過期時間之前可以直接從瀏覽器快取中訪問資料。由於是絕對時間內,使用者可能將本讀時間進行修改,從而導致瀏覽器判斷快取失效,重新請求資源。在不考慮修改,時差或者誤差等因素也可能照成客戶端於服務端的時間不一致,致使快取失效。
優點:
http 1.0產物,可以在http 1.0和1.1中使用,簡單、易用。
以時刻標識失效時間。
缺點:
時間是由伺服器傳送的,如果伺服器時間和客戶端時間不一致,可能會出現問題。
存在版本問題,到期之前的修改客戶端是不可知的。
cache-control的優先順序比expires的優先順序高
。該欄位表示資源快取最大有效時間,在該時間內,客戶端不需要向伺服器傳送請求。前者的出現是為了解決expires
在瀏覽器中,時間被手動更改導致快取判斷錯誤的問題。如果同時存在則使用cache-control
。
常見的取值有(完整的列表可以檢視mdn):
舉個栗子?:
[外鏈轉存失敗,源站可能有防盜煉機制,建議將儲存下來直接上傳(img-7ukawq0j-1611561201603)(
圖中cache-control
指定了max-age
,public
,快取時間為31536000秒(365天)。
也就是說,在365天內再次請求這條資料,都會直接獲取快取資料庫中的資料,直接使用。
優點:
http 1.1產物,以時間間隔標識失效時間,解決了expires
伺服器和客戶端相對時間的問題。
比expires多了很多選項設定。
缺點:
存在版本問題,到期之前的修改客戶端是不可知的。
協商快取就是強制快取失效後,瀏覽器攜帶快取標識向伺服器發起請求,由伺服器根據快取標識決定是否使用快取的過程。而整個過程是需要發出請求的。
協商快取由2組欄位(不是2個),控制協商快取的字段有:
etag/if-none-match 的優先順序高於last-modified/if-modified-since。
伺服器通過last-modified
字段告知客戶端(返回資源的同時在header新增),表示資源最後一次被修改的時間,瀏覽器將這個值和內容一起記錄在快取資料庫中
下一次請求相同的資源時,瀏覽器會從自己的快取中找出「不確定是否過期的」快取,因此在請求頭中將上次的last-modified
的值寫入到請求頭的if-modified-since
字段
伺服器會將if-modified-since
的值與last-modified
字段進行對比。如果相等,這表示未修改,響應304;反之則表示修改了,響應 200 狀態碼,並返回資料
優點:
不存在版本問題,每次請求都會去伺服器進行校驗。伺服器對比最後修改時間如果相同則返回304,不同返回200及資源內容。
如果返回的是 304,返回的僅僅是乙個狀態碼而已,並沒有實際的檔案內容,因此在響應體的體積上節省是很好的優點
缺點:
只要資源發生了修改,無論內容是否發生了實質性的改變,都會將該資源返回客戶端。例如週期性重寫,但這種情況下資源包含的資料實質是一樣的。
以時刻作為標識,無法識別一秒內多次修改的情況。如果資源更新的速度是秒以下的單位,那麼該快取是不能被使用的,因為它的時間最低單位是秒。
某些伺服器不能精確的得到檔案最後修改時間。
如果檔案是伺服器動態生成的,那麼該方法的更新時間永遠是生成的時間,儘管檔案可能並沒有變化,所以也起不到快取的作用。
為了解決上述問題,出現了一組新的字段etag/in-none-match
。
etag
是上一次載入資源時,伺服器返回的。它的作用是唯一用來標識資源是否有變化
瀏覽器在下一次發起請求時,會將上一次返回的etag
值賦值給if-none-match
並新增在request header
中。服務端匹配傳入的值與上次是否一致,如果一致返回304,瀏覽器則讀取本地快取,否則返回200和更新後的資源及新的etag
優點:可以更加精確的判斷資源是否被修改,可以識別一秒內多次修改的情況
不存在版本問題,每次請求都會去伺服器進行校驗
缺點:計算etag
值需要效能損耗
分布式伺服器儲存情況下下,計算etag
的演算法如果不一致,會導致瀏覽器從乙個伺服器上獲取得頁面內容後到另一台伺服器上進行驗證時出現etag不匹配的情況
對於強制快取,伺服器通知瀏覽器乙個快取時間,在快取時間內,下次請求,直接用快取,不在時間內,執行比較快取策略。
對於協商快取,將快取資訊中的etag
和last-modified
通過請求傳送給伺服器,由伺服器校驗,返回304狀態碼時,瀏覽器直接使用快取。
前端快取之HTTP快取
說真的,當自己還很小白的時候,明明修改了js的內容了,但是就是沒有載入成功,那時候感覺好神奇,好沒道理。後來知道了這是因為快取的原因。說實話,現在基於各種框架的開發,基本上沒有在業務 過程中關注快取的事情了,當然,不包括使用localstorage和cookie。今天自己學習了一些關於前端快取的東西...
前端http快取
協商快取 禁用快取 指的是瀏覽器第一次請求資源時,瀏覽器快取在本地,並設定時間,如果在這個時間內再次請求,便會讀取快取的資源。對應策略為expires 和 cache control,cache control的優先順序高於expires。強制快取不會請求伺服器。expires 我們用pragma來...
前端快取之HTTP快取(二)
http快取 當客戶端向服務端請求資源時,會先去到瀏覽器快取,如果瀏覽器快取有需要請求資源的副本,就可以直接從瀏覽器快取中提取,而不會去到伺服器。常見的http快取都只能快取get方式請求響應的資源,不能處理其他型別的響應。http快取都是從第二次請求開始的,當第一次請求資源時,伺服器會返回資源,並...