寫在前面
本來是筆記,沒想到寫著寫著就有了點文章的意思,那乾脆就完善一下發上來吼!這裡總結了幾乎所有與快取有關的內容,包括HTTP快取中的所有頭部和相應用法說明,以及對應的分組,幫助大家記憶,還有離線快取中需要注意的點。
喜歡請點贊,有問題歡迎留言討論,如有紕漏還請指正。?
HTML5離線快取
manifest
HTML5離線快取主要通過html
元素的manifest
屬性指定一個字尾為manifest
的檔案,該檔案為網頁指定哪些檔案需要被快取,哪些不需要快取,以及獲取失敗的處理方式等等,該檔案主要包含四個部分:
-
CACHE MANIFEST:標題,位於檔案首行,如果沒有指定標題,會導致檔案解析失敗
-
CACHE:該部分指定需要快取的檔案列表,內容為相對路徑,對應
html
檔案中引入的路徑,一般來說主文件無需新增,預設快取。 -
NETWORK:指定不需要快取的檔案,即永遠從服務端獲取。
-
FALLBACK:指定檔案獲取失敗後的處理方式。如:
CACHE MANIFEST
CACHE:
./js/main.js
./css/main.css
NETWORK:
signup.html # 不快取登陸頁面
FALLBACK:
signup.html offline.html
# 當無法獲取到該路徑下的請求時,所有請求都會被轉發到default.html檔案來處理
/app/ajax/ default.html
複製程式碼
其工作流程大致如下:
- 首次訪問頁面,瀏覽器載入頁面和所需資源
- 解析到
html
元素的manifest
檔案,載入CACHE
以及FALLBACK
對應的資源到快取中 - 從現在起你將完全使用瀏覽器快取中的檔案,即使強制重新整理也不會生效。隨後瀏覽器會嘗試檢查
manifest
檔案是否更新(聯機狀態才會檢查)。若manifest
檔案更新,瀏覽器會下載所有資源並更新快取。 - 離線狀態下訪問已快取的資源時,瀏覽器會從快取中讀取,而相應的,訪
NETWORK
中的資源則會對應讀取FALLBACK
。
注意點:只有manifest
檔案更新,瀏覽器才會重新下載新資源,意味著僅僅更改資原始檔內容是不會觸發更新的。這一問題可以通過在manifest
中新增版本註釋來解決。且更新快取並不會立即生效,需下次訪問生效!可通過瀏覽器API監聽相應的事件,提醒使用者重新整理瀏覽器。
applicationCache API
這是一個操作快取的瀏覽器介面,window.applicationCache
物件可以觸發一系列與快取狀態相關的事件,其status屬性0~5也對應了不同的狀態,這裡不展開了就:
window.applicationCache.oncached = function (e) {
console.log('cached!')
}
window.applicationCache.onchecking = function (e) {
console.log('checking!')
}
window.applicationCache.ondownloading = function (e) {
console.log('downloading!')
}
window.applicationCache.onerror = function (e) {
console.log('error!', e)
}
window.applicationCache.onnoupdate = function (e) {
console.log('noupdate!')
}
window.applicationCache.onupdateready = function (e) {
console.log('updateready!')
}
複製程式碼
另外可通過在瀏覽器位址列輸入:chrome://appcache-internals(因瀏覽器而異)
可以選擇檢視細節或刪除快取
HTTP快取
強快取
Cache-Control(HTTP/1.1)
通用欄位
- no-cache:本地可以快取,但是每次使用都要向伺服器驗證,無論是否過期
- no-store:完全不可以快取,每次都要去伺服器拿最新的值
- max-age:客戶端瀏覽器快取時間
- no-transform: 禁止代理改動返回的內容,如禁止代理伺服器壓縮圖片
請求欄位
- max-stale:(寬容)代理快取過期不要緊,只要在時間限制內就行
- min-fresh:(限制)代理快取需要一定新鮮度,要提前拿,否則拿不到
- only-if-cached:客戶端只接受代理伺服器的快取,不會去源伺服器拿,代理過期則直接返回504(Gateway Timeout)
響應欄位
- public:所有中間層都可以快取(客戶端,代理)
- private:只有客戶端可以快取
- s-maxage:代理伺服器快取時間(會覆蓋max-age,expires)
- must-revalidate:快取過期之前可以直接使用,一旦過期必須向伺服器驗證。會忽略max-stale頭部
- proxy-revalidate:中間伺服器接收到客戶端帶有這個頭部的請求時,在返回資料前先去源伺服器驗證快取的有效性。
- vary:vary是作為響應頭由源伺服器返回資料時新增的,其值就是當前請求的首部欄位,如:Accept,User-Agent等,代理伺服器會一併快取Vary頭部的和頭部相關的內同。作用是告訴下游伺服器如何正確匹配快取。
關於vary頭部
不同客戶端需要的內容可能是不一樣的,如有的支援gzip,有的不支援。伺服器提供的同一個介面,客戶端進行同樣的網路請求,對於不同種類的客戶端可能需要的資料不同,伺服器端的返回方式、返回資料也會不同,所以會通過Accept-Encoding,User-Agent
等資訊區別對待。
假如針對IE6
和Chrome
需要使用不同的編碼方式傳輸,代理伺服器中如果只判斷同一個介面和請求,就很有可能導致兩個瀏覽器拿到同樣的資料,毫無疑問會導致一些列問題,如亂碼等。同一個PC端和移動端應用也是如此,你提供給移動端和PC端的內容可能不同,代理伺服器可以通過判斷Vary
的User-Agent
來防止移動端誤用PC端快取。Vary
頭部的作用就體現在這裡,通過其包含的請求頭資訊來有區別的匹配快取。
具體參考:MDN-Vary ,HTTP請求的響應頭部Vary的理解
Expires(HTTP/1.0)
受限於客戶端時間,需要配合last-modified
使用。且客戶端時間與伺服器時間不同步可能會導致快取失效。屬於HTTP/1的歷史遺留產物,現階段僅用於相容。
Pragma: no-cache(HTTP/1.0)
同為HTTP/1
歷史遺留產物,一般只在為了相容HTTP/1的場合下使用。其在HTTP響應中的行為並沒有被確切規範。若cache-control
不存在的話,其行為與cache-contorl: no-cache
一致。
協商快取
協商快取生效,返回304(Not Modified)響應。若協商快取失效,返回200和請求結果。
Last-Modified/If-Modified-Since/If-Unmodified-Since
若瀏覽器檢測到響應頭中的Last-Modified
頭部,且強快取未命中時,在下次資源請求時新增請求頭If-Modified-Since
,其值對應Last-Modified
的值,若伺服器資源修改時間與If-Modified-Since
不等,說明資源變動,協商快取失效,返回新的資源。此外,If-Unmodified-Since
顧名思義。
缺點:Last-Modified
只能以秒計時若在一秒內修改多次,伺服器是感知不到的,這會導致不能正確傳送最新新資源到客戶端
E-Tag/If-Match/If-None-Match
伺服器響應請求時,通過雜湊演算法計算出檔案的一個唯一標識,並附帶在E-Tag
響應頭中,只要資源變化,E-Tag就會重新生成。同樣的,在未命中強快取且檢測到E-Tag的時候,瀏覽器就會為請求附加If-Match/If-None-Match
請求頭,其值對應E-Tag
,若驗證成功則返回304。
缺點:E-Tag
的計算,會消耗伺服器的效能,若資源頻繁變動,則伺服器需要頻繁計算。
E-Tag和Last-Modified的比較
E-Tag
精度更高,但效能相對於Last-Modified
稍遜一籌- 二者同時存在時優先考慮
E-Tag
策略
- 對於頻繁變動的資源,我們應該優先考慮使用協商快取。雖不能減少HTTP請求,但能夠顯著減小響應體積。甚至部分資料禁止快取,永遠要獲取最新值,如股市動態等。
- 對於幾乎不變的資源,優先考慮強快取。設定一個非常大的
max-age
等等。例如網站logo等。
快取來源
Service Worker
Service Worker基於HTTPS,且可以攔截全站請求以判斷資源是否快取,若快取命中則直接使用,否則使用fetch獲取最新資源。與瀏覽器內建快取策略不同的是,Service Worker可以自定義哪些資源需要快取,如何匹配快取,如何讀取快取。其生命週期中主要使用:
-
install 事件:抓取資源進行快取
-
activate 事件:遍歷快取,清除過期的資源
-
fetch 事件:攔截請求,查詢快取或者網路,返回請求的資源
具體不再展開,有興趣可以自行百度,或參考:MDN - Service Worker
Memory Cache
讀取速度極快,微秒級速度,但容量較小,且時效性差,一般關閉當前Tab標籤頁就會失效(隨程式釋放)。
Disk Cache
比Memory Cache容量大,可快取的時間也更長。