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 uma página responde rapidamente às interações do usuário. Quanto menor o INP de uma página, melhor ela poderá responder às interações do usuário.

Bons valores de INP são 200 milissegundos ou menos, valores ruins são maiores do que 500 milissegundos, e tudo o que está entre eles precisa ser melhorado.

O começo confuso

Quando o Google introduziu o INP como uma métrica experimental com potencial de evoluir para uma das Core Web Vitals, a equipe do Economic Times assumiu o desafio de corrigi-la antes de fazer a mudança para uma, já que fornecer uma experiência do usuário de alto nível é crucial para nossos valores comerciais principais.

A INP tem sido uma das métricas mais difíceis de resolver até agora. No início, não ficou claro como medir a INP com eficiência. O que tornou isso mais difícil foi a falta de suporte da comunidade, incluindo a maioria dos provedores de Real User Monitoring (RUM) que ainda não ofereciam suporte a ele. No entanto, tínhamos as ferramentas RUM do Google, como o Chrome User Experience Report (CrUX, na sigla em inglês), a biblioteca JavaScript web-vitals e outras que davam suporte a elas. Isso nos deu uma noção do nosso progresso ao avaliar o caminho à frente. Quando começamos,nosso INP estava perto de mil milissegundos no nível da 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á foi bem documentado e com apoio da comunidade. Apesar de já estarmos atingindo os limites das Core Web Vitals, não estávamos tão bem em termos de TBT porque levamos mais de três segundos quando começamos.

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

A TBT é uma métrica de laboratório que mede a capacidade de resposta de uma página da Web em relação à entrada do usuário durante o carregamento dela. Qualquer tarefa que leva mais de 50 milissegundos para ser executada é considerada longa. 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. O TBT também correla bem com o INP.

Aqui está uma comparação rápida do nosso TBT antes e depois das etapas de melhoria:

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 3.260 milissegundos.
A linha de execução principal durante a inicialização antes de otimizar o TBT. A duração da 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. A duração da 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 análise do HTML e criação do DOM até análise de CSS e aplicação de estilos, bem como avaliação e execução de 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 com outro trabalho, ela poderá não responder às entradas do usuário de forma eficiente e causar uma experiência instável 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 pequenas medidas, como diminuir a prioridade do carregamento de recursos de negócios menos críticos. 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 do pacote inicial do aplicativo.

Uma captura de tela da ferramenta de cobertura no Chrome DevTools. Aqui, a ferramenta exibe partes não usadas de arquivos JavaScript e CSS durante o carregamento da página.

Reduzir o tamanho do DOM

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

Uma 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 DOM de duas maneiras:

  • Primeiro, renderizamos os itens do menu a pedido do usuário (ao clicar). Diminuiu o tamanho do DOM em cerca de 1.200 nós.
  • Em segundo lugar, carregamos lentamente widgets menos importantes.

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

Uma captura de tela da auditoria INP no CrUX. O INP da página é de 539 milissegundos, o que excede o valor "insatisfatório" o limite mínimo.

Nesse ponto, quase ficamos sem 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 então que decidimos atualizar o código boilerplate de interface personalizado para a versão mais recente do React junto com o Next.js para usar melhor os hooks e evitar uma nova renderização desnecessária de componentes.

Devido às atualizações mais frequentes e à redução do tráfego comparativamente menor em comparação com outras partes do site, começamos a migrar nossas páginas de temas 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.

Uma captura de tela da auditoria INP no CrUX. O INP da página é de 257 milissegundos, o que está dentro do campo "Precisa de melhorias" limites.

Tendência INP CrUX

O tráfego recebido nas páginas de tópicos representa uma parte significativamente menor do tráfego geral. Por isso, ele é o local ideal para testes. Os resultados do CrUX, juntamente com os resultados comerciais, foram muito encorajadores e nos levaram a expandir nossos esforços por 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. Valores em "insatisfatório" e "precisa de melhorias" os limites caíram um pouco, enquanto os valores dentro do valor o limite aumentou.

Análise TBT de mPulse da Akamai

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

Uma 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 e migrar para o Next.js nos ajudaram a reduzir a INP em 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.

Uma captura de tela do Google Analytics comparando as visualizações de página com a taxa de rejeição. Devido às otimizações feitas para a 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

Para resumir, a INP ajudou extensivamente a determinar problemas de desempenho no tempo de execução em partes do site do Economic Times. É uma das métricas mais eficazes para causar um impacto positivo nos resultados comerciais. Devido aos números muito animadores que observamos como resultado desse esforço, estamos motivados a ampliar nossos esforços de otimização para outras áreas de nosso site e colher benefícios adicionais.