HTML5的一個(gè)重要特性就是離線存儲(chǔ),所謂的離線存儲(chǔ)就是將一些資源文件保存在本地,這樣后續(xù)的頁面重新加載將使用本地資源文件,在離線情況下可以繼續(xù)訪問web應(yīng)用,同時(shí)通過一定的手法(更新相關(guān)文件或者使用相關(guān)API),可以更新、刪除離線存儲(chǔ)等操作;
HTML5的離線存儲(chǔ)使用一個(gè)manifest文件來標(biāo)明哪些文件是需要被存儲(chǔ)的,使用如 <html manifest='offline.manifest'> 來引入一個(gè)manifest文件,這個(gè)文件的路徑可以是相對(duì)的,也可以是絕對(duì)的,如果你的web應(yīng)用很多,而且希望能集中管理manifest文件,那么靜態(tài)文件服務(wù)器是個(gè)不錯(cuò)的選擇。
對(duì)于manifest文件,要求:文件的mime-type必須是 text/cache-manifest類型。如果你是JAVA工程,在你的web.xml中配置請(qǐng)求后綴為manifest的格式:
- <mime-mapping>
- <extension>manifest</extension>
- <mime-type>text/cache-manifest</mime-type>
- </mime-mapping>
這樣可以控制請(qǐng)求到的manifest文件格式為text/cache-manifest的。
manifest文件的格式:
- CACHE MANIFEST# 這一句必須存在,而且必須放在頭部# 指明緩存入口CACHE:index.htmlstyle.cssimages/logo.pngscripts/main.js# 以下資源必須在線訪問NETWORK:login.php# 如果index.php無法訪問則用404.html代替FALLBACK:/index.php /404.html
這樣幾步就可以完成對(duì)離線存儲(chǔ)的支持。接下來要思考的,是如何更新離線存儲(chǔ)?
當(dāng)用戶本地再次聯(lián)網(wǎng)的時(shí)候,本地的離線存儲(chǔ)資源需要檢查是否需要更新,這個(gè)更新過程,也是通過manifest的更新來控制的,更新了manifest文件,瀏覽器會(huì)自動(dòng)的重新下載新的manifest文件并在下一次刷新頁面的時(shí)候進(jìn)行資源文件的重新請(qǐng)求(第三次刷新替換本地緩存為最新緩存),而且這個(gè)請(qǐng)求是全局性的,也就是所有在manifest緩存列表中的文件都會(huì)被請(qǐng)求一次,而不是單獨(dú)請(qǐng)求某個(gè)特定修改過的資源文件,因?yàn)閙anifest是不知道哪個(gè)文件被修改過了的。
對(duì)于全局更新的擔(dān)心是不必要的,因?yàn)閷?duì)于沒有更新過的資源文件,請(qǐng)求依舊是304響應(yīng),只有真正更新過的資源文件才是200.
所以控制離線存儲(chǔ)的更新,需要2個(gè)步驟,一是更新資源文件,二是更新manifest文件,特別的,更新manifest文件是不需要修改什么特定內(nèi)容的,只要是這個(gè)文件隨意一處被修改,那么瀏覽器就會(huì)感知,對(duì)于我們的資源文件通常名稱是固定的,比如**.css,更新內(nèi)容不會(huì)帶有文件名更新的情況下,需要更新manifest文件怎么操作呢?一個(gè)比較好的方式是更新任意一處# 開頭的注釋即可,其目的只是告訴瀏覽器這個(gè)manifest文件被更新過。
以上的這些內(nèi)容,其更新操作都是瀏覽器自動(dòng)完成的。同樣的,W3C定義了離線存儲(chǔ)的API規(guī)范:http://www.whatwg.org/specs/web- ... k/#applicationcache
提供了如下API:
- // 更新,一般來說更新下載是通過用戶**(如瀏覽器)自動(dòng)完成的,但是這個(gè)方法適用于一些長(zhǎng)期打開的頁面,比如郵件系統(tǒng),可能這個(gè)頁面是長(zhǎng)期打開的,而不會(huì)有刷新動(dòng)作,所以這個(gè)就比較適合做自動(dòng)更新下載
- void update();
- // 取消
- void abort();
- // 替換緩存內(nèi)容 ,對(duì)于manifest文件的改變,通常是下一次的刷新才會(huì)觸發(fā)下載更新,第三次刷新才會(huì)切換使用新的緩存文件,通過這個(gè)方法,可以強(qiáng)制將緩存替換
- void swapCache();
提供了如下的事件:
- Event handler Event handler event type
- onchecking checking
- onerror error
- onnoupdate noupdate
- ondownloading downloading
- onprogress progress
- onupdateready updateready
- oncached cached
- onobsolete obsolete
最后說一個(gè)對(duì)于manifest比較特別的地方:對(duì)于某個(gè)文件a.htm,其中有 <html manifest='a.manifest'> ,那么離線存儲(chǔ)中,會(huì)自動(dòng)將a.htm加入到列表中,這意味著a.htm的再次刷新將從本地緩存中獲取,這樣的機(jī)制從官方得到的答復(fù)是“特別的設(shè)計(jì)”,而對(duì)我們來說,這種強(qiáng)加的特性在后續(xù)的開發(fā)過程中會(huì)有不少問題。
比如:
1、如何計(jì)算PV UV,由于當(dāng)前頁面被強(qiáng)制加入manifest,那么PV 和UV的統(tǒng)計(jì),成了一個(gè)難題,因?yàn)檎?qǐng)求不再是發(fā)送到服務(wù)器;
2、對(duì)于某個(gè)使用manifest的文件,其帶有的參數(shù)可能是隨機(jī)性的統(tǒng)計(jì)參數(shù),如sid=123sss, sid=234fff ,尤其是比如商品詳情的id字段等,這樣每個(gè)頁面都自動(dòng)加入到manifest中,將會(huì)帶來很大的存儲(chǔ)開銷,而且是毫無意義的;
所以伴隨而來的,是如何在現(xiàn)有的體系架構(gòu)下進(jìn)行數(shù)據(jù)統(tǒng)計(jì)的難題,一個(gè)常規(guī)的方案是進(jìn)入離線存儲(chǔ)頁面后自動(dòng)發(fā)出ajax請(qǐng)求,以告知服務(wù)器統(tǒng)計(jì)PV UV;
對(duì)于第二個(gè)問題,可能就比較棘手,但是將GET請(qǐng)求的方式改成POST的方式確實(shí)是個(gè)解決問題的方案。