Em busca da correção do INP

Reduzir o TBT em 30 vezes e migrar para o Next.js ajudou o The Ecomonic Times a reduzir o INP quase quatro vezes, levando a uma redução de 50% na taxa de rejeição e um aumento de 43% nas visualizações de página.

Daya Ram Yadav
Daya Ram Yadav
Saurabh Rajpal
Saurabh Rajpal

Interaction to Next Paint (INP) é uma métrica que avalia a capacidade de resposta de um site em relação à entrada do usuário. Uma boa capacidade de resposta significa que a página responde rapidamente às interações do usuário. Quanto menor o INP de uma página, melhor ela responde às interações do usuário.

Valores de INP bons são de 200 milissegundos ou menos, valores ruins são maiores que 500 milissegundos, e qualquer valor entre esses dois extremos precisa ser melhorado.

O início confuso

Quando o Google lançou a INP como uma métrica experimental com potencial de se tornar uma das principais métricas da Web, a equipe do Economic Times aceitou o desafio de corrigi-la antes que ela se tornasse uma métrica, já que oferecer uma experiência do usuário de nível mundial é crucial para nossos valores comerciais principais.

A INP tem sido uma das métricas mais difíceis de resolver até agora. No começo, não estava claro como medir a INP de forma eficaz. O que dificultou foi a falta de apoio da comunidade, incluindo a maioria dos provedores de monitoramento de usuários reais (RUM, na sigla em inglês) que ainda não oferecem suporte. No entanto, tínhamos ferramentas do RUM do Google, como o Relatório de experiência do usuário do Chrome (CrUX), a biblioteca JavaScript web-vitals e outras que ofereciam suporte a ele, o que nos deu uma ideia de onde estávamos enquanto avaliávamos o caminho a seguir. Quando começamos, o INP estava perto de 1.000 milissegundos no nível de origem.

Algo que surgiu ao corrigir o INP no campo foi que uma das métricas do laboratório a serem segmentadas poderia ser o tempo total de bloqueio (TBT, na sigla em inglês). O TBT já estava bem documentado e tinha o apoio da comunidade. Apesar de já atender aos limites das Core Web Vitals, não estávamos indo tão bem no TBT, porque ele era de mais de três segundos quando começamos.

O que é o TBT e quais medidas tomamos para melhorá-lo?

O TBT é uma métrica de laboratório que mede a capacidade de resposta de uma página da Web à entrada do usuário durante o carregamento. Qualquer tarefa que leve mais de 50 milissegundos para ser executada é considerada longa, e o tempo após o limite de 50 milissegundos é conhecido como tempo de bloqueio.

O TBT é calculado pela soma do tempo de bloqueio de todas as tarefas longas durante o carregamento da página. Por exemplo, se houver duas tarefas longas durante o carregamento, o tempo de bloqueio será determinado da seguinte maneira:

  • A Tarefa A leva 80 milissegundos (30 milissegundos a mais que 50 milissegundos).
  • A tarefa B leva 100 milissegundos (50 milissegundos a mais que 50 milissegundos).

O TBT da página será de 80 milissegundos (30 + 50). Quanto menor o TBT, melhor. Além disso, o TBT também correlaciona-se bem com o INP.

Confira uma comparação rápida do laboratório da nossa TBT antes e depois de tomar medidas para melhorá-la:

Uma imagem composta de tarefas longas durante a inicialização, conforme mostrado no painel de desempenho do Chrome DevTools, e um relatório de métricas da página. A linha de execução principal fica bloqueada durante o carregamento da página por 3.260 milissegundos.
A linha de execução principal durante a inicialização antes de otimizar o TBT. O TBT é de 3.260 milissegundos.
Uma imagem composta de tarefas longas durante a inicialização, conforme mostrado no painel de desempenho do Chrome DevTools, e um relatório das métricas da página. A linha de execução principal é bloqueada durante o carregamento da página por 120 milissegundos.
A linha de execução principal durante a inicialização após a otimização do TBT. O TBT é de 120 milissegundos.

Minimizar o trabalho da linha de execução principal

A linha de execução principal do navegador lida com tudo, desde a análise de HTML, a criação do DOM, a análise de CSS e a aplicação de estilos, além de avaliar e executar JavaScript. A linha de execução principal também processa as interações do usuário, ou seja, clicar, tocar e pressionar teclas. Se a linha de execução principal estiver ocupada fazendo outro trabalho, ela poderá não responder às entradas do usuário de maneira eficiente e causar uma experiência ruim para o usuário.

Essa foi a tarefa mais difícil para nós, porque temos nossos próprios algoritmos para detectar a identidade do usuário e veicular anúncios com base no status da assinatura e em scripts de terceiros para testes A/B, análises e muito mais.

No início, tomamos medidas pequenas, como priorizar o carregamento de recursos de negócios menos importantes. Em segundo lugar, usamos requestIdleCallback para trabalhos não críticos, o que pode ajudar a reduzir o TBT.

if ('requestIdleCallback' in window) {
  this.requestIdleCallbackId = requestIdleCallback(fetchMarketsData.bind(this), {timeout: 3000});
} else {
  fetchMarketsData(); // Fallback in case requestIdleCallback is not supported
}

É recomendável especificar um tempo limite ao usar requestIdleCallback, porque isso garante que, se o tempo determinado se passar e o callback ainda não tiver sido chamado, ele será executado imediatamente após o tempo limite.

Minimize o tempo de avaliação do script

Também fazemos o carregamento lento de bibliotecas de terceiros usando Componentes carregáveis. Também removemos JavaScript e CSS não utilizados criando um perfil da página com a ferramenta de cobertura no Chrome DevTools. Isso nos ajudou a identificar áreas em que o tree shaking era necessário para enviar menos código durante o carregamento da página e, portanto, reduzir o tamanho inicial do pacote do aplicativo.

Captura de tela da ferramenta de cobertura no Chrome DevTools. Aqui, a ferramenta mostra partes não utilizadas de arquivos JavaScript e CSS durante o carregamento da página.

Reduzir o tamanho do DOM

De acordo com o Lighthouse, tamanhos DOM grandes aumentam o uso da memória, causam recálculos de estilo mais longos e produzem reflows de layout dispendiosos.

Captura de tela da auditoria de tamanho do DOM no Lighthouse. O número de elementos DOM relatados é de 2.706 elementos.

Reduzimos o número de nós do DOM de duas maneiras:

  • Primeiro, renderizamos os itens do menu conforme a solicitação do usuário (ao clicar). O tamanho do DOM foi reduzido em cerca de 1.200 nós.
  • Em segundo lugar, carregamos de forma lenta os widgets menos importantes.

Por causa de todos esses esforços, reduzimos o TBT significativamente e nosso INP foi reduzido em quase 50%:

Captura de tela da auditoria de INP no CrUX. O INP da página é de 539 milissegundos, o que excede o limite "ruim".

Nesse ponto, quase não tínhamos mais vitórias fáceis para reduzir ainda mais o TBT (e o INP por proxy), mas sabíamos que tínhamos muito espaço para melhorias. Foi quando decidimos fazer upgrade do nosso boilerplate de interface personalizado para a versão mais recente do React com o Next.js para usar melhor os hooks e evitar a renderização desnecessária de componentes.

Devido a atualizações mais frequentes e a um tráfego relativamente menor em comparação com outras partes do site, começamos a migrar nossas páginas de tópicos para o Next.js. Também usamos o PartyTown para transferir mais trabalho pesado da linha de execução principal para os web workers, além de técnicas como requestIdleCallBack para adiar tarefas não críticas.

Como a melhoria do INP ajudou o The Economic Times?

TBT e INP atuais na origem

No momento da publicação desta postagem, o TBT da nossa origem era de 120 milissegundos, uma redução de 3.260 milissegundos quando começamos nossos esforços de otimização. Da mesma forma, o INP da nossa origem foi de 257 milissegundos após nossos esforços de otimização, uma queda em relação aos mais de 1.000 milissegundos.

Captura de tela da auditoria de INP no CrUX. O INP da página é de 257 milissegundos, o que está dentro dos limites "melhorias necessárias".

Tendência do INP CrUX

O tráfego recebido nas páginas de tópicos representa uma parte significativamente menor do tráfego geral. Por isso, era o lugar ideal para a experimentação. Os resultados do CrUX e os resultados de negócios foram muito encorajadores e nos levaram a expandir nossos esforços em todo o site para colher mais benefícios.

Uma captura de tela das distribuições INP conforme visualizada no CrUX em um período de quatro meses, começando em julho de 2022 e terminando em outubro de 2022. Os valores nos limites "insatisfatório" e "precisa de melhorias" diminuíram um pouco, e os valores no limite "bom" aumentaram.

Análise TBT de mPulse da Akamai

Usamos o Akamai mPulse como nossa solução de RUM, que mede o TBT no campo. Observamos uma diminuição consistente no TBT, que corresponde aos resultados dos nossos esforços para reduzir o INP. Como pode ser visto na captura de tela abaixo, os valores de TBT caíram de aproximadamente 5 segundos para cerca de 200 milissegundos no campo.

Captura de tela de um gráfico no mPulse da Akamai, mostrando uma queda no TBT ao longo de aproximadamente um mês.

Resultado comercial

No geral, nossos esforços para reduzir o TBT em 30 vezes, além da migração para o Next.js, nos ajudaram a reduzir o INP quase quatro vezes, o que levou a uma redução de 50% na taxa de rejeição e um aumento de 43% nas visualizações de página nas páginas de tópicos.

Captura de tela do Google Analytics comparando visualizações de página e taxa de rejeição. Graças às otimizações feitas na INP no site do The Economic Times, houve uma redução de 50% na taxa de rejeição e um aumento de 43% nas visualizações de página.

Conclusão

Em resumo, o INP ajudou a determinar problemas de desempenho no momento da execução em partes do site do Economic Times. Ela provou ser uma das métricas mais eficazes para impactar positivamente os resultados de negócios. Devido aos números muito encorajadores que observamos como resultado desse esforço, estamos motivados a ampliar nossos esforços de otimização para outras áreas do site e colher mais benefícios.