本文将从三部分展开介绍,逐步为读者呈现一套清晰的前端性能优化方案。
1、介绍一套合理有效的参考模型(RAIL性能模型)
2、给出一套实用的性能测试手段
3、给出基于此标准的性能提升方案(结合我们自己项目中的业务实例)
一、参考模型
web性能优化,这是大家耳熟能详的东西了。一说到性能优化,大家可能马上就会想到从一些时间节点切入,例如:
首字节时间
白屏时间
首屏时间
用户可交互时间
DOMContentLoaded时间(页面所有内容解析完成时触发)
onLoad时间(等待页面所有资源加载完成时触发)
不同的人会有不同的衡量标准,有的比较重视白屏时间,有的比较关注首屏时间,这并非是完全一致的。
而除此之外,我们可能会考虑其他方面的性能优化问题,例如:
DOM渲染
60FPS动画
Javascript Benchmarks (JS基准)
手段不少,标准也很多,从这些方向着手,都会起到一定的效果,但问题在于众多的标准往往就会导致没有标准。
我们几乎没有人可以把时间完全投入在优化上,因此,我们需要一个标准,来告诉我们现在要去优化什么东西,或者什么东西暂时不需要优化。
想要建立一套合理有效的参考模型,就不得不谈及性能优化要解决的痛点。那就是慢。
比如,一个DOM操作很慢、一个网页加载很慢、加载一个
This is the call to action text element.
3、Long Tasks
单线程的JS用事件循环的方式来处理各个事件。
事件任务被浏览器放入事件循环队列中,单线程会逐个处理事件循环队列中的任务。
如果有一个任务消耗了特别长的时间,就会阻塞队列中的其他任务。
同时 js 线程和 ui 渲染线程是互斥的,执行JS会阻塞ui渲染。此时,用户在使用时将会感受到卡顿和闪烁,这是当前 web 页面不好的用户体验的主要来源。
测试 Long tasks
const observer = new PerformanceObserver(function(list) {
for (const entry of list.getEntries()) {
console.log({
eventCategory: 'Performance Metrics',
eventAction: 'longtask',
eventValue: Math.round(entry.startTime + entry.duration),
eventLabel: JSON.stringify(entry.attribution),
})
}
})
observer.observe({type: "longtask", buffered: true})
4、TTI
TTI ( time to interactive ) ,(持续)互动时间,指的是应用既完成了视觉上的渲染,又可以响应用户输入(并且随后有5秒网络和主线程不活动时间)的时刻。
TTL 作为一种度量标准,主要描述的,是页面或应用程序,何时包含有用的内容,以及主线程何时空闲并自由响应用户交互(可维持5秒流畅交互)。
互动时间作为一种性能指标,突出显示了JavaScript主线程空闲数秒的时刻,并基于反映出网站或应用程序与之交互时的效率。由于它依赖于主线程,因此在很大程度上取决于JavaScript的数量以及给定设备的CPU速度。应用不能响应用户输入的原因主要包括:
TTI 指明了页面的 js 脚本都被加载完成且主线程处于空闲状态 的时间
测量TTL:chrome 提供的性能分析工具 Lighthouse 可以测量出页面的 TTL。
三、性能提升方案
我们掌握了用户为中心的性能量化标准,是为了指导我们优化性能的方向。
1、优化 FP/FCP
- 在 移除影响 FP/FCP 的 css 和 js 代码
- 将影响首屏渲染的关键 css 代码最小集合直接 inline 写在 中
- 对 react 这种客户端渲染框架,做 ssr
- 本地缓存
2、优化 FMP/TTI
- 首先需要确定页面中的最关键元素,例如上文中的视频组件,然后需要保证关键组件相关的代码最先加载并且使得关键组件在第一时间被渲染且可交互
- 图片和组件懒加载
- 延缓加载一些对渲染关键组件无用的代码
- 减少 html dom 个数和层数
- 尽量缩减 FMP 和 TTI 的时间间隔,最好让用户知道当前页面并未完全可交互。避免用户想要交互,但是页面没有响应的情况。