Android开发——H5容器加载速度优化方案

1. 背景介绍

在偏重活动运营的电商App中,受制于App版本审核,具备开发周期短、可灵活发布等特点的H5页面受到青睐,承载了很多重要业务。但App Webview存在令人烦恼的性能问题,特别突出的是加载速度慢,和Native页面相比用户体验较差。因此本文将从H5加载速度优化方面,总结了XCache、Prefetch、容器预热三种优化方案,以及上线后的提速效果分享。

2. XCache离线缓存提速方案

2.1 方案背景

为了有效解决 Android H5的性能问题,除了使用Android WebView自身的缓存机制,还可以自己针对某一需求场景构建缓存机制
通常来说,加载一个h5页面最耗时的部分就在于页面资源的下载,如html、css、js以及图片文件,如果这些文件不需要下载,那么剩下的时间开销基本就是业务数据的下载以及页面的解析渲染了。

2.2 方案总体介绍

Android开发——H5容器加载速度优化方案_第1张图片

  • 首先构建Admin后台管理系统,主要帮助开发人员对H5资源进行配置管理,主要包括资源的版本管理、总容量管理以及资源的发布。
  • XCache服务器负责提供资源的下载接口,CDN作为资源镜像,在Server接口连续失败后提供备用接口。
  • 移动端在合适的时机拉取资源配置表,以及资源本身,并在WebView发起资源请求时,判断是否命中资源缓存,从而提高加载速度(尤其是弱网环境),并节省流量。
  • 在资源被访问以及命中缓存后,将相关的数据进行上传统计,从而协助发现问题、调整策略。

2.3 Android端具体方案介绍

Android开发——H5容器加载速度优化方案_第2张图片

  • 资源配置表检查更新接口的触发时机:启动/打开webview/切前台/退出webview,配置表需要实时更新,但是如果连续触发,疲劳度控制在30s内不重复触发。
  • 资源配置表接口的异常兜底机制:接口后端连续异常code 5次,使用的CDN上最新资源镜像(APP内置最新CDN镜像链接)。
  • 根据和上一次的资源配置表进行diff,获取资源的"增、删、更新"信息,其中,同样的资源根据版本号进行更新。
  • 资源的下载时机:当APP空闲时机,并且处于Wi-Fi环境,同时子线程队列下载优先级为最低,下载下来的资源需要进行MD5校验防止恶意攻击。
  • 缓存策略:在移动端支持两级缓存:内存缓存、磁盘缓存,均以LRU作为缓存策略,内存缓存的优先级大于磁盘缓存。其中,内存缓存容量大小设置为10M(内存紧张释放内存缓存), 磁盘缓存容量大小设置为100M。
  • 在H5页面资源请求中,如果命中了配置表中的资源,则优先寻找本地缓存,缓存命中则直接使用,若没有发现本地缓存(原因有很多,比如非Wi-Fi环境下资源没有被提前下载),则自行下载使用的同时,将资源放入内存缓存以及磁盘缓存,方便第二次的缓存命中。

2.4 提速效果总结

2.4.1 白屏时间更短
  • 以签到页为例, Android端页面白屏100ms以内的占比从原来的28.4%提升到了71.2%
2.4.2 更为用户省流量
  • 每年XCache将为用户节省的流量约为53.63TB。(PV * 缓存命中率 * 资源大小 = 省流)
2.4.3 留住了更多“没有耐心”的用户
  • 以签到页为例, 每天因为不愿意等H5白屏而选择退出的用户至少减少了1200名

3. Prefetch数据并行加载提速方案

3.1 方案背景

如果说XCache离线缓存提速方案解决的是H5资源文件下载慢的问题,那么Prefetch并行加载就是从数据的角度来进行的优化。
Android开发——H5容器加载速度优化方案_第3张图片

  • 以超级会员页H5为例,整个H5的加载流程是串行的,业务接口必须在H5资源ready、以及js环境ready之后才会发出;
  • 针对待优化页面,如果在H5页面被打开的同时,客户端协助H5提前将业务请求发出,并维护该数据在内存中,并通过JsBridge将数据提供给H5,H5便不需要再发出请求,从而利用并行特性,缩短H5的白屏时间。

3.2 方案总体介绍

Android开发——H5容器加载速度优化方案_第4张图片

  • 在客户端首次打开H5页面时,拉取prefetch配置文件,其中动态配置了待优化页面、协助客户端完成url—>api。
  • 考虑到H5页面的业务请求不仅依赖于Native注入的Native Cookie,还依赖于H5的一些特有Cookie,因此客户端在拉取配置表的同时,需要触发一次H5 Cookie的请求,且该Cookie不会污染Native Cookie,仅用于Prefetch请求。
  • 当客户端拦截并感知到待优化页面被打开时,主动拉取H5侧的业务数据,用hash算法将数据存在内存Map中,其中hash(url+api)作为key,并约定H5侧通过jsbridge以及相同的key来获取数据。该数据的生命周期很短,退出H5或者被H5侧拿走即清空。
  • 最后在H5侧的相关页面中,修改少量逻辑,在获取业务数据的地方,优先通过jsbridge向客户端拉取业务数据,如果拉取成功,便省去了自行请求的时间,从而达到优化的目的。如果拉取失败,则降级为自行请求的旧逻辑。

3.3 业内方案对比

云音乐Prefetch方案 本Prefetch方案
差异 H5严格信任客户端的异步回调数据, 无错误兜底 H5仅在当前拉取一次客户端数据, 有错误兜底
优点 Prefetch优化的命中率较高 有Prefetch错误兜底, 白屏率更低; 前端出现白屏一定不会是Prefetch的引入导致的
缺点 无兜底, 两端任何细节出错就是白屏, 出错难排查 如果接口过于耗时(>800ms),Prefetch优化会失效, 因此总体的优化命中率会变低,大概88%

由于业内方案中,任何细节出错(譬如Prefetch配置表拉取失败、客户端拦截过程出错等等),都会导致H5侧都无法获取到数据,从而导致白屏。
因此我们采用了更加安全、以及解耦的方案,H5仅在当前拉取一次客户端数据,并加入兜底机制,降低由于优化导致的白屏情况,以及出现白屏不用花精力在“是不是因为Prefetch导致的”。而因为接口过于耗时导致优化成功率降低到88%左右,也是完全可以接受的。

3.4 提速效果总结

3.4.1 轻量级
  • 不需要预工作, 不拖慢App速度,因为Prefetch是在用户点击进入H5的那一刻才开始工作, 所以不会存在类似于XCache的预加载环节。
3.4.2 H5页面呈现速度更快
  • 为了排除其他业务对优化效果量化的影响,Android端单独上线Prefetch,同一时间iOS未上线Prefetch。
  • 签到页H5的首屏完整呈现达标率均值提升6.3%, 对照组iOS降低6.7%;超会页H5的首屏完整呈现达标率均值提升4.1%, 对照组iOS降低2.4%

4. 容器预热提速方案

4.1 方案背景

当App首次打开时,默认是并不初始化浏览器内核的;只有当创建WebView实例的时候,才会创建WebView的基础框架,所以启动浏览器内核的开销都算到了用户首次打开H5页面里。WebView首次初始化后,一些WebView共用的全局服务或资源对象仍没有释放,因此第二次打开H5页面会变快。

首次H5打开时间 第二次H5打开时间
Android WebView 1554.6ms 1044.1ms

经过测试,第二次H5的打开速度比首次打开要快32.8%。

4.2 方案总体介绍

容器预热 选择性的容器预热
优点 有效的减少WebView在App中的首次打开时间 同左,且尽量减少额外的内存消耗
缺点 不可避免的额外内存开销 -
  • 我们可以在App启动之后,并且空闲时,预先将容器WebView进行一次初始化, 当第二次初始化WebView的时候速度就快多了, 或者直接将其拿来使用。
  • 同时,我们针对“不爱打开H5”的用户,有选择性的进行容器预热,从而尽量避免额外的内存开销。

4.3 提速效果总结

  • 由于方案未上线,预计将为用户减少30%以上的首次H5打开时间。

5. 文章总结

相对于React Ntive、Flutter等跨端方案,H5开发有着更加灵活的便利性,因此总能在移动互联网的浪潮中占据一席之地。本文从资源缓存、数据并行加载、容器预热三个方面对H5进行了加载速度优化,都有比较好的提速效果,提升了用户的使用体验。

你可能感兴趣的:(Android开发,HTML5)