原文: 聊一聊H5應用緩存-Manifestcss
Manifest 是 H5提供的一種應用緩存機制, 基於它web應用能夠實現離線訪問(offline cache). 爲此, 瀏覽器還提供了應用緩存的api--applicationCache. 雖然manifest的技術已被web標準廢棄, 但這不影響咱們嘗試去了解它. 也正是由於manifest的應用緩存機制如此誘人, 餓了麼 和 office 365郵箱等都還在使用着它!html
對manifest熟悉的同窗能夠跳過此節.html5
鑑於manifest應用緩存的技術, 咱們能夠作到:ios
離線訪問: 即便服務器掛了, 或者沒有網絡, 用戶依然能夠正常瀏覽網頁內容.git
訪問更快: 數據存在於本地, 省去了瀏覽器發起http請求的時間, 所以訪問更快, 移動端效果更爲明顯.github
下降負載: 瀏覽器只在manifest文件改動時纔去服務器下載須要緩存的資源, 大大下降了服務器負載.web
manifest緩存的過程以下(來自網絡):chrome
主流瀏覽器都支持manifest應用緩存技術. 以下表格:api
IE | Edge | Firefox | Chrome | Safari | Opera | ios | Android |
---|---|---|---|---|---|---|---|
10+ | 12+ | 3.5+ | 4+ | 4+ | 11.5+ | 7.1+ | 2.3+ |
H5標準中, Offline Web applications 部分有以下描述:瀏覽器
This feature is in the process of being removed from the Web platform. (This is a long process that takes many years.) Using any of the offline Web application features at this time is highly discouraged. Use service workers instead. [SW]
所以後續我將在其餘文章中繼續介紹 service workers, 本篇繼續關注manifest.
manifest使用緩存清單進行管理, 緩存清單須要與html標籤進行關聯. 以下:
<html manifest="test.appcache"> ... </html>
在html標籤中指定manifest文件, 便表示該網頁使用manifest進行離線緩存. 該網頁內須要緩存的文件列表須要在 test.appcache 文本文件中指定.
就像寫做文同樣, manifest採用經典的三段式. 分別爲: CACHE
, NETWORK
和 FALLBACK
. 以下, 先看一個栗子?:
CACHE MANIFEST # v1.0.0 content.css NETWORK: app.js FALLBACK: /other 404.html
其中第一行必須以 CACHE MANIFEST
開頭, 後可跟若干字符註釋, 註釋從#號開始. 跟在 CACHE MANIFEST
行後的文件, 每行列出一個, 這些文件是須要緩存的文件. 所以 content.css 會被緩存, 不須要訪問網絡.
第二段內容以 NETWORK:
開始, 跟在該行後的文件表示須要訪問網絡. 如: app.js 將直接從網絡上下載, 並不走manifest cache, 若是除了第一段中緩存的文件之外, 其餘文件都從網絡上獲取, 那麼此時可將 app.js 改成 * (通配符).
第三段內容以 FALLBACK:
開始, 跟在該行後的文件表示會有一個替代方案. 如: 當訪問 /other 路徑時, 若是訪問失敗, 那麼將自動加載 404.html 做爲替代.
每一個manifest緩存都有一個狀態, 標示着緩存的狀況. 一份緩存清單隻有一個緩存狀態, 即便它被多個頁面引用. 如下是各個緩存狀態:
UNCACHED(未緩存): 代表應用緩存對象尚未初始化完成.
IDLE(空閒): 應用緩存並未處於更新狀態.
CHECKING(檢查): 正在檢查是否存在更新.
DOWNLOADING(下載): 清單更新後, 從新下載所有資源到臨時緩存中.
UPDATEREADY(更新就緒): 新版本的緩存下載完成, 所有就緒, 隨即觸發事件 updateready.
OBSOLETE(廢棄): 應用緩存已被廢棄.
上述緩存狀態常量依次取值0, 1, 2, 3, 4, 5.
applicationCache是操做應用緩存的瑞士軍刀, 也是惟一的一把刀.
首先咱們來獲取該對象.
//webview下 var cache = window.applicationCache; //shared worker中 var cache = self.applicationCache;
如下是其屬性和方法介紹(大神請繞過):
status: 返回當前頁面的應用緩存的狀態, 一般開啓應用緩存的頁面可能返回1, 其餘頁面則返回0.
update(): 手動觸發應用緩存的更新.
(1) 如有更新, 則依次觸發①檢查事件(Checking event), ②下載事件(Downloading event), ③下載進度事件(Progress event), ④更新完成事件(UpdateReady event);
(2) 若無更新, 則依次觸發①檢查事件(Checking event), ②無更新事件(NoUpdate event);
(3) 在未開啓應用緩存的頁面調用將拋出Uncaught DOMException
錯誤.
update() 方法一般在長時間不關閉的頁面使用, 好比說郵箱應用, 用於按期檢測可能的更新.
abort(): 取消應用緩存的更新. 可用於節省有限的網絡帶寬.
swapCache(): 若是存在一個更新版本的應用緩存, 那麼它將切換過去, 不然將拋出 Uncaught DOMException
錯誤. 一般, 咱們會在updateready事件觸發以後手動調用swapCache()方法, swapCache的切換隻對後續加載的緩存文件有效, 已經加載成功的資源並不會從新加載.
那麼如何利用好上述api更新一個頁面的應用緩存呢? 別急, Beginner's Guide to Using the Application Cache 一文中提供了以下的樣板方法:
// Check if a new cache is available on page load. window.addEventListener('load', function(e) { window.applicationCache.addEventListener('updateready', function(e) { if (window.applicationCache.status == window.applicationCache.UPDATEREADY) { // Browser downloaded a new app cache. // Swap it in and reload the page to get the new hotness. window.applicationCache.swapCache(); if (confirm('A new version of this site is available. Load it?')) { window.location.reload(); } } else { // Manifest didn't changed. Nothing new to server. } }, false); }, false);
manifest的緩存和瀏覽器默認的緩存是兩套機制, 相互獨立, 而且不受瀏覽器緩存大小限制(Chrome下測試結果).
各個manifest文件的緩存相互獨立, 各自在獨立的區域進行緩存. 即便是緩存同一個文件, 也可能因爲緩存的版本不一致, 而形成各個頁面資源不一致.
遵循全量緩存的規律. 即: manifest文件改動後, 將從新緩存一遍全部的文件(包括html自己和動態添加的須要緩存的文件,即便緩存列表中沒有該html). 第一次緩存過程當中若是出現緩存失敗的文件, 那麼, 第二訪問, 又將從新緩存一遍全部的文件. 以此類推.
manifest文件自己不能寫進緩存清單, 不然連同html和資源在其緩存失效以前, 將永遠不能得到更新.
即便manifest文件丟失, 緩存依然有效. 不過今後之後, 引入該manifest的html, 將永遠不能得到更新.
一般, webview的緩存有以下三種現象:
普通網頁(無manifest文件), 不受manifest緩存影響, 緩存只走 http cache.
包含manifest文件的網頁, 緩存文件只受manifest緩存影響(只有manifest文件改變時纔會更新緩存資源), 緩存資源徹底與 http cache 無關, 可是 NETWORK
段落後須要訪問網絡的文件, 將繼續走 http cache.
webview直接加載manifest緩存過的文件時, 優先加載第一個manifest緩存的該文件, 若是沒有找到manifest緩存, 那麼它將自動尋找 http cache 或者 在線加載.
一般只使用一個manifest文件, 並保證緩存的文件儘量的少, 以減少manifest每次更新清單中文件所耗費的時間和流量.
若是必定要使用兩個及以上manifest文件, 緩存文件請儘可能不要相同.
若是以上兩條都不能保證, 那麼, 請保證儘量在manifest緩存的狀態更新時, 主動去刷新網頁.(此時並不能保證不一樣網頁之間同一個緩存文件版本一致)
若是緩存的文件須要加參數運行, 建議將參數內容加到hash中, 如:cached-page.html#parameterName=value
manifest 的引入可使用絕對路徑或者相對路徑, 若是你使用的是絕對路徑, 那麼你的manifest文件必須和你的站點處於同一個域名下.
manifest文件你能夠保存爲任意的擴展名, 可是響應頭中如下字段須取如下定值, 以保證manifest文件正確被解析, 而且它沒有http緩存.
Content-Type: text/cache-manifest Cache-Control: max-age=0 Expires: [CURRENT TIME]
更新manifest文件後, webview將自動更新緩存.
js更新緩存(手動觸發manifest更新): window.applicationCache.update();
chrome瀏覽器下經過訪問 chrome://appcache-internals/ 能夠查看緩存在本地的資源文件.
另外, 除了本文參考的一篇 MDN 的文章以及 HTML5 Rocks的 Beginner's Guide to Using the Application Cache 一文, 還有以下三個連接可供您比較閱讀, 謝謝.
Cache manifest in HTML5 on Wikipedia
Offline Web Applications W3C Working Group Note
Offline Web applications at WHATWG
本問就討論這麼多內容,你們有什麼問題或好的想法歡迎在下方參與留言和評論.
本文做者: louis
本文連接: http://louiszhai.github.io/20...
參考文章