共计 2870 个字符,预计需要花费 8 分钟才能阅读完成。
简介: 快让我叉会儿腰~
作者:闲鱼技术 - 颂晨
背景
闲鱼前端页面的性能经常被人念叨,凡跳转、必跳鱼 的印象深入人心,局部页面甚至须要跳四五下能力关上,最近咱们对闲鱼前端页面系统性的做了些优化,因为闲鱼前端技术栈绝对多元,不同栈技术原理各不相同,优化计划也有所差别,本文次要介绍目前闲鱼占比拟重的 Weex 页面的优化过程。
闲鱼 Weex 页面多以前端渲染为主,其关上过程与 Web 页面稍微相近,大抵分为以下几个阶段:
咱们将「从开始加载(navigationStart)到屏幕首次 paint(绘制)像素内容」的这段时间称为 白屏工夫(FP),将「从开始加载(navigationStart)到首屏内容全副渲染实现」的这段时间称为 首屏工夫(FSP),受限于统计口径,目前 Weex 下的首屏工夫是不蕴含图片下载及后续过程的。
优化前后
咱们拿闲鱼的直播频道页和玩家频道页作为参考,通过录屏的形式看下优化前后的比照:
通过录屏分帧的形式咱们统计了下这两个频道页在不同零碎不同机型下的首屏时长:
能够看到,优化前 iOS、Android 支流机型上的首屏工夫都要超过 2s,低端机甚至要 3-5s,优化后各机型的首屏工夫均大幅降落,低端机首屏时长管制到了 2s 内,中高端机近乎直开。
拆解剖析
确定优化计划前咱们对现有的 Weex 页面做了拆解剖析,从后果来看,以下几个因素对首屏工夫的影响较大:
- Bundle 体积:不仅影响 Bundle 加载时长,同时也影响 Bundle 的解析执行耗时(低端机尤为显著)
- 首屏数据申请:页面渲染必须在首屏数据申请返回后,接口耗时间接影响首屏工夫
- 首屏渲染范畴:首屏渲染量间接影响渲染时长(低端机尤为显著)
优化计划
基于下面的剖析调研,咱们初步把优化计划定为四层:
依照预期优化成果,Weex 页面的关上过程是这样的:
体现在上述的四层构造中,次要蕴含以下几个优化点:
Bundle 离线
具体实现是将 Weex Bundle 以资源包为单位、以 URL 前缀为索引,通过肯定的更新策略离线到客户端本地,之前的更新策略次要有 拜访后装置、启动装置 ** 两种,对应的更新机会如下:
这套机制在容器层有对立的计划撑持,然而包命中率始终不高(25% – 55%),导致最终成果差强人意,剖析后发现默认的更新策略(拜访后装置)与页面回访率强相干,闲鱼的前端页面大都是频道导购型的页面,回访率人造不高,所以包命中率绝对应也不会高。
本次优化次要是对更新策略进行了扩大,减少了“闲时装置 ”的更新策略:会在定时更新期间被动装置,如果装置后未应用,则会在一周之后淘汰;如果一周内应用过,则进入惯例的更新淘汰机制(一个月未应用淘汰)。
在“闲时装置”的更新策略上线后,包命中率大幅晋升(稳固后 90% 左右),页面性能也失去了显著晋升:
不依赖首屏接口渲染的页面甚至能够达到「直开」:
数据预取
传统的首屏数据申请都是在 Bundle 解析完当前发动的,首屏数据返回后渲染页面,是个典型的串行过程。
本次优化中咱们把这个串行的过程并行化了:
- 将首屏申请的配置序列化当前作为参数配置到了 URL 上,同时反对一些动静替换的参数(譬如经纬度、城市等参数);
- 在 navigationStart 的时候由客户端提取首屏申请配置,而后发动申请,并将后果以特定的 Hash Key(通过首屏配置生成的)作为索引存储到本地;
- 在业务层真正发动首屏申请的时候会通过 Hash Key 进行比对,命中后将数据取出来返回给业务层;
时序图如下:
非凡状况下的时序图:
具体的技术细节本文不再赘述,数据预取的优化策略上线后,首屏工夫也失去了肯定水平的晋升,如下(iOS 侧因为各优化策略并行上线,没能做到繁多变量采集性能数据,暂以 Android 侧为参考):
Bundle 离线、数据预取 的优化策略上线后,局部页面在中高端机型上迫近「直开」:
渐进式首屏
渐进式首屏解决的是「最初一公里」的问题,因为在上了「离线包」和「数据预取」的计划后,咱们发现:页面首屏工夫肯定水平上还是受限于首屏接口申请耗时,该计划就是为了升高用户侧的白屏期待时长,具体从以下三个方面着手:
-
以接口申请配置生成的索引对接口数据进行缓存
- 当用户首次进入时,以骨架屏占位来期待业务数据加载;
- 当用户非首次进入时,会依据接口申请配置生成的索引在本地缓存中查找缓存数据,并实现首屏渲染,同时并行发送接口申请,待新数据返回后,触发页面更新,实现最终渲染;
-
低端机降级计划
为了用户体验可能更好,在此咱们尝试了低端机降级优化计划。以直播频道为例:
- 只对首屏 Tab 做缓存数据占位优化
- 缩小了低端机上首屏渲染展现数据量
-
图片渲染成果优化
渐进式首屏带来的一个问题是界面更新时的闪动(特地是图片占大篇幅的时候),为了优化此问题,咱们将图片从加载到呈现的过程改为了渐显过渡,肯定水平上打消了图片闪动的僵硬感。
按需渲染
渲染页面作为首屏链路中的一环,不同技术栈、不同设施环境下,在页面首屏工夫中也会有不同的占比。类 Weex、RN 通过前端脚本映射原生组件的技术计划,渲染门路总结起来是:渲染前端 Virtual DOM -> 映射为 Native 指令 -> 将指令传输到 Native 侧 -> Native 执行指令实现渲染。在前三个步骤上,较重的业务逻辑或不合理的代码通常会带来较长的 计算 、 通信 耗时,中低端机器上尤为显著。通过按需渲染能够无效解决这一问题。
按需渲染次要思路是通过只渲染首屏可见视图来最小化首屏渲染耗时。本次优化中,次要针对以下几个场景做了按需渲染:
- 多 Tab 状况下,对于有性能要求的非首屏 tab 页,做数据预加载、页面懒渲染解决
- 对带 / 不带回收机制的长列表做首屏只渲染可见条目,残余懒渲染解决。可缩小带回收机制列表的脚本计算、通信耗时,缩小不带回收机制列表的全链路渲染耗时。
- 自建或应用轻量级组件替换非必要的重量级组件,如: xSlider。
优化上线后,鱼塘广场页中低端机型的首屏性能有了局部数据上的晋升:
低端机上优化前端渲染阶段比照:
Bundle 瘦身
**
Bundle 体积一方面间接影响 Bundle 下载工夫,另一方面也会影响 Android 端的渲染性能(耗时随 Bundle 体积减少 1-2ms/KB),咱们在 Bundle 体积上的优化计划较为惯例,包含:
- 通过 Webpack Bundle Analyzer 剖析依赖,缩小同 npm 包不同版本依赖
- 形象公共模块,进步代码复用率
- 重构根底工具类库,反对按需加载打包
总结
闲鱼前端的性能优化临时告一段落,优化过程中积淀了较多的通用能力,像 Bundle 离线、数据预取、渐进式首屏等等,这些能力在后续会有更大的施展空间,一些能力也会变得更加智能,譬如目前的数据预取是在 navigationStart 的时候发动的,这个机会曾经比传统的页面加载时的机会提前了许多,但其实还能够更加提前,譬如能够在闲鱼客户端中常驻个 TaskSchedule,专门用来解决数据预取的 Task,同时能够联合用户的拜访习惯做智能数据预取。
在前端性能要求越来越高的背景下,传统的 Web 加载流程已无奈再满足性能优化的须要,所以呈现了各种新兴容器 + 配套能力,所以下一代容器的规范状态应该是什么样的?