一、背景百度App在2016年上半年尝试了feed流业务形态,到2017年下半年,经过10个版本迭代,产品形态初步探索已经基本完成。在整个feed流表单的闭环中,新闻详情页(文中简称着陆页)是一个重要的组成部分。如果页面打开后加载时间过长,会严重影响用户体验。因此,我们对H5的首屏显示速度进行了长期的优化,比如着陆页。本文将详细阐述整个优化思路和技术细节。每次用户急切的想要浏览感兴趣的文章,却因为加载时间长,不耐烦的选择返回。为了提升用户体验,我们开展了以下工作:通过用户反馈、QA测试等多种渠道,我们发现了着陆页首屏加载缓慢的问题。图,以文末渲染为准)NA、kernel、H5根据三端上报的数据,划分各自H5的加载过程,上报给统计端,产生平均值和80%的性能报表分析性能报告,找出不合理的耗时点,并进行优化。使用AB实验,对比优化前后的性能报告数据,得出优化结果。同时评估用户体验等相关指标。按照长线优化的方法,不断分析定位性能瓶颈和优化,通过AB实验评估效果,最终实现我们的落地页瞬间打开的目标3.Hybrid方案及性能瓶颈简述(1)方案简述在选型中,为了满足跨平台和动态化的需求,采用了Hybrid等相对成熟的方案。Hybrid,顾名思义,就是混合开发,即半原生半Web的方式。页面中复杂的交互功能都是通过端能力的方式调用原生API来实现的。成本低,灵活性好,适用于偏爱信息展示的H5场景。下图展示了百度App中Hybrid的实现机制和加载过程(二)性能瓶颈为了分析Hybrid方案首屏显示慢的原因,找到具体的性能瓶颈,客户端和前端分别针对各自的加载进程。关键节点埋点统计,通过性能监控平台的日志展示。下图为某日全网用户登陆页首屏80%显示速度。可以根据Hybrid加载过程来划分数据各个阶段的性能点,可以看出从点击到首屏显示大约需要2600ms,其中初始化NA组件需要350ms,初始化Hybrid需要170ms,执行JS获取文本渲染需要1400ms前端H5,完成图片加载和渲染需要700ms。分析下四个阶段性能损失主要出现在什么地方:1)初始化NA组件从点击到登陆页框的初始化。主要工作是初始化WebView,尤其是第一次入口(第一次创建WebView平均耗时500ms)2)Hybrid初始化这个阶段的工作主要包括两部分。一种是根据调用协议传递的相关参数,对发送到本地Hybrid模板的Hybrid模板进行校验和解压。耗时约100ms;另外,WebView.loadUrl执行后,会触发Hybrid模板header和body的解析3)Textloading&renderingexecution此阶段内核已经完成了Hybrid模板header和body的解析.这时需要加载解析页面所需的JS文件,并通过JS调用能力发起对文本数据的请求。客户端从服务端获取数据后,以JsCallback的形式回传给前端。前端需要解析客户端传来的JSON格式的文本数据,构建DOM结构,然后触发内核的渲染进程;这个过程涉及请求JS、加载、解析、执行等一系列步骤,还有终端能力调用、JSON解析、DOM构建等操作,比较耗时4)图片加载步骤(3),前端获取的文本数据中包含着陆页的图片地址集。文字渲染完成后,前端需要再次执行图片请求。客户端收到顺序设置的图片地址后向服务器请求并完成下载,客户端会调用一个IO将文件写入缓存,同时将对应图片的本地地址发回给前端结束,最后通过内核再发起一次IO操作,获取图像数据流进行渲染;总体看,图像渲染时间取决于前端分析效率、端能力执行效率、下载速度、IO速度等因素。通过分析,延伸出一些关于Hybrid方案的思考:为什么渲染这么慢?图片请求可以提前序列化吗?行逻辑可以改成并行的WebView初始化时间吗?可以优化吗?四、百度App落地页优化方案(一)CloudHybrid基于之前对Hybrid性能的分析,我们内部孵化了一个名为CloudHybrid的项目,解决了落地页顶部屏幕显示慢的痛点;一句话描述CloudHybrid方案,采用后端直出+prefetch+拦截的方式,简化页面渲染流程,推进&并行化网络请求逻辑,进而提升H5首屏速度1.直后走出终端——第一屏的快速渲染静态直出页面对于Hybrid方案,终端预置加载的html文件只是一个模板文件,里面包含了一些简单的JS和CSS文件。HTML加载到终端后,需要执行JS通过终端能力向服务器异步请求文本数据。获取到数据后,需要经过解析JSON、构造DOM、套用CSS样式等一系列耗时的步骤,最终内核才能渲染出画面;为了提高首屏显示速度,可以使用后端渲染技术(smarty)将文本数据和前端代码整合,直出首屏内容,直出的html文件包含首屏显示需要的内容和样式,内核可以直接渲染;首屏外部内容(包括相关推荐、广告等)可以在内核渲染首屏后执行JS,使用preact异步渲染。第一个屏幕已经在服务器上呈现。这样的内容不需要二次处理,可以大大提高显示速度。直接一点,移动端feed落地页首屏性能数据从2600ms优化到不到2000ms。b.动态信息回填为了保证首屏渲染结果的准确性,除了在服务端整合文本内容和前端代码外,还需要一些影响页面渲染的客户端状态信息,比如地址首图的大小、字体大小、夜间模式等。这里我们采用动态回填的方式,前端会在直出的html中定义一系列特殊字符作为占位符;在loadingUrl之前,客户端会使用正则匹配找到这些占位字符,并根据协议将它们映射到端点。信息;客户端回填处理后的html内容已经具备显示首屏的所有条件。直出页面的显示速度已经非常快;但是在实际开发中,你可能会遇到这样的问题,即使你的数据加载速度很快,在Activity切换过程中仍然会出现无法渲染H5页面的问题(可以联系开发者模式,让动画变慢)timetoverify),导致视觉白屏现象(如上面(上图)我们通过研究源码发现,系统在处理视图绘制时,有一个属性setDrawDuringWindowsAnimating。从名字我们可以看出这个属性是用来控制窗口在动画过程中是否可以正常绘制的,而它恰好是在Android4.2AndroidN和AndroidN之间,系统考虑组件切换的流程。这个字段是假的。我们可以使用反射来手动修改这个属性。改进后的效果如下图/***让Activity过渡动画过程页面可以正常渲染*/privatevoidsetDrawDuringWindowsAnimating(Viewview){if(Build.VERSION.SDK_INT>Build.VERSION_CODES.M||Build.VERSION.SDK_INT
