从Weex到Web,性能逆势破局!飞猪双11性能优化实践

avatar
公众号 @fliggyfe

本文来自飞猪前端工程师@太吾同学,今年飞猪双十一会场前端性能的优化负责PM,来一起看看从 Weex 到 Web 我们的性能优化实践。

一、前言

没有最快,只有更快!在前端开发领域,性能是一个永恒的话题。它不仅仅代表着给予用户的体验,甚至直接会影响到业务的效果,业界共识的说法:页面加载时长每增加 1 秒,用户流失 10%。反过来说性能每快一点,就会带来更多的用户,使业务 GMV 提升,想一想今年双十一 4982 亿的销售额背后有我一份功劳时,心里还有点小激动呢,嘿嘿 但是飞猪今年双十一和去年双十一,会场部分最大的区别就是从 Rax0.6 on WeexRax1.0 on Web。今年上半年启动导购域“端渲染”升级,前端渲染引擎回归到 WebView,初步的结论是在强网和离线的情况下加载体感方面相差无几,但从数据上看 Web 首屏性能数据略差一点。但大家都知道,在 Web 上,已经很久没有页面实践,需要重新探索优化方向

今年双 11,前端在性能方面的目标就是体感上要超过 Weex,数据上也要争取超过 Weex

面临的挑战

为 Follow 集团主推方案,使用 Rax1.0 统一 DSL,一码多端支持 H5、小程序和未来的 Flutter,飞猪从 618 大促开始,就将会场渲染侧全量切换到 Rax 1.0 Web 渲染,当时对于性能方面的优先级不是那么高。 之后,性能优化专项重启,开始着手进行 Web 方面的优化研究,力争提升双 11 的用户体验。双 11 总项目组对性能方面提出一个近乎苛刻的目标:比日常会场性能提高 25% 面对这个目标,传统意义的前端方面优化已经不足以支撑,于是我们联合客户端、服务端以及其他 BU 同学,进行了一场协同战役

二、优化手段

既然要达到这个目标,传统的优化手段已经不足以支撑带来如此巨大的提升,并且一些基本该优化的地方已经被层层框架给做完了,于是需要另辟蹊径。整体梳理页面加载流程,在现有优化手段下,落地更多增进手段。 image.png 与客户端合作(预渲染、离线包、Data-Prefetch...)、重启 SSR 方案。同时在兼顾数据的同时,也需要同时兼顾用户的体感,做了两种 Snapshot 的方案(Mtop 缓存、Html 缓存),最后保障页面间跳转顺滑完成 SPA 方案。 下图展示了所有会场所使用的优化手段 C1BCB553-2815-4BE0-8E77-F9ACCA2C647E.png 图 3.1 所有会场所使用的优化手段

  • **主会场:**为了保证主会场的最佳体验,使用客户端提供的终极大招 - 预渲染;
  • 榜单会场、超级宝贝、酒店会场、机票会场、万券齐发:对于首屏没有异步模块的场景,使用 SSR 配合 Data-Prefetch,极致提升用户可见页面时间;
  • 全部会场:因为模块基本没有变化,全部会场使用 HTML 缓存类型的 Snapshot 方案,用户可以更快浏览该页面;
  • 超级宝贝、榜单会场、我的双 11:针对底部重要会场,采用 Mtop 接口缓存类型的 Snapshot 方案,提升用户浏览体验;
  • 所有会场均通过统一渲染页推送离线包和 Data-Prefetch;
  • 为同时保证分会场分别运营和页面之间切换的流畅性,底部 Tab 五页面之间使用类SPA 方案,使页面切换起来无缝衔接。

可以说为了追求用户的体验,从速度到体感都做了全方位的考虑,性能优化从来就不是技术的狂欢,是可以真正给业务带来价值的事情

** 下面简单介绍一下本次双十一会场主要使用的优化手段。

一)端侧预渲染

如果不考虑可能带来的 Crash 风险,这应该是提升最大的方案了

在双十一这种大促的场景下,通过端控制开关,将下发的配置 URL 以“离屏”的方式初始化好容器并 loadUrl,在上屏之前完成页面的 Rasterization(栅格化)。当用户点击页面入口时,客户端会直接将准备好的 Webview 推到前台直接展示,形成几乎无感的打开效果

效果对比

开启预渲染未开启预渲染
预渲染11.gif未开启预渲染.gif

方案流程图

在客户端通过配置下发的方式初始化 WebView,并通过内存管控保证 APP 的稳定性,同时在展示逻辑上和前端配合,保证数据的一致性,最终通过释放后续的一系列处理管理多次访问的情况。 image.png

二)SSR(Server-side render or Serverless-side render )

披荆斩棘的战士,带着荣光归来

中文名:服务端渲染,顾名思义也就是将渲染的工作放在服务端进行,这种方式很早就存在,早在 Ajax 出现之前全部都是这种方式,由服务端返回给浏览器完整的 Html 内容,但传统 BFF 架构的到来,使得这种方式逐渐慢慢消失,但借着 Serverless 大潮的到来,当 Faas 遇上 SSR,迸发出的火花却让人着迷 今年 3 月份,狼叔的一篇分享《前端新思路:组件即函数和 Serverless SSR 实践》中重新将 SSR 做了概念上的升级,从传统意义上的Server-side render 升级为 Serverless side render,基于 FaaS 环境,提供端侧页面渲染能力 但这条路也充满了挑战,从 8 月底开始了解淘系要搭建业务的 SSR 之后,飞猪侧 9 月开始跟进方案,原本计划国庆会场投入试点,因为种种原因,仅上线不到一天就被下线。但项目组最终还是顶住压力,在双十一的五个重点会场(榜单会场、超级宝贝、万券齐发、酒店会场、机票会场)使用 SSR,并有着非常优异的效果

效果对比

SSR 代表首屏即可视,相比 CSR 减少模块加载以及页面渲染,将可视时间大幅提前。

开启 SSR未开启 SSR
开启SSR.gifssr-pre.gif

方案流程图

整体方案保证性能优势以及改造成本小的前提,采取异步 SSR 方案,即将 HTML 放在接口中返回,在规避高低端机容器影响的同时,又可同时复用客户端的离线以及数据预加载能力,还保证 CSR 到 SSR 的平滑切换。 image.png 对 SSR 方案刚兴趣的小伙伴可以看看《飞猪营销域 SSR 总结 - 双十一会场再加速》

三)SnapShot(页面快照)

将用户体感页面可见时间继续提前

原本设计 SnapShot 是在非千人千面的场景下,多次访问可以更快的可见页面,将上一次访问的 HTML 直接缓存在本地,下一次进入页面时,首先展示缓存的页面,但后来发现在会场这种每天基本都会变阵的场景下,模块的删减以及顺序的调整,都会使得在缓存页面到真实页面展示的过程中发生不可避免的闪动,而这种闪动是有点无法接受的,于是项目组重新设计出 Mtop 接口缓存的方式,配合模块缓存,基本上可以实现与之前同样的效果并且避免了页面闪动的问题 同时项目组发现 HTML 缓存的方式也并非毫无用武之地,双十一会场上线前,针对所有会场进行 Review 优化手段,发现在全部会场这个场景下,会场基本无变化,使用 HTML 缓存的方式简直再合适不过,于是我们将使用 Snapshot 的页面分为两类,适合的才是最好的,达到所有页面都可以尽可能快且没有展示问题地呈现给用户

效果对比

开启 Snapshot 后,整体页面无 Loading,基本达到页面的直出效果。

开启 Snapshot未开启 Snapshot
开启Snapshot.gif未开启Snapshot.gif

四)SPA

完成用户体感的“最后一公里”,多页面间跳转实现无感知

各分会场需要进行分别运营,目前的搭建体系又不支持单页面拆分运营,通过底部 Tab 包框将多页面假装聚合成一个页面,但页面之间的跳转造成的切换割裂体感是一直被人所诟病的,本次改造升级完成了类 SPA 的方案,将 Tab 中的页面数据请求后,直接渲染成真实的 Dom,切换通过 Display 的方式,基本在高端机上实现了将多页面聚合成单页面,多页面间跳转无感知,给予用户最好的体验

效果对比

从多页面之前的 replace 操作,页面跳转中出现白屏,到目前页面中 DOM 的替换,用户体感大幅提升,也取消了用户点击 Tab 却跳页面割裂的感觉。

开启 SPA未开启 SPA
SPA切换.gif未开启SPA.gif

方案流程图

搭建页面框架共用一套渲染引擎,且每个页面的所有模块通过 Fetch 获取,每个模块独立发布,且支持模块拆 combo 后单独缓存,非常适合 SPA 方案。同时项目组针对高低端机做了不同处理,在高端机上请求单 Tab 数据完成后,预加载其他几个 Tab 数据,切换时直接取用,提供更好的体验。 image.png

五)资源&数据预缓存

最快的请求是不发请求

利用飞猪端侧的 Fcache/DataPrefetch 机制,结合飞猪端总控配置下发通道,将页面内使用的静态资源主动下发到客户端进行缓存,使用户访问页面时无需请求静态资源,此外在页面发起跳转时在端侧提前触发页面的 MTOP 数据请求,减少接口请求等待时间。

Fcache 方案 (资源缓存)

会场的离线方案采用 url+package 的方式,在配置后台录入 url 后,后台通过 puppeteer 去跑这个 URL,把请求的资源缓存下来,其中还包括一些滚屏操作,把懒加载的资源也抓下来,最后通过通过读配置去匹配资源缓存。 image.png

DataPrefetch 方案 (数据预加载)

数据预加载拥有三个状态:Memory、Ongoing、Miss。我们认为将请求放在客户端发出一定会减少真实的请求时间,所以即使真实请求发出时,客户端还未完成请求,只要 key 匹配,会等待客户端数据,而不是重新进行一次请求发送。 image.png

三、监控&诊断

优化手段之余,也需要对会场页面的性能趋势进行持续的监控,对于异常 Case 进行排查,为此,项目组开发了实时的性能稳定性实时大盘(图 3.4.1)、双 11 会场小时级性能大盘平台(图 3.4.2)、耗时异常长的慢会话跟踪小工具(图 3.4.3)。 image.png 图 3.4.1 image.png 图 3.4.2 图片 1.png 图 3.4.3

四、成果

飞猪端内双 11 所有会场首屏可见时间达成既定目标,较日常会场首屏耗时环比降低 25%,较 618 以及国庆会场首屏耗时环比降低 20%image.png 图 5.1 双十一分组整体性能耗时趋势图

命中 SSR 的情况下首屏可见时间更是被拉入 1s 内,开启 SSR 的会场在使用 Web 后也可以重提秒开率,在业务频繁变阵影响首屏模块的基础上,达到周整体秒开率 60%以上,机票会场秒开率 75% 以上。

五、技术规划

本次技术上有着很多新尝试和迭代升级,在经过双 11 的磨练之后,需要朝着更加易用和通用的方向发展,主要分为以下几个部分:

1、SSR 方案优化

SSR 在端内提供了巨大提升,首先需要完善同步方案,实现端外场景的提升。其次,在现有基础上增加 AbTest,来支持更有说服力的业务效果对比;最后优化 SSR 在服务端的执行速度以及弹性扩容能力。

2、客户端优化

接下来会尝试多 Webview 的 Tab 切换,接入 PHA 方案。并将更多的唤端情况列入优化方向,如冷启动场景的专项优化。

3、配套设施

优化的背后离不开配套设施的支持,在现有基础上支持卡口、巡检、监控等功能,实现性能问题及时治理。

六、总结

作为一位前端开发工程师,担任双 11 会场性能 PM,特别是对于今年从 Weex 到 Web,性能水位重新被拉高,是挑战也是机会。 在保障业务不受影响的情况下,确保用户打开会场可以得到极致体验。从页面各阶段的耗时分析,到借助兄弟团队能力,整个过程步步为营,最终支撑双 11 会场圆满结束。在整个过程中,通过应用大量的优化手段和创新方案,提高用户的秒开率来侧面帮助业务转化提升;将预渲染、SSR 逐渐落入更多场景,为之后的全面性能提升做铺垫;联合客户端、服务端,打破前端能力和边界,进而探索性能深水区;提升性能数据提升的同时,兼顾性能数据监控,实时把控异常情况。 最后,为明年双 11 立个 Flag:明年不再需要性能保障,而是在页面生产出来的时候,就是满足性能标准的!