iOS html5使用緩存並及時更新方案總結


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

一、使用Webview自帶緩存機制

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

 

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

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

    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設置 不緩存,那么結果還是會緩存的;  

    <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代碼;

 

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

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

   

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

    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開發網絡篇—數據緩存》一文;

 

二、使用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,如果資源很大的話,在移動端使用也很耗流量;

   

 


免責聲明!

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



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