【定义指标】: 围绕几个关键问题构建出了指标框架: 1 是否正在发生? 导航是否成功启动?服务器有响应吗? 2 是否有用? 是否渲染了足够的内容让用户可以深入其中? 3 是否可用? 页面是否繁忙,用户是否可以与页面进行交互? 4 是否令人愉快? 交互是否流畅自然,没有延迟和卡顿?
【如何对指标进行测量】: 性能指标一般通过以下两种方式来进行测量:
- 在实验室中: 使用工具在稳定、受控的环境中模拟页面加载 (FCP、LCP、TTI、TBT、CLS)
- 功能在发布到生产环境中之前,不可能基于真实用户体验对性能特征进行测量,
- 因此在功能发布之前,在实验室中对其进行测试是防止性能回归(prevent performance regressions)的最佳方法。
- 在实际情况中: 基于真实用户的实际页面加载与页面交互 (FCP、LCP、FID、CLS)
- 要想真正了解您的网站为用户呈现的性能表现,唯一的方法就是在这些用户进行页面加载和页面交互时对页面性能进行实测。
- 这种类型的测量通常被称为真实用户监控(Real User Monitoring),或简称为 RUM。
这两个选项没有优劣之分,事实上,您通常会需要同时使用这两个方式来确保良好的性能。
【指标类型】: 与用户对性能的感知相关(只用一项指标去捕获页面的所有性能特征是远远不够的)
- Perceived load speed 感知加载速度: 页面在屏幕上加载并渲染出所有视觉元素的速度。
- Load responsiveness 加载响应度: 为了使组件对用户交互作出快速响应,页面加载和执行任何所需 JavaScript 代码的速度。
- Runtime responsiveness 运行时响应度: 页面在加载后,对用户交互的响应速度。
- Visual stability 视觉稳定性: 页面上的元素是否会出现让用户感到意外的偏移,并对用户交互造成潜在的干扰?
- Smoothness 平滑度: 过渡和动画在页面状态切换的过程中是否具有稳定的帧速率和顺滑的流动性?
【需要测量的重要指标】 (这些指标能从 chrome 的Lighthouse等工具计算或者获取,当前还未涵盖运行时响应度和平滑度)
FCP(First Contentful Paint) 首次内容绘制
指标测量页面从开始加载到页面内容的任何部分在屏幕上完成渲染的时间。
- "内容"指的是文本、图像(包括背景图像)、
<svg>
元素或非白色的<canvas>
元素。 - FCP 与 LCP 的重要区别: 虽然部分内容已完成渲染,但并非所有内容都已经完成渲染。
- 可交互是 FCP 之后的时间点,页面在 50ms 内响应用户的交互。(执行时间超过 50 毫秒的任何任务称为长任务)
- 如果主线程正在解析、编译和执行 JavaScript,则它不可用,因此无法及时(小于 50ms)响应用户交互。
TTI(Time to Interactive) 可交互时间
指标测量页面从开始加载到主要子资源完成渲染,并能够快速、可靠地响应用户输入所需的时间。(实验室)。 TTI 是安静窗口(没有长任务且不超过两个正在处理的网络 GET 请求)之前最后一个长任务的结束时间。
TBT(Total Blocking Time) 总阻塞时间
指标测量FCP 与 TTI 之间的总时间,这期间主线程被阻塞的时间过长,无法作出输入响应。
- 一个页面的总阻塞时间是在 FCP 和 TTI 之间发生的每个长任务的阻塞时间总和。
- 如果任务时长足够长(例如超过 50 毫秒),那么用户很可能会注意到延迟,并认为页面缓慢或卡顿。
LCP(Largest contentful paint) 最大内容绘制
指标测量页面从开始加载到最大文本块或图像元素在屏幕上完成渲染的时间。
- 最大内容绘制考量的元素类型: 1
<img>
元素; 2 内嵌在<svg>
元素内的<image>
元素; 3<video>
元素(使用封面图像); - 4 通过
url()
函数(而非使用 CSS 渐变)加载的带有背景图像的元素; 5 包含文本节点或其他行内级文本元素子元素的块级元素。 - LCP 主要受四个因素影响: 缓慢的服务器响应速度、JavaScript 和 CSS 渲染阻塞、资源加载时间、客户端渲染。
FID(First input delay) 首次输入延迟
指标测量从用户第一次与页面交互(例如当他们单击链接、点按按钮或使用由 JavaScript 驱动的自定义控件)直到浏览器对交互作出响应,并实际能够开始处理事件处理程序所经过的时间。
- 一般来说,发生输入延迟(又称输入延时)是因为浏览器的主线程正忙着执行其他工作,所以(还)不能响应用户。
- 可能导致这种情况发生的一种常见原因是浏览器正忙于解析和执行由您的应用程序加载的大型 JavaScript 文件。
- 在此过程中,浏览器不能运行任何事件侦听器,因为正在加载的 JavaScript 可能会让浏览器去执行其他工作。
- 较长的首次输入延迟通常发生在首次内容绘制(FCP)和可交互时间(TTI)之间
- 以下所有 HTML 元素都需要等待主线程上正在进行的任务完成运行:
- 文本字段、复选框和单选按钮
<input>、<textarea>
、下拉选择列表<select>
、链接<a>
- 文本字段、复选框和单选按钮
CLS(Cumulative layout shift) 累积布局偏移
指标测量整个页面生命周期内发生的所有意外布局偏移中最大一连串的布局偏移
(会话窗口)分数。
- 每当一个可见元素的位置从一个已渲染帧变更到下一个已渲染帧时,就发生了布局偏移 。
- 只有当现有元素的起始位置发生变更时才算作布局偏移。
- 如果将新元素添加到 DOM 或是现有元素更改大小,且不会导致其他可见元素的起始位置发生改变,则不算作布局偏移。
- 布局偏移的场景,例如:
- 阅读文章时,文本时在毫无预警的情况下移位,导致找不到先前阅读的位置;
- 正要点击一个链接或一个按钮时,点击或者手指落下的瞬间,链接移位了,结果点到了别的东西。
- 页面内容的意外移动的原因通常是由于异步加载资源,或者动态添加 DOM 元素到页面现有内容的上方。
- 罪魁祸首可能是未知尺寸的图像或视频、实际渲染后比后备字体更大或更小的字体,或者是动态调整自身大小的第三方广告或小组件。
- 只有当现有元素的起始位置发生变更时才算作布局偏移。
- 一连串的布局偏移,也叫会话窗口,是指一个或多个快速连续发生的单次布局偏移,每次偏移相隔的时间少于 1 秒,且整个窗口的最大持续时长为 5 秒。
- 最大的一连串是指窗口内所有布局偏移累计分数最大的会话窗口。
- 布局偏移分数 = 影响分数 * 距离分数
- 前一帧和当前帧的所有不稳定元素的可见区域集合(占总可视区域的部分)就是当前帧的影响分数(0~1)。
- 距离分数指的是任何不稳定元素在一帧中位移的最大距离(水平或垂直)除以可视区域的最大尺寸维度(宽度或高度,以较大者为准)。
- 比如一个元素在前一帧顶头占屏幕 50%,下一帧下移了可见区域高度的 25%(顶头空 25%)。布局偏移分数则为
0.75*0.25=0.1875
除此之外,Web 性能工作组还推出了一系列较低级别的标准化 API,可用于实现您自己的自定义指标:
用户计时 API、长任务 API、元素计时 API、导航计时 API、资源计时 API、服务器计时
当前针对 2020 年的指标构成侧重于用户体验的三个方面——加载性能、交互性和视觉稳定性——并包括以下指标(及各指标相应的阈值):
- Largest Contentful Paint (LCP): 最大内容绘制,测量加载性能。(测量页面的主要内容何时完成加载)
- 为了提供良好的用户体验,LCP 应在页面首次开始加载后的 2.5 秒内发生。
欠佳: >4000ms
- 为了提供良好的用户体验,LCP 应在页面首次开始加载后的 2.5 秒内发生。
- First Input Delay (FID): 首次输入延迟,测量交互性。
- 为了提供良好的用户体验,页面的 FID 应为 100 毫秒或更短。
欠佳: >300ms
- 为了提供良好的用户体验,页面的 FID 应为 100 毫秒或更短。
- Cumulative Layout Shift (CLS): 累积布局偏移,测量视觉稳定性。
- 为了提供良好的用户体验,页面的 CLS 应保持在 0.1. 或更少。
欠佳: >0.25
- 为了提供良好的用户体验,页面的 CLS 应保持在 0.1. 或更少。
为了确保您能够在大部分用户的访问期间达成建议目标值,对于上述每项指标,一个良好的测量阈值为页面加载的第 75 个百分位数,且该阈值同时适用于移动和桌面设备。
【各项指标改进方式】 : 参看 如何改进 FCP、 如何改进 TTI、 如何改进 TBT、 如何改进 LCP、如何改进 FID、如何改进 CLS
如何改进 FCP | 如何改进 TTI | 如何改进 TBT 和 FID |
---|---|---|
消除阻塞渲染的资源 | 缩小 JavaScript | 减少第三方代码的影响 |
缩小 CSS | 预连接到所需的来源 | 减少 JavaScript 执行时间 |
移除未使用的 CSS | 预加载关键请求 | 最小化主线程工作 |
预连接到所需的来源 | 减少第三方代码的影响 | 保持较低请求数和较小传输大小 |
减少服务器响应时间 (TTFB) | 最小化关键请求深度 | |
避免多个页面重定向 | 减少 JavaScript 执行时间 | |
预加载关键请求 | 最小化主线程工作 | |
避免巨大的网络负载 | 保持较低请求数和较小传输大小 | |
使用高效的缓存策略服务静态资产 | ||
避免 DOM 过大 | ||
最小化关键请求深度 | ||
确保文本在网页字体加载期间保持可见 | ||
保持较低请求数和较小传输大小 |
如何改进 LCP | 如何改进 CLS |
---|---|
使用 PRPL 模式做到即时加载 | 首选转换动画,而不是触发布局偏移的属性动画。 |
优化关键渲染路径 | 除非是对用户交互做出响应,否则切勿在现有内容的上方插入内容。 |
优化 CSS | 始终在图像和视频元素上包含尺寸属性,或者通过使用 CSS 长宽比容器之类的方式预留所需的空间 |
优化图像 | |
优化网页字体 | |
优化 JavaScript |
LCP 主要受四个因素影响: 缓慢的服务器响应速度、JavaScript 和 CSS 渲染阻塞、资源加载时间、客户端渲染。
- 浏览器从服务器接收内容所需的时间越长,在屏幕上渲染任何内容所需的时间就越长。更快的服务器响应速度能直接改善包括 LCP 在内的各项页面加载指标。
- 浏览器在能够渲染任何内容之前,需要将 HTML 标记解析为 DOM 树。如果 HTML 解析器遇到任何外部样式表(
<link rel="stylesheet">
)或同步 JavaScript 标签(<script src="main.js">
),则会暂停解析。- 脚本和样式表都是阻塞渲染的资源,这些资源会使 FCP 延迟,进而导致 LCP 延迟。延迟加载任何非关键的 JavaScript 和 CSS,从而提高网页主要内容的加载速度。
- 加载许多其他类型资源所需的时间也会影响绘制时间。影响 LCP 的元素类型为:
<img>
元素、内嵌在<svg>
元素内的<image>
元素、<video>
元素(使用封面图像测量 LCP)、通过 url()函数(而非使用 CSS 渐变)加载的带有背景图像的元素、包含文本节点或其他行内级文本元素的块级元素
- 如果您正在搭建一个主要在客户端进行渲染的网站(诸如 React、Angular 和 Vue 这类的框架和库构建单页应用),那么应该特别小心网站在使用大型 JavaScript 包时可能对 LCP 产生的影响。
具体优化方式:
- 缓慢的服务器响应速度(使用 Time to First Byte 首字节时间 (TTFB) 来测量服务器响应时间)。改进 TTFB 的方式:
- 优化您的服务器(在服务器上运行的许多网络框架都有性能指导)
- 将用户路由到附近的 CDN(使用 CDN 来确保您的用户永远不必为发送到远距离服务器的网络请求而等待。)
- 缓存资产(配置反向代理、缓存服务器、配置和管理云服务提供商的缓存行为、使用提供边缘服务器的 CDN)
- 优先使用缓存提供 HTML 页面(使用Service Worker API)
- 尽早建立第三方连接(使用
rel="preconnect"
告知浏览器页面打算尽快建立连接,使用dns-prefetch
更快地完成 DNS 查找) - 使用签名交换(签名交换 (SXG) 是一种交付机制,通过提供采用了易于缓存格式的内容来实现更快的用户体验。)
- 阻塞渲染的 JavaScript 和 CSS。
- 减少 CSS 阻塞时间
- 削减 CSS: CSS 文件可以包含空格、缩进或注释等字符。这些字符对于浏览器来说都不是必要的,而对这些文件进行削减能够确保将这些字符删除
- 插件:webpack:optimize-css-assets-webpack-plugin; gulp:gulp-clean-css; Rollup: rollup-plugin-css-porter
- 延迟加载非关键 CSS
- 如果是在您网站的单独页面上使用,可以将所有未使用的 CSS 完全删除或移动到另一个样式表。
- 对于任何初始渲染时不需要的 CSS,请使用 loadCSS 来异步加载文件,这里运用了
rel="preload"
和 onload。<link rel="preload" href="stylesheet.css" as="style" onload="this.rel='stylesheet'" />
- 内联关键 CSS: 通过把用于首屏内容的任何关键路径 CSS 直接包括在
<head>
中来将这些 CSS 进行内联。
- 削减 CSS: CSS 文件可以包含空格、缩进或注释等字符。这些字符对于浏览器来说都不是必要的,而对这些文件进行削减能够确保将这些字符删除
- 减少 JavaScript 阻塞时间
- 削减和压缩 JavaScript 文件、延迟加载未使用的 JavaScript、最大限度减少未使用的 polyfill
- 减少 CSS 阻塞时间
- 缓慢的资源加载速度
- 优化和压缩图像:(首先考虑不使用图片或删除无关图片、压缩图片、新的图片格式、使用响应式图片、使用图片 CDN)
- 预加载重要资源:( 重要资源例如字体、首屏图像或视频,以及关键路径 CSS 或 JavaScript 使用
<link rel="preload">
来更加及时地获取该资源。) - 压缩文本文件: 压缩诸如 Gzip(所有浏览器) 和 Brotli(几乎所有较新的浏览器) 之类的算法可以显著缩减在服务器和浏览器之间传输的文本文件(HTML、CSS、JavaScript)大小
- 基于网络连接交付不同资产(自适应服务): 当加载构成页面主要内容的资源时,根据用户的设备或网络条件按需获取不同的资源。可以使用网络状况 API、设备内存 API 和硬件并发 API 来实现。
- 使用 Service Worker 缓存资产: Service Worker 还可用于缓存任何静态资源,并在收到重复请求时将资源直接提供给浏览器,而无需通过网络。
- 客户端渲染(诸如 React、Angular 和 Vue 这类的框架和库)
- 最小化关键 JavaScript
- 使用服务端渲染
- 使用预渲染
- 其他补充:
- 使用 PRPL 模式做到即时加载:
PRPL
: Preload(预加载) 最重要的资源、尽快 Render(渲染) 初始路由、Pre-cache(预缓存) 剩余资源、Lazy load(懒加载) 其他路由和不重要资源 - 优化关键渲染路径: 优先显示与当前用户操作相关的内容
- 优化 CSS: 延迟加载非关键 CSS、最小化 CSS、提取关键 CSS、使用媒体查询优化 CSS 背景图像
- 优化图像: 合理的尺寸、压缩图像、使用响应式图像、使用 webP 图像、图像 CDN 优化
- 优化网页字体: 在字体加载期间避免不可见的文本、优化 WebFont 加载和呈现、减小 WebFont 大小
- 优化 js(针对客户端渲染的网站): 使用 PRPL 模式、代码拆分、删除未使用的代码、缩小和压缩网络有效负载
- 使用 PRPL 模式做到即时加载:
该项指标需要真实的用户交互才能测量响应延迟。
为了有助于在实验室中预测 FID,建议测量总阻塞时间。虽然这两项指标的测量内容不同,但 TBT 的改进通常能够带来 FID 的相应改进。
糟糕的 FID 主要是由繁重的 JavaScript 执行导致的。优化网页上 JavaScript 的解析、编译和执行方式将直接降低 FID。
- 分割长任务: 将长时间运行的代码拆解为更小的异步任务。
- 优化您的页面,做好交互准备
- 第一方脚本执行会延迟交互准备
- JavaScript 体积膨胀、执行时间过长和分块效率低下会延迟页面对用户输入作出响应的时机,并影响 FID、TBT 和 TTI。
- 渐进式加载代码和功能可以有助于分散工作量,改善交互准备。
- 考虑将更多逻辑转移到服务器端,或在构建期间静态生成更多内容。
- JavaScript 体积膨胀、执行时间过长和分块效率低下会延迟页面对用户输入作出响应的时机,并影响 FID、TBT 和 TTI。
- 数据获取会影响交互准备的许多方面
- 等待一连串的级联获取(例如组件的 JavaScript 和数据获取)会影响交互延迟。请尽量最大限度地减少对级联数据获取的依赖。
- 大型内联数据存储会延长 HTML 解析时间并影响绘制和交互指标。请尽量最大限度地减少需要在客户端进行后处理的数据量。
- 第三方脚本执行也会加剧交互延迟
- 许多网站包括的第三方标签和分析会使网络一直处于忙碌状态,并使主线程周期性地无响应,从而影响交互延迟。
- 请探究按需加载第三方代码的相关做法(例如,不要加载还未滚动到可视区域附近的非首屏广告)。
- 在某些情况下,第三方脚本会在主线程的优先级和带宽方面抢占第一方脚本,并延迟页面做好交互准备的时机。
- 请尝试优先加载您认为可以为用户提供最大价值的内容。
- 许多网站包括的第三方标签和分析会使网络一直处于忙碌状态,并使主线程周期性地无响应,从而影响交互延迟。
- 第一方脚本执行会延迟交互准备
- 使用 Web Worker: 被阻塞的主线程是输入延迟的主要原因之一。
- Web Worker 能够让 JS 在后台线程上运行。将非用户界面操作移动到单独的工作线程上可以缩减主线程阻塞时间,从而改善 FID。
- MDN 的官方示例使用,在 main 线程接收用户输入的值,传递给 worker 线程,在 worker 中进行复杂计算,将结果传回。
- Web Worker 能够让 JS 在后台线程上运行。将非用户界面操作移动到单独的工作线程上可以缩减主线程阻塞时间,从而改善 FID。
- 减少 JavaScript 执行时间: 限制页面上 JavaScript 的数量可以减少浏览器执行 JavaScript 代码所需的时间
- 延迟加载未使用的 js: (将资源包代码拆分为多个块动态导入、使用 async 或 defer 延迟加载任何非关键 js,包括第三方脚本)
- 最大限度减少未使用的 polyfill: 使用了现代 JS 语法或者现代浏览器 API,要使代码在旧版本浏览器中正常工作,需对代码进行转译并包括 polyfill。网站中包括 polyfill 和转译代码会带来性能方面的一个主要担忧: 如果新版本浏览器不需要这些资源,则不必进行下载。
- 使用模块/非模块模式来交付两个单独的资源包
<script type="module" src="modern.js"></script> <script nomodule src="legacy.js" defer></script>
- 使用
@babel/preset-env
来只将计划定位的浏览器所需的 polyfill 包括在其中
- 使用模块/非模块模式来交付两个单独的资源包
- 其他能够改进 FID 的单个性能技巧:
- 减少第三方代码的影响
- 针对
<script>
标记使用async
或defer
属性、建立与所需来源的早期连接、延迟加载、优化使用第三方脚本的方式
- 针对
- 减少 JavaScript 执行时间
- 通过代码拆分减少 JavaScript 负载、缩小和压缩网络有效负载、删除未使用的代码、使用 PRPL 模式实现即时加载。
PRPL
: Preload(预加载)最重要的资源、尽快 Render(渲染)初始路由、Pre-cache(预缓存)剩余资源、Lazy load(懒加载)其他路由和不重要资源
- 通过代码拆分减少 JavaScript 负载、缩小和压缩网络有效负载、删除未使用的代码、使用 PRPL 模式实现即时加载。
- 最小化主线程工作
- 原因:默认情况下,渲染器进程的主线程通常处理大部分代码:它解析 HTML 并构建 DOM,解析 CSS 并应用指定的样式,以及解析、评估和执行 js。 主线程还处理用户事件。因此,每当主线程忙于做其他事情时,网页可能无法响应用户交互,从而导致糟糕的体验。
- 脚本评估: 优化第三方脚本、消除输入处理程序的抖动、使用 web worker
- 样式和布局: 减少样式计算的范围和复杂性、避免大型、复杂的布局和布局抖动
- 渲染: 坚持仅合成器的属性和管理层计数、简化绘制复杂度和减少绘制区域
- 解析 HTML 和 CSS: 提取关键 CSS、压缩 CSS、延迟加载非关键 CSS
- 脚本解析和编译: 通过代码拆分减少 JavaScript 负载、删除未使用的代码
- 垃圾收集: 使用
performance.measureUserAgentSpecificMemory()
监控网页的总内存使用情况(chrome 实验性质)
- 保持较低的请求数和较小的传输大小:优化 CSS 和 JS、Images、Fonts、Documents、Media
- CSS 和 JavaScript: 默认情况下,对 CSS 和 JavaScript 文件的请求是渲染阻塞的。换句话说,在所有 CSS 和 JavaScript 请求完成之前,浏览器无法将内容呈现到屏幕上。(影响所有指标)
- 图片: 一个常见问题是当移动用户加载页面并看到图像已开始加载但需要一段时间才能完成时 (影响 FCP、Speed Index/FID?)
- 字体: 字体文件加载效率低下可能会导致页面加载期间文本不可见 (影响 FCP)
- 文件: 如果您的 HTML 文件很大,则浏览器必须花费更多时间解析 HTML 并从解析的 HTML 构建 DOM 树。 (影响 FCP)
- 媒体: 动画 GIF 文件通常非常大。(影响 FCP)
- 减少第三方代码的影响
对于大多数网站来说,您可以通过遵循一些指导原则来避免所有的意外布局偏移:
- 始终在您的图像和视频元素上包含尺寸属性,或者通过使用 CSS 长宽比容器之类的方式预留所需的空间。 这种方法可以确保浏览器能够在加载图像期间在文档中分配正确的空间大小。请注意,您还可以使用 unsized-media 功能策略在支持功能策略的浏览器中强制执行此行为。
- 除非是对用户交互做出响应,否则切勿在现有内容的上方插入内容。 这样能够确保发生的任何布局偏移都在预期之内。
- 首选转换动画,而不是触发布局偏移的属性动画。 动画过渡的目标是提供状态与状态之间的上下文连续性。
CLS 较差的最常见原因及对策:
- 无尺寸的图像: 始终在图像和视频元素上包含 width 和 height 属性。或者通过使用 CSS 长宽比容器预留所需的空间。
- 无尺寸的广告、嵌入和 iframe
- 广告:因为通常是动态广告尺寸,在广告的不同生命周期可能引发布局偏移
- 为广告位静态预留空间、广告位未返回广告时显示占位符避免折叠预留空间、根据广告历史数据选择最有可能的尺寸
- 嵌入和 iframe: 可嵌入小组件使能够在页面中嵌入可移植的网络内容,但通常无法提前预知某个嵌入会有多大
- 通过使用占位符或后备回调符为嵌入预先计算足够的空间来最大程度减少 CLS
- 广告:因为通常是动态广告尺寸,在广告的不同生命周期可能引发布局偏移
- 动态注入的内容: 除非是对用户交互做出响应,否则避免在现有内容的上方插入内容。这样能够确保任何布局偏移的发生都在预期之内。
- 如果动态添加内容是用户体验的一个重要部分,使用以下方法避免意外布局偏移:
- 在一个固定尺寸的容器中用新内容替换旧内容,或者使用轮播,在过渡后删除旧内容。
- 让用户主动加载新内容,这样他们就不会对偏移(例如出现"加载更多"或"刷新"按钮)感到惊讶。
- 无缝加载屏幕外的内容,并向用户叠加一个通知,说明内容已经可用(例如,显示一个 "向上滚动 "按钮)。
- 如果动态添加内容是用户体验的一个重要部分,使用以下方法避免意外布局偏移:
- 导致不可见文本闪烁 (FOIT)/无样式文本闪烁 (FOUT) 的网络字体: 下载和渲染网络字体可能通过两种方式导致布局偏移:
- 后备字体替换为新字体(FOUT:无样式文本闪烁)、新字体完成渲染前显示"不可见"文本(FOIT:不可见文本闪烁)
- 在关键网络字体上使用
<link rel=preload>
、将<link rel=preload>
和font-display: optional
结合使用
- 在更新 DOM 之前等待网络响应的操作: (参看上面
保持较低的请求数和较小的传输大小
) - 动画: 倾向于选择
transform
动画,而不是触发布局偏移的属性动画。- 对 CSS 属性值的更改可能需要浏览器对这些更改做出反应。许多值都会触发重排、绘制和合成,例如
box-shadow
和box-sizing
- 对 CSS 属性值的更改可能需要浏览器对这些更改做出反应。许多值都会触发重排、绘制和合成,例如
如需深入了解如何改进 CLS,请参阅优化 CLS 和调试布局偏移。
衡量性能并寻找机会加快网页加载速度。Lighthouse 性能评分审计权重:
(Lighthouse 8) Audit | Weight | (Lighthouse 6) Audit | Weight |
---|---|---|---|
First Contentful Paint | 10% | First Contentful Paint | 15% |
Speed Index | 10% | Speed Index | 15% |
Largest Contentful Paint | 25% | Largest Contentful Paint | 25% |
Time to Interactive | 10% | Time to Interactive | 15% |
Total Blocking Time | 30% | Total Blocking Time | 25% |
Cumulative Layout Shift | 15% | Cumulative Layout Shift | 5% |
一旦 Lighthouse 收集完性能指标(主要以毫秒为单位报告),它会通过查看指标值在其 Lighthouse 评分分布中的位置,将每个原始指标值转换为从 0 到 100 的指标分数。
得到各项指标值之后访问Lighthouse Scoring Calculator手动计算。
或者访问网站https://pagespeed.web.dev/
输入有效网址地址直接查看分析结果。
或者直接使用GoogleChrome/lighthouse工具库。
0 到 49(红色):差; 50 到 89(橙色):需要改进; 90 到 100(绿色):好
性能审核 Overview
指标
- First Contentful Paint
- 阈值单位秒:
0~1.8
Green (fast)、1.8~3
Orange (moderate)、> 3
Red (slow)
- 阈值单位秒:
- Speed Index:
速度指数
衡量页面加载期间内容的视觉显示速度。- 阈值单位秒:
0~3.4
Green (fast)、3.4~5.8
Orange (moderate)、> 5.8
Red (slow) - 优化: 最小化主线程工作、减少 js 执行时间、确保在 webfont 加载期间文本保持可见
- 阈值单位秒:
- Time to Interactive
- 阈值单位秒:
0~3.8
Green (fast)、3.9~7.3
Orange (moderate)、> 7.3
Red (slow)
- 阈值单位秒:
- Max Potential First Input Delay: 最大潜在首次输入延迟,测量用户可能遇到的最坏情况的首次输入延迟。
- 阈值单位毫秒:
0~130
Green (fast)、130~250
Orange (moderate)、> 250
Red (slow)
- 阈值单位毫秒:
- Total Blocking Time
- 阈值单位毫秒:
0~200
Green (fast)、200~600
Orange (moderate)、> 600
Red (slow)
- 阈值单位毫秒:
- Largest Contentful Paint
- 阈值单位秒:
0~2.5
Green (fast)、2.5~4
Orange (moderate)、> 4
Red (slow)
- 阈值单位秒:
- First CPU Idle (Lighthouse 6.0 弃用,考虑使用 Total Blocking Time 和 Time To Interactive 代替)
- First Meaningful Paint (Lighthouse 6.0 弃用,考虑使用 Largest Contentful Paint 代替)
- CLS 没算在性能指标中
机会
- 消除阻塞渲染的资源:
<script>
加载关键的 js 和 css,其他的延迟加载、缩小 css、删除未使用代码 - 适当大小的图像: 使用响应式图像(多个版本按条件加载)、图像 CDN、使用基于矢量的图像格式(SVG)
- 延迟离屏图像: 考虑在所有关键资源完成加载后延迟加载页面中的所有屏幕外或隐藏(offscreen or hidden)图像以降低 TTI
- 缩小 CSS: webpack 的
optimize-css-assets-webpack-plugin
插件等 - 缩小 JavaScript: 使用 Terser 等 JavaScript 压缩工具。
- 删除未使用的 CSS: (主线程会下载、解析并处理它遇到的所有外部样式表影响性能,未使用的 CSS 还会减慢浏览器构建渲染树的速度)
- 对图像进行高效编码: 使用图像 CDN、压缩图像、用视频替换动画 GIF、延迟加载图像、提供响应式图像、提供尺寸正确的图像、使用 WebP 图像
- 以现代格式提供图像: AVIF 和 WebP 是图像格式具有更出色的压缩和质量特征。
- 启用文本压缩: Brotli 比 gzip 更好。(浏览器请求资源时,它将使用
Accept-Encoding
HTTP 请求标头来指示它支持哪些压缩算法。服务器应返回Content-Encoding
HTTP 响应标头以指示它使用的压缩算法) - 预连接到所需的源: 考虑添加
<link rel="preconnect">
或dns-prefetch
资源提示来建立与重要第三方源的早期连接。 - 减少服务器响应时间 (TTFB): 优化您的服务器、使用 CDN、优化数据查询方式、迁移到更快的数据库等
- 避免多个页面重定向: 将指向标记的资源的链接指向资源的当前位置。(重定向会减慢页面加载速度。浏览器必须向新位置发出另一个 HTTP 请求才能检索资源(额外的跨网络行程))
- 预加载关键请求: 使用
<link rel="preload">
- 将视频格式用于动画内容: 大型 GIF 无法提供动画内容。通过将大型 GIF 转换为视频,可以节省大量用户带宽。
- 减少第三方代码的影响: 针对
<script>
标记使用async
或defer
属性、建立与所需来源的早期连接、延迟加载、优化使用第三方脚本的方式 - 避免非合成动画: 浏览器的用来将 HTML、CSS 和 JavaScript 转换为像素的算法统称为渲染流水线。在渲染流水线的每一步,浏览器都使用上一个操作的结果来创建新数据。非合成动画是触发渲染流水线较早步骤之一(“样式”、“布局”或“绘制”)的动画。非合成动画的性能更差,因为它们迫使浏览器做更多工作。坚持仅合成器的属性和管理层计数和高性能动画。
- 使用 Facade 延迟加载第三方资源: Facade 是一个静态元素,它外表与实际嵌入的第三方内容相似,但没有功能性,因此对页面加载的消耗要小得多。延迟加载第三方资源降低性能消耗。
诊断
- 避免巨大的网络有效负载: 在真正需要请求之前尽量推迟它们、将请求优化得尽可能小、缓存请求,避免在重复访问页面时重新下载资源
- 使用高效的缓存策略服务静态资产: 配置服务器以返回
Cache-Control
HTTP 响应标头。将不可变的静态资产缓存很长时间。 - 避免 DOM 过大: 仅在需要时才创建 DOM 节点,当不再需要时,应销毁节点、简化 CSS 选择器、 子树修改 DOM 更改断点
- 避免链接关键请求: 最小化关键资源的数量、优化关键字节数以减少下载时间(往返次数)、优化剩余关键资源的加载顺序
- 用户计时标记和措施: User Timing API为提供了一种衡量应用程序 JavaScript 性能的方法。为此,可以在 JavaScript 中插入 API 调用,然后提取可用于优化代码的详细计时数据。
- 减少 JavaScript 执行时间: 通过代码拆分减少 JavaScript 负载、缩小和压缩网络有效负载、删除未使用的代码、使用 PRPL 模式实现即时加载。
- 最小化主线程工作: 参看
优化 FID
对应部分 - 确保在 webfont 加载期间文本保持可见: 临时显示系统字体(在
@font-face
中使用font-display: swap
为字体提供一个非常小的阻塞周期和无限的交换周期。)、预加载网络字体<link rel="preload" as="font">
- 保持较低的请求数和较小的传输大小: 参看
优化 FID
对应部分
快速加载中还有更多提升网站性能的技术。
web.dev中有很多 web 开发方面的指导,后续还有网络安全和网络可靠性等内容。
Web 性能指页面加载到可交互和可响应所消耗的时间,以及页面在交互时的流畅度。
既包括客观的度量如加载时间,每秒帧数和到页面可交互的时间;也包括用户的对页面内容加载时间的主观感觉。
- CSS and JS 动画性能:动画对提供友好的用户体验有着关键的作用,正确使用 CSS 和 JS 动画。
- DNS 预获取: DNS-prefetch (DNS 预获取) 是尝试在请求资源之前解析域名。帮助开发人员掩盖 DNS 解析延迟。
- 懒加载: 懒加载是一种将资源标识为非阻塞(非关键)资源并仅在需要时加载它们的策略。缩短页面加载时间。
- 性能监控: 综合监控和真实用户监控 (RUM) 是两种监视和提供 Web 性能见解的方法。
- 优化启动性能: 尽可能异步地启动。这意味着不要将所有的启动代码在应用主线程中的唯一一个事件处理函数中运行。
- 关键渲染路径: 优化关键渲染路径(包含了 DOM,CSSOM,render tree 和 layout)可提高渲染性能。
- 渲染页面: 页面内容快速加载和流畅的交互是用户希望得到的 Web 体验。