试用新的 Lighthouse API,衡量整个用户体验历程中的性能和最佳实践。
Lighthouse 是一款出色的工具,可用于测试初始网页加载期间的性能和最佳实践。不过,传统上,使用 Lighthouse 分析网页生命周期的其他方面一直很困难,例如:
- 使用温存缓存加载网页
- 已启用 Service Worker 的网页
- 考虑潜在的用户互动
这意味着 Lighthouse 可能会遗漏重要信息。核心网页指标基于所有网页加载情况,而不仅仅是缓存为空的网页加载情况。此外,您还可以衡量 Cumulative Layout Shift (CLS) 等指标在网页打开期间的整个时间内的表现。
Lighthouse 推出了新的用户体验流程 API,可让您在网页生命周期的任何时间点进行实验室测试。Puppeteer 用于编写网页加载脚本并触发合成用户互动,您可以通过多种方式调用 Lighthouse,以便在这些互动期间捕获关键数据分析。也就是说,您可以在网页加载期间和与网页互动期间衡量性能。您可以在 CI 中运行无障碍功能检查,不仅仅在初始视图上,还可以在结账流程的深层运行,以确保没有任何问题出现回归。
现在,几乎所有为了确保用户体验流程正常运行而编写的 Puppeteer 脚本都可以在任何时间插入 Lighthouse,以便衡量性能和最佳实践。本教程将介绍新的 Lighthouse 模式,这些模式可衡量用户体验流程的不同部分:导航、快照和时间段。
设置
用户体验流程 API 目前仍处于预览阶段,但目前已在 Lighthouse 中提供。如需试用以下演示,您需要使用 Node 14 或更高版本。创建一个空目录,然后在其中运行以下命令:
# Default to ES modules.
echo '{"type": "module"}' > package.json
# Init npm project without the wizard.
npm init -y
# Dependencies for these examples.
npm install lighthouse puppeteer open
导航
新的 Lighthouse“导航”模式实际上是对(到目前为止)标准 Lighthouse 行为的命名:分析网页的冷加载。此模式用于监控网页加载性能,但用户体验流程还可以带来新的分析洞见。
如需通过脚本让 Lighthouse 捕获页面加载情况,请执行以下操作:
- 使用 Puppeteer 打开浏览器。
- 启动 Lighthouse 用户流。
- 前往目标网址。
import fs from 'fs';
import open from 'open';
import puppeteer from 'puppeteer';
import {startFlow} from 'lighthouse/lighthouse-core/fraggle-rock/api.js';
async function captureReport() {
const browser = await puppeteer.launch({headless: false});
const page = await browser.newPage();
const flow = await startFlow(page, {name: 'Single Navigation'});
await flow.navigate('https://web.dev/performance-scoring/');
await browser.close();
const report = await flow.generateReport();
fs.writeFileSync('flow.report.html', report);
open('flow.report.html', {wait: false});
}
captureReport();
这是最简单的流程。打开后,该报告会显示仅包含单个步骤的摘要视图。点击该步骤即可显示相应导航的传统 Lighthouse 报告。
与 Lighthouse 通常的做法一样,此页面在加载时会先清除所有缓存或本地存储空间,但实际访问网站的用户会混合使用冷缓存和温缓存,因此像这样的冷加载与用户返回到仍有温缓存的页面之间可能会存在很大的性能差异。
捕获温加载
您还可以向此脚本添加第二次导航,这次停用 Lighthouse 在导航中默认执行的缓存和存储清除操作。下一个示例会加载 web.dev 上自己的一篇文章,以了解缓存能带来多大的好处:
async function captureReport() {
const browser = await puppeteer.launch({headless: false});
const page = await browser.newPage();
const testUrl = 'https://web.dev/performance-scoring/';
const flow = await startFlow(page, {name: 'Cold and warm navigations'});
await flow.navigate(testUrl, {
stepName: 'Cold navigation'
});
await flow.navigate(testUrl, {
stepName: 'Warm navigation',
configContext: {
settingsOverrides: {disableStorageReset: true},
},
});
await browser.close();
const report = await flow.generateReport();
fs.writeFileSync('flow.report.html', report);
open('flow.report.html', {wait: false});
}
captureReport();
生成的流程报告如下所示:
通过结合使用冷加载和温加载,您可以更全面地了解真实用户的体验。如果您的网站允许用户在一次访问中加载多个网页,则此功能可以让您更真实地了解用户在现场的体验。
快照
快照是一种新模式,可在单一时间点运行 Lighthouse 审核。与正常运行 Lighthouse 不同,系统不会重新加载网页。这样,您就可以设置页面并在其确切状态(例如下拉菜单处于打开状态或表单已部分填充)下对其进行测试。
在本例中,假设您想检查 Squoosh 中一些高级设置的新界面是否通过了自动 Lighthouse 检查。只有在已加载图片且选项菜单展开即可显示高级设置时,这些设置才会显示。
此过程可使用 Puppeteer 编写脚本,您实际上可以在每个步骤拍摄 Lighthouse 快照:
async function captureReport() {
const browser = await puppeteer.launch({headless: false});
const page = await browser.newPage();
const flow = await startFlow(page, {name: 'Squoosh snapshots'});
await page.goto('https://squoosh.app/', {waitUntil: 'networkidle0'});
// Wait for first demo-image button, then open it.
const demoImageSelector = 'ul[class*="demos"] button';
await page.waitForSelector(demoImageSelector);
await flow.snapshot({stepName: 'Page loaded'});
await page.click(demoImageSelector);
// Wait for advanced settings button in UI, then open them.
const advancedSettingsSelector = 'form label[class*="option-reveal"]';
await page.waitForSelector(advancedSettingsSelector);
await flow.snapshot({stepName: 'Demo loaded'});
await page.click(advancedSettingsSelector);
await flow.snapshot({stepName: 'Advanced settings opened'});
browser.close();
const report = await flow.generateReport();
fs.writeFileSync('flow.report.html', report);
open('flow.report.html', {wait: false});
}
captureReport();
生成的报告显示,结果总体上不错,但可能需要手动检查一些无障碍功能标准:
时间跨度
实测(例如通过 CrUX 获得)和实验(例如通过 Lighthouse 获得)性能结果之间的最大区别之一是缺少用户输入。这时,时间范围(上一个用户体验历程模式)可以派上用场。
时间范围用于在一段时间内运行 Lighthouse 审核,该时间范围可能包含或不包含导航。这是一种很好的方式,可以捕获互动期间网页上发生的情况。例如,默认情况下,Lighthouse 会在网页加载期间衡量 CLS,但在实际场景中,CLS 是从初始导航到网页关闭期间衡量的。如果用户互动是 CLS 触发因素,Lighthouse 之前无法捕获并帮助解决此问题。
为了说明这一点,下面是一个测试网站,它模拟了在滚动过程中将广告注入到文章中,但未为广告预留空间。在一系列长卡片中,当其槽进入视口时,系统会偶尔添加一个红色方块。由于未为这些红色方块预留空间,因此位于其下方的卡片会被移开,导致布局发生偏移。
常规的 Lighthouse 导航栏的 CLS 为 0。不过,滚动后,网页就会出现布局偏移问题,并且 CLS 值也会上升。
以下脚本将生成包含这两项操作的用户体验历程报告,以显示差异。
async function captureReport() {
const browser = await puppeteer.launch({headless: false});
const page = await browser.newPage();
// Get a session handle to be able to send protocol commands to the page.
const session = await page.target().createCDPSession();
const testUrl = 'https://pie-charmed-treatment.glitch.me/';
const flow = await startFlow(page, {name: 'CLS during navigation and on scroll'});
// Regular Lighthouse navigation.
await flow.navigate(testUrl, {stepName: 'Navigate only'});
// Navigate and scroll timespan.
await flow.startTimespan({stepName: 'Navigate and scroll'});
await page.goto(testUrl, {waitUntil: 'networkidle0'});
// We need the ability to scroll like a user. There's not a direct puppeteer function for this, but we can use the DevTools Protocol and issue a Input.synthesizeScrollGesture event, which has convenient parameters like repetitions and delay to somewhat simulate a more natural scrolling gesture.
// https://chromedevtools.github.io/devtools-protocol/tot/Input/#method-synthesizeScrollGesture
await session.send('Input.synthesizeScrollGesture', {
x: 100,
y: 600,
yDistance: -2500,
speed: 1000,
repeatCount: 2,
repeatDelayMs: 250,
});
await flow.endTimespan();
await browser.close();
const report = await flow.generateReport();
fs.writeFileSync('flow.report.html', report);
open('flow.report.html', {wait: false});
}
captureReport();
这会生成一份报告,比较常规导航与包含导航和滚动操作的时间段:
深入了解每个步骤后,您会发现仅包含导航的步骤的 CLS 为 0。很棒的网站!
不过,“导航和滚动”步骤却是另一回事。目前,时间范围内仅提供总屏蔽时间和累计布局偏移,但此网页上的延迟加载内容显然会降低网站的 CLS。
以前,Lighthouse 无法识别这种有问题的 CLS 行为,但它几乎肯定会在真实用户的体验中出现。对脚本化互动进行性能测试可显著提高实验室保真度。
寻求反馈
Lighthouse 中的新用户体验历程 API 可以执行许多新操作,但衡量用户遇到的情况可能仍然很复杂。