在 本專欄 的 這一篇文章 中,給各位引出了一個“不同尋常的”性能體驗優化方式 —— 離線緩存,并介紹了它的簡單用法,本文來詳細說說!
啥是離線緩存
離線緩存又叫“ApplicationCache”,是從浏覽器緩存中分出來一塊緩存區,用來存儲一定的資源。它是HTML5的新特性。你可以使用它将構成web應用程式的資源,如HTML、css、JavaScript、圖檔等存儲到本地緩存中,這樣不僅可以使以後進來時更加友善,還可以在離線狀态時“無差别”繼續使用web應用!
離線緩存和普通的浏覽器網頁緩存有明顯的差別:
- 緩存目标:任何網頁都會自動強制緩存目前網頁(無重新整理情況下的上一個頁面),而離線緩存針對整個web應用程式,且隻儲存你明确指定的資源。
- 離線緩存的安全性高于浏覽器網頁緩存!
- 離線緩存在無網絡狀态下幾乎也能正常運作!
離線緩存的一些特性
1、對象
HTML5離線緩存有一個專門的對象(JavaScript實作),也就是俗稱的ApplicationCache API。我們可以通過控制它來動态控制緩存 —— 它可以觸發一系列與緩存狀态有關的事件。而且它和緩存宿主對象的關系是一一對應的。
比較離譜的是:離線緩存和H5一樣,不被IE9及以下的浏覽器支援。我們可以用以下代碼檢測目前浏覽器是否支援離線緩存:
if(window.applicationCache){
console.log("浏覽器支援離線緩存")
}else{
console.log("浏覽器不支援離線緩存")
}
2、屬性
applicationCache對象是有status屬性的,它可以傳回目前applicationCache的狀态 —— 這是很有用的,本文将介紹另一種更新緩存的方法,就和此有關:
- 0:未緩存(UNCACHED)
- 1:空閑(IDLE),應用緩存已是最新,并且沒有被标記為“廢棄”
- 2:檢查中(CHECKING),此時applicationCache對象已經和一個應用緩存關聯了
- 3:下載下傳中(DOWNLOADING)
- 4:更新準備就緒(UPDATEREADY),此狀态表示緩存不是最新的,而且可以更新
- 5:“廢棄”(OBSOLETE),該緩存已過期
其中“ IDLE ”是緩存中最典型的狀态,它說明目前應用程式的所有資源都已經緩存,而且不需要更新。
3、事件
對于不同的狀态,ApplicationCache API提供了特定的事件和回調特性:
- checking:當檢查更新,或者第一次下載下傳manifest檔案時,首先會被觸發
- noupdate:當檢查到manifest檔案不需要更新時觸發
- downloading:第一次下載下傳或更新manifest檔案時觸發,而且全程隻觸發一次!
- progress:在manifest檔案下載下傳過程中可被周期性觸發
- cached:manifest檔案下載下傳完畢而且緩存成功後觸發
- updateready:當manifest檔案下載下傳完畢後觸發,此後可通過重新加載頁面讀取緩存檔案或通過
方法更新緩存檔案swapCache()
- obsolete:請求資源出錯(如通路manifest緩存檔案404或410)時觸發
離線緩存的實作(應用)
它是通過配置一個配置檔案manifest進行的,文首連結文章中已經說明:
CACHE MANIFEST
# 2020-10-28 v1.1.0
1.html
/css/ss1.css
/img/cur.png
/img/loading.gif
/img/loading2.gif
/img/QQ圖檔20190521233736.jpg
/img/Cache_46072b3594a9a6b5..jpg
/img/牌.png
/img/logo.png
/js/ss1.js
NETWORK:
* # 這裡星号表示除緩存檔案外的全部資源
FALLBACK:
/ /1.html
它實際上是一個文本檔案,列出了所有需要執行操作的資源!第一行必須以CACHE MANIFEST開頭。
manifest檔案實際上隻包含三個部分:需要緩存的、不能緩存的,和無網時的代替檔案:
- CACHE MANIFEST - 在此标題下列出的檔案将在首次下載下傳後進行緩存(到本地)(:以後進來都不請求了直接拿
- NETWORK - 在此标題下列出的檔案需要每次與伺服器連接配接請求資源,且不會被緩存
- FALLBACK - 在此标題下列出的檔案規定當頁面無法通路時的回退頁面(比如 404 頁面),這裡代碼中的意思是“當無法建立網際網路連接配接時,用 “1.html” 替代 / (根)目錄下的所有檔案”
離線緩存不隻是前端的事:它需要伺服器的支援!
筆者團隊在項目中使用的Tomcat伺服器,需要更改web.xml檔案(conf目錄下):
注意: 代碼中extension的值必須和你自己寫的manifest檔案的字尾名一緻!
<mime-mapping>
<extension>appcache</extension>
<mime-type>text/cache-manifest</mime-type>
</mime-mapping>
注意:
如果manifest檔案以及manifest檔案所列出的資源無法加載,整個緩存的更新過程則無法進行,浏覽器會使用最後一次成功的緩存。
CACHE、NETWORK、FALLBACK在manifest中的順序是任意的,每一部分可以出現一次或多次。
CACHE是必需的,NETWORK和FALLBACK是可選的。
如何引用?
在web應用程式中每個需要緩存的頁面都需要包含manifest檔案的引用:
<html manifest="cache.appcache"><!-- manifest屬性值為manifest檔案路徑+名稱 -->
這裡的路徑可以使用絕對URL(http/https開頭),也可以使用相對路徑!
離線緩存的更新
有一件很可怕的事:伺服器資源更新了但是使用者看不到!這是由于設定了離線緩存但是緩存檔案資源沒有更新導緻的!
更新HTML5離線緩存目前有兩種比較常用的方法:
- 修改manifest檔案
在上面代碼中,你會發現第二行第一個字元是“#”:這表示注釋。但是它也可以滿足其他用途 —— 修改日期和版本号的注釋行是一種使浏覽器重新緩存資源檔案的方法!
(時間和版本号注釋行通常在manifest檔案的第二行)
- 使用applicationCache對象的
事件更新資源update()
比較疑惑的是:這種方式必須也要更新manifest檔案!
使用這種方式觸發時需要先調用事件:
applicationCache.update()
,這将使浏覽器嘗試更新使用者的緩存。然後判斷當
applicationCache.status
處于 UPDATEREADY 狀态(前面說過的“更新準備就緒”)時,調用
applicationCache.swapCache()
即可将原緩存換成新緩存:
var appCache=window.applicationCache;
appCache.update();
//...
if(appCache.status==window.applicationCache.UPDATEREADY){
appCache.swapCache();
}
window.addEventListener("load",function(e){
window.applicationCache.addEventListener("updateready",function(e){
if(window.applicationCache.status==window.applicationCache.READY){
window.applicationCache.swapCache();
if(confirm("資源有更新,是否重新裝載?")){
window.location.reload();
}
}
})
})