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: login.asp
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
02.jpg
好接著執行簡易IIS伺服器.exe
試試看吧。
當iis開啟時
當iis關閉時(是關閉,暫停看不出效果)
可以看見圖片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,應用到更新.
通過控制檯我們能夠窺探一二:
- 第一次重新整理,應用程式快取更新準備事件,
- 第二次重新整理才會看到效果。
快取立即執行
我們的產品已經更新了使用者卻要第二次進來才能夠看到,這樣使用者體驗也太差了吧,有什麼方式能夠解決呢?好在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檔案發生改變時,資源請求本身也會觸發更新
相關文章
- 利用Node實現HTML5離線儲存HTML
- HTML5離線儲存Manifest原理及使用詳解HTML
- localForage——輕鬆實現 Web 離線儲存Web
- HTML5離線應用與客戶端儲存HTML客戶端
- HTML5學習之離線儲存基礎知識HTML
- Html5 Web的5中離線儲存方式之localStorageHTMLWeb
- HTML5的五種客戶端離線儲存方案HTML客戶端
- 離線儲存manifest
- InnoDB儲存引擎MVCC實現原理儲存引擎MVC
- HTML5 Web 客戶端五種離線儲存方式彙總HTMLWeb客戶端
- HTML5中的網路儲存實現方式HTML
- 突破本地離線儲存的JS庫 localforageJS
- 分離mysql和儲存實現雙web負載均衡MySqlWeb負載
- Web應用中的離線資料儲存Web
- HTML5 web儲存HTMLWeb
- Java HashMap原理及內部儲存結構JavaHashMap
- MySQL中InnoDB儲存引擎的實現和執行原理MySql儲存引擎
- Nebula Graph 的 KV 儲存分離原理和效能測評
- 資料庫連線池的實現及原理資料庫
- Docker容器實現原理及容器隔離性踩坑介紹Docker
- HTML5 之本地儲存HTML
- CRC原理及實現
- 本地儲存Cookie、Storage、indexDB、ServiceWork離線訪問網站CookieIndex網站
- v7000儲存硬碟離線如何恢復資料硬碟
- AOP如何實現及實現原理
- 貝塞爾曲線原理、推導及Matlab實現Matlab
- 容器化RDS—— 計算儲存分離 or 本地儲存
- 實現AVPlayer離線快取快取
- Prometheus TSDB儲存原理Prometheus
- Git的儲存原理Git
- 區塊鏈資訊儲存是如何實現安全儲存區塊鏈
- 線性表的順序儲存C++程式碼實現C++
- Ceph分散式儲存-原理介紹及簡單部署分散式
- 學習筆記:InnoDB儲存結構及多版本實現筆記
- 將HTML5 Canvas的內容儲存為圖片藉助toDataURL實現HTMLCanvas
- EMC儲存崩潰raid離線恢復資料方法AI
- wxdown 公眾號離線文章儲存(GO語言開發)Go
- HTML5系列:HTML5本地儲存HTML