最近一段時間研究了一下H5在iOS移動端表現時使用緩存並可及時更新方案,總結以下:css
當咱們使用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的離線緩存功能;
此處,我採用的就是給http鏈接添加版本號的方式。在iOS webview加載時序和緩存問題總結中已經描述過,好比:index1.html?v=1.1.0 index.js?v=1.0.0 index.css?v=1.0.0 若是在html端修改了那個內容,就能夠直接在對面的版本號上加一,固然也能夠採用時間戳或者隨機數的方法;此時更新了版本號以後,http請求就會無視以前的緩存文件(由於原本就不是同一個鏈接地址了),重新從服務器端拉取最近的數據內容,而後渲染到界面上的就是最近的內容了;
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開發網絡篇—數據緩存》一文;
使用html5的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》的文章,大致是從無到有,又想回滾到無的情形。