標籤:
最近公司舉辦技術大賽,我和同事一起製作了一個叫做10K Hours的Mobile Web App,可以協助你通過一萬小時的努力,成為某個領域的專家。正好前段時間翻譯了一本書《HTML5 Mobile Development Cookbook》,中文譯本在此。其中講到了不少移動端Web開發的Best Practices,正好就用到了10K Hours這個應用上。其中我覺得非常有用但是又讓人頭痛的一個功能就是AppCache:它可以讓使用者在訪問一次網頁以後,下次再來時不能訪問網路的情況下,也可以使用這個Web App;但是當頁面資源被緩衝以後,非常難去更新它們??下面就是App Cache的詳細介紹和提示:
什麼是AppCache
下面是來自W3C的解釋:
In order to enable users to continue interacting with Web applications and documents even when their network connection is unavailable — for instance, because they are traveling outside of their ISP‘s coverage area — authors can provide a manifest which lists the files that are needed for the Web application to work offline and which causes the user‘s browser to keep a copy of the files for use offline.
簡單來說就是可以讓開發人員在網路出問題的情況下,可以部分或全部訪問網站的靜態資源。
可能有些朋友會疑惑AppCache與瀏覽器自動緩衝和localStorage的區別,這裡我簡單講一下:在預設設定下,瀏覽器會根據request header自動緩衝靜態檔案,但是在請求該檔案時還是會發出http request,而一旦被AppCache緩衝住的檔案就不會發送http request,除非人工觸發緩衝更新;localStorage也是一種緩衝,但是它緩衝的是資料,而AppCache緩衝的是檔案。
如何使用AppCache
要引入AppCache一般有三個步驟:
1. 聲明manifest檔案
manifest可以告訴瀏覽器網站的cache行為,下面是一個完整的manifest檔案樣本:
CACHE MANIFEST
# Time: Wed May 22 2013 17:07:07 GMT+0800 (CST)
CACHE:
index.html
stylesheet.css
images/logo.png
scripts/main.js
NETWORK:
myApp/api
http://api.twitter.com
FALLBACK:
images/large/ images/offline.jpg
CACHE MANIFEST表明該檔案用於AppCache的配置,必須放在第一行
# Time: Wed May 22 2013 17:07:07 GMT+0800 (CST)是一個時間戳記,用於觸發快取檔案的更新,這個會在後面詳細講到。
CACHE指定需要被緩衝的檔案。這些檔案會被緩衝到AppCache中,以後這些檔案都會從AppCache中載入。
NETWORK指定不需要被緩衝的檔案。這些檔案不會被緩衝到AppCache中,一般用於一些動態頁面或資料。
注意:一些瀏覽器會給緩衝容量加入上限,比如Chrome瀏覽器就是使用一個共有的緩衝池,如果超出上限,以前緩衝的檔案有可能會被清除掉。
FALLBACK指定當網路不可用時的替代檔案,這些檔案在網路可用時不會從AppCache中讀取,只有當網路不可用時才會從AppCache中讀取。樣本中指定當images/large/中的任意檔案無法訪問時,都從AppCache中讀取images/offline.jpg檔案。
我們一般使用.appcache作為manifest檔案的尾碼,這個是WHATWG的建議,同時也獲得了更多瀏覽器的支援。
2. 在頁面中引入manifest檔案
引入manifest檔案需要在html標籤中加入manifest屬性,其值為manifest檔案地址,例如:
<html manifest="example.appcache">
...
</html>
注意:你需要在每個用到AppCache的頁面都加入manifest屬性,除非該頁面就在緩衝列表中,而擁有manifest屬性的頁面會自動被緩衝住,不需要再加入緩衝列表了。
3. 修改伺服器端的mime-type
為了讓伺服器端可以正確的處理manifest檔案,需要在mine-type中加入text/cache-manifest。比如在Apache伺服器中,可以添加以下行到設定檔中:
AddType text/cache-manifest .appcache
更新緩衝
完成manifest檔案的配置以後,你會發現你的頁面載入速度暴增,可以算是秒載,但是你也會悲催的發現,任何檔案的修改將不會被反應到頁面上,那麼當我們有檔案修改的時候應該怎麼辦呢?
修改manifest檔案
有兩種情況可以導致緩衝更新:
- 使用者清除快取資料。
- manifest檔案修改。
所以我們要更新緩衝,其實只有一個辦法,那就是修改manifest檔案。這個時候我們就可以看到在上個例子中那個被注釋掉的時間戳記(# Time: Wed May 22 2013 17:07:07 GMT+0800 (CST))的作用了,每當任意一個被緩衝的檔案修改後,我們都應該修改manifest檔案的時間戳記,讓瀏覽器知道有檔案更改,應該更新緩衝。
當瀏覽器檢測到manifest檔案更改以後,它會發起請求更新所有被緩衝的檔案,但是這時候還不會馬上更新到頁面中,還需要使用者再次重新整理頁面,才能看到新的內容。也就是說,當我們有檔案修改以後,需要使用者重新整理兩次才能看到新的內容,這個對於使用者來說是很奇怪的體驗。這個時候我們可以利用AppCache提供的一些介面來解決這個問題。
AppCache介面
AppCache提供了以下的事件介面:
checking:用戶端正在檢查manifest檔案的更新,或者嘗試下載manifest檔案時觸發。注意:這個事件總是首先觸發的。
noupdate:用戶端檢查manifest檔案,並且manifest檔案沒有更新時觸發。
downloading:用戶端發現manifest檔案需要更新並開始更新,或者開始下載manifest中列舉的快取檔案時觸發。
progress:用戶端下載manifest中列巨額的快取檔案時觸發。
cached:manifest中的檔案被下載,並且被緩衝以後觸發。
updateready:當新的快取檔案下載完成後觸發,可以利用swapCache()來應用新的檔案。
其中最重要的就是updateready這個事件,我們可以利用JavaScript綁定這個事件,在緩衝更新的時候自動重新整理來應用這些更新,例如:
// 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);
AppCache的Debug
當我們在本地調試的時候,我們如何知道AppCache是否起效果,並緩衝了哪些檔案呢?Chrome的開發人員工具提供了這些資訊,開啟開發人員工具,在Resource => Application Cache中就可以看到緩衝了哪些檔案,如所示:
但是在這裡不能對Cache進行刪除操作,也不能看到其他網站的Cache。如果想看到所有網站的AppCache資訊,並且刪除其中某一個的話,可以進入chrome://appcache-internals/,這個管理頁面會列出所有瀏覽器中的AppCache資訊,包括manifest地址、緩衝大小、更新時間、建立時間等等??
打造離線使用的Mobile Web App