在 移動 App 開發領域,主流的開發模式可分爲 Native、Hybrid、WebApp 三種方式。然而 2013 年,純 WebApp 開發模式的發展受到必定挫折,以 Facebook 爲表明的獨立 App 轉投 Native 陣營。可是開發者對 WebApp 更新速度快,跨平臺優點的渴望卻並未減弱,最終的結果是促成了 Hybrid App 在 2013 年數量的激增,而且增加的速率很是之快。 簡單的說,Hybrid App是 Native App 和 Mobile Web 兩者混合開發的產物,HTML5 的頁面被嵌入到 Natvie App 的 webview 中。所以它綜合了更新速度快,交互體驗好,跨平臺等優勢。css
本文分享的就是 HTML5 頁面(尤爲是被嵌入的 H5 應用) 藉助 Hybrid 架構來提高本身的加載速度和性能的一種解決方案。該方案要求你對 Hybrid App 進行如下三步驟的改造:html
一:模塊化你的 H5 頁面/應用,引入模塊加載器(可選)web
模塊加載器沒必要多說,SeaJS、requireJS、kissy loader 等耳熟能詳,任你挑選。使用模塊化的方式來開發你的應用,不只僅將有利於後期的代碼維護,在 Hrbrid 的架構中,還將會有利於性能的提高。chrome
或許你有疑問:模塊開發粒度越細化,加載時請求的JS、CSS等靜態資源的數量越多,頁面的性能不會越差嗎?個人回答是:若是你僅僅是使用了模塊加 載器並異步加載各個模塊,那麼加載的性能必定不好,由於請求的數量太多。固然你確定會想到在發佈前打包合併靜態資源,那麼對這樣的解決方案我只能給到 50 分,由於被打包合併的文件中只要有一個子文件發生變化,那麼整個文件(JS或CSS)都要被從新下載,對移動帶寬而言仍是個負擔。瀏覽器
怎麼破?請繼續進行步驟二:緩存
二:啓用 AppCache ,並引入增量更新機制性能優化
作過 WebApp 的同窗應該會了解 mainfest 文件,Html5提供的應用緩存功能,開發者只要把需被緩存的靜態資源文件名羅列在這個列表中便可保證二次訪問時無 需從新加載。看起來不錯!這樣前面說的模塊化開發形成的請求數量過多的問題,至少在二次訪問時不會再發生了。嗯,這樣的方案能夠給到 70 分吧。其實,Html5 提供的 mainfest 緩存機制有個比較大的問題(兼容性就先不提了):若是 mainfest 列表中的一個資源文件須要更新,那麼整個 mainfest 中的其它文件也都須要被從新下載一遍。 也便是說二次訪問沒有問題了,可是 Html5 應用更新時仍是會出現全量下載的問題。服務器
別忘了,咱們是 Hybrid App,還能夠充分利用 Native 層的強大能力,因此拋棄mainfest吧,讓 Native 來幫助 Html5 應用緩存靜態資源文件。整體思路是:網絡
一、Html5 應用首次啓動時,調用 Native 提供的加載資源文件專用的 Device API 來請求所需的資源文件,由 Native 層發出真正的資源請求,並將請求結果緩存在手機的SD卡上。固然,這裏徹底能夠優化爲一次 zip 包請求,由於 native 可以提供強大的解壓能力。架構
二、H5 應用再次啓動時,全部的靜態資源都是經過 Device API 讀取本地緩存,無需再走網絡。
三、H5 應用出現靜態資源更新時,在應用啓動時首先經過 Device API 加載須要更新的文件,並更新本地緩存,其它未變動文件繼續走緩存。
流程看起來挺順,其中有幾個關鍵問題須要解決:
一、如何經過 Device API 加載資源文件?
這裏使用模塊加載器的優點就體現出來了,只須要在加載器中作點小修改,不直接走Http請求了,而直接調用 Native 提供的文件加載 DeviceAPI 便可。 若是你沒有模塊加載器,就須要寫統一的函數來作加載資源的功能了。
其實 Native 也提供了攔截機制,可以攔截到 H5 應用發出的全部 Http 請求並進行自定義處理,惋惜這樣好的功能在 Andorid 4.0 如下版本不支持。 故現階段仍是主動調用 Device API 更靠譜。
二、如何知道須要進行資源的更新?
每次靜態資源發佈都會產生一個惟一的發佈時間戳(或是全部資源內容的MD5編碼),H5應用啓動後,可將當前時間戳保存下來,等應用下次啓動時,請求最新的發佈時間戳並與本地時間戳進行對比,若不一樣,則首先進行靜態資源的增量更新。
三、如何判斷哪些是須要被增量更新替代的資源文件?
這個問題的回答會比較複雜些,核心思路是經過對先後兩次資源文件(js、css、image等)發佈的內容對比完成:
如此,H5 應用藉助 Native 應用的能力完成了資源的緩存與增量更新,能夠保證 H5 應用在啓動與更新時的加載速度。固然也有方案藉助 HTML5 的 localstorage 來替代 Native 的緩存更新策略,可是會收到兩點限制:
一、若 Hybrid App 比較複雜,涉及多個子域甚至主域的靜態資源共享,則 localstorage 的方案在存儲空間上有上限,是5M。
二、Native 可以支持更新包的 zip 打包下載,一次請求,並解壓覆蓋本地緩存。 localstorage 沒法實現。
若應用能夠忽略以上兩點,使用 localstorage 緩存的策略徹底 ok。
三:啓用 spdy 協議
spdy 協議在移動開發上大有可爲,它是HTTP協議的加強版本,可以經過一次TCP連接同時請求到多個資源文件,請求速度上的提高那是天然的 了,很是強大!chrome 等 webkit 內核瀏覽器都已經支持。 惋惜如果藉助瀏覽器自身使用 spdy 協議則要求靜態資源文件(js、css、image)必須是 https 的域名服務,且部署了支持 spdy 協議的後臺server。相信大多數靜態服務器都仍是http 服務,是沒法經過瀏覽器來直接支持的。
仍是那句話,由於咱們是 hybrid 應用,能夠發揮native的優點! native 層徹底能夠實現基於 spdy 協議請求的 device API,供 H5 應用(JS)來調用。這樣就不須要 https 域名服務器也能使用 spdy了。
若是你的 Hybrid 應用已經支持了 spdy 協議,那麼你能夠考慮再也不須要把增量更新的資源文件打包成 zip 下載了,直接 spdy 協議並行下載便可!
SPDY 與 HTTP 協議速度對比:
總結:
本文提供了一種基於 Hybrid 架構的 H5 應用加載性能優化方案,若有疑問及建議,歡迎探討在石破的博客中探討。