在移动 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 进行如下三步骤的改造:web
一:模块化你的 H5 页面/应用,引入模块加载器(可选)chrome
模块加载器没必要多说,SeaJS、requireJS、kissy loader 等耳熟能详,任你挑选。使用模块化的方式来开发你的应用,不只仅将有利于后期的代码维护,在 Hrbrid 的架构中,还将会有利于性能的提高。浏览器
或许你有疑问:模块开发粒度越细化,加载时请求的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 应用加载性能优化方案,若有疑问及建议,欢迎探讨在石破的博客中探讨。