1. 场景
场景1
- 了解过性能优化吗?
- 输入url到看到整个页面经历了什么过程?
- ... 场景2
- 页面加载慢,不知道是前端问题还是后端问题,又该如何找到问题和解决
- 页面交互卡顿,不知道具体哪里出了问题
- ...
2. 什么是Web性能
MDN上对于Web性能的定义:Web性能用户对加载时间和运行时的直观体验。Web 性能指页面加载到可交互和可响应所消耗的时间,以及页面在交互时的流畅度——滚动是否顺滑?按钮能否点击?弹窗能否快速打开,动画是否平滑?Web 性能既包括客观的度量如加载时间,每秒帧数和到页面可交互的时间;也包括用户的对页面内容加载时间的主观感觉。
3.如何进行Web性能优化
- 需要了解性能指标-多快才算快
- 使用专业工具可量化地评估出网站或应用的性能表现
- 之后立足于网站页面响应的生命周期,分析出造成较差性能表现的原因
- 迭代优化
4. 性能模型
4.1 RAIL性能模型
RAIL是Response,Animation,Idle和Load的首字母缩写,是一种中由 Google Chrome团队于2015年提出的性能模型,用于提升浏览器的用户体验和性能。
RAIL模型的理念是“以用户为中心,最终目标不是让网站在任何特定设备上都能运行很快,而是使用户满意”
这个名字分别是四个英文单词的首字母。
- 响应(Response):应该尽可能快速的响应用户,应该在100ms以内响应用户输入
- 动画(Animation):在展示动画的时候,每一帧应该以16ms进行渲染,这样可以保持动画效果的一致性,并且避免卡顿
- 空闲(Idle):当使用javascript主线程的时候,应该把任务划分到执行时间小于50ms的片段中去,这样就可以释放线程以进行用户交互
- 加载(Load):应该在小于1s的时间内加载完成网站,并开始进行用户交互
为什么是50ms?
根据网络条件和硬件的不同,用户对性能延迟的理解也有所不同。例如,通过快速的wifi连接在功能强大的台式机加载网站通常在1秒内完成,用户对此已经习以为常。在3G连接速度较慢的移动设备上加载网站需要花费更多时间,因此移动用户通常更加耐心,在移动设备上加载5s是一个更现实的目标。
这四个单词代表带来用户直观体验的四个方面,这些方面会以不同的方式影响整个网站的性能。 我们将用户作为之后性能优化的中心,首先需要了解用户对于延迟的反应。用户感知延迟的时间窗口,如下表所示
| 延迟 | 用户反映 |
|---|---|
| 0~16ms | 人眼可以感知每秒60帧的动画,即每帧16ms,除了浏览器一帧画面绘制到屏幕上所需时间,留给网站大约10ms的时间来生成一帧 |
| 0~100ms | 在该时间范围内响应用户操作,用户会感觉很流畅,响应很迅速 |
| 100ms~300ms | 会感觉到轻微的延迟 |
| 300ms~1000ms | 在此范围内,用户会感觉到在浏览器在执行任务 |
| >1s | 用户的注意力将离开对执行任务的关注 |
| >10s | 用户感到失望,可能会放弃任务 |
响应
目标:应该尽可能快速的响应用户,应该在100ms或者100ms以内响应用户输入。
网站性能对于响应方面的要求是,在用户感知延迟之前接受到操作的反馈。比如用户进行了文本输入、按钮单击、表单切换及启动动画等操作后,必须在100ms内收到反馈,如果超过100ms,用户就会感知到延迟。 在执行开销大的工作时,尽量放在后台异步执行。即便后台处理要数百毫秒才能完成的操作,也应当给用户及时的反馈。
动画
目标:在展示动画的时候,每一帧应该以16ms进行渲染,这样可以保持动画效果的一致性,并且避免卡顿。
目前大多数设备的屏幕刷新率为60次/秒,那么浏览器渲染动画或页面的每一帧的速率也需要跟设备屏幕的刷新率保持一致。所以根据计算,一帧的时间为1000/60约等于16.7ms,16.7ms内要完成脚本执行,回流和重绘等。浏览器绘制大约需要6ms来渲染页面,剩下的大约10ms用来生成一帧。
空闲
目标:当使用JavaScript主线程的时候,应该把任务划分到执行时间小于50ms的片段中去,这样可以释放线程以进行用户交互。
众所周知,浏览器是单线程的(尽管Web Worker支持后台线程)。这也就意味着用户交互、渲染、脚本执行都在同一个线程上。如果线程在执行复杂的javascript时,主线程就无法对用户输入做出及时的反馈,例如点击。因此,js应该分成在50ms或者50ms以内执行的多个代码块。
加载
目标:应该在小于1s的时间内加载完成你的网站,并可以进行用户交互。
页面的加载时间是老生常谈的话题了。要达成在1s内加载出来目标,我们首先要考虑关键渲染路径的优化,优先加载首屏需要的资源,对于不必要的可以在空闲时间加载。
4.2 Web Vitals
Web Vitals是Google在2020年5月提出来的新的用户体验量化方式,使用它来衡量网站的用户体验,并将这些衡量结果用作排名算法的一部分。Google对它的定义是一个良好网站的基本指标。过去衡量一个网站的性能好坏,需要使用的指标太多了。Web Vitals简化了指标,现在我们只需要聚焦于Web Vitals指标的表现即可。
Core Web Vitals是应用于所有Web页面的Web Vitals的子集。每个Core Web Vitals都代表了一个方面的用户体验,在该领域是可衡量的,并反映了以用户为中心的关键结果的真实体验。
- 加载性能(LCP):显示最大内容元素所需时间。为了提供良好的用户体验,LC应在页面首次开始加载后的 2.5s内发生。
- 交互性(FID):首次输入延迟时间。为了提供良好的用户体验,页面的FID应为100ms或更短。
- 视觉稳定性(CLS):累计布局偏移。为了提供良好的用户体验,页面应保持 0.1的CLS或更少。
这些指标都以用户为中心的重要结果为基准,可进行现场测量,并具有等价的实验性指标。例如,虽然 LCP 是页面加载指标的质量天花板,但它也高度依赖于首次内容绘制 (FCP) 和首字节时间 (TTFB),这对于监控和改进仍然至关重要。
5. 性能指标
性能本身是相对的。所以在性能优化的时候,精确的可量化的指标很重要。只有精确的可量化的指标,我们才可以根据这些指标进行快速准确的优化性能。
5.1 背景
最初,我们使用TTFB(Time to First Byte)、DomContentLoaded和load这些衡量文档加载进度的指标,但他们不能直接反映用户视觉体验。
为了能衡量用户视觉体验,Web标准中定义了一些性能指标,这些指标被各大浏览器标准化实现,例如First Paint和First ContentfulPaint。还有一些由Web孵化器社区组(WICG)提出的性能指标,如Largest Contentful Paint、Time to Interactive、First Input Delay、First CPU Idle。另外还有Google提出的 First Meaningful Paint、Speed Index,百度提出的First Screen Paint。
这些指标都是以用户为中心的目标中不断演变出来的,有的已经不再建议使用,有的被各种测试工具实现,有的则作为通用标准由各大浏览器提供的可用于在生产环境测量的API。
5.2 常用指标
TTFB(Time To First Byte)
首字节时间,是指浏览器发起第一个请求到数据返回第一个字节所消耗的时间,这个时间包含了网络请求时间,后端处理时间。
FP(First Paint)
首次绘制。首次绘制包括了任何用户自定义的背景绘制,同时将第一个像素点绘制到屏幕的时刻。
FCP(First Contentful Paint)
首次内容绘制,俗称白屏时间。浏览器将第一个dom元素绘制到页面上的时间,内容必须是文本、图片(包括背景图像)、元素或非白色元素,也包括带有正在加载中的 Web 字体的文本。
但注意这只是用户第一次看到页面内容的时间,这内容不一定是有意义的内容。
FMP(First Meaning Paint)
首次有意义绘制。对于用户有意义的内容第一次绘制到页面上的时间,例如百度首页搜索框首次出来的时间。每个页面的有意义内容因页面而异。
首次有意义绘制是页面可用性的量度标准。
LCP(Large Contentful Paint)
页面内可见的最大内容元素的渲染时间,用来表示用户感知的页面加载时间。
LCP 的目的是衡量页面的主要内容在用户浏览器中显示所需的时间,侧重于用户的感知体验,而不是衡量加载过程各个步骤的一长串指标。
FID(First Input Delay)
从用户第一次与页面交互(即当他们单击链接、点击按钮或使用自定义的、由 JavaScript 驱动的控件)到浏览器实际能够响应该交互的时间。
FID用来衡量页面对用户输入的响应。输入延迟是因为浏览器主线程在忙于其他事情,解析执行js,加载js等。所以正如上文说的那样,要对大型js文件进行切割。
TTI(Time To Interactive)
页面首次可以交互的时间,浏览器可以持续响应用户输入。
完全达到可交互状态的时间点是在最后一个长任务(Long Task)完成的时间, 并且在随后的 5 秒内网络和主线程是空闲的。
简而言之就是满足三个条件:
- 从FCP指标后开始计算
- 持续5s内无长任务(执行时间超过50ms)且无两个以上正在进行中的GET请求
- 往前回溯至5s前的最后一个长任务结束的时间
长任务是50毫秒以上才能完成的任务
CLS(Cumulative Layout Shift)
累积布局偏移,用来衡量页面稳定性。
ClS测量在页面的整个生命周期内发生的每个意外布局移位的所有单独布局移位分数的总和。它基于一个公式,该公式计算页面上的组件在页面加载时移动或“移位”的次数,次数越少越好。
举个例子,在页面加载过程中,出现了一个你想要点击的按钮,当你去点击的时候,因为页面某个元素加载完成导致页面布局发生了改变,按钮不在了那个位置,你就会点到另外的地方上了。
SI(Speed index)
页面内容渲染所需要的时间,该值越低越好。它显示页面渲染内容部分的平均时间,取决于视口的大小。 每隔100ms页面计算一次页面渲染的百分比,直至完成。
TBT(Total Blocking Time)
阻塞总时间,记录FCP到TTI之间所有长任务的阻塞时间总和。
大于50ms的任务叫做长任务,自然,小于50ms叫做短任务。
举个例子,假如FCP到TTI之间页面一共执行了下图所示的长任务和短任务。
每个长任务的阻塞时间等于他所执行的总时间减去50ms。
因此,根据上面的定义,我们得知TBT时间等于200+40+105=345ms。
指标总结
名称 备注 TTFB(Time To First Byte)(首字节时间) 是指浏览器发起第一个请求到数据返回第一个字节所消耗的时间,这个时间包含了网络请求时间,后端处理时间 FP(First Paint)(首次绘制) 首次绘制包括了任何用户自定义的背景绘制,同时将第一个像素点绘制到屏幕的时刻 FCP(First Content Paint)(首次内容绘制) 首次内容绘制是浏览器将第一个dom渲染到屏幕的时间,可以是任何文本,图像,svg等的时间 FMP(First Meaningful Paint)(首次有意义绘制) 首次有意义绘制是页面可用性的量度标准 LCP(Large Contentful Paint)(主要内容绘制) 衡量页面的主要内容在用户浏览器中显示所需的时间 FID(First Input Delay)(首次输入延迟) 用户首次和页面交互到页面响应交互的时间 TTI(Time To Interactive)(首次可交互) 首次可交互的时间 CLS(Cumulative Layout Shift)(累计布局偏移) 测量视觉稳定性 SI(Speed Index)(速度指标) 页面内容渲染所消耗的时间 TBT(Total Block Time)(总阻塞时间) FCP到TTI之间所有长任务的阻塞时间总和