一、什麼是瀏覽器快取?
為了節約網路資源的加速瀏覽,瀏覽器在使用者磁碟上對最近請求過的文件進行儲存,當訪問者再次請求這個頁面時,瀏覽器就可以直接從本地磁碟讀取資源並展示,這樣就可以加速頁面的閱覽。
二、快取的好處有哪些?
1.緩解伺服器壓力(不用每次去伺服器請求資源);
2.提升效能(開啟本地資源速度當然比開啟請求回來資源的速度要快得多);
3.減少頻寬消耗(獲取資料相當於下載資源的過程,必定會佔用一定的網路頻寬——就是您家的網速啦~);
三、快取策略
根據獲取資源的請求頭(Headers)判斷它是否命中強快取,如命中,則瀏覽器返回200,並直接從本地獲取快取資源,不會發請求到服務端;如沒有沒命中強快取,客戶端會傳送請求到服務端,服務端通過請求頭(Headers)裡面欄位驗證這個資源是否命中協商快取(啟發式快取),如命中,服務端將請求返回304,但不返回資源,從而告訴客戶端直接從快取中獲取資源;當協商快取也沒命中時,服務端將返回200,並將資源傳送給客戶端。
1.什麼是強快取?
概念:客戶端第一次問伺服器要某個資源時,伺服器丟還給客戶端所請求的這個資源同時,告訴客戶端將這個資源儲存在本地,並且在未來的某個時點之前如果還需要這個資源,直接從本地獲取就行了,不用向伺服器請求。這種方式快取下來的資源稱為強快取。
建立關係:
a.瀏覽器第一次跟伺服器請求一個資源,伺服器在返回這個資源時,在相應頭部會加上Cache-Control:max-age=xxx(http1.0中是expries欄位,同時出現使用cache-control),如下圖:
b.瀏覽器接收到資源後,連同response header一起快取下來;
c.瀏覽器再次請求同一個資源時,會先從快取中找到這個資源,獲取date(第一次資源返回的響應時間)和Cache-Control中的max-age並計算出一個有效期(date + max-age),然後再和瀏覽器請求時間比較最後判斷是否命中快取;
d.如果沒有命中快取,瀏覽器直接向伺服器發起請求,Cache-Control會在重新獲取到伺服器返回資源時更新。
Cache-Control的值及含義:
public指示響應可被任何快取區快取,包括終端使用者和CDN等代理伺服器。
private只允許被終端使用者的瀏覽器端快取,對於單個使用者的整個或部分響應訊息,不能被代理伺服器將其儲存在共享快取裡。伺服器僅僅描述當使用者的部分響應訊息,此響應訊息對於其他使用者的請求無效。
no-cache禁止使用強快取,設定了no-cache之後並不代表瀏覽器不快取,而是在快取前要向伺服器確認資源是否被更改。因此有的時候只設定no-cache防止快取還是不夠保險,還可以加上private指令,過期時間max-age=0。
no-store禁止使用快取,每次都要去伺服器重新請求,用於防止重要的資訊被無意的釋出。
max-age表示自第一次收到響應後的xxx ms以後可以用快取。
min-fresh表示客戶端希望在指定的時間內獲取最新的響應。
max-stale表明客戶端願意接收一個已經過期的資源。 可選的設定一個時間(單位秒),表示響應不能超過的過時時間。
注意:命中強快取時,瀏覽器同樣會收到status=200的response,chrome中可通過size區分從伺服器返回的資源還是強快取獲得的資源。
2.什麼是協商快取?
概念:客戶端第一次問伺服器要某個資源時,伺服器丟還給客戶端所請求的這個資源同時,將該資源的一些資訊也返回給客戶端,告訴客戶端將這個資源快取在本地。當客戶端下一次需要這個資源時,將請求以及相關資訊一併傳送給伺服器,由伺服器來判斷客戶端快取的資源是否需要更新:如不需要更新,就直接告訴客戶端獲取本地快取資源(304);如需要更新,則將最新的資源連同相應的資訊一併返回給客戶端。
建立關係:
Last-Modified & If-Modified-Since(缺點:無法精確到毫秒)
a.瀏覽器第一次請求一個資源,伺服器返回了該資源時,會在response headers中加上Last-Modified,這個response headers表示這個資源在伺服器上的最後一次修改時間;
b.當瀏覽器再次請求該資源時,會在request headers中加上If-Modified-Since,這個值即為上一次伺服器返回的Last-Modified時間;伺服器再次收到資源請求時,將If-Modified-Since時間和資源在伺服器上的最後修改時間與對比,如果If-Modifid-Since與最後修改時間一致,則命中快取,伺服器返回304,瀏覽器從快取中獲取資源;
c.若未命中快取,伺服器返回資源同時,瀏覽器快取資源的Last-Modified會被更新。
ETag & If-None-Match(缺點:ETag本身需要消耗 CPU,而它的優先順序比 Last-Modified 高,當它存在時伺服器無論 Last-Modified 是否存在都會使用它判斷,ETag在分散式系統中生成的值可能不一樣,會導致快取失效)
a.瀏覽器第一次請求一個資源,會在response headers中加上ETag(這個ETag是根據該資源生成的唯一標識,這個唯一標識是個字串,只有伺服器認為資源有變化且應該提供新的資源時才會改變ETag),瀏覽器將資源連同ETag一併快取。
b.當瀏覽器再次請求該資源時,會在request headers中加上If-None-Match,該值即為第一次伺服器返回的ETag值;
c.伺服器收到資源請求後,會根據要請求的資源重新計算生成相應的ETag,然後與If-None-Match比較。對比結果一致即命中快取,不一致則未命中快取,返回資源同時將新的ETag。
以下情況使用ETag & If-None-Match,除此之外使用Last-Modified & If-Modified-Since:
1.存在週期性重寫某些資源,但資源實際包含的內容並無變化;
2.被修改的資訊並不重要,如註釋等;
3.Last-Modified無法精確到毫秒,但有些資源更新頻率有時會小於一秒。
四、常見快取方式
1.獲取靜態資源:
Cache-Control: public, max-age=31536000
Expires: (一年後的今天)
ETag: (基於內容生成)
Last-Modified: (過去某個時間)
Vary:Accept-Encoding
2.獲取動態資源:
Cache-Control: public, max-age=0
Expires: (當前時間)
ETag: (基於內容生成)
Last-Modified: (過去某個時間)
Vary:Accept-Encoding
五、快取處理
1.圖片快取:
通過前端變化,讓js每次生成一個隨機數作引數放在url後邊
2.js、css快取:
a.引入js、css檔案時加個版本號,如果每次釋出新的js程式碼,更新對應的版本號。
b.如果內容較少可以通過script和style標籤將js和css程式碼寫到html頁面中,但內容較多時不容易維護
3.介面快取:
在請求的介面後面加一個時間戳
4.微信快取頁面