HTML5離線存儲原理及實現

前言

使用 HTML5,通過創建 cache manifest 文件,可以輕鬆地創建 web 應用的離線版本。

HTML5引入了應用程序緩存,這意味着 web 應用可進行緩存,並可在沒有因特網連接時進行訪問。 應用程序緩存爲應用帶來三個優勢:

  • 離線瀏覽 – 用戶可在應用離線時使用它們
  • 速度 – 已緩存資源加載得更快
  • 減少服務器負載 – 瀏覽器將只從服務器下載更新過或更改過的資源。

原理和環境

如上面提到的HTML5的離線存儲是基於一個新建的.appcache文件的,通過這個文件上的解析清單離線存儲資源,這些資源就會像cookie一樣被存儲了下來。之後當網絡在處於離線狀態下時,瀏覽器會通過被離線存儲的數據進行頁面展示。

就像cookie一樣,html5的離線存儲也需要服務器環境。
這裏提供一個小工具——簡易iis服務器,把它放在項目更目錄下,雙擊運行即可模擬服務器環境。
鏈接: http://pan.baidu.com/s/1jG86UV0 密碼: ja9h

解析清單

在開始之前要先了解下manifest(即.appcache文件),上面的解析清單要怎麼寫。

manifest 文件是簡單的文本文件,它告知瀏覽器被緩存的內容(以及不緩存的內容)。

manifest 文件可分爲三個部分:

  • CACHE MANIFEST - 在此標題下列出的文件將在首次下載後進行緩存
  • NETWORK - 在此標題下列出的文件需要與服務器的連接,且不會被緩存
  • FALLBACK - 在此標題下列出的文件規定當頁面無法訪問時的回退頁面(比如 404 頁面)

在線的情況下,用戶代理每次訪問頁面,都會去讀一次manifest.如果發現其改變, 則重新加載全部清單中的資源

CACHE MANIFEST

第一行,CACHE MANIFEST,是必需的:

CACHE MANIFEST /theme.css /logo.gif /main.js

上面的 manifest 文件列出了三個資源:一個 CSS 文件,一個 GIF 圖像,以及一個 JavaScript 文件。當 manifest 文件加載後,瀏覽器會從網站的根目錄下載這三個文件。然後,無論用戶何時與因特網斷開連接,這些資源依然是可用的。

NETWORK

白名單,使用通配符”*”. 則會進入白名單的open狀態. 這種狀態下.所有不在相關Cache區域出現的url都默認使用HTTP相關緩存頭策略.

下面的 NETWORK 小節規定文件 “login.asp” 永遠不會被緩存,且離線時是不可用的:

NETWORK: login.asp

可以使用星號來指示所有其他資源/文件都需要因特網連接:

NETWORK: *

FALLBACK

下面的 FALLBACK 小節規定如果無法建立因特網連接,則用 “offline.html” 替代 /html5/ 目錄中的所有文件:

ALLBACK: /html5/ /404.html

註釋:第一個 URI 是資源,第二個是替補。

更新緩存

一旦應用被緩存,它就會保持緩存直到發生下列情況:

  • 用戶清空瀏覽器緩存
  • manifest 文件被修改
  • 由程序來更新應用緩存

Demo

case/ |-- index.html | |-- demo.appcache | |-- 簡易IIS服務器.exe | `-- image |-- 01.jpg `-- 02.jpg

index.html

<!DOCTYPE html> <html lang="en" manifest="demo.appcache"> <head> <meta charset="UTF-8"> <title>HTML5離線存儲</title> </head> <body> <img src="image/01.jpg" alt=""> <img src="image/02.jpg" alt=""> </body> </html>

demo.appcache

CACHE MANIFEST #v01 image/01.jpg NETWORK: * FALLBACK: /

image文件夾下存儲着
01.jpg
01.jpg
02.jpg
02.jpg

好接着執行簡易IIS服務器.exe試試看吧。
當iis開啓時
Alt text
當iis關閉時(是關閉,暫停看不出效果)
Alt text

可以看見圖片1成功被離線展示出來了,圖片2像正常情況一樣顯示不出來。

現在我想把圖片2圖片1的位置換一下呢.
Html部分置換一下

<body> <img src="image/02.jpg" alt=""> <img src="image/01.jpg" alt=""> </body>

這時候發現問題來了,html明明修改了爲什麼圖片沒有置換過來呢,我不是在demo.appcache文件的NETWORK寫了星號嗎?除了CACHE MANIFEST文件其它都採用在線模式。查資料得知:引入manifest的頁面,即使沒有被列入緩存清單中,仍然會被用戶代理緩存。
好吧,那我把.appcache文件更新下,於是乎把頭部的版本號修改一下#v02。刷新下頁面還是沒反應!再刷新,有了!爲什麼?

對於瀏覽器來說,manifest的加載是要晚於其他資源的. 這就導致check manifest的過程是滯後的.發現manifest改變.所有瀏覽器的實現都是緊隨這做靜默更新資源.以保證下次pv,應用到更新.

通過控制檯我們能夠窺探一二:

  • 第一次刷新,應用程序緩存更新準備事件,
    Alt text
  • 第二次刷新纔會看到效果。
    Alt text

緩存立即執行

我們的產品已經更新了用戶卻要第二次進來才能夠看到,這樣用戶體驗也太差了吧,有什麼方式能夠解決呢?好在html5給javascript提供了相關的API。

API篇幅太多自行查看把,這裏我曬下我測試成功的code:

/*code1,簡單粗暴的*/
applicationCache.onupdateready = function(){
applicationCache.swapCache();
location.reload();
};
/*code2,緩存公用方法*/
// var EventUtil = {
// addHandler: function(element, type, handler) {
// if (element.addEventListener) {
// element.addEventListener(type, handler, false);
// } else if (element.attachEvent) {
// element.attachEvent(“on” + type, handler);
// } else {
// element["on" + type] = handler;
// }
// }
// };
// EventUtil.addHandler(applicationCache, “updateready”, function() { //緩存更新並已下載,要在下次進入頁面生效
// applicationCache.update(); //檢查緩存manifest文件是否更新,ps:頁面加載默認檢查一次。
// applicationCache.swapCache(); //交換到新的緩存項中,交換了要下次進入頁面才生效
// location.reload(); //重新載入頁面
// });

code1一般用在頁面加載時直接觸發,而code2的方式可後期檢查更新。

注意事項

  • 站點離線存儲的容量限制是5M
  • 如果manifest文件,或者內部列舉的某一個文件不能正常下載,整個更新過程將視爲失敗,瀏覽器繼續全部使用老的緩存
  • 引用manifest的html必須與manifest文件同源,在同一個域下
  • 在manifest中使用的相對路徑,相對參照物爲manifest文件
  • CACHE MANIFEST字符串應在第一行,且必不可少
  • 系統會自動緩存引用清單文件的 HTML 文件
  • manifest文件中CACHE則與NETWORK,FALLBACK的位置順序沒有關係,如果是隱式聲明需要在最前面
  • FALLBACK中的資源必須和manifest文件同源
  • 當一個資源被緩存後,該瀏覽器直接請求這個絕對路徑也會訪問緩存中的資源。
  • 站點中的其他頁面即使沒有設置manifest屬性,請求的資源如果在緩存中也從緩存中訪問
  • 當manifest文件發生改變時,資源請求本身也會觸發更新
轉載:http://www.codeceo.com/article/html5-cache.html
發佈了25 篇原創文章 · 獲贊 10 · 訪問量 10萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章