web app指南之構建html5離線應用


創建運行在手機上的web app時,鑒於手機用戶的網絡情況,我們需要考慮到用戶離線使用的情況。

html5支持構建離線應用程序。使用它的本地緩存機制可以將應用所需的資源文件都緩存到本地,從而實現應用的離線使用。首先要說明的是,本地緩存和傳動的瀏覽器網頁緩存是不同的,網頁緩存基於網頁,也就是緩存一個網頁的內容,而不是整個app。同時網頁緩存並不可靠,我們不知道我們的app中哪個頁面已經緩存,該頁面的哪些資源已經緩存,而本地緩存對於緩存內容是完全可控的。

使用離線緩存,除了可以使應用可以離線使用外,還能幫助有效的加快網頁加載速度(本地的自然更快),同時降低服務器負載(只需要下載更新的內容)。

正如之前所提到的,本地緩存可以指定要緩存的內容,這同過配置manifest來實現。可以為整個app配置manifest,也可以為單獨某個頁面來配置。

簡單的manifest格式如下:

CACHE MANIFEST
index.html
stylesheet.css
images/logo.png
scripts/main.js

文件的第一行必須是CACHE MANIFEST。

該manifest聲明了需要緩存的html頁面,css,圖片以及js文件。

再看一個比較復雜的manifest文件:

CACHE MANIFEST
# 指定一個版本號 # version 1 # 該類別指定要緩存的資源文件 CACHE: /favicon.ico index.html stylesheet.css images/logo.png scripts/main.js # 指定不進行緩存的資源文件 NETWORK: login.php http://foocoder.com # 每行指定兩個文件,第一個為在線時使用的資源,第二個是離線時使用的資源 FALLBACK: /main.py /static.html images/large/ images/offline.jpg *.html /offline.html

其中#號開頭的為注釋。因為只有在manifest文件發生改變時才會更新,所以我們可以加個版本號方便控制。

從該文件中可以看到分為了三個類別:

CACHE類別指定需要被緩存的資源文件。

NETWORK類別指定不緩存的資源文件,即只在聯網的情況下才能訪問。

FALLBACK每一行都會指定兩個文件,第一個為在線時使用的資源,第二個為離線時使用的備用資源。其中*為通配符,表示在線時使用所有的.html文件。

配置好manifest文件之后,我們只需要在頁面上引用即可。如下,在html 標簽的manifest屬性下指定manifest文件的地址:

<html manifest="app.manifest">
...
</html>

該地址可以是絕對地址也可以是相對地址,但是該文件的嗎MIME 類型必須是text/cache-manifest,所以需要在服務器做相應配置對該類型添加支持,例如嗎,對於apache服務器,需要在配置mime.types中添加如下內容:

AddType text/cache-manifest .manifest

到這里為止,就完成了離線緩存的基本內容,在manifest文件發生變化時,瀏覽器會檢查manifest文件並更新緩存。

我們不得不考慮一個問題,瀏覽器如何處理本地緩存?當服務端更新了應用程序后,用戶打開時是不是會使用最新的資源了?答案是否定的。這需要了解下在使用離線緩存的情況下,瀏覽器與服務端的整個交互過程。

1.首次訪問

在首次訪問時,沒有什么特別,瀏覽器解析index.html,請求所有的資源文件。隨后就會處理manifest文件,請求所有的manifest中的資源文件,注意,即使之前已經請求過了所有的資源文件,這里必須進行重復請求。最后將這些文件緩存到本地。

2.再次訪問

再次訪問時,瀏覽器發現有本地緩存,所以會加載本地緩存內容。隨后會向服務端請求manifest文件,如果manifest文件未更新,返回304代碼,瀏覽器不做處理。如果manifest已經更新過,則請求所有manifest中的資源文件,重新對其緩存。

所以,即使服務端更新了manifest和其他資源,用戶打開時扔是之前的頁面。需要重新打開才能使用更新過后的資源。

有辦法立刻更新緩存么?是可以的。我們可以使用applicationCache對象做到這一點。但是也只是能做到立刻更新緩存,還是需要用戶重新打開也沒才會生效。接下來就看看如何用applicationCache對象立刻更新緩存。

window.applicationCache下有個status屬性。可以通過其知道當前的緩存狀態

var appCache = window.applicationCache;

switch (appCache.status) {
  case appCache.UNCACHED: // UNCACHED == 0
    return 'UNCACHED';
    break;
  case appCache.IDLE: // IDLE == 1
    return 'IDLE';
    break;
  case appCache.CHECKING: // CHECKING == 2
    return 'CHECKING';
    break;
  case appCache.DOWNLOADING: // DOWNLOADING == 3
    return 'DOWNLOADING';
    break;
  case appCache.UPDATEREADY:  // UPDATEREADY == 4
    return 'UPDATEREADY';
    break;
  case appCache.OBSOLETE: // OBSOLETE == 5
    return 'OBSOLETE';
    break;
  default:
    return 'UKNOWN CACHE STATUS';
    break;
};

既然可以獲得狀態,我們只需要請求更新,隨后在狀態為appCache.UPDATEREADY時更新緩存時即可。

applicationCache.update()方法會嘗試更新用戶緩存,而applicationCache.swapCache()方法會對本地緩存進行更新:

var appCache = window.applicationCache;
 
appCache.update(); // 開始更新
 
if (appCache.status == window.applicationCache.UPDATEREADY) {
  appCache.swapCache();  // 更新緩存
}

正如之前所說的,即使更新了緩存,還是需要重新加載才能使用最新的資源,此時可以提示用戶更新。只需要監聽onUpdateReady事件,該事件在緩存被下載到本地后出發,從而可以在此時提示用戶:

window.addEventListener('load', function(e) {

  window.applicationCache.addEventListener('updateready', function(e) {
    if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
     //更新本地緩存
      window.applicationCache.swapCache();
      if (confirm('已經有新的版本,是否立刻切換到最新版?')) {
        window.location.reload();
      }
    } else {
     
    }
  }, false);

}, false);

applicationCache對象還提供了其他事件,分別為:

onchecking,onerror,onnoupdate,ondownloading,onprogress,onupdateready,oncached和onobsolete

在整個瀏覽器與服務端交互的過程中,所有的錯誤都會出發error事件,我們可以通過監聽error事件進行處理:

var appCache = window.applicationCache;
 
appCache.addEventListener('error', handleCacheError, false);
 
function handleCacheError(e) {
  alert('Error: Cache failed to update!');
};

歡迎留言交流。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM