WebView 预加载&秒开方案调研

1,501 阅读6分钟

Android WebView 加载 H5

一般流程

webview加载一般流程

现状分析

Zeta Math 首页 challenge 排行榜 WebView

环境:测试环境
网络:公司内网WIFI
设备:一加8
系统:Android11
APPZeta Math

e3c90c30-69c9-4d13-9bd5-b63be1536481.png 初始化 WebView Activity\Fragment 耗时约 110ms 首次初始化WebView约 170ms 开始请求到请求成功耗时约 680ms

环境:正式环境
网络:公司内网WIFI
设备:一加8
系统:Android11
APPZeta Math

10f939ab-553c-4c12-a4b6-6042717a7758.png 初始化 WebView Activity\Fragment 耗时约 110ms 首次初始化WebView约 1240ms 开始请求到请求成功耗时约 800ms

环境:正式环境
网络:国内5G,美服VPN,967ms延迟
设备:一加8
系统:Android11
APPZeta Math

95470e53-4382-4e0e-8395-7f191c44a6cc.png 初始化 WebView Activity\Fragment 耗时约 110ms 首次初始化WebView约 2170ms 开始请求到请求成功耗时约 9660ms

  • 注:WebView 初始化过程中像是有网络请求的操作,从 init 到 onLoadStart 回调之间的耗时时长能明显感受到受网速影响,具体原因有待考察

影响WebView加载速度的因素

  • 手机硬件性能
  • 网络!网络!网络!
  • 浏览器内核
  • 前端代码优化、JS解析效率、浏览器缓存
  • ···

耗时问题

  • 实例化 WebView 耗时较长
  • 串行的加载流程:如图 WebView 加载的一般流程可见,一次完整的加载流程默认来说是一个串行操作
  • 资源加载耗时,每次都要重新请求,增加请求耗时

WebView 预加载

全局 WebView 实例

APP 客户端启动时,初始化一个 WebView 实例池,并默认创建一个全局 WebView 实例。当页面需要打开一个 H5 前端页时,就从这里面拿出一个实例,并在实例池中继续增加一个作为备用,保持 APP 中 WebView 实例数比实际打开的H5页面多1

  • 优点:节省WebView实例化时间,实现简单
  • 缺点:占用额外内存开销,影响性能

后台预加载 WebView 全部内容

前端提出的方案,希望提前给到 url 以在后台提前创建 WebView 将 H5 页全部加载完成,需要时直接取出 WebView 使用

  • 优点:完全在后台提前加载完成 WebView,能极大减少使用时的 loading 等待时间
  • 缺点:占用极多额外内存开销和网络开销,用户可能并不会使用但却仍然加载了一个完整的前端页

WebView 秒开提速方案

缓存机制

名称原理优点适用对象说明
浏览器缓存使用HTTP协议头部字段进行缓存控制支持HTTP协议层存储静态资源Android默认实现
Dom Storage通过存储键值对实现存储空间大,数据在本地,安全便捷类似Cookies,存储临时的简单数据类似Android中的SP
Web SQL DataBase基于SQL利用数据库优势,增删改查方便存储复杂、数据量大的结构化数据不推荐使用,用IndexedDB替代
IndexedDB通过存储键值对实现(NoSQL)存储空间大、使用简单灵活存储复杂、数据量大的结构化数据集合Dom Storage和Web SQL DataBase的优点
AppCache类似浏览器缓存,以文件为单位进行缓存构建方便离线缓存,存储静态资源对浏览器缓存的补充
File System提供一个虚拟的文件系统可存储二进制数据、预加载资源和之间编辑文件通过文件系统管理数据目前Android不支持

Webview - 缓存机制 & 资源预加载方案

Android WebView缓存机制和性能优化

并行流程

image.png 最理想的并行流程,将 Activity 初始化、WebView 初始化与请求主页面 html 并行,请求页面 css、js 与请求数据、资源并行,最终统一交给 WebView进行渲染,减少串行渲染造成的等待耗时。

拦截请求与共享缓存

现状:目前两端之间只专注自己的业务,前端自己通过网络请求下载资源。 Android WebViewClient 提供了一个shouldInterceptRequest用于支持外部拦截前端页请求,WebView 每次请求网络资源时会回调该方法。 image.png 该回调方法传入了请求 url ,返回 WebResourceResponse 代表获取到的资源对象,默认返回 null,即代表由浏览器内核自己去完成网络请求。 优点:这里可以由客户端进行拦截网络请求,配置网络请求策略,共享客户端缓存或使用持久化的本地资源,节省内存及网络开销,而前端对此是完全无感知的。

预置公共模版(需前端配合)

精简并抽取公共的 JS 和 CSS 文件作为通用的页面模板(可以按业务类型来生成多套模板文件),打包到客户端中,减少每次打开 H5 需要请求的内容从而缩短总耗时。 此策略可以结合全局 WebView 实例在后台提前加载好公共模版。

复用 WebView

在全局 WebView 实例池预加载的基础上尝试增加复用 WebView 的逻辑,当 WebView 使用完毕后不再销毁,而是将正文数据清空并再次存入缓存池中,等下次直接注入新的正文数据进行复用,减少频繁创建 WebView 及加载模版带来的开销。

延迟加载(前端优化)

尽可能优先加载首屏必须内容,对于一些非首屏必需的网络请求、 JS 调用、埋点上报等,都可以后置到首屏显示后再执行。

替换浏览器内核

如腾讯X5内核,内核级加速,相较于原生 WebView 它能提速30%,节省流量20%,并还附带其他比如:更安全、防 http 劫持、视频播放优化、文件预览等功能支持。 缺点:由于是腾讯深度定制,不太灵活。

三方 WebView 提速方案

腾讯VasSonic

并行加载:将 webview 初始化和主 url html 请求分开 本地缓存:将请求的主 url 获得的 html 数据进行本地缓存 局部刷新:sonic通过和前端的约定标记分割出那些可变的块的不变的字符块,然后通过js与android交互通知原生局部刷新,缺点是需要前端支持 截流动态加载:主 html 流还没有下载完成,而 webview 已经初始化完成,这时候会中断下载过程,将已经下载的流和未下载的节点流包封装成 SonicSessionStream 传给 WebView

CacheWebView

一种自定义的缓存策略,扩大 WebView 缓存空间,强制缓存静态资源,从缓存中拿页面已经加载过的资源。

参考文献

WebView性能、体验分析与优化——美团技术团队

Android WebView H5 秒开方案总结

Android提速 WebView加载H5技术调研

Android H5秒开方案调研—今日头条H5秒开方案详解