iOS html5使用緩存並及時更新方案總結 iOS webview加載時序和緩存問題總結 iOS webview加載時序和緩存問題總結

  最近一段時間研究了一下H5在iOS移動端表現時使用緩存並可及時更新方案,總結以下:css

1、使用Webview自帶緩存機制

  當咱們使用webview加載html資源時的,本質上就是一個向服務器索取資源的http請求過程,若是此時咱們設置對於http請求時的緩存策略,那麼就能夠很好的把資源文件保存在內存空間和本地的沙盒文件中(iOS);當咱們下次在加載的時候,若是加載的是同一個http請求地址時,此時 若是本地有緩存,那麼直接返回本地資源;若是沒有本地緩存則向服務器請求地址;大體以下過程html

 

具體的流程和相關設置以下:

  1.IOS端加載html頁面內容,此處我使用的 NSURLRequestReturnCacheDataElseLoad的緩存策略,即有緩存時使用緩存,無緩存時,直接向服務器請求;html5

    NSURL *url = [NSURL URLWithString:self.url];
    NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url cachePolicy:NSURLRequestReturnCacheDataElseLoad timeoutInterval:20];
    [webView loadRequest:request];

  2.html5端:不須要設置以下代碼,經測試發現,若是在上面的iOS端設置好了http加載的緩存策略時,優先以IOS端的設置的緩存策略爲主,即ios 設置了緩存策略,而html5設置 不緩存,那麼結果仍是會緩存的;  ios

    <meta http-equiv="Pragma" content="no-cache" />
    <meta http-equiv="Cache-Control" content="no-cache" />
    <meta http-equiv="Expires" content="0" />

  3.iOS端不須要設置清除緩存的代碼,在iOS webview加載時序和緩存問題總結中,寫了相關不使用緩存的removeCache的iOS代碼;web

 

加載和使用緩存的結果以下:

 1.此時在ios app的沙盒文件中將保存好已經緩存的文件,若是此時沒有退出APP,那麼緩存的內容同時也會保存在內存中;以下圖(此處針對的UIWebView):數據庫

   

 2.此時能夠看到這Caches文件中,後面的Paul.H5下面多了Cache.db的數據庫,打開數據庫能夠看到如下內容;注意 此時的圖片資源也是保存在Paul.H5下面的文件中;api

    2.1 已經請求過的鏈接地址表:瀏覽器

    

    2.2緩存的資源文件緩存

    

 

 3.上面測試的時候都是UIWebView 測試的,一樣的使用WKWebView測試時,打開cache.db時,發現沒有內容,不過加載時,仍舊是存在緩存文件的,只不過WKWebView的緩存是在不一樣的文件夾中,以下:服務器

   3.1 在WKWebView時,cache.db中不存在緩存的文件

    

 

  3.2 下面多了WebKit 的文件夾,後面有幾個二級制文件,裏面存儲的就是WKWebVieW下面的緩存文件了(包含了JS/CSS/圖片);

  

 4.此時,已經緩存好了全部的資源的文件,在下次使用WebView加載時,就能夠很順利的使用緩存的文件了,即時在沒網絡的時候,也是可使用緩存的文件的,相似於下面介紹的application cache的離線緩存功能; 

 

如何即時更新html5的內容

  此處,我採用的就是給http鏈接添加版本號的方式。在iOS webview加載時序和緩存問題總結中已經描述過,好比:index1.html?v=1.1.0  index.js?v=1.0.0 index.css?v=1.0.0  若是在html端修改了那個內容,就能夠直接在對面的版本號上加一,固然也能夠採用時間戳或者隨機數的方法;此時更新了版本號以後,http請求就會無視以前的緩存文件(由於原本就不是同一個鏈接地址了),重新從服務器端拉取最近的數據內容,而後渲染到界面上的就是最近的內容了;

 

使用webview緩存和注意事項

  1.使用 NSURLRequestReturnCacheDataElseLoad時,若是加載的html5文件是個多頁面的內容時,在UIWebView中加載時,從html5的首頁index.html 點擊<a href="index2.html"></a>時跳轉時,在沒有網絡的時候,不會採用緩存好的index2.html的文件,也就是跳轉不過去,而在WKWebView加載時,則能夠很順利的跳轉和使用緩存好的index2.html的資源的文件,不知道是我測試的有問題,仍是自己就是個Bug;

  2.使用此類緩存時,若是緩存的html JS中含有其餘的http 網絡請求,(好比須要先請求數據 後在模板引擎渲染界面)的時候;那麼在無網絡時,建議作個無網絡的界面處理,否則界面可能就很亂了哈。有點囉嗦了,見諒!!!

   3.關於緩存時間的問題,因爲每次加載新的html內容時,都會緩存html新的內容,好比index.html?v=1.1.0 此時就會緩存v1.1.0中html的內容,如此長久下去,緩存的內容就會愈來愈多,建議在IOS端作一個按期清理的緩存的代碼,能夠參考《iOS開發網絡篇—數據緩存》一文;

 

2、使用html Application Cache Api

  使用html5的application cache的離線緩存文件的策略方法也是一個不錯的選擇,可是這裏不推薦使用,也不建議使用,貌似存在不少的問題;

    

  Application Cache的使用

  0.manifest文件加載原理過程圖:

 

    

 

  1.看看在移動的兼容性

    

   能夠看出,在移動的兼容性仍是很高的,裏面只說了在安卓4.4時,退出app時,會存在丟失緩存的問題;

  2.application cache的使用

    2.1 建立 .manifest的文件,以下圖所示

    

 

    manifest文件首先必須已  CACHE MANIFEST開頭, 而後包含了三個部分CACHE: NETWORK: FALLBACK:三個部分,上面有介紹就不重複了;

       2.2 manifest文件的使用;

    

    只須要在 html中添加manifest數據,並寫好對面的.manifest的地址便可;完成上面的步驟後,就已經完成application cache的全部過程了

    2.3 manifest 離線緩存加載的過程:

    2.3.1  首次加載時:

    

    2.3.2 若是.manifest 文件沒有更新時;

    

    3.application cache經常使用api  

window.applicationCache.update()  //update方法調用時,頁面會主動與服務器通訊,檢查頁面當前的緩存是否爲最新的,如不是,則下載更新後的資源
window.applicationCache.swapCache()  //updateready後,更新到最新的應用緩存

一般結合上述兩個方法和相應的屬性咱們能夠手動觸發文件的更新(前提是 manifest文件改動).

var appCache = window.applicationCache;
appCache.update(); //檢查更新
if (appCache.status == window.applicationCache.UPDATEREADY) { 
//若是存在更新,而且已經下載ok,則替換瀏覽器緩存
  appCache.swapCache();  
}

可是,此時頁面並不能用上最新的文件,只是瀏覽器的緩存已經改變,網頁實際內容仍是原來的內容,還須要手動進行reload,才能進行更新文件

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

  window.applicationCache.addEventListener('updateready', function(e) {
    if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
      if (confirm('文件有更新,手否從新加載文件')) {
        window.location.reload();
      }
    } else {
      //若是,拒絕則不刷新網頁
    }
  }, false);

}, false);

  

  4.如何及時更新html js等文件

    這裏,我採用和webView緩存更新的方法同樣,經過添加版本號的方式,每次更新了那些文件的文件的內容,則在原有的版本號的基礎上加一;能夠看看上面的.manifest文件參考一下;(注意html中js css版本號要與.manifest中的文件保持一致)這裏特別說明一下,manifest更新時的過程;若是manifest文件更新事後,.manifest中全部緩存的資源文件都會從新去服務器中發起新的請求,若是請求文件有更新 則下載最新的文件,若是無更新 返回http code 304;最最重要的事,第一次刷新時,是不會更新最新的文件的;這第一次刷新的過程,只是會下載最新的文件保存到緩存中而已,只有在下一次刷新的時候,纔會從新從緩存中拉取最近數據,更新界面;並且特別注意,index1.html是必定會被緩存的,好像這個application cache的機制就是這麼設定的;

     

  5.application cache在移動端中加載後緩存的位置

   在iOS webView 加載使用了 application Cache的html文件,此時的緩存文件保存在如下的目錄中。。下面的OffineWebApplicationCache文件下下面的ApplicationCache.db的數據中;

  

  查看數據庫中資源文件:

  

   6.關於使用application cache過程當中的坑以及不推薦的地方(轉自知乎和其餘地方,本人未作測試):

    6.1  更新機制:一旦你採用了manifest以後,你將不能清空這些緩存,只能更新緩存,或者得用戶本身去清空這些緩存。其中標記了 manifest 的 html 自己也被緩存,並且沒法清除;這裏一旦更新到錯誤的頁面,將被緩存起來,而沒法有機會訪問到正確的頁面,那麼就只能杯具了,因此保證更新的頁面資源的正確性顯得尤其重要。另外電信之類的運營商很喜歡在一些流量大的網站進行劫持廣告,這樣的話,極可能在更新過程將這些廣告給緩存起來了,那就杯具了。

    6.2  manifest自己的編寫要求比較嚴格,要注意換行跟路徑文件名之類的問題。否則緩存將無效。

    6.3 若是更新的資源中有一個資源更新失敗了,將致使所有更新失敗,將用回上一版本的緩存。

    6.4 二次更新的問題,即在更新新版本過程當中,用戶須要第一次時訪問的仍是舊的資源,須要第二次進去纔是新的資源。若是此時後臺接口發生變化,訪問第一次時的舊數據極可能將出現兼容問題。

      6.5 限制大小問題,通常是最多緩存5mb,不過通常是夠用的。

    6.6 回滾問題,這個能夠參考以前的一篇《慎用manifest》的文章,大致是從無到有,又想回滾到無的情形。

    6.7 在安卓4.4中 關閉app後,緩存會丟失;(未作測試)!
       6.8 過多頻繁的網絡請求;每次更改manifest文件後,都會把CACHE:中的資源都向服務器中訪問,哪怕返回的是304,若是資源很大的話,在移動端使用也很耗流量;
相關文章
相關標籤/搜索