HTML5的一個重要特性就是離線存儲,所謂的離線存儲就是将一些資源檔案儲存在本地,這樣後續的頁面重新加載将使用本地資源檔案,在離線情況下可以繼續通路web應用,同時通過一定的手法(更新相關檔案或者使用相關API),可以更新、删除離線存儲等操作;
HTML5的離線存儲使用一個manifest檔案來标明哪些檔案是需要被存儲的,使用如 <html manifest='offline.manifest'> 來引入一個manifest檔案,這個檔案的路徑可以是相對的,也可以是絕對的,如果你的web應用很多,而且希望能集中管理manifest檔案,那麼靜态檔案伺服器是個不錯的選擇。
對于manifest檔案,要求:檔案的mime-type必須是 text/cache-manifest類型。如果你是JAVA工程,在你的web.xml中配置請求字尾為manifest的格式:
- <mime-mapping>
- <extension>manifest</extension>
- <mime-type>text/cache-manifest</mime-type>
- </mime-mapping>
複制代碼
這樣可以控制請求到的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
複制代碼 其中 CACHE 不是必須存在的,可以直接在 CACHE MANIFEST 行之下直接寫需要緩存的檔案,在這裡指明的檔案将被緩存到浏覽器本地。在NETWORK之下指明的檔案,是強制必須通過網絡資源擷取的,在FALLBACK下指明的是一種失敗的回調方案,比如上述index.php無法通路,那麼就發出404.htm請求
這樣幾步就可以完成對離線存儲的支援。接下來要思考的,是如何更新離線存儲?
當使用者本地再次聯網的時候,本地的離線存儲資源需要檢查是否需要更新,這個更新過程,也是通過manifest的更新來控制的,更新了manifest檔案,浏覽器會自動的重新下載下傳新的manifest檔案并在下一次重新整理頁面的時候進行資源檔案的重新請求(第三次重新整理替換本地緩存為最新緩存),而且這個請求是全局性的,也就是所有在manifest緩存清單中的檔案都會被請求一次,而不是單獨請求某個特定修改過的資源檔案,因為manifest是不知道哪個檔案被修改過了的。
對于全局更新的擔心是不必要的,因為對于沒有更新過的資源檔案,請求依舊是304響應,隻有真正更新過的資源檔案才是200.
是以控制離線存儲的更新,需要2個步驟,一是更新資源檔案,二是更新manifest檔案,特别的,更新manifest檔案是不需要修改什麼特定内容的,隻要是這個檔案随意一處被修改,那麼浏覽器就會感覺,對于我們的資源檔案通常名稱是固定的,比如**.css,更新内容不會帶有檔案名更新的情況下,需要更新manifest檔案怎麼操作呢?一個比較好的方式是更新任意一處# 開頭的注釋即可,其目的隻是告訴浏覽器這個manifest檔案被更新過。
以上的這些内容,其更新操作都是浏覽器自動完成的。同樣的,W3C定義了離線存儲的API規範:http://www.whatwg.org/specs/web- ... k/#applicationcache
提供了如下API:
- // 更新,一般來說更新下載下傳是通過使用者**(如浏覽器)自動完成的,但是這個方法适用于一些長期打開的頁面,比如郵件系統,可能這個頁面是長期打開的,而不會有重新整理動作,是以這個就比較适合做自動更新下載下傳
- void update();
- // 取消
- void abort();
- // 替換緩存内容 ,對于manifest檔案的改變,通常是下一次的重新整理才會觸發下載下傳更新,第三次重新整理才會切換使用新的緩存檔案,通過這個方法,可以強制将緩存替換
- void swapCache();
複制代碼
提供了如下的事件:
- Event handler Event handler event type
- onchecking checking
- onerror error
- onnoupdate noupdate
- ondownloading downloading
- onprogress progress
- onupdateready updateready
- oncached cached
- onobsolete obsolete
複制代碼
最後說一個對于manifest比較特别的地方:對于某個檔案a.htm,其中有 <html manifest='a.manifest'> ,那麼離線存儲中,會自動将a.htm加入到清單中,這意味着a.htm的再次重新整理将從本地緩存中擷取,這樣的機制從官方得到的答複是“特别的設計”,而對我們來說,這種強加的特性在後續的開發過程中會有不少問題。
比如:
1、如何計算PV UV,由于目前頁面被強制加入manifest,那麼PV 和UV的統計,成了一個難題,因為請求不再是發送到伺服器;
2、對于某個使用manifest的檔案,其帶有的參數可能是随機性的統計參數,如sid=123sss, sid=234fff ,尤其是比如商品詳情的id字段等,這樣每個頁面都自動加入到manifest中,将會帶來很大的存儲開銷,而且是毫無意義的;
是以伴随而來的,是如何在現有的體系架構下進行資料統計的難題,一個正常的方案是進入離線存儲頁面後自動發出ajax請求,以告知伺服器統計PV UV;
對于第二個問題,可能就比較棘手,但是将GET請求的方式改成POST的方式确實是個解決問題的方案。