Medir o caminho crítico de renderização

Publicado em: 31 de março de 2014

A base de toda estratégia de performance sólida é uma boa medição e instrumentação. Não é possível otimizar o que não pode ser medido. Este guia explica diferentes abordagens para medir o desempenho do caminho de renderização crítica (CRP, na sigla em inglês).

  • A abordagem do Lighthouse executa uma série de testes automatizados em uma página e gera um relatório sobre a performance de CRP dela. Essa abordagem oferece uma visão geral rápida e básica de alto nível da performance de CRP de uma página específica carregada no navegador, permitindo que você teste, itere e melhore rapidamente a performance dela.
  • A abordagem da API Navigation Timing captura métricas de monitoramento de usuários reais (RUM). Como o nome sugere, essas métricas são capturadas de interações de usuários reais com seu site e fornecem uma visão precisa do desempenho do CRP no mundo real, conforme vivenciado pelos usuários em vários dispositivos e condições de rede.

Em geral, uma boa abordagem é usar o Lighthouse para identificar oportunidades óbvias de otimização do CRP e instrumentar seu código com a API Navigation Timing para monitorar o desempenho do app em situações reais.

Auditar uma página com o Lighthouse

O Lighthouse é uma ferramenta de auditoria de apps da Web que executa uma série de testes em uma página específica e mostra os resultados em um relatório consolidado. Você pode executar o Lighthouse como uma extensão do Chrome ou um módulo NPM, o que é útil para integrar o Lighthouse a sistemas de integração contínua.

Leia Auditoria de apps da Web com o Lighthouse para começar.

Quando você executa o Lighthouse como uma extensão do Chrome, os resultados do CRP da sua página são semelhantes, listando as durações da cadeia e a ordem dos arquivos carregados pelo navegador.

A combinação da API Navigation Timing e de outros eventos do navegador emitidos durante o carregamento da página permite capturar e registrar o desempenho de CRP no mundo real de qualquer página.

Cada um dos rótulos no diagrama corresponde a um carimbo de data/hora de alta resolução que o navegador rastreia para todas as páginas carregadas. Este diagrama ignora todos os carimbos de data/hora relacionados à rede.

Então, o que essas marcações de tempo significam?

  • domLoading: esse é o carimbo de data/hora inicial de todo o processo. O navegador está prestes a começar a analisar os primeiros bytes recebidos do documento HTML.
  • domInteractive: marca o ponto em que o navegador terminou de analisar todo o HTML e a construção do DOM foi concluída.
  • domContentLoaded: marca o ponto em que o DOM está pronto e não há folhas de estilo bloqueando a execução do JavaScript. Isso significa que agora podemos (potencialmente) construir a árvore de renderização.
    • Muitas estruturas JavaScript aguardam esse evento antes de começar a executar a própria lógica. Por isso, o navegador captura os carimbos de data/hora EventStart e EventEnd para que possamos acompanhar a duração dessa execução.
  • domComplete: como o nome sugere, todo o processamento foi concluído e todos os recursos da página (imagens etc.) terminaram de ser baixados. Em outras palavras, o ícone de carregamento parou de girar.
  • loadEvent: como uma etapa final em cada carregamento de página, o navegador dispara um evento onload que pode acionar outra lógica de aplicativo.

A especificação HTML determina condições específicas para cada evento: quando ele deve ser acionado, quais condições precisam ser atendidas e outras considerações importantes.

Para nossos fins, vamos nos concentrar em alguns marcos importantes para o CRP:

  • domInteractive marca quando o DOM está pronto.
  • Normalmente, domContentLoaded marca quando o DOM e o CSSOM estão prontos.
    • Se não houver JavaScript de bloqueio do analisador, DOMContentLoaded será disparado imediatamente após domInteractive.
  • domComplete marca quando a página e todos os subrecursos dela estão prontos.
<!DOCTYPE html>
<html>
  <head>
    <title>Critical Path: Measure</title>
    <meta name="viewport" content="width=device-width,initial-scale=1" />
    <link href="style.css" rel="stylesheet" />
    <script>
      function measureCRP() {
        var t = window.performance.timing,
          interactive = t.domInteractive - t.domLoading,
          dcl = t.domContentLoadedEventStart - t.domLoading,
          complete = t.domComplete - t.domLoading;
        var stats = document.createElement('p');
        stats.textContent =
          'interactive: ' +
          interactive +
          'ms, ' +
          'dcl: ' +
          dcl +
          'ms, complete: ' +
          complete +
          'ms';
        document.body.appendChild(stats);
      }
    </script>
  </head>
  <body onload="measureCRP()">
    <p>Hello <span>web performance</span> students!</p>
    <div><img src="awesome-photo.jpg" /></div>
  </body>
</html>

Testar

Neste exemplo, a API Navigation Timing captura todos os carimbos de data/hora relevantes. Nosso código aguarda o disparo do evento onload, que acontece depois de domInteractive, domContentLoaded e domComplete. Em seguida, ele calcula a diferença entre os vários timestamps.

Agora temos alguns marcos específicos para acompanhar e uma função básica para gerar essas medições. Você pode modificar esse código para enviar essas métricas a um servidor de análise em vez de imprimir os resultados. Assim, você pode acompanhar a performance da página e identificar aquelas que podem se beneficiar da otimização.

E o DevTools?

Embora esta documentação às vezes use o painel de rede do Chrome DevTools para ilustrar conceitos de CRP, o DevTools não é adequado para medições de CRP porque não tem um mecanismo integrado para isolar recursos críticos. Execute uma auditoria do Lighthouse para ajudar a identificar esses recursos.