我们为了改进 Mail.ru 首页上的 Core Web Vitals,进行了几个月的工作。结果是,Cumulative Layout Shift (CLS) 的第 75 个百分位提高了 60%,平均会话时长增加了 2.7%,核心部分的转化率提高了 10% 以上。
起点
Mail.ru 是俄语互联网上领先的电子邮件服务之一,从流量方面跻身俄罗斯前 5 名。对于许多人来说,Mail.ru 是一项重要资源。它每月可获得几亿次访问,是一个门户网站,用户可以在这里访问电子邮件、新闻、社交媒体、效果互联网搜索等。
Mail.ru 希望为访问者提供高质量的用户体验,因此开始着手改进 Core Web Vitals。在讨论我们的优化策略之前,应先说明 Mail.ru 首页的一些技术细节。
虽然这个项目很久以来都是使用我们的内部模板引擎 Fest 开发的,但我们在 2019 年开始迁移到 Svelte 3。
Svelte 在实现响应式时不使用虚拟 DOM,可降低资源密集型程度。Svelte 的方法从生产软件包中移除未使用的函数,因为不使用这些函数时,编译器不会生成实现这些函数的代码。在编译期间会移除未使用的代码,使软件包更小。这可能有助于缩短页面启动期间的总阻塞时间 (TBT)。
跟踪效果指标
在优化 Core Web Vitals 之前,评估实际性能会很有帮助。在推出 Core Web Vitals 之前,我们在内部性能信息中心内跟踪了其他指标,例如 First Contentful Paint (FCP)。
我们对指标收集脚本进行了修改,以收集核心网页指标并将其传输到性能信息中心进行可视化。根据 Google 的建议,我们的脚本使用 PerformanceObserver API 来获取指标,这些指标是 Mail.ru 内的通用前端“平台”的一部分。
信息中心为用户显示了以下指标(2021 年 3 月 15 日至 21 日这一周的平均值):
指标组名称 | 核心网页指标 | 其他网页指标 | |||||
---|---|---|---|---|---|---|---|
指标名称 | LCP | FID | CLS | FCP | 待定 | TTI | |
根据核心网页指标阈值统计的用户占比 | good | 52% | 92% | 33% | 35% | 42% | 43% |
需要改进 | 19% | 5% | 23% | 38% | 16% | 25% | |
弱 | 29% | 3% | 44% | 27% | 42% | 32% |
改进 Core Web Vitals
虽然有大量关于改进核心网页指标的指南,但每个项目都面临着独特的挑战。对于 Mail.ru 首页,我们发现了以下优化机会:
- 为广告横幅植入占位符以降低 CLS。
- 使用服务器端渲染 (SSR) 来减少 Largest Contentful Paint (LCP)。
- 代码拆分,以缩短 LCP 和 First Input Delay (FID)。
改善 CLS 的框架
CLS 是 Mail.ru 首页表现最差的字段指标之一。我们后续在 Chrome 开发者工具的“性能”面板中对此页面进行分析后发现,广告是导致问题的根源。为了提高版式的稳定性,我们的团队决定在展示广告之前使用占位符来预留空间。
实现占位符时,第一步是确定替换占位符的内容的尺寸。幸运的是,桌面版 Mail.ru 首页严格记录了广告尺寸。在与设计团队沟通后,他们将采用 SVG 动画的界面骨架用作占位符,以缩短用户感知到的内容加载时间。
SSR 的回归
为了简化从 Fest 到 Svelte 的过渡,我们逐步重写现有项目,而不是重新开始。到 2021 年 3 月,我们将大部分前端迁移到 Svelte,在分类和解决后端性能问题后,最终将 SSR 引入了我们的生产应用。
实施 SSR 后,该团队发现了 CLS 回归的原因,而这一原因最初并未注意到:在呈现网页上的第一项内容时,新闻版块并未插入。在首次绘制服务器提供的网页标记与在客户端插入新闻版块之间有一定延迟。这种行为导致广告框架发生变化,从而加剧了 CLS。
虽然 Chrome 的开发者工具显示了 Layout Shift 事件,但我们一开始找不到导致这种情况的原因。虽然 SSR 本身并不是问题,但它有助于后来找到解决方案。修复导致绘制延迟的问题代码提高了新闻组件的布局稳定性。
SSR 的另一个影响 CLS 是组件水合之前和之后的移动,这可能会导致进一步布局偏移。我们在移动版中尤其遇到此问题,需要特别注意 hydrated 组件标记。对于此问题,一个很好的解决方案是尽可能将更多显示逻辑从 JavaScript 传输到 CSS。
代码拆分和未使用的 polyfill
为了提高感知的网页加载速度,需要降低 LCP 和 FID 值。为了实现此目的,一种方法是使用代码拆分。除了 Mail.ru 首页本身,我们的团队还在开发用于门户导航的微件。目前已嵌入我们公司的许多项目中。
由于历史原因,该微件会作为同步加载脚本插入到网页的开头。随着时间的推移,此脚本中的 polyfill 所占的份额有所增加。为了限制加载这些 polyfill 对性能的负面影响,我们对现代浏览器和旧版浏览器都实现了代码拆分。
我们决定不要使用 module
/nomodule
模式来为现代浏览器或旧版浏览器加载 JavaScript 软件包,因为 <script>
元素的 type="module"
属性并未定位到能够满足我们需求的先进浏览器。为了解决这个问题,Mail.ru 使用内部工具在后端识别现代浏览器版本,并可以相应地进行调整以适应这些浏览器。
在后端可以识别浏览器后,我们就为现代浏览器和旧版浏览器实现了代码拆分。结果是,现代浏览器上的同步加载 JavaScript 微件的大小缩减了 43.3%。这种做法也已应用于其他一些门户脚本。
除了缩减软件包大小并对核心网页指标产生积极影响之外,代码拆分还能提升开发者体验。我们只有 3.5% 的用户使用旧版浏览器,并且这种占有率呈下降趋势,因此,实现代码拆分使我们的开发者能够使用最新的浏览器 API,而不会给所有用户带来旧版浏览器必要的 polyfill 膨胀。
成果
完成优化后,我们在实测数据中观察到了 2021 年 5 月 24 日至 30 日这一周的平均值:
指标组名称 | 核心网页指标 | 其他网页指标 | |||||
---|---|---|---|---|---|---|---|
指标名称 | LCP | FID | CLS | FCP | 待定 | TTI | |
根据核心网页指标阈值统计的用户占比 | good | 58% (+6%) | 93% (+1%) | 93% (+60%) | 43% (+8%) | 49% (+7%) | 51% (+8%) |
需要改进 | 18% | 4% | 3% | 34% | 17% | 24% | |
弱 | 24% | 3% | 4% | 23% | 34% | 25% |
下面的图表显示了网页性能指标值的变化情况,具体因“平台”而异。请注意图表上的两个重要日期:
- 2021 年 3 月 23 日:包含最后一页部分的迭代版本已迁移到 Svelte;
- 2021 年 4 月 19 日:发布了包含返回的 SSR 和布局已修改的迭代版本,以更正 CLS 回归问题。
5 月 1 日至 5 月 10 日期间的值有所下降,这是因为 5 月的节假日是俄罗斯的节假日。
通过“平台”获得的结果与 Chrome 用户体验报告 (CrUX) 中指标值的增长一致。
我们将推出首次改进前一周的平均用户会话时长值与推出首次改进后的 1 周的平均用户会话时长值进行比较,结果显示其增长了 2.7%。此外,网页的大部分版块的转化次数都大幅提高。特别是,Mail.ru 电子邮件应用的转化次数增加了 11.6%,新闻版块的转化次数增加了 13.5%。
181%
良好 CLS 阈值的提升幅度
2.7%
平均会话时长增幅
13.5%
新闻版块转化率提高
最令人意外的结果是营销横幅的点击率 (CTR) 提高了 17.4%(由于引入 SSR 和预加载代码,其呈现时间显著缩短)。
在分析网页上的其余部分后,我们发现绝大多数部分的效果都得到了显著提升。即便是“天气”和“新型冠状病毒”等并非我们网页上的关键版块,我们的转化率也分别提高了 9.6% 和 9.5%。
总结
提高性能并非易事,因为所涉及的工作可能会耗费更长时间。您应定期监控指标随时间的变化,并确保所有新产品功能均不会导致 Core Web Vitals 指标下降。为此,我们会在性能预算中监控核心网页指标的变化。
最重要的是,我们向产品团队的所有成员(从经理和设计师到测试人员和质量检查人员)强调了核心网页指标的重要性。每个团队成员都应该了解绩效指标,并有能力改进这些指标。我们还会定期将效果优化目标纳入业务流程。要想成功提供优质的用户体验,需要所有团队成员的共同努力。