Publicado em 14 de outubro de 2025
A Interaction to Next Paint (INP) é uma métrica essencial das Core Web Vitals para medir a capacidade de resposta. No Fotocasa, o Google Search Console destacou um número significativo de páginas que mudaram para "Precisa de melhorias" e "Ruim" quando a INP substituiu o First Input Delay (FID) em 2024. Este estudo de caso descreve as ferramentas e estratégias usadas para diagnosticar e resolver esses problemas, melhorando substancialmente o INP.
Onde a equipe da Fotocasa começou
Antes da mudança do FID para o INP, quase todas as páginas em computadores e dispositivos móveis estavam dentro do limite "Bom", o que significa que todas as Core Web Vitals da época (LCP, CLS e FID) estavam funcionando bem. No entanto, depois da mudança para a INP, quase todas as páginas passaram para "Precisa melhorar" e algumas até para "Ruim", já que os valores da INP excederam consistentemente 200 milissegundos para a maioria das interações do usuário.
Essa mudança fez com que a equipe da Fotocasa percebesse que estava negligenciando um aspecto crucial da experiência do usuário. Enquanto a FID mede apenas o atraso da primeira interação, a INP avalia a capacidade de resposta de todas as interações, considerando o processamento de entrada e os atrasos de apresentação. Essa medição mais ampla é uma proxy muito melhor para a verdadeira interatividade (conforme declarado pelo Google) e destacou oportunidades perdidas.
Embora o Google Search Console forneça dados de performance de campo, ele não oferece insights em tempo real. Os dados são agregados em uma janela de 28 dias, o que dificulta identificar exatamente quais interações estavam causando problemas no momento.
Era necessário acompanhar o INP em tempo real para identificar as interações mais lentas e mais usadas pelos usuários e reproduzi-las de maneira confiável nos ambientes de desenvolvimento da equipe. Também foi importante entender o impacto das mudanças feitas, não apenas quais correções ajudaram, mas também quais ajustes pioraram as coisas sem querer.
Por isso, usamos um conjunto de ferramentas para diagnosticar e resolver os problemas. Os mais importantes foram:
- O Chrome DevTools, especificamente a guia "Performance".
- Um sistema RUM (Real User Monitoring, em inglês) personalizado criado pela equipe da Fotocasa no Datadog usando a biblioteca web-vitals.
- Ferramentas para desenvolvedores do React.
Ferramentas para diagnosticar o problema
Para diagnosticar e depurar problemas de desempenho do INP, usamos as seguintes ferramentas.
Google Chrome DevTools
Uma excelente maneira de detectar e reproduzir problemas relacionados às Core Web Vitals em um aplicativo da Web é usar a guia "Performance" no Google Chrome DevTools. A guia "Performance" mede automaticamente as métricas das Core Web Vitals, oferecendo feedback instantâneo sobre carregamento, interatividade e mudança de layout. Ela é consistente com a forma como essas métricas são informadas a outras ferramentas do Google.
Para identificar e resolver problemas de INP, a equipe da Fotocasa geralmente começava limitando a CPU para simular o desempenho de dispositivos de baixo e médio custo. Isso permitiu que a equipe da Fotocasa observasse o comportamento da página em condições mais restritas. A sessão foi gravada usando o criador de perfil, e os rastreamentos foram analisados com cuidado, com foco na interação do usuário para identificar problemas de desempenho.
Ao identificar gargalos, é especialmente útil examinar as subpartes do INP e as tarefas que o navegador realiza em cada uma delas. Por exemplo, na imagem a seguir, é possível ver que o INP é bastante alto devido a dois recálculos de estilo causados por mudanças no estilo do corpo do documento.
A Fotocasa configurou um sistema para rastrear o INP e outras métricas das Core Web Vitals, garantindo que os problemas de desempenho sejam identificados e resolvidos rapidamente. Quando uma métrica ultrapassa um limite específico (com base nos intervalos definidos pelo Google), a atribuição é registrada para que o problema possa ser analisado e resolvido.
Para esse sistema, a biblioteca web-vitals foi usada para capturar essas métricas de usuários reais de uma forma que corresponda com precisão à maneira como elas são medidas pelo Chrome e informadas a outras ferramentas do Google (como o Chrome User Experience Report, o PageSpeed Insights, o relatório de velocidade do Search Console e outras).
Para ter uma visão abrangente e um acompanhamento centralizado, a Fotocasa usou o Datadog para coletar e visualizar os dados, permitindo que a equipe tomasse decisões informadas e orientadas por dados. As métricas personalizadas mantêm a eficiência de custo e permitem rastrear quase todos os usuários no site da Fotocasa.
Esse sistema permite que a equipe da Fotocase monitore rapidamente se as modificações afetam as métricas ou se ocorrem alterações imprevistas, o que pode comprometer os resultados. A métrica INP pode ser dividida em partes, como atraso de entrada, duração do processamento e atraso de apresentação, para identificar precisamente qual parte da interação é a principal responsável por tempos de interação longos.
Ao detectar anomalias, como a ilustrada nas figuras 7 e 8, a Fotocasa respondeu imediatamente e usou o OpenSearch, outra ferramenta que ajudou a identificar onde a alteração pode estar ocorrendo. Os dados fornecidos pela biblioteca web-vitals ajudaram a identificar o destino (o elemento DOM potencialmente responsável por um valor de métrica elevado) e ajudam a equipe a se concentrar mais na correção do problema.
Além disso, é possível definir vários filtros, como tipo de página, dispositivo ou estado de carregamento, para simplificar cenários e entender melhor como a INP está sendo afetada.
Ferramentas para desenvolvedores do React
As ferramentas para desenvolvedores do React foram usadas para melhorar os recursos de depuração do Fotocasa, que oferece um recurso avançado para destacar visualmente os componentes que foram renderizados novamente.
Para ativar esse recurso, acesse a guia Profiler. Clique na engrenagem no lado direito da barra superior, acesse a guia Geral e marque a caixa de seleção Destacar atualizações quando os componentes forem renderizados. Com essa opção ativada, os componentes são destacados quando são renderizados novamente, fornecendo uma representação visual dinâmica.
Como descobrir a causa de uma nova renderização
Depois de identificar um componente que foi renderizado novamente, a próxima pergunta é: "Por que isso aconteceu?" O React DevTools responde a isso com uma dica útil na visualização do gráfico de chamas.
Para acessar essas informações, grave uma sessão do criador de perfil. Ao analisar a saída do criador de perfil, você encontra informações úteis:
- No canto superior direito, o número de commits do React é exibido.
- O gráfico de chamas representa visualmente a árvore de componentes, com cinza indicando componentes que não foram renderizados novamente. Cada barra representa um momento em que a árvore de componentes do React mudou e quando uma mudança correspondente foi confirmada no DOM.
- Ao passar o cursor sobre cada componente no gráfico de chamas, o motivo da nova renderização vai aparecer no subtítulo Por que isso foi renderizado?.
Os motivos para uma nova renderização de um componente podem incluir:
- Esta é a primeira vez que o componente foi renderizado.
- O contexto mudou
- Hooks mudaram
- Props changed
- Estado alterado
- O componente pai renderizado
Como descobrir o tempo de renderização
As cores no gráfico de chamas transmitem informações significativas. Cores como vários tons de azul indicam que um componente exigiu um tempo de renderização relativamente curto em comparação com outros componentes. Por outro lado, cores como laranja e vermelho significam que um componente teve mais tempo de renderização.
Como a equipe da Fotocasa corrigiu o problema
Remover renderizações desnecessárias
As renderizações ocorrem sempre que o React precisa atualizar a interface com novos dados. Isso geralmente vem de uma ação do usuário, uma resposta da API ou outros eventos importantes que exigem uma atualização da interface. Como cada renderização executa JavaScript, muitas delas de uma só vez, especialmente em uma grande árvore de componentes, podem bloquear a linha de execução principal e causar problemas de desempenho.
Há dois tipos de renderização:
- Renderizações necessárias: quando um componente realmente precisa ser atualizado porque possui ou usa dados novos.
- Renderizações desnecessárias: quando um componente é atualizado sem nenhuma mudança significativa, geralmente devido ao gerenciamento de estado ineficiente ou ao tratamento inadequado de propriedades.
Alguns renderizações desnecessárias geralmente não são um grande problema, já que o React é rápido o suficiente para que os usuários geralmente não percebam. No entanto, se eles ocorrerem com muita frequência ou em uma árvore de componentes pesada, poderão prejudicar a experiência do usuário e afetar negativamente o INP da página.
Esse foi o caso da equipe da Fotocasa. Eles perceberam que o site tinha muitas renderizações desnecessárias. Esses eventos ocorreram em dois cenários principais:
- Durante o carregamento da página: aumentar o número de tarefas longas na linha de execução principal e atrasar a primeira interação, o que afetou negativamente o INP da página.
- Durante as interações do usuário: aumentar o tempo de processamento da maioria das interações, o que também prejudicou o INP.
Muitas renderizações desnecessárias acabaram sendo otimizadas no site da Fotocasa. Uma das maiores otimizações realizadas foi na página de pesquisa. Houve três renderizações desnecessárias no carregamento da página. Depois que eles foram removidos, os seguintes resultados foram observados:
- Menos tarefas longas (consulte a figura abaixo)
- Menos tempo total de bloqueio (compare as figuras 14 e 15)
Colocation de estado
O posicionamento inadequado do estado do React pode deixar um aplicativo mais lento e fazer com que a interface pareça não responder. Quando o estado de um componente muda, os componentes filhos são renderizados novamente por padrão, a menos que um recurso de escape seja usado (por exemplo, memo).
Como explicado na seção anterior, as renderizações não são ruins por natureza, mas renderizar a página inteira devido a uma atualização de estado específica pode levar a interações mais lentas, já que as atualizações do DOM ocorrem após a renderização.
Por exemplo, na página de pesquisa, há uma caixa de diálogo que mostra todos os filtros quando um botão é clicado.
O estado que controla o estado aberto da caixa de diálogo, nesse caso, foi colocado na página de pesquisa. Quando esse estado mudou, toda a página foi renderizada novamente, causando um INP ruim, principalmente em dispositivos mais lentos, como visto quando o controle da CPU foi usado no DevTools:
Mudar o estado o mais próximo possível do componente que aciona a mudança resolve esse problema. Nesse caso específico, o estado pode ser colocado no componente de botão dos filtros. Assim, quando o estado mudar, apenas o botão será renderizado novamente.
Remover estados desnecessários
Os estados não podem conter informações redundantes ou duplicadas. Se isso acontecer, pode levar a renderizações desnecessárias e causar problemas.
Por exemplo, na barra de filtros da Fotocasa, há um texto que representa o número de filtros aplicados a uma determinada pesquisa:
O número de filtros aplicados é calculado com base no estado do aplicativo. No entanto, isso não apenas resultou em uma nova renderização desnecessária de todo o componente, mas, em alguns casos, também levou a uma mudança de layout, já que esse componente é renderizado do lado do servidor:
const [filtersCount, setFiltersCount] = useState(DEFAULT_COUNTER)
useEffect(() => {
const counter = filters
? Object.keys(filters)
?.reduce(reducerCounter, [])
?.filter((param) => searchParams?.[param]).length
: DEFAULT_COUNTER
setFiltersCount(counter)
}, [searchParams]);
Para resolver esse problema, o valor foi derivado do objeto de filtros usando uma variável em vez de usar o estado:
const counter = filters
? Object.keys(filters)
?.reduce(reducerCounter, [])
?.filter((param) => searchParams?.[param]).length
: DEFAULT_COUNTER;
Reduzir renderizações caras
Quando uma interação ocorre em um aplicativo React, ela normalmente aciona uma mudança de estado. Como explicado anteriormente, quando o estado de um componente muda, ele é renderizado novamente com todos os filhos.
Se uma dessas funções de renderização de componentes for lenta, isso afetará negativamente o INP da página, já que provavelmente uma tarefa longa será gerada, e o DOM vai levar mais tempo para ser atualizado.
A equipe da Fotocasa tentou minimizar ao máximo os cálculos demorados na função de renderização dos componentes. O Chrome DevTools e o React Developer Tools foram muito úteis para detectar operações de renderização lentas.
Atrasar a execução do código
Além de otimizar a função de renderização dos componentes, outras funções foram otimizadas para minimizar tarefas longas o máximo possível. No entanto, algumas tarefas não puderam ser otimizadas porque dependiam de código de terceiros.
Um exemplo foi o Analytics. Nesse caso, foi decidido atrasar a execução do código de análise e priorizar as atualizações do DOM quando ocorriam interações do usuário. Para isso, a equipe da Fotocasa usou uma biblioteca chamada idlefy, que também garantiu que o código de análise continuasse sendo executado mesmo se o navegador fosse fechado imediatamente depois.
Cultura de performance
O trabalho de desempenho não é um esforço único, mas algo que precisa ser considerado em todos os recursos lançados para produção. Todos na equipe precisam estar alinhados. Caso contrário, as regressões nas Core Web Vitals são quase inevitáveis.
Para ficar por dentro disso, a equipe da Fotocasa compartilhou ativamente conhecimento e estabeleceu uma estrutura clara para identificar problemas de performance com base nos dados de RUM do Datadog da Fotocasa, incluindo como reproduzi-los. Alertas para as Principais métricas da Web, especialmente o INP, foram configurados no sistema RUM para notificar a equipe da Fotocasa diretamente no Slack. Essa abordagem manteve o desempenho em mente e ajudou a detectar problemas antes que eles se tornassem regressões.
Resultados
Para melhorar o INP no Fotocasa, foi preciso combinar otimizações técnicas e mudanças culturais. Ao eliminar renderizações desnecessárias, otimizar o posicionamento de estado, reduzir renderizações caras e adiar códigos não críticos, a equipe da Fotocasa conseguiu mover todas as páginas de computador de "precisa de melhorias" para "boa" e melhorou significativamente as páginas para dispositivos móveis, atualizando quase todas as páginas "ruins" e "precisa de melhorias" para "boa".
Essas mudanças melhoraram a experiência geral do usuário da Fotocasa e, junto com outras iniciativas, geraram um aumento de 27% nos anúncios de contato e de lead por telefone, fortalecendo diretamente as principais métricas de negócios da empresa.
O monitoramento em tempo real com o Datadog permitiu que a equipe da Fotocasa validasse as melhorias do INP, detectasse rapidamente anomalias e evitasse regressões. Além dessas conquistas, a Fotocasa também conseguiu incorporar a performance da Web à cultura de desenvolvimento, garantindo que a INP e as Core Web Vitals continuem sendo uma prioridade em todas as versões.