云音乐前端体验优化实践

前端大学

共 4565字,需浏览 10分钟

 · 2020-11-03

(给前端大学加星标,提升前端技能.

作者:贺文超

https://www.yuque.com/binfe/cquxg7/rh12qe

本次分享主要围绕云音乐在 C 端性能体验的部分实践经历,包括评估标准和监控能力建设,以及在网络、容器等方面的性能优化实践。

团队面临的挑战

云音乐从19年初开始,前端从落地页、APP 内长尾页面的开发,逐步承担起 APP 内部分新业务场景的开发职责。

这个阶段,网页的使用体验也逐渐受到外部的关注。由于网页和客户端页面的原生体验上有所差别,加之前端团队的体验意识尚弱,部分业务上线后收到了一些负面反馈,前端在技术选型上也受到诸多挑战。

因此我们意识到,团队急需思考和解决页面体验的问题。而面对多产品和业务线的团队结构,要做到体验问题在整个团队 有标准、能发现、快解决,对于工程化能力会有较高的要求。

体验工程化

为了解决前端交付体验问题,我们首要的事情是统一体验的度量标准,并辅以自动化的发现、反馈、追踪流程,包括:

  • 前端应用能够自动接入性能监控,以达到100%的监控覆盖率

  • 监控系统实时收集网页上报的性能数据,并对页面的收录和实验室环境测试,结合度量标准对页面进行评估,针对不达标的页面实时预警。

  • 监控系统对问题进行持续追踪和反馈,推进开发解决体验问题。

我们希望通过这个流程逐步建立起从发现问题到解决问题、复盘沉淀的良性循环,持续提高团队优秀体验应用的交付能力。

体验度量标准化

度量标准的选择

一套完善的度量评估标准,首先要有对好坏的定义。由于用户感官性能是当下首要关注的内容,因此在标准的选择上我们对比了与此相关的度量模型和工具链:

Lighthouse 5.x(19年)

Lighthouse 这款工具基于预设环境来提供性能评估模型和分析。其中 5.x 版本的评估模型包含6个维度,不同维度在性能上权重不同。它的特点是:

  • 在预设环境进行测试,排除各种设备、环境因素,关注纯代码侧性能。

  • 评估模型尽量体现用户真实的感官体验,而不是单纯的加载速度。另外模型和算法会不断优化完善。

  • 能够评估第三方页面(可以帮助我们对比和外部页面的差异)。

  • 提供包含优化建议的分析报告。

为了解决开发在本地测试中硬件、网络情况不一致导致的问题,我们搭建了内部的 Lighthouse 测试服务,用相同配置的一组测试机进行前后一致的测试。同时设置了统一的 CPU 和网络模拟限制,来达到较好的结果对比度。

Performance API

W3C 定义的三个 Performance API 提供真实环境中各阶段时间节点:

  • Navigation Timing,网页各个阶段的时间节点

  • Resource Timing,页面静态资源的加载时间

  • Long Tasks,长耗时任务

例如我们前期最关注的 Navigation Timing,包含了如下图所示的网页访问时各个阶段的时间节点。

Performance API 的特点是:

  • 体现真实环境下,各种综合因素下的性能表现。

  • 维度为各个阶段时间的具体开销,相对 Lighthouse 指标更加稳定。

  • 需要主动上报,适用于内部页面测试。

Lighthouse 为主的度量标准

我们选择了以 Lighthouse 为主进行度量,Performance API 和其他手段为辅的方式。

其中体验基线(及格线)的定义是在如下 CPU 和网络统一限制环境下,Lighthouse 测试稳定达到80分+:

由于基线只能反映前端研发侧的性能质量,而无法评估到容器、网络等真实环境因素。因此在及格线之外,我们补充了其他指标,以便结合数据进行网络、容器等方面的通用能力优化。包括 Performance API 各个阶段数据、页面秒开率、容器初始化时间等。

选择 Lighthouse 为主的度量标准主要依据是:

  • 易于理解。由于 Lighthouse 排除真实环境中硬件、网络等干扰因素,关注纯开发侧性能, 能够拿到开发易于理解、对优化有直观帮助的指标数据。

  • 关注用户真实体验。Lighthouse 面向感官性能,而不只关注加载快慢,这和我们关注用户真实体验的原则一致。

  • 有助于团队快速形成正向循环。性能分析报告和优化建议有助于团队在之前积累不足的背景下快速获得体验优化的正向反馈。

  • 由于能够评估第三方页面,方便我们了解当前行业的整体情况,进行横向评估和对比。

基于 Web Vitals 的新标准

标准不是一成不变的,2020年5月在 Google 提出了 Web Vitals 后,我们也补充收集了这部分数据。

Web Vitals 是 Google 面向未来的性能度量重心。为了进一步减少开发者的理解成本,它的核心理念是网站开发者不一定要成为性能优化专家。

首先, Web Vitals 基于更易标准化、更加贴近用户真实感受的原则对指标进行了升级,并在指标之上定义了 Core Web Vitals,开发者只需要聚焦在最核心的三个指标上。

另外,这些指标被集成到了更多的工具中,包括 Lighthouse、新版本的Chromium 内核浏览器等。这样便可以统一线上和实验室环境中性能测试的度量衡,解决了之前不同工具测试标准不一致而带来的诸多问题。

目前我们已经能够收集到各个工具链的 Web Vitals 数据,目前在评估观察中。后续或许会基于 Core Web Vitals 对体验基线进行升级。

体验评估体系

自动接入性能监控系统

由于团队有统一的发布系统作为收敛点,在发布系统新建应用时,可以为所有应用自动接入性能监控系统。

应用创建时,发布系统自动在相关平台上生成唯一标志,后续每次应用构建时,自动在 HTML 页面中插入相应 SDK 的下载逻辑即可。

同时,已发布的应用也可以在发布系统上通过同样的方式一键接入监控系统。

自动收录页面并测试

我们希望这些接入了性能监控 SDK 的页面能够被自动收录并进行 Lighthouse 测试。

  • 线上应用接入性能监控 SDK 后,真实用户访问页面时会上报性能数据。我们能够基于这些数据收集到所有被访问过的真实 URL,并通过一定规则将同类页面进行聚合。

  • 对单日 PV 达到一定数量的聚类,选取任一真实链接进行收录。

  • 最后通过定时服务对收录的页面进行定期测试。

这样便完成了线上页面的全量收录和定时测试。

页面评估、预警、指引

每次测试后都会生成 Lighthouse 分析报告,我们针对一段时间内多次测试未达基线的页面推送邮件预警,并提供相应的优化建议,引导页面负责人进行优化改进。

持续追踪和反馈

通过实时预警和定期的邮件推送,开发能够持续了解到所负责前端应用的体验问题。

另外团队的体验大盘也提供了实时的团队整体概况和走势,并通过标杆应用、排行榜透出等等提高体验问题的曝光度。

长期上,我们通过双线组织促进团队研发能力的养成:

  • 体验小分队作为虚拟组织,负责平台能力提供和横向信息拉齐。

  • 各业务小组负责业务内应用的实际优化和能力沉淀等等。

应用侧体验优化效果

经过多个季度的努力,前端应用在体验方面的交付质量有了显著的提升。

基于动静分离的优化实践

前端业务侧的体验优化是最基础、也是最重要的一环。然而网页的性能体验受到网络、容器等因素的综合影响,针对代码侧的单一优化必然存在难以跨越的性能上限。以云音乐业务来看,即使是优化过的前端应用,真实场景下收集到的 domReady 均值依然超过 1s。所以我们提出了全链路体验优化的计划,关注到容器初始化开始的整个加载过程。

动静分离是稳定性保障和性能优化中常见的措施。例如在前端开发中,我们为静态资源设置长期缓存,以便能减轻服务器压力并缩短二次访问的链路。而在容器和网络阶段的优化中,我们也可以利用此思想,将相对稳定的内容提前下载和执行,从而减少用户真实操作到来时的开销。

本次也将重点分享与动静分离相关的两项优化措施。

利用 CDN 进行网络优化

通过将内容分发至全球的海量加速节点,使用户可以就近获取内容,提高网络稳定性和性能。

几乎每个公司在静态资源(静态网页、CSS、JS、图片、媒体资源等)的分发上都应用了 CDN,其实在动态应用(或者动静混合型应用)中, CDN 也能够在性能和稳定性方面发挥很好的作用。因此我们为 SSR 应用中动态生成的 HTML 也提供了 CDN 域名。网页上 CDN 可能带来的性能优化包括:

  • 建连时间优化

  • 回源路径优化(理论收益)

  • 缓存带来的收益(针对可缓存资源)

动静分离

由于 SSR 应用经历了服务端渲染的过程。如果要设置缓存,首先需要对页面内容进行动静分离。SSR 应用中,如果页面上的某个内容满足以下条件,就可以认为该内容是可静态化的:

  • 允许一段时间的时效性问题

  • 不因人而异(与用户态不相关)

  • 不因设备而异

举个例子,如果对视频详情页进行动静分离,可以将视频基本内容作为静态内容、其他内容作为动态内容。

遵循源站的设置

动静混合型应用的每个页面可能对时效性的要求不同,如果一个页面绝大部分内容都是动态的则不能设置缓存。所以不同于静态应用可以设置固定的缓存时长,动态应用的 CDN 缓存策略需要遵循源站,由服务端为每个页面设置合适的缓存时长。

优化效果

网页上 CDN 的收益主要集中在建连时间和内容传输时间的优化上,内部应用实际上能够带来60-100ms左右的提升。由于这个收益覆盖了绝大多数域名,所以整体收益还是比较可观的。

另外在稳定性保障和优雅降级上,CDN 也有良好的表现。例如在服务不可用时,用户也可以看到较为友好的页面:

公共资源预加载

在云音乐 APP 内,前端应用以 CSR 页面为主,这使端内有更大的空间进行预处理工作。另外云音乐分散的部署模式导致绝大部分前端应用为小型应用,每个页面中 React 等公共代码占了大部分。

基本思路

因此我们想到,通过代码的动静分离将应用无关的公共部分单独打包,并提前加载执行。可以提前完成大部分代码的下载和执行开销。

公共资源包会在 APP 预加载容器中提前预热执行,在用户真实访问到来时,只需要加载剩余的代码。基本流程如下:

  • APP 启动时预创建 Webview

  • Webview 预加载引用了公共资源包代码的空白 HTML

  • 用户访问时,如果命中某个公共包则复用 Webview,后续只需要做加载剩余业务代码、纠正地址栏等操作即可

  • 每消耗一个 Webview 对象,就重新创建一个

优化效果

目前公共资源预加载方式的应用能够获得 40%+ 的时间优化。下图是某页面的优化前后对比:

扩展场景

对于应用的性能提升效果,实际上与公共部分在业务应用代码中的占比有关系。由于我们可以同时支持多个公共资源包预加载,因此针对核心的垂直场景,可以扩展为完整代码的预加载优化,从而节省 100% 的代码执行开销。

小结

今天主要和大家分享了云音乐在 C 端性能体验的一部分实践经历,包括评估标准和监控能力建设,以及在网络、容器等方面的性能优化实践。由于篇幅原因仅包含了部分实践内容,欢迎大家针对前端体验相关的问题继续交流探讨。

❤️爱心三连击

点分享
点点赞
点在看
浏览 39
点赞
评论
收藏
分享

手机扫一扫分享

举报
评论
图片
表情
推荐
点赞
评论
收藏
分享

手机扫一扫分享

举报