一個想法
在研究 PhoneGap 的時候一直在想一個問題,怎麼提升移動網絡下的網絡性能?特別是靜態文件,屢次加載徹底是浪費。
HTTP 協議中控制緩存也比較糾結,總會有個 304 請求,並且各類協議,各類 HTTP header,都不統一。並且 304 實際上也是進行了一次 HTTP 請求的。
由於用的是 PhoneGap,能夠用 Navtive Code 來進行擴展,因此想到一個點子,是否能有一個靜態文件升級功能?遠程有一個文件標記着靜態文件包的最新版本,若是有更新,這個插件就自動把靜態文件下載到本地。而後 PhoneGap 打開的頁面使用本地緩存的靜態文件便可。徹底不須要任何請求!
HTML Application Cache
正當我糾結怎麼實現的時候,發現了 HTML5 種已經有相似的東西了,並且實現的功能和個人需求如出一轍。由於它就是爲離線應用設計的。
php
離線訪問對基於網絡的應用而言愈來愈重要。雖然全部瀏覽器都有緩存機制,但它們並不可靠,也不必定總能起到預期的做用。HTML5 使用 ApplicationCache 接口解決了由離線帶來的部分難題。
使用緩存接口可爲您的應用帶來如下三個優點:
應用緩存(又稱 AppCache)可以讓開發人員指定瀏覽器應緩存哪些文件以供離線用戶訪問。即便用戶在離線狀態下按了刷新按鈕,您的應用也會正常加載和運行。
離線瀏覽 – 用戶可在離線時瀏覽您的完整網站css
速度 – 緩存資源爲本地資源,所以加載速度較快。html
服務器負載更少 – 瀏覽器只會從發生了更改的服務器下載資源。
html5
詳細介紹:http://www.html5rocks.com/zh/tutorials/appcache/beginner/
一些坑後綴與 mime type:
上面的那篇文章說,緩存清單文件並無標準的後綴名,你能夠自定義一個後綴名並在你的 Web 服務器上指定 mime type。
例如:
java
AddType text/cache-manifest .appcache
動態輸出 .appcache 緩存清單,實現緩存功能:http://www.sitesketch101.com/creating-a-dynamic-html5-cache-manifest/android
利用 iframe 事先動態頁面的 Application Cache 功能:http://labs.ft.com/2012/11/using-an-iframe-to-stop-app-cache-storing-masters/
web
具體怎麼選,到底用不用,就須要你本身去抉擇了。
Android 下 PhoneGap 應用程序的問題:
又是 Android 下,我在 iPhone 中,PhoneGap 跑起來後一點問題都沒,上了 Android 就死活不成功。最鬱悶的是, Application Cache 會有幾個事件,能夠經過這幾個事件判斷 Application Cache 是否正常。在 Android 的瀏覽器下,功能是好的,事件也被正確觸發了。可是上了 PhoneGap 後,事件被正確地觸發了,可是功能卻老是有問題。後來一樣是在網上找到了解決方案:
ajax
public class HelloWorld extends DroidGap { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Set by <content src="index.html" /> in config.xml super.init(); android.webkit.WebSettings settings = super.appView.getSettings(); String appCachePath = this.getCacheDir().getAbsolutePath(); settings.setAppCachePath(appCachePath); settings.setAllowFileAccess(true); settings.setAppCacheEnabled(true); // super.loadUrl(Config.getStartUrl()); super.loadUrl("http://192.168.0.104:8080/cache/index.html"); } }
爲何要多加這些代碼?由於 Android 中的 Web瀏覽器控件默認是禁用 Application Cache 功能的。加上以上代碼後恢復正常。
可以讓我鬱悶的是,PhoneGap 2.5 發佈的時候,說本身修復了這個問題了。以前的版本的確須要手動開啓 Application Cache,2.5中已經把這個問題修復了。可我在 2.6 中依然遇到了這個問題, 十分詭異…
跨域:
Application Cache 和 ajax 請求同樣沒法跨域,PhoneGap 中通常是用一個本地的 index 文件,而後把類庫也打包在本地,而一些業務的 js 和常常變的 css 就放在服務器上。這樣的話,就遇到跨域的問題了,index 文件和 .appcache 文件不在同一個域下。
很糾結,很難解決,後來一想:打包在本地不就是爲了緩存起來加快訪問速度嗎?Application Cache 也是解決一樣的問題。既然有了 Application Cache,那爲什麼還要把一些靜態文件打包放在本地呢?嗯,把整個網站都放到服務器上,包括index.html ,而後問題就解決了。
禁用 Application Cache:
在折騰的過程當中,我想把緩存去掉了。因而我把 index.html 中對緩存清單的引用去掉了,可是卻沒有效果!後來仔細想了一下,瀏覽器更新的流程以下:
先緩存了 index.html 和 .css 文件,我把 index.html 中對緩存清單的引用去掉了,但是 .appcache 文件還在服務器上。瀏覽器打開頁面的時候直接去訪問 .appcache 文件,發現沒有變動,就認爲緩存沒有更新了。因此在這種場景下,修改 index.html 是沒有效果的,你必須把 .appcache 刪掉後才能夠禁用 Application Cache。
完整更新和二次刷新:
下面說的是兩個暫時沒法解決的問題,是 Application Cache 的機制所決定的。首先是完整更新的問題,若是你的緩存清單更新了,它會把清單裏的全部靜態文件下載一遍。雖然問題也不大,可是爲什麼不能指定更新的文件呢?可它的機制目前就是這樣的,無解。
另外一個很鬱悶的問題:若是你的緩存清單更新了,用戶須要刷新2次後才能用到你最新的文件。
第一次刷新會更新緩存的文件,可是頁面已經加載好以前的文件了,js 也已經執行完了。
第二次刷新纔會用到更新好的文件。
仔細想一想這樣作也是有道理的,由於不可能每次刷新都去等緩存清單加載後再去加載。加載完成後也不可能再把新的文件替換並執行,特別是 js 。
其實這個問題也是有辦法解決的,由於緩存更新完畢後會觸發一個事件,能夠在這個事件裏提醒用戶是否要刷新頁面?或者直接強制刷新?總之這裏的問題其實不會很大。
跨域