Android提速 WebView加载H5技术调研

引言

        现在很多科技公司都在如火如荼采用Weex或是Flutter等新技术来进行混合开发。这些技术都是通过一种语言映射到原生(Android and iOS)的方式来提高用户体验,并且Weex还具有前端动态化部署的能力(Flutter还不支持) 。这无疑是现在移动混合开发的最优解,但是也增加了新技术学习成本、踩坑风险及人力成本。

        在手机性能越来越好及网络(5g)越来越快的大潮流下,混合开发中最原始的、最便捷的、最轻量级的采用WebView调用H5页面重新受到青睐。对于一个小公司或是创业公司来说,小步快跑、快速验证、人力控制和WebView的优点不默而合。

         WebView的原始弊疾一直被人诟病,一个字,慢。所以本文在研究了前人WebView加速技术的基础上,提出一种快速提速首屏加载速度的方案。

        为了弄清楚到底慢在什么地方,首先来看一下在Android端加载WebView页面的一般流程(iOS应该也差不多,可类比)。

1、Android 加载H5网页一般流程

        在深入研究了H5加载流程后,粗略画了一个从打开网页到显示完全的流程图。如下图1.1所示。

Android提速 WebView加载H5技术调研_第1张图片
图1.1 Android加载网页时间流

           上图1.1忽略了很多细节,比如请求页面之前需要进行网络连接、脚本js解析等技术细节,将注意力转移到重要到流程节点上。本文将移动端加载H5页面分为以下三个阶段:

(1)WebView无响应状态

(2)白屏状态

(3)加载状态

    1.1 WebView无响应状态

         无响应表示这时候WebView并没有准备好,这时候是完全阻塞的状态。WebView初始化是后续其他任何任务的前提。现在普遍认为无响应态即WebView是否初始化,但本文认为在实际原生开发背景下,可将这一时间点提前到进入页面之前

    1.1.1 进入WebView页面

        本文的目的是研究如何提速WebView,需要能将起始点尽量提前。 Android通过Intent进入一个页面也是需要花费时间的,这个时间平均在30~60ms之间(实验7.1),如果有耗时的操作时间可能会更长。这个过程看似简单但在实际开发中可能会包含一些耗时的操作,比如页面初始化包含UI的初始化等等。

    1.1.2  WebView初始化

        WebView初始化即加载游览器内核,这是和直接在游览器打开一个H5页面最大的不同。在App中打开一个H5页面首先是要加载游览器内核,尤其是第一次打开。从美团技术团队WebView性能、体验分析与优化一文可知这个时间消耗也在几百毫秒之间。再次打开Android系统会缓存WebView相关资源速度会比第一次要快。

    1.2、白屏状态

         游览器内核初始化已完成,开始建立连接请求url对应的主html页面以及相关css样式,js资源,并开始边加载边渲染,直到界面上开始出现内容的这段时间。

         这个时间通过人眼可不好计算,幸好W3c提供的navigation Timing交互性能监测指标可以帮助我们量化这个指标参数。下面我们就来看一下这幅图1.2(图片来源网络)。


Android提速 WebView加载H5技术调研_第2张图片
图1.2 w3c navigation Timing

具体文字定义说明(参考来自网上):

navigationStart 加载起始时间

redirectStart 重定向开始时间

redirectEnd 重定向结束时间

fetchStart 浏览器发起资源请求时间

domainLookupStart 查询DNS的开始时间

domainLookupEnd 查询DNS的结束时间

connectStart 开始建立TCP请求的时间

secureConnectionStart  如果在进行TLS或SSL,则返回握手时间

connectEnd 完成TCP链接的时间

requestStart 发起请求的时间

responseStart 服务器开始响应的时间

domLoading  开始渲染dom的时间

domInteractive 未知

domContentLoadedEventStart 开始触发DomContentLoadedEvent事件的时间

domContentLoadedEventEnd DomContentLoadedEvent事件结束的时间

domComplete dom渲染完成时间

loadEventStart 触发load的时间,

loadEventEnd load事件执行完的时间

        从图1.2游览器加载网页的时序图中稍加整理得到性能指标的重要参数,业界衡量移动web app交互性能的优劣主要也是通过以下几个性能指标:

dns解析时间: domainLookupEnd - domainLookupStart

tcp建立连接时间: connectEnd - connectStart

白屏时间: responseStart - navigationStart

dom渲染完成时间: domContentLoadedEventEnd - navigationStart

页面onload时间: loadEventEnd - navigationStart

      而我们需要获取的是白屏时间,可以通过上面的计算公式获取。

    1.3、加载状态

        加载状态是页面已经开始渲染,人眼已经可见页面轮廓和部分元素。从图1.1可以看出,加载状态并不是等到整个html或是css、js等加载完成,而是加载到一部分就开始渲染,即边加载边渲染。页面加载时间同样可以通过W3c的navigation Timing获取。

2、WebView 加载H5页面速度监控

根据图1.1将整个流程分成三个阶段,主要监控的三个重要指标是:

    2.1 、WebView无响应时间

    2.2、WebView白屏时间

    2.3 、WebView加载时间

todo: 需要实验数据支持,后续补上

3、影响WebView加载速度的因素

        影响WebView加载速度的因素有很多,这就对相关性能监控提出更高要求,需要统计多条求平均值,且对比优化要尽量排除以下因素影响。

现列表比较重点的因素供大家参考。

      手机硬件(如1000块钱手机和6000块钱手机性能还是差别很大)

     游览器内核(如X5内核)

     网络、网络、网络环境重要事情说三遍!(这个变量就非常之大)

    前端代码是否优化(如雅虎14条)

   后端(如nginx部署是否开启缓存和Gzip压缩等)

    。。。

4、业界主流的提速方案分析

    4.1、VasSonic

        VasSonic是大厂腾讯出品,算是业界公认的这方面综合性最完整的一整套提速方案了。它用到了很多技术来帮助提速,下面单列其中重要技术来简单介绍下。

并行加载:将webview初始化和主url html请求分开

        抽离出webview的代理类SonicSession,ui无关,从而可单开线程专门用来请求主html文件和缓存等相关工作。webview与SonicSession相互协作,从而实现并行处理缩短耗时。sonic框架的核心在于提供了一套webview与SonicSession通信协作机制来处理相互之间复杂的状态流程。比如webview是否初始化完成、主html流是否下载完成,是否需要调用缓存、数据下载完成而webview还是初始好怎么处理,初始化完成而数据还只下载一部分该如果处理都是sonic需要处理的主要关键节点。

本地缓存:将请求的主url 获得的html数据进行本地缓存

局部刷新

        任何h5页面理论上都可以抽象出一个模版,分为不变的html 字符串和可变的html 字符串部分。sonic通过和前端的约定标记分割出那些可变的块的不变的字符块,然后通过js与android交互通知原生局部刷新,缺点是需要前端支持。

        sonic1.0版为了实现局部刷新需要后端支持,通过在主html请求头部header增加自定义标示sha1来决定是返回整个html或是动态部分。而在sonic2.0中不需要后端接入,后端返回整个html文件,端上(Android or Ios)根据与前端约定的标签分割为模版(不变)和非模版(变化)部分,然后与本地缓存比较来实现局部刷新还是整体刷新。

截流动态加载:

        这种情况出现请求的主html流还没有下载完成,而webview已经初始化完成,这时候会中断下载过程,将已经下载的流和未下载的节点流包封装成SonicSessionStream。当webview.load(url)时候通过webviewClient.shouldInerceptRequest将sonicSessionStream传给webview。

模拟后台(2.0新增)

    4.2、CacheWebView

        CacheWebView是一种自定义的缓存策略,主要是为解决缓存文件大小扩容。

        Android WebView系统自带缓存也即http协议缓存,是一种被动缓存。缓存策略既不灵活,缓存空间大小是剩余空间的1/8。CacheWebView作者通过资源拦截的方式自定义一套缓存策略,并能自定义缓存空间的大小,能支持100M以上的缓存空间。采用此方法同时也能在图1.1中的白屏状态和加载状态两个阶段提速加载速度。

5、提速WebView可行性方案

        本文在以上研究的基础上,提出对图1.1改造后的WebView加载方案图5.1供大家参考。和图1.1相比其核心思想是尽可能将整个串行动作变成并行来缩短时间。

Android提速 WebView加载H5技术调研_第3张图片
5.1  改造后的WebView加载流程图

整个WebView页面加载过程中,可以将页面(Activity)和WebView相分离;

WebView加载过程中也可以抽离出初始化过程和加载主url html的过程。

边加载边渲染过程中也可通过自定义缓存策略加快渲染目的。

结合不同公司的情况,可选择在以下几个方面发力来实现快速提速方案。

5.1、替换原生WebView为腾讯X5 WebView

        腾讯X5属于内核级加速,已对游览器内核深度定制和优化。 它的优点有很多,比如下图5.2是从其官网截取的一张图片。相较于原生WebView它能提速30%,节省流量20%,并还附带其他比如:更安全、防http劫持、视频播放优化、文件预览等功能支持。接入的成本相对来说不是很高,只要接入或替换原生的Webview及相关类即可。Android手机只要安装了微信或是qq 默认都集成进来了x5内核,不需要客户端额外下载。即使没有集成x5内核,也会先用原生WebView加载,sdk会在wifi情况下静默下载,下载完成下次加载切换到x5 WebView。

Android提速 WebView加载H5技术调研_第4张图片
图5.2、X5游览器的功能优势

优点:内核级加速、更省流量、更安全及附带其他功能。

缺点:由于是腾讯深度定制,不太灵活。

5.2、预加载 WebView

         从美团技术团队WebView性能、体验分析与优化一文中可知,WebView初始化过程需要消耗70~700ms不等的时间,假定取平均值200ms。如果能提高200ms,对于打开速度体验要求很高的场景还是值得一试。

          现在采用全局webview方案实施的并不多,本文猜测可能更多的考虑的是内存消耗问题。假如App中采用H5混合开发较多,并且对部分H5页面打开速度有极致要求,还是可以考虑采用这种方案。比如App启动初始化一个WebView实例池,初始化默认只有一个WebView实例,当打开一个H5页面,从里面拿出一个实例,并相应的在实例池中增加一个备用。总之始终保持WebView实例数比实际打开的H5页面数多1。当前端页面销毁的同时WebView实例响应减1。

优点:预加载时间点提前,简单粗暴

缺点:会有一定的内存开销,需要在用户体验和性能做很好的平衡,

5.3 、预加载H5通用js、css及图片等资源文件

         任何一个项目如果按照数据模型来分都可以分为静态部分和动态部分。前端开发人员可以抽离出不常改动的资源文件如js、css、image图标等。尤其用到的第三方js库,基本不会改动。

         将不常改动的js及css文件放置到App assets目录中或是在app启动时加载一个带有通用资源模版的html页面,将资源缓存到本地。缓存可以借助系统自带缓存或是通过资源拦截自定义缓存路径和缓存策略。

优点:加快页面渲染速度

缺点:占有一定存储空间,需要考虑缓存更新策略

5.4、并行加载url对应的主html文件

        在打开一个网页的同时,通过新开线程获取url对应的html文件,然后通过Android WebView提供loadDataWithBaseURL(html)来加载。sonic主要通过此方式来加快打开速度。

优点:并行加载,提高速度

缺点:需考虑主UI线程和加载url线程之间的通信问题,复杂度增强

5.5、缓存html页面中的css、js及图片资源

        可充分运行游览器自带的缓存,但是系统缓存的空间有限,并且不能自定义缓存策略。Android端可通过WebviewClient通过shouldInterceptRequest方法拦截资源请求,采用原生的主流网络请求框架如okhttp3来请求,并自定义缓存策略和保存路径。

5.6、服务端渲染(动态直出,需前端配合)

        在现在前端Vue项目中,已看不到显示的内容在直接在html标签里面,取而代之的直接是一段js bundle。于是在游览器渲染过程中,需要先将js bundle转成html标签,才能生成dom开始渲染。这个转换过程需要花费时间。如果在这个转换过程中有任务阻塞,还会大大消耗大量时间,最直观的就是很长的一段白屏出现。采用服务端渲染,后端帮转换完成,游览器只是html标签dom渲染,会大大增快展示的速度。

6、实操流程图

        最后,本文给出一个可实际操作的方案流程图供大家参考学习。

Android提速 WebView加载H5技术调研_第5张图片
图6.1 实操流程图

7、优化结果数据实验(todo)

7.1  进入页面需要花费的时间

7.2  WebView初始化需要花费的时间

7.3 无响应状态时间、白屏状态时间以及加载状态时间三个优化因子的量化收集

7.3 替换X5 WebView 后加载速度对比

7.4 采用自定义缓存策略后加速前后对比

7.5 采用图6.1整体优化方案后前后对比

参考

1、Android Webview H5 秒开方案实现 

 https://juejin.im/post/5b94ca52e51d450e7d097f38 

2、为什么你做的H5开屏那么慢?H5首屏秒开方案探讨

 https://blog.csdn.net/w990997566/article/details/79373739

3、WebView性能、体验分析与优化

https://tech.meituan.com/2017/06/09/webviewperf.html

4、WebView 缓存机制 & 资源加载方案

https://www.jianshu.com/p/5e7075f4875f

5、CacheWebView

https://github.com/yale8848/CacheWebView

6、Android webview交互性能监测指标获取方法

https://www.jianshu.com/p/0f04db422b33

7、WebView性能、体验分析与优化(美团)

https://blog.csdn.net/yu280265067/article/details/73379145

8、Navigation Timing获取页面加载各个阶段所需时间

https://www.jianshu.com/p/0e3a851ed711

9、移动 H5 首屏秒开优化方案探讨

https://blog.cnbang.net/tech/3477

10、腾讯祭出大招VasSonic,让你的H5页面首屏秒开

https://mp.weixin.qq.com/s/5SASDtiBCHzoCN-YBZy1nA

你可能感兴趣的:(Android提速 WebView加载H5技术调研)