极致的 Hybrid 混合式开发(去啊App Hybrid 实战)

原文连接:https://yq.aliyun.com/articles/43?spm=a2c4e.11153940.blogcont2939.13.4a692e9bnvCw7Wphp

 

该文章来自于阿里巴巴技术协会(ATA)精选文章。

IO 优化

今天 去啊 App 5.1.1 已经发布了,航旅 Hybrid 混合架构有了更进一步的落地,这轮优化目标是搞定H5真正的“无缝秒出”。html

先来看效果,去啊App 2G 网络下购买国际机票,30秒完成,除了搜索入口页,列表往下到付款页的前端都是H5 Page,你们感觉一下:前端

be4c2c9b4fa8d3e0d2e7ec92df37403a.gif

目测性能是可观的。尽管H5包的离线化隔绝了弱网对秒出的干扰,设备本地 IO 耗时也是不能忽视的,算上zip的解压缩,仅在设备本地 IO 彻底一个 HTML(包含其携带的资源文件)也会达到秒级的耗时,在iphone5上也会有0.5秒左右的白屏时间。git

另外,HTML 自己的优化依然没法绕过,WebView 里 JS 的运行效率一般是 Mobile Browser 里的四分之一。因此 JS 必须尽量靠后的介入渲染,CSS 必须尽量靠前的介入渲染。而在当下前端开发习惯来看,页面一般会至少阻塞加载一个种子文件(好比kissy),而在Mobile设备中,哪怕是无干扰Dom的JS阻塞运行都会带来0.3秒左右的白屏延时。github

因此,H5容器的IO优化和HTML渲染提早是本期改造的重点,即:npm

  1. H5 容器加载资源的 IO 优化:干掉zip包的即时解压,离线包更新后当即解压散列到SD卡,每次建立 View 时直接从设备读文件,本地文件管理依然基于标准的H5包规范。
  2. HTML 自己的页面优化,CSS 提早,JS 置后。

“CSS 提早和JS置后”的动做是由工具来完成。即只要构建工具统一,开发者不须要关心如何摆放脚本最优,只需关注实现业务逻辑便可,举个例子,JS 置后的作法是这样:编程

其实无非是将同步的脚本改为异步。先保证带样式的页面框架秒出来,而后去执行 JS。从性能数据上甚至看不出差异,但从感官上的提高很是明显,我宁愿让你先看到界面,而不是白屏。json

IO 优化(续)

从策略上,作到这两点足够应付大多数场景,能保证页面任什么时候候能秒出来。但在咱们整个 Hybrid 架构中,咱们设计了比较灵活的 H5 离线化,即用虚拟域来确保在线离线的一致,好比酒店团购H5页面,浏览器扫码打开是一个在线页面,用去啊App扫码进来就是一个离线页面,同一份代码,一个走网络加载,一个走本地加载:浏览器

这样设计主要是为了作线上线下的开关切换,紧急问题可随时配置到线上页面,线上页面是能够随时部署的,离线页面则涉及到推包。为了作这层开关,就会带来判断文件是线上仍是离线的问题。缓存

由于H5容器虚拟域的代理层会引导 WebView 去本地而不是网络读文件。若是读不到本地文件,再建立一个HTTP请求去对应的线上请求文件。若是经过 IO 一次再判断本地是否存在文件,显然实际的 IO 次数依然降不下来(全部的资源文件请求都必需要 IO 一次手机硬盘),为了下降实际 IO 次数,咱们针对每一个 H5 离线包生成一个本地资源文件列表(cache_info.json),并同时将域名路径和文件路径作成了映射 Map,这个映射表读入内存后备用,涉及到H5的访问,用这个 Map 过滤下就能直接找到要读的文件位置,Map 匹配不上就直接建立HTTP从网上取文件了,这样能够避免无必要的 IO。

AngularJS 在移动端的加速

去啊 Hybrid 中存在大量的列表页,好比上面的团购和视频中国际机票的例子,AngularJS 是最适用于这种场景。但 AngularJS 目前没有专门针对 Mobile 作优化,而在 Mobile 设备里,hashchange带动数据模型data-model的变动,进而经过View来渲染。首次渲染稍慢,由于要等Model准备好才出视图,不管如何界面也秒不出来(从hashchange到出界面至少0.8 秒)数据结构在稍微复杂点,当即破1秒,固然这个时间是伴随着首次加载构建DOM的干扰。

几点改造:

  1. AngularJS 种子文件异步载入
  2. 非数据关联的HTML一概预装在页面
  3. 首次加载干掉任何影响页面抖动的 HashChange
  4. 基础数据的离线化(好比城市列表)

这几点无非是让首次渲染能尽快的展示,接下来 OPOA 中的编程就是 AngularJS 所擅长的了。

离线包里的 TMS 如何载入

咱们知道 AWP 只支持静态 HTML 的发布,这没什么好解释的,毕竟,高性能要求更简单粗暴且有效的缓存,全静态就能够全缓存,尤为是在移动终端的破网里面,缓存尤为重要,但 TMS 动态内容如何生成?咱们都知道 AWP 平台提供了一个<!--HTTP:url-->的标签(使用说明),TMS 变动后就从新生成一份HTML 推送到CDN上。

那么问题来了,离线包里怎么作?

咱们团队的同窗写了offline-tms-parser模块,clam会将<!--HTTP:url-->标签构建:

<!--HTTP:http://abc.php,gbk:HTTP-->

构建为:

<script 
    src="http://trip.taobao.com/market/trip/h5_offline_service.php? callback=handle_tms_fragment&src=http%3A%2F%2Fabc.php" 
    charset="gbk"></script>

这样,在离线包里的 TMS 内容就和 H5 页面彻底分开了,毕竟 TMS 因为变动频繁,是没办法直接作离线化的。但上面这段脚本显然会阻塞页面渲染,因此offline-tms-parser提供了异步的版本,即将:

<!--HTTP:http://abc.php?async,gbk:HTTP-->

构建为:

<script id="tms_fragment_1">
get_tms_fragment("http://abc.php", "gbk", "tms_fragment_1");
</script>

而后在 H5 页面顶部塞一个get_tms_fragment的实现便可。

如此,基于 AWP 平台开发业务将不受任何影响,工具帮咱们处理好 TMS 和 H5 页面的百分百解耦,离线包里也能够大量使用 TMS 了。

尽管如此,也必须不能滥用 TMS,代码逻辑层面的 View 和 Data 的解耦仍然是必需要作的。

让人期待的 grunt-kmb

本期优化面向 H5 离线容器的代码改造的重点是上面这几项,但还有一项激动人心的变化: grunt-kmb,没错,构建流程也须要瘦身和简化了。

grunt-kmb是团队另外一位同窗正在开发的 grunt-kmc 的替代方案。相比于 grunt-kmc 基于正则匹配的模块解析,grunt-kmc 彻底基于 uglify-js 提供的 JavaScript 语法解析树(AST),先看对比:

grunt-kmc 的速度:

grunt-kmb 的速度:

整整一倍的提速,太让人垂涎期待了。

What's Next

本期的优化没有多少高科技的东西,大都是体力活,将技术作透。好的体验真的是靠点滴的积累,须要花时间去磨。

其实从去啊App Hybrid 刚开始设计并作初版优化到如今已经有半年多时间,这期间离不开客户端同窗的全心投入,由于 H5 的优化必须借助高性能的 WebView 容器,但靠 H5 或者 Web 技术自己不管如何是没法作到秒出的。再配上《高性能网站建设指南》里零碎的优化技巧,H5 在 Hybrid 中彻底能够作到秒出,再配备离线包动态推送和埋点采集等基础设施,Web 技术的瓶颈在 Mobile 中就能得到必定的突破。

我在此次集团前端技术峰会上的汇报里,提到过咱们面临的挑战:

去啊 App 是介于工具化的钱包App和运营化的手淘App之间,既有营销活动,也有工具化、流程化的 PageFlow。将标准化的 PageFlow 的性能作到极致,接下来的挑战就是如何将运营活动也作到智能的推送,完成这类页面的离线部署。

固然,活动页面的离线化部署目前来看不是咱们面临最急迫的难题,最棘手的是数据打通的问题:

看这个场景,在钱包App作了一个引流的入口,唤起了去啊App,并定位到机票搜索结果页:

目前咱们很难跟踪唤起的效果,手机里的App是信息孤岛,很难经过简单的传参来把跨 App 的 PageFlow 串联起来。即便参数能带过来,但身份信息、登录状态和帐号关联可否也能带过来呢,每一项都是颇有挑战。

我在前两天给航旅的新人培训上,分享了我理解的《Mobile First》,这段话是值得分享给你们一块儿共勉的:

内聚的 App 和散列的 Web 彷佛是一个不可调和的矛盾。企业倾向于认为只有提供愈来愈多地功能,才能知足用户不断膨胀的需求,但又会打破原有应用的简便易用。当二者没法调和,信息膨胀到必须散列到不一样的端时,经过 Web 技术将这些信息孤岛关联起来就显得相当重要。

因此,咱们以前所作的全部技术的优化,都是在为构建无线“前端/终端”技术体系夯实根基,因此这一轮无线All In 从某种意义上看是一种原始积累,第二轮无线All In才会迎来真正的非标商品的个性化、多元化时代。这时咱们的技术体系将着重解决这几类问题:

  1. 千人千面,重点解决面向不一样人群作手机里的定制化功能的问题
  2. 无线大数据,重点解决打破App间的信息孤岛,让跨端的数据化运营更加高效、可靠
  3. 无线开源,让 B 商家参与进来,像手淘一个(Native)商品详情页通吃全部商品的时代很快就会被更个性、多彩的非标商品打破,这时,大量垂直领域的产品模式设计更多要靠商家参与,而不是咱们本身那几个产品经理,因此,更开源、更自由的手机店铺,闭环服务才是王道。

说到闭环,去啊的机票购买流程,是无线端闭环的经典案例:

这个例子是从钱包的入口开始购机票流程,经过短信、Push、下载、唤起等操做,将用户捣腾到去啊App里(整个过程体验流畅,估计你也很难分清楚哪些Page是H5的、哪些是Native的吧)。

So,开源 + 闭环,是我理想中的无线 Hybrid 技术的终极状态,去啊 Hybrid 技术积累也才刚刚开始。