Fluxos de usuários do Lighthouse

Teste a nova API Lighthouse para medir a performance e as práticas recomendadas em todo o fluxo do usuário.

Brendan Kenny
Brendan Kenny

O Lighthouse é uma ferramenta fantástica para testar o desempenho e as práticas recomendadas durante o carregamento inicial da página. No entanto, é tradicionalmente difícil usar o Lighthouse para analisar outros aspectos da vida útil de uma página, como:

  • A página é carregada com um cache aquecido
  • Páginas com um service worker ativado
  • Considerar possíveis interações do usuário

Isso significa que o Lighthouse pode perder informações importantes. As Core Web Vitals se baseiam em todos os carregamentos de página, não apenas naqueles com cache vazio. Além disso, métricas como a Cumulative Layout Shift (CLS) podem ser medidas durante todo o tempo em que uma página está aberta.

O Lighthouse tem uma nova API de fluxo de usuários que permite testes de laboratório a qualquer momento na vida útil de uma página. O Puppeteer é usado para criar scripts de carregamentos de página e acionar interações sintéticas do usuário. O Lighthouse pode ser invocado de várias maneiras para capturar insights importantes durante essas interações. Isso significa que a performance pode ser medida durante o carregamento da página e durante as interações com a página. As verificações de acessibilidade podem ser executadas na CI, não apenas na visualização inicial, mas também no fluxo de finalização de compra, para garantir que nada regrida.

Quase todos os scripts do Puppeteer escritos para garantir que um fluxo de usuário funcional agora podem ter o Lighthouse inserido em qualquer ponto para medir o desempenho e as práticas recomendadas. Este tutorial vai mostrar os novos modos do Lighthouse que podem medir diferentes partes dos fluxos de usuários: navegações, snapshots e períodos.

Configuração

As APIs de fluxo de usuários ainda estão em visualização, mas já estão disponíveis no Lighthouse. Para testar as demonstrações abaixo, você precisa da versão 14 ou mais recente do Node. Crie um diretório vazio e execute nele:

# 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

O novo modo "navegação" do Lighthouse dá um nome ao comportamento padrão do Lighthouse (até agora): analisar o carregamento frio de uma página. Esse é o modo a ser usado para monitorar o desempenho do carregamento da página, mas os fluxos de usuários também abrem a possibilidade de novos insights.

Para criar um script do Lighthouse que capture o carregamento de uma página:

  1. Use o Puppeteer para abrir o navegador.
  2. Inicie um fluxo de usuário do Lighthouse.
  3. Navegue até o URL de destino.
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();

Esse é o fluxo mais simples. Quando aberto, o relatório mostra uma visualização resumida com apenas a etapa. Ao clicar nessa etapa, um relatório do Lighthouse tradicional para a navegação será exibido.

Um relatório de fluxo do Lighthouse mostrando uma única navegação
Confira o relatório ativo

Como é típico do Lighthouse, essa página é carregada com qualquer cache ou armazenamento local limpo primeiro, mas os usuários reais que visitam um site terão uma mistura de visitas com caches frios e quentes, e pode haver uma grande diferença de desempenho entre um carregamento frio como esse e um usuário que retorna à página com um cache ainda quente.

Como capturar um carregamento a quente

Também é possível adicionar uma segunda navegação a esse script, dessa vez desativando a limpeza de cache e armazenamento que o Lighthouse faz por padrão nas navegações. O próximo exemplo carrega um artigo no próprio web.dev para ver os benefícios do armazenamento em cache:

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();

O relatório de fluxo resultante será parecido com este:

Um relatório de fluxo do Lighthouse mostrando duas navegações, uma fria e outra quente, que tem uma pontuação de performance mais alta
Confira o relatório ativo

A combinação de carregamentos frios e quentes oferece uma imagem mais completa da experiência dos usuários reais. Se você tem um site em que os usuários carregam muitas páginas na mesma visita, isso pode dar uma visão mais realista do que eles estão enfrentando no campo.

Snapshots

Os snapshots são um novo modo que executa auditorias do Lighthouse em um único momento. Ao contrário de uma execução normal do Lighthouse, a página não é recarregada. Isso permite configurar uma página e testá-la no estado exato: com um menu suspenso aberto ou um formulário parcialmente preenchido, por exemplo.

Neste exemplo, suponha que você queira verificar se uma nova interface para as configurações avançadas no Squoosh passa nas verificações automatizadas do Lighthouse. Essas configurações só ficam visíveis se uma imagem tiver sido carregada e o menu de opções for aberto para mostrar as configurações avançadas.

Menu de configurações avançadas do Squoosh
Menu de configurações avançadas do Squoosh

Esse processo pode ser programado com o Puppeteer, e é possível capturar um snapshot do Lighthouse em cada etapa:

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();

O relatório resultante mostra que os resultados em geral são bons, mas pode haver alguns critérios de acessibilidade que precisem ser verificados manualmente:

Um relatório de fluxo do Lighthouse mostrando um conjunto de snapshots feitos
Acessar o relatório em tempo real

Períodos

Uma das maiores diferenças entre os resultados de desempenho em campo (como no CrUX) e no laboratório (como no Lighthouse) é a falta de entradas do usuário. É aí que um período, o último modo de fluxo do usuário, pode ajudar.

Um período executa auditorias do Lighthouse por um período, que pode ou não incluir uma navegação. Essa é uma ótima maneira de capturar o que está acontecendo com uma página durante as interações. Por exemplo, por padrão, o Lighthouse mede o CLS durante o carregamento da página, mas no campo, o CLS é medido desde a navegação inicial até o fechamento da página. Se as interações do usuário forem o gatilho da CLS, isso é algo que o Lighthouse anteriormente não poderia detectar e ajudar a corrigir.

Para demonstrar isso, aqui está um site de teste que simula a injeção de anúncios em um artigo durante a rolagem sem que o espaço tenha sido reservado para eles. Em uma série longa de cards, um quadrado vermelho é adicionado ocasionalmente quando o slot entra na janela de visualização. Como o espaço não foi reservado para esses quadrados vermelhos, os cards abaixo deles são deslocados, causando mudanças no layout.

Uma navegação regular do Lighthouse terá um CLS de 0. No entanto, após a rolagem, a página terá mudanças de layout problemáticas e o valor da CLS aumentará.

Teste o site de demonstração

O script a seguir vai gerar um relatório de fluxo de usuários com as duas ações para mostrar a diferença.

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();

Isso gera um relatório comparando uma navegação normal com um período que contém uma navegação e uma rolagem posteriores:

Um relatório de fluxo do Lighthouse mostrando um conjunto de snapshots tirados
Acessar o relatório em tempo real

Analisando cada etapa, a etapa de navegação mostra um CLS de 0. Ótimo site!

O relatório do Lighthouse que abrange apenas a navegação na página com todas as métricas em verde

No entanto, a etapa "Navegar e rolar" conta uma história diferente. No momento, apenas o tempo de bloqueio total e o deslocamento cumulativo de layout estão disponíveis em períodos, mas o conteúdo carregado de forma lenta nessa página claramente diminui o CLS do site.

O relatório do Lighthouse mostrando a navegação e a rolagem nas páginas com falha de CLS

Antes, o Lighthouse não conseguia identificar esse comportamento problemático da CLS, embora ele quase certamente aparecesse na experiência de usuários reais. O teste de desempenho em interações com script melhora significativamente a fidelidade do laboratório.

Procurando feedback

As novas APIs de fluxo de usuário do Lighthouse podem fazer muitas coisas novas, mas ainda pode ser complicado medir os tipos de cenários que seus usuários encontram.

Se tiver dúvidas, acesse os fóruns de discussão do Lighthouse e envie bugs ou sugestões no Issue Tracker.