離線Web app

創建運行在手機上的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文件發生改變時才會更新,所以我們可以加個版本號方便控制。
離線存儲的manifest一般由三個部分組成:
1.CACHE:表示需要離線存儲的資源列表,由于包含manifest文件的頁面將被自動離線存儲,所以不需要把頁面自身也列出來。
2.NETWORK:表示在它下面列出來的資源只有在在線的情況下才能訪問,他們不會被離線存儲,所以在離線情況下無法使用這些資源。不過,如果在CACHE和NETWORK中有一個相同的資源,那么這個資源還是會被離線存儲,也就是說CACHE的優先級更高。
3.FALLBACK:表示如果訪問第一個資源失敗,那么就使用第二個資源來替換他,比如上面這個文件表示的就是如果訪問根目錄下任何一個資源失敗了,那么就去訪問offline.html。

這個過程中有幾個問題需要注意。

  • 如果服務器對離線的資源進行了更新,那么必須更新manifest文件之后這些資源才能被瀏覽器重新下載,如果只是更新了資源而沒有更新manifest文件的話,瀏覽器并不會重新下載資源,也就是說還是使用原來離線存儲的資源。
  • 對于manifest文件進行緩存的時候需要十分小心,因為可能出現一種情況就是你對manifest文件進行了更新,但是http的緩存規則告訴瀏覽器本地緩存的manifest文件還沒過期,這個情況下瀏覽器還是使用原來的manifest文件,所以對于manifest文件最好不要設置緩存。
  • 瀏覽器在下載manifest文件中的資源的時候,它會一次性下載所有資源,如果某個資源由于某種原因下載失敗,那么這次的所有更新就算是失敗的,瀏覽器還是會使用原來的資源。
  • 在更新了資源之后,新的資源需要到下次再打開app才會生效,如果需要資源馬上就能生效,那么可以使用window.applicationCache.swapCache()方法來使之生效,出現這種現象的原因是瀏覽器會先使用離線資源加載頁面,然后再去檢查manifest是否有更新,所以需要到下次打開頁面才能生效。

配置好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對象還提供了其他事件,分別為:
oncheckingonerroronnoupdateondownloadingonprogressonupdatereadyoncachedonobsolete

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

var appCache = window.applicationCache;  
   
appCache.addEventListener('error', handleCacheError, false);  
   
function handleCacheError(e) {  
  alert('Error: Cache failed to update!');  
};  
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 230,321評論 6 543
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,559評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,442評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,835評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,581評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,922評論 1 328
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,931評論 3 447
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 43,096評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,639評論 1 336
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,374評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,591評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,104評論 5 364
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,789評論 3 349
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,196評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,524評論 1 295
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,322評論 3 400
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,554評論 2 379

推薦閱讀更多精彩內容

  • 轉載:H5緩存機制淺析-移動端Web加載性能優化【干貨】 作者:賀輝超,騰訊游戲平臺與社區產品部 高級工程師 目錄...
    meng_philip123閱讀 11,542評論 6 48
  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,826評論 18 139
  • Android 自定義View的各種姿勢1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 172,738評論 25 708
  • 0. 前言 前面有被用戶投訴 APP 流量消耗厲害: 于是乎考慮了流量方面的問題。暫時 APP 中涉及流量的幾個方...
    zyl06閱讀 24,162評論 5 63
  • 一 王子墨小巧玲瓏,聰明可人,可就是太淘氣,上課聽講還不錯,雖然不停地做小動作,但從其眼神中尚能感覺到他已聽懂,可...
    幸福夢中仙閱讀 287評論 0 2