快取專題:HTML5離線快取與HTTP快取

雨涼念秋發表於2020-04-06

寫在前面

本來是筆記,沒想到寫著寫著就有了點文章的意思,那乾脆就完善一下發上來吼!這裡總結了幾乎所有與快取有關的內容,包括HTTP快取中的所有頭部和相應用法說明,以及對應的分組,幫助大家記憶,還有離線快取中需要注意的點。

喜歡請點贊,有問題歡迎留言討論,如有紕漏還請指正。?

HTML5離線快取

manifest

HTML5離線快取主要通過html元素的manifest屬性指定一個字尾為manifest的檔案,該檔案為網頁指定哪些檔案需要被快取,哪些不需要快取,以及獲取失敗的處理方式等等,該檔案主要包含四個部分:

  1. CACHE MANIFEST:標題,位於檔案首行,如果沒有指定標題,會導致檔案解析失敗

  2. CACHE:該部分指定需要快取的檔案列表,內容為相對路徑,對應html檔案中引入的路徑,一般來說主文件無需新增,預設快取。

  3. NETWORK:指定不需要快取的檔案,即永遠從服務端獲取。

  4. FALLBACK:指定檔案獲取失敗後的處理方式。如:

CACHE MANIFEST

CACHE:
./js/main.js
./css/main.css

NETWORK:
signup.html # 不快取登陸頁面

FALLBACK:
signup.html offline.html
# 當無法獲取到該路徑下的請求時,所有請求都會被轉發到default.html檔案來處理
/app/ajax/ default.html
複製程式碼

其工作流程大致如下:

  1. 首次訪問頁面,瀏覽器載入頁面和所需資源
  2. 解析到html元素的manifest檔案,載入CACHE以及FALLBACK對應的資源到快取中
  3. 從現在起你將完全使用瀏覽器快取中的檔案,即使強制重新整理也不會生效。隨後瀏覽器會嘗試檢查manifest檔案是否更新(聯機狀態才會檢查)。若manifest檔案更新,瀏覽器會下載所有資源並更新快取。
  4. 離線狀態下訪問已快取的資源時,瀏覽器會從快取中讀取,而相應的,訪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等資訊區別對待。

假如針對IE6Chrome需要使用不同的編碼方式傳輸,代理伺服器中如果只判斷同一個介面和請求,就很有可能導致兩個瀏覽器拿到同樣的資料,毫無疑問會導致一些列問題,如亂碼等。同一個PC端和移動端應用也是如此,你提供給移動端和PC端的內容可能不同,代理伺服器可以通過判斷VaryUser-Agent來防止移動端誤用PC端快取。Vary頭部的作用就體現在這裡,通過其包含的請求頭資訊來有區別的匹配快取。

具體參考:MDN-VaryHTTP請求的響應頭部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的比較

  1. E-Tag精度更高,但效能相對於Last-Modified稍遜一籌
  2. 二者同時存在時優先考慮E-Tag

策略

  1. 對於頻繁變動的資源,我們應該優先考慮使用協商快取。雖不能減少HTTP請求,但能夠顯著減小響應體積。甚至部分資料禁止快取,永遠要獲取最新值,如股市動態等。
  2. 對於幾乎不變的資源,優先考慮強快取。設定一個非常大的max-age等等。例如網站logo等。

快取來源

Service Worker

Service Worker基於HTTPS,且可以攔截全站請求以判斷資源是否快取,若快取命中則直接使用,否則使用fetch獲取最新資源。與瀏覽器內建快取策略不同的是,Service Worker可以自定義哪些資源需要快取,如何匹配快取,如何讀取快取。其生命週期中主要使用:

  1. install 事件:抓取資源進行快取

  2. activate 事件:遍歷快取,清除過期的資源

  3. fetch 事件:攔截請求,查詢快取或者網路,返回請求的資源

具體不再展開,有興趣可以自行百度,或參考:MDN - Service Worker

Memory Cache

讀取速度極快,微秒級速度,但容量較小,且時效性差,一般關閉當前Tab標籤頁就會失效(隨程式釋放)。

Disk Cache

比Memory Cache容量大,可快取的時間也更長。

相關文章