从“等等”到“秒开”再到“直开”,是什么让闲鱼社区相见恨晚?

背景闲鱼前端页面的性能常常被人念叨 , 凡跳转、必跳鱼 的印象深入人心 , 部分页面甚至需要跳四五下才能打开 , 最近我们对闲鱼前端页面系统性的做了些优化 , 由于闲鱼前端技术栈相对多元 , 不同栈技术原理各不相同 , 优化方案也有所差异 , 本文主要介绍目前闲鱼占比较重的 Weex 页面的优化过程 。 闲鱼 Weex 页面多以前端渲染为主 , 其打开过程与 Web 页面略微相近 , 大致分为以下几个阶段:
从“等等”到“秒开”再到“直开”,是什么让闲鱼社区相见恨晚?文章插图
我们将「从开始加载(navigationStart)到屏幕首次 paint(绘制)像素内容」的这段时间称为 白屏时间(FP) , 将「从开始加载(navigationStart)到首屏内容全部渲染完成」的这段时间称为 首屏时间(FSP) , 受限于统计口径 , 目前 Weex 下的首屏时间是不包含图片下载及后续过程的 。
优化前后我们拿闲鱼的直播频道页和玩家频道页作为参考 , 通过录屏的方式看下优化前后的对比:
从“等等”到“秒开”再到“直开”,是什么让闲鱼社区相见恨晚?文章插图
从“等等”到“秒开”再到“直开”,是什么让闲鱼社区相见恨晚?文章插图
通过录屏分帧的方式我们统计了下这两个频道页在不同系统不同机型下的首屏时长:
从“等等”到“秒开”再到“直开”,是什么让闲鱼社区相见恨晚?文章插图
可以看到 , 优化前 iOS、Android 主流机型上的首屏时间都要超过 2s , 低端机甚至要 3-5s , 优化后各机型的首屏时间均大幅下降 , 低端机首屏时长控制到了 2s 内 , 中高端机近乎直开 。
拆解分析确定优化方案前我们对现有的 Weex 页面做了拆解分析 , 从结果来看 , 以下几个因素对首屏时间的影响较大:

  1. Bundle 体积:不仅影响 Bundle 加载时长 , 同时也影响 Bundle 的解析执行耗时(低端机尤为明显)
  2. 首屏数据请求:页面渲染必须在首屏数据请求返回后 , 接口耗时直接影响首屏时间
  3. 首屏渲染范围:首屏渲染量直接影响渲染时长(低端机尤为明显)
优化方案基于上面的分析调研 , 我们初步把优化方案定为四层:
从“等等”到“秒开”再到“直开”,是什么让闲鱼社区相见恨晚?文章插图
按照预期优化效果 , Weex 页面的打开过程是这样的:
从“等等”到“秒开”再到“直开”,是什么让闲鱼社区相见恨晚?文章插图
体现在上述的四层结构中 , 主要包含以下几个优化点:
Bundle 离线
具体实现是将 Weex Bundle 以资源包为单位、以 URL 前缀为索引 , 通过一定的更新策略离线到客户端本地 , 之前的更新策略主要有 访问后安装、启动安装** 两种 , 对应的更新时机如下:
从“等等”到“秒开”再到“直开”,是什么让闲鱼社区相见恨晚?文章插图
这套机制在容器层有统一的方案支撑 , 但是包命中率一直不高(25% - 55%) , 导致最终效果差强人意 , 分析后发现默认的更新策略(访问后安装)与页面回访率强相关 , 闲鱼的前端页面大都是频道导购型的页面 , 回访率天然不高 , 所以包命中率相对应也不会高 。 本次优化主要是对更新策略进行了扩展 , 增加了 “闲时安装” 的更新策略:会在定时更新期间主动安装 , 如果安装后未使用 , 则会在一周之后淘汰;如果一周内使用过 , 则进入常规的更新淘汰机制(一个月未使用淘汰) 。 在 “闲时安装” 的更新策略上线后 , 包命中率大幅提升(稳定后 90% 左右) , 页面性能也得到了显著提升:
从“等等”到“秒开”再到“直开”,是什么让闲鱼社区相见恨晚?文章插图
不依赖首屏接口渲染的页面甚至可以达到「直开」:
从“等等”到“秒开”再到“直开”,是什么让闲鱼社区相见恨晚?文章插图
从“等等”到“秒开”再到“直开”,是什么让闲鱼社区相见恨晚?文章插图
数据预取
传统的首屏数据请求都是在 Bundle 解析完以后发起的 , 首屏数据返回后渲染页面 , 是个典型的串行过程 。 本次优化中我们把这个串行的过程并行化了:
  1. 将首屏请求的配置序列化以后作为参数配置到了 URL 上 , 同时支持一些动态替换的参数(譬如经纬度、城市等参数);
  2. 在 navigationStart 的时候由客户端提取首屏请求配置 , 然后发起请求 , 并将结果以特定的 Hash Key(通过首屏配置生成的)作为索引存储到本地;
  3. 在业务层真正发起首屏请求的时候会通过 Hash Key 进行比对 , 命中后将数据取出来返回给业务层;