Lighthouse 用户流

试用新的 Lighthouse API 以衡量整个用户体验流程的性能和最佳做法。

布伦丹·肯尼
Brendan Kenny

Lighthouse 是一个很棒的工具,可用于测试初始页面加载期间的性能和最佳做法。不过,传统上很难使用 Lighthouse 来分析网页生命周期的其他方面,例如:

  • 使用温缓存加载网页
  • 具有已激活 Service Worker 的页面
  • 考虑潜在的用户互动

这意味着 Lighthouse 可能会错过重要信息。核心网页指标基于所有网页加载,而不仅仅是缓存为空的加载。此外,Cumulative Layout Shift (CLS) 等指标在网页打开的整个过程中都是可衡量的。

Lighthouse 有一个新的用户流 API,允许在页面生命周期内的任何时间点进行实验室测试。Puppeteer 用于为网页加载编写脚本并触发合成用户互动,并且可以通过多种方式调用 Lighthouse,以捕获这些互动期间的关键数据洞见。也就是说,您可以在网页加载期间和与网页互动时衡量效果。无障碍功能检查可以在 CI 中运行,不仅可以针对初始视图运行,还可以在结账流程的深层执行,以确保不会出现回归问题。

现在,为确保正常运行的用户流而编写的几乎所有 Puppeteer 脚本都可以随时插入 Lighthouse,以衡量整个过程中的性能和最佳做法。本教程将介绍可以衡量用户流的不同部分(导航、快照和时间跨度)的全新 Lighthouse 模式。

初始设置

用户流 API 仍处于预览版阶段,但今天 Lighthouse 中提供了这些 API。如需试用以下演示,您将需要 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 捕获网页加载的脚本编写脚本,请执行以下操作:

  1. 使用 Puppeteer 打开浏览器。
  2. 启动 Lighthouse 用户流。
  3. 前往目标网址。
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 的典型情况一样,此页面在加载时先清除了所有缓存或本地存储空间,但访问网站的真实用户会混合访问具有冷缓存和温缓存的访问,并且此类冷加载与返回包含仍然温缓存的页面的用户之间可能存在很大的性能差异。

捕获温负载

您还可以向此脚本添加第二个导航,这次会停用 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 审核的新模式。与正常的 Lighthouse 运行不同,页面不会重新加载。这解锁了以下功能:设置网页并以其确切状态进行测试:例如,打开下拉菜单或填充部分表单。

在本示例中,假设您想要检查 Squoosh 中“高级设置”的某个新界面是否通过了自动化的 Lighthouse 检查。仅当图片已加载且选项菜单展开即可显示高级设置时,这些设置才会显示。

Squoosh 高级设置菜单
Squoosh 高级设置菜单

此过程可通过 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();

生成的报告显示结果总体上不错,但可能需要手动检查一些无障碍功能标准:

显示截取的一组快照的 Lighthouse 流程报告
实时查看报告

时间跨度

现场(如 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();

此操作会生成一个报告,将常规导航与包含导航和之后滚动的时间范围进行比较:

显示截取的一组快照的 Lighthouse 流程报告
实时查看报告

深入了解每个步骤后,仅限导航的步骤显示的 CLS 为 0。太棒了!

Lighthouse 报告仅涵盖网页导航和所有绿色指标

不过,“导航和滚动”步骤则是不同的情况。目前,时间跨度中仅提供 Total Blocking Time 和 Cumulative Layout Shift,但此页面上的延迟加载内容明显符合网站的 CLS。

Lighthouse 报告涵盖存在失败 CLS 的页面导航和滚动

以前,Lighthouse 无法确定这种有问题的 CLS 行为,但几乎可以肯定的是,它会出现在真实的用户体验中。针对脚本互动进行性能测试可显著提高实验室保真度。

寻求反馈

Lighthouse 中的全新用户流 API 可以执行许多新操作,但衡量用户遇到的场景类型可能仍然比较复杂。

如有任何疑问,请在 Lighthouse 论坛中与我们联系,并在问题跟踪器中提交任何错误或建议。