原文:
Manifest 是 H5提供的一種應(yīng)用緩存機(jī)制, 基于它web應(yīng)用可以實(shí)現(xiàn)離線訪問(offline cache). 為此, 瀏覽器還提供了應(yīng)用緩存的api--applicationCache. 雖然manifest的技術(shù)已被web標(biāo)準(zhǔn)廢棄, 但這不影響我們嘗試去了解它. 也正是因?yàn)閙anifest的應(yīng)用緩存機(jī)制如此誘人, 餓了么 和 office 365郵箱等都還在使用著它!
對manifest熟悉的同學(xué)可以跳過此節(jié).
鑒于manifest應(yīng)用緩存的技術(shù), 我們可以做到:
離線訪問: 即使服務(wù)器掛了, 或者沒有網(wǎng)絡(luò), 用戶依然可以正常瀏覽網(wǎng)頁內(nèi)容.
訪問更快: 數(shù)據(jù)存在于本地, 省去了瀏覽器發(fā)起http請求的時(shí)間, 因此訪問更快, 移動(dòng)端效果更為明顯.
降低負(fù)載: 瀏覽器只在manifest文件改動(dòng)時(shí)才去服務(wù)器下載需要緩存的資源, 大大降低了服務(wù)器負(fù)載.
manifest緩存的過程如下(來自網(wǎng)絡(luò)):
主流瀏覽器都支持manifest應(yīng)用緩存技術(shù). 如下表格:
IE | Edge | Firefox | Chrome | Safari | Opera | ios | Android |
---|---|---|---|---|---|---|---|
10+ | 12+ | 3.5+ | 4+ | 4+ | 11.5+ | 7.1+ | 2.3+ |
H5標(biāo)準(zhǔn)中, 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]
因此后續(xù)我將在其他文章中繼續(xù)介紹 service workers, 本篇繼續(xù)關(guān)注manifest.
manifest使用緩存清單進(jìn)行管理, 緩存清單需要與html標(biāo)簽進(jìn)行關(guān)聯(lián). 如下:
<html manifest="test.appcache"> ...</html>
在html標(biāo)簽中指定manifest文件, 便表示該網(wǎng)頁使用manifest進(jìn)行離線緩存. 該網(wǎng)頁內(nèi)需要緩存的文件列表需要在 test.appcache 文本文件中指定.
就像寫作文一樣, manifest采用經(jīng)典的三段式. 分別為: CACHE
, NETWORK
和 FALLBACK
. 如下, 先看一個(gè)栗子?:
CACHE MANIFEST# v1.0.0content.cssNETWORK:app.jsFALLBACK:/other 404.html
其中第一行必須以 CACHE MANIFEST
開頭, 后可跟若干字符注釋, 注釋從#號開始. 跟在 CACHE MANIFEST
行后的文件, 每行列出一個(gè), 這些文件是需要緩存的文件. 因此 content.css 會(huì)被緩存, 不需要訪問網(wǎng)絡(luò).
第二段內(nèi)容以 NETWORK:
開始, 跟在該行后的文件表示需要訪問網(wǎng)絡(luò). 如: app.js 將直接從網(wǎng)絡(luò)上下載, 并不走manifest cache, 如果除了第一段中緩存的文件以外, 其他文件都從網(wǎng)絡(luò)上獲取, 那么此時(shí)可將 app.js 改為 * (通配符).
第三段內(nèi)容以 FALLBACK:
開始, 跟在該行后的文件表示會(huì)有一個(gè)替代方案. 如: 當(dāng)訪問 /other 路徑時(shí), 如果訪問失敗, 那么將自動(dòng)加載 404.html 作為替代.
每個(gè)manifest緩存都有一個(gè)狀態(tài), 標(biāo)示著緩存的情況. 一份緩存清單只有一個(gè)緩存狀態(tài), 即使它被多個(gè)頁面引用. 以下是各個(gè)緩存狀態(tài):
UNCACHED(未緩存): 表明應(yīng)用緩存對象還沒有初始化完成.
IDLE(空閑): 應(yīng)用緩存并未處于更新狀態(tài).
CHECKING(檢查): 正在檢查是否存在更新.
DOWNLOADING(下載): 清單更新后, 重新下載全部資源到臨時(shí)緩存中.
UPDATEREADY(更新就緒): 新版本的緩存下載完成, 全部就緒, 隨即觸發(fā)事件 updateready.
OBSOLETE(廢棄): 應(yīng)用緩存已被廢棄.
上述緩存狀態(tài)常量依次取值0, 1, 2, 3, 4, 5.
applicationCache是操作應(yīng)用緩存的瑞士軍刀, 也是唯一的一把刀.
首先我們來獲取該對象.
//webview下var cache = window.applicationCache;//shared worker中var cache = self.applicationCache;
以下是其屬性和方法介紹(大神請繞過):
status: 返回當(dāng)前頁面的應(yīng)用緩存的狀態(tài), 通常開啟應(yīng)用緩存的頁面可能返回1, 其他頁面則返回0.
update(): 手動(dòng)觸發(fā)應(yīng)用緩存的更新.
(1) 若有更新, 則依次觸發(fā)①檢查事件(Checking event), ②下載事件(Downloading event), ③下載進(jìn)度事件(Progress event), ④更新完成事件(UpdateReady event);
(2) 若無更新, 則依次觸發(fā)①檢查事件(Checking event), ②無更新事件(NoUpdate event);
(3) 在未開啟應(yīng)用緩存的頁面調(diào)用將拋出Uncaught DOMException
錯(cuò)誤.
update() 方法通常在長時(shí)間不關(guān)閉的頁面使用, 比如說郵箱應(yīng)用, 用于定期檢測可能的更新.
abort(): 取消應(yīng)用緩存的更新. 可用于節(jié)省有限的網(wǎng)絡(luò)帶寬.
swapCache(): 如果存在一個(gè)更新版本的應(yīng)用緩存, 那么它將切換過去, 否則將拋出 Uncaught DOMException
錯(cuò)誤. 通常, 我們會(huì)在updateready事件觸發(fā)之后手動(dòng)調(diào)用swapCache()方法, swapCache的切換只對后續(xù)加載的緩存文件有效, 已經(jīng)加載成功的資源并不會(huì)重新加載.
那么如何利用好上述api更新一個(gè)頁面的應(yīng)用緩存呢? 別急, 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的緩存和瀏覽器默認(rèn)的緩存是兩套機(jī)制, 相互獨(dú)立, 并且不受瀏覽器緩存大小限制(Chrome下測試結(jié)果).
各個(gè)manifest文件的緩存相互獨(dú)立, 各自在獨(dú)立的區(qū)域進(jìn)行緩存. 即使是緩存同一個(gè)文件, 也可能由于緩存的版本不一致, 而造成各個(gè)頁面資源不一致.
遵循全量緩存的規(guī)律. 即: manifest文件改動(dòng)后, 將重新緩存一遍所有的文件(包括html本身和動(dòng)態(tài)添加的需要緩存的文件,即使緩存列表中沒有該html). 第一次緩存過程中如果出現(xiàn)緩存失敗的文件, 那么, 第二訪問, 又將重新緩存一遍所有的文件. 以此類推.
manifest文件本身不能寫進(jìn)緩存清單, 否則連同html和資源在其緩存失效之前, 將永遠(yuǎn)不能獲得更新.
即使manifest文件丟失, 緩存依然有效. 不過從此以后, 引入該manifest的html, 將永遠(yuǎn)不能獲得更新.
通常, webview的緩存有如下三種現(xiàn)象:
普通網(wǎng)頁(無manifest文件), 不受manifest緩存影響, 緩存只走 http cache.
包含manifest文件的網(wǎng)頁, 緩存文件只受manifest緩存影響(只有manifest文件改變時(shí)才會(huì)更新緩存資源), 緩存資源完全與 http cache 無關(guān), 但是 NETWORK
段落后需要訪問網(wǎng)絡(luò)的文件, 將繼續(xù)走 http cache.
webview直接加載manifest緩存過的文件時(shí), 優(yōu)先加載第一個(gè)manifest緩存的該文件, 如果沒有找到manifest緩存, 那么它將自動(dòng)尋找 http cache 或者 在線加載.
通常只使用一個(gè)manifest文件, 并保證緩存的文件盡可能的少, 以減小manifest每次更新清單中文件所耗費(fèi)的時(shí)間和流量.
如果一定要使用兩個(gè)及以上manifest文件, 緩存文件請盡量不要相同.
如果以上兩條都不能保證, 那么, 請保證盡可能在manifest緩存的狀態(tài)更新時(shí), 主動(dòng)去刷新網(wǎng)頁.(此時(shí)并不能保證不同網(wǎng)頁之間同一個(gè)緩存文件版本一致)
如果緩存的文件需要加參數(shù)運(yùn)行, 建議將參數(shù)內(nèi)容加到hash中, 如:cached-page.html#parameterName=value
manifest 的引入可以使用絕對路徑或者相對路徑, 如果你使用的是絕對路徑, 那么你的manifest文件必須和你的站點(diǎn)處于同一個(gè)域名下.
manifest文件你可以保存為任意的擴(kuò)展名, 但是響應(yīng)頭中以下字段須取以下定值, 以保證manifest文件正確被解析, 并且它沒有http緩存.
Content-Type: text/cache-manifestCache-Control: max-age=0Expires: [CURRENT TIME]
更新manifest文件后, webview將自動(dòng)更新緩存.
js更新緩存(手動(dòng)觸發(fā)manifest更新): window.applicationCache.update();
chrome瀏覽器下通過訪問 chrome://appcache-internals/ 可以查看緩存在本地的資源文件.
另外, 除了本文參考的一篇 MDN 的文章以及 HTML5 Rocks的 Beginner's Guide to Using the Application Cache 一文, 還有如下三個(gè)鏈接可供您比較閱讀, 謝謝.
Cache manifest in HTML5 on Wikipedia
Offline Web Applications W3C Working Group Note
Offline Web applications at WHATWG
本問就討論這么多內(nèi)容,大家有什么問題或好的想法歡迎在下方參與留言和評論.
本文作者: louis
本文鏈接: http://louiszhai.github.io/20...
參考文章
聯(lián)系客服