Publicado em: 1º de fevereiro de 2023, última atualização: 20 de setembro de 2026
Desde o lançamento, a iniciativa Core Web Vitals busca medir a experiência real do usuário em um site, em vez de detalhes técnicos por trás de como um site é criado ou carregado. As três métricas das Core Web Vitals foram criadas como métricas centradas no usuário, uma evolução das métricas técnicas atuais, como DOMContentLoaded ou load, que mediam tempos que geralmente não estavam relacionados à forma como os usuários percebiam o desempenho da página. Por isso, a tecnologia usada para criar o site não deve afetar a pontuação, desde que o site tenha um bom desempenho.
A realidade é sempre um pouco mais complicada do que o ideal, e a arquitetura de aplicativo de página única nunca foi totalmente compatível com as Core Web Vitals. Em vez de carregar páginas da Web distintas e individuais conforme o usuário navega pelo site, esses aplicativos da Web usam as chamadas "navegações suaves", em que o conteúdo da página é alterado pelo JavaScript. Nesses aplicativos, a ilusão de uma arquitetura de página da Web convencional é mantida alterando o URL e enviando URLs anteriores no histórico do navegador para permitir que os botões de voltar e avançar funcionem como o usuário espera.
Muitos frameworks de JavaScript usam esse modelo, mas cada um de uma maneira diferente. Como isso está fora do que o navegador tradicionalmente entende como uma "página", medir isso sempre foi difícil: onde está o limite entre uma interação na página atual e uma nova?
A equipe do Chrome já está pensando nesse desafio há algum tempo e quer padronizar a definição do que é uma "navegação suave" e como as Core Web Vitals podem ser medidas para isso, de maneira semelhante à medição de sites implementados na arquitetura convencional de várias páginas (MPA, na sigla em inglês).
Fizemos várias melhorias na proposta com base no feedback dos desenvolvedores e lançamos duas novas APIs de desempenho para ajudar a resolver esse problema no Chrome 151. Além disso, disponibilizamos as métricas de navegação suave no Chrome User Experience Report (CrUX) como métricas experimentais.
O que é uma navegação suave?
Criamos a seguinte definição de navegação suave:
- A navegação é iniciada por uma ação do usuário.
- A navegação resulta em uma mudança de URL visível para o usuário.
- A interação resulta em uma pintura visível.
Para alguns sites, essa definição pode levar a falsos positivos (em que os usuários não consideram que uma "navegação" tenha acontecido) ou falsos negativos (em que o usuário considera que uma "navegação" tenha acontecido, apesar de não atender a esses critérios). Envie seu feedback no repositório de especificações de navegação flexível.
Suporte do DevTools para navegações suaves
Adicionamos suporte a navegações suaves ao painel de desempenho do DevTools na visualização Métricas em tempo real e na visualização de trace com suporte a Insights e marcadores:
Como o Chrome implementa as navegações suaves para desenvolvedores web?
Depois que o recurso de navegação suave for ativado (mais detalhes na próxima seção), o Chrome vai mudar a forma como informa algumas métricas de performance:
- Um evento
soft-navigationPerformanceTimingserá emitido após cada navegação suave ser detectada. - Essa entrada
soft-navigationvai incluir umnavigationId, o novo URL no atributoname, bem como uminteractionIdda interação inicial. - Uma ou mais entradas
interaction-contentful-paintserão emitidas após interações que causam uma pintura com conteúdo. Ele vai conter uma entradalargestContentfulPaintque pode ser usada para medir a Largest Contentful Paint (LCP) em navegações suaves. - O atributo
navigationIdé adicionado a cada um dos tempos de desempenho (first-paint,first-contentful-paint,largest-contentful-paint,interaction-contentful-paint,first-input-delay,eventelayout-shift). Isso corresponde à entrada de navegação em que o evento foi emitido. Quando essas entradas abrangem navegações suaves, elas podem conter onavigationIdanterior ou seguinte, dependendo de quando a entrada foi emitida. Saiba mais sobre isso na seção Informar as métricas no URL apropriado. - O
soft-navigationvai incluir uma funçãogetLargestInteractionContentfulPaint()para recuperar a maior entradainteraction-contentful-paintdessa navegação. Isso pode ser usado como a LCP inicial para essa navegação, que pode ser atualizada à medida que mais entradasinteraction-contentful-paintpara essa interação são observadas. Isso substitui um atributolargestInteractionContentfulPaintdisponível em testes de origem anteriores. - É possível que algumas entradas de
interaction-contentful-painttenham ocorrido antes da navegação suave (se a atualização do URL não acontecer até depois dessas pinturas). Nesses casos, a funçãogetLargestInteractionContentfulPaint()evita a necessidade de armazenar em buffer e analisar entradas antigas após a finalização de uma navegação flexível. A entrada retornada porgetLargestInteractionContentfulPaint()é uma cópia exata da maior entrada deinteraction-contentful-paintno momento em que foi emitida. Portanto, essa entrada pode ter usado onavigationIdanterior, já que foi quando a exibição aconteceu, mas essas exibições precisam ser medidas em relação ao novonavigationId. - A entrada
soft-navigationtambém vai incluirpaintTimeepresentationTimecomo o FCP para essa navegação. - As entradas
interaction-contentful-painttambém serão emitidas após outras interações, mas a LCP de um URL precisa ser restrita às entradasinteraction-contentful-paintque correspondem às navegações suavesinteractionIdpara excluir essas entradas e também apenas às propriedadeslargestContentfulPaintdentro delas.
Essas mudanças vão permitir que as Core Web Vitals e algumas das métricas de diagnóstico associadas sejam medidas por navegação na página, embora haja algumas nuances que precisam ser consideradas.
Quais são as implicações de ativar as navegações suaves no Chrome?
Estas são algumas das mudanças que os proprietários de sites precisam considerar depois de ativar esse recurso:
- O monitoramento das entradas
soft-navigationpermite "dividir" as entradas de desempenho em cada "navegação". - As métricas CLS e INP já podem ser divididas como você quiser, em vez de serem medidas durante todo o ciclo de vida da página. No entanto, o recurso de navegação suave oferece uma medida padronizada de quando isso acontece, independentemente da tecnologia usada.
- A entrada
largest-contentful-painté finalizada em uma interação (necessária para iniciar uma navegação suave), portanto, só pode ser usada para medir a LCP da navegação "rígida" inicial. Isso significa que isso não vai mudar quando as navegações suaves forem medidas, de modo que a LCP para o carregamento inicial da página de navegação rígida possa ser medida como sempre foi. - A nova entrada
interaction-contentful-paintque será emitida pelas interações pode ser usada para medir a LCP de navegações suaves analisando a propriedadelargestContentfulPaintdentro dela, mas há algumas considerações sobre como usar essa entrada que vamos discutir neste artigo. - Nem todos os usuários vão ter acesso a esse recurso de navegação suave, principalmente aqueles que usam outros navegadores ou versões do Chrome anteriores à 151. Alguns usuários podem não informar métricas baseadas em navegação suave, mesmo que informem métricas das Core Web Vitals.
Verifique com seu provedor de RUM se ele oferece suporte à medição das Core Web Vitals por navegação suave. Muitos estão planejando testar esse novo padrão e vão levar em conta as considerações anteriores. Enquanto isso, alguns provedores também permitem medições limitadas de métricas de performance com base nas próprias heurísticas.
Para mais informações sobre como medir as métricas de navegações suaves, consulte a seção "Como medir as Core Web Vitals por navegação suave".
Como faço para ativar as navegações suaves no Chrome?
O recurso de navegações suaves é ativado por padrão no Chrome 151.
Detecção de recursos de suporte à API Soft Navigations
Use o código a seguir para testar se a API é compatível:
if (PerformanceObserver.supportedEntryTypes.includes('soft-navigation')) {
// Monitor Soft Navigations
}
ou então:
if ('SoftNavigationEntry' in window) {
// Monitor Soft Navigations
}
Como posso medir as navegações suaves?
Quando houver suporte, as métricas poderão ser informadas usando a API PerformanceObserver, como as outras métricas. No entanto, há algumas considerações extras que precisam ser levadas em conta para essas métricas.
Informar navegações suaves
É possível usar um PerformanceObserver para observar as navegações suaves. Confira a seguir um exemplo de snippet de código que registra entradas de navegação flexível no console, incluindo navegações flexíveis anteriores nesta página usando a opção buffered:
const observer = new PerformanceObserver(console.log);
observer.observe({ type: "soft-navigation", buffered: true });
Isso pode ser usado para finalizar as métricas de página de ciclo de vida completo da navegação anterior.
Informar as métricas em relação ao URL apropriado
Quando uma navegação suave é detectada, as Core Web Vitals da página anterior precisam ser finalizadas e informadas para o URL anterior, e um novo monitoramento precisa ser iniciado para o novo URL.
O atributo name da entrada soft-navigation apropriada vai conter o novo URL para informar as métricas do relatório, e o navigationId será a referência exclusiva para essa navegação (já que o mesmo URL pode ser visitado várias vezes durante a vida útil de um aplicativo de página única).
Isso precisa ser definido como cada entrada soft-navigation e usado para informar métricas até que a próxima entrada soft-navigation seja recebida.
Informe o URL correto de interaction-contentful-paint
É preciso ter mais cuidado ao calcular a LCP com base em entradas interaction-contentful-paint, já que nem todas as entradas interaction-contentful-paint devem ser mapeadas usando o navigationId e informadas como LCP para esse URL:
- O primeiro problema é que as entradas
interaction-contentful-paintpodem ser emitidas antes da navegação flexível se uma pintura ocorrer antes da atualização do URL. Nesses casos, onavigationIdserá para o URL antigo. Se o URL for atualizado primeiro, a pintura vai concluir a navegação suave e, nesse caso, a entradasoft-navigationserá emitida primeiro, e ointeraction-contentful-paintterá o novo URL. - O segundo problema é que as entradas
interaction-contentful-paintvão continuar sendo emitidas para interações mais recentes, já que o escopo dessa métrica de performance vai além da LCP para navegações suaves. Queremos considerar apenas as pinturas do carregamento de navegação flexível para a LCP, e não as de interações subsequentes.
Portanto, o interactionId, e não o navigationId, precisa ser usado para mapear as entradas interaction-contentful-paint para soft-navigation-entries e conseguir o URL correto. Isso vai processar todas as entradas com navigationIds antigos e filtrar as entradas interaction-contentful-paint que não devem ser consideradas para a LCP.
Além disso, processe primeiro a função getLargestInteractionContentfulPaint() das entradas soft-navigation para lidar com as entradas interaction-contentful-paint que ocorreram antes da emissão de soft-navigation entries.
Como receber o startTime de navegações suaves
Todos os tempos de desempenho, incluindo os de navegações leves, e as entradas usadas para calcular as métricas das Core Web Vitals são informados como um tempo a partir do tempo inicial de navegação nas páginas "pesada". Portanto, o horário de início da navegação suave precisa ser subtraído dos tempos das métricas de carregamento da navegação suave (por exemplo, LCP) para que sejam informados em relação a esse horário.
O horário de início da navegação pode ser obtido de maneira semelhante, mapeando para a entrada soft-navigation apropriada e usando o startTime dela.
O startTime é o momento da interação inicial (por exemplo, um clique em um botão) que iniciou a navegação flexível. Isso é um pouco diferente das "navegações completas", em que o "horário de início" é quando a nova página é "confirmada" no navegador e depois que parte do código do manipulador de eventos é executada. Os horários de início da navegação suave também incluem esse código do manipulador de eventos, já que medimos a partir do horário de início da interação.
Medir as Core Web Vitals por navegação flexível
Para medir as Core Web Vitals, detecte as entradas soft-navigation e redefina as métricas ao recebê-las. A FCP pode ser emitida com base em presentationTime, e a LCP pode ser inicializada na entrada getLargestInteractionContentfulPaint(). A INP e a CLS precisam ser inicializadas como 0, assim como seriam para um carregamento de página.
A LCP, a INP e a CLS podem ser medidas e monitoradas normalmente, exceto pelo uso de interaction-contentful-paint para a LCP, desde que as correspondências de interactionId sejam fornecidas. O interactionId pode ser usado para nomear as entradas de um URL, conforme discutido anteriormente.
Os tempos ainda serão retornados em relação ao horário de início da navegação "hard" original. Para calcular a LCP de uma navegação flexível, por exemplo, você precisa pegar o tempo de interaction-contentful-paint e subtrair o horário de início da navegação flexível, conforme detalhado anteriormente, para conseguir um tempo relativo à navegação flexível.
Algumas métricas são medidas ao longo da vida útil da página: a LCP, por exemplo, pode mudar até que uma interação ocorra. A CLS e a INP podem ser atualizadas até que a página seja fechada, independentemente de qualquer interação. Portanto, as métricas da navegação anterior precisam ser finalizadas à medida que cada nova navegação suave ocorre. Isso significa que as métricas iniciais de navegação "hard" podem ser finalizadas antes do normal ao medir as Core Web Vitals com navegações suaves.
Da mesma forma, ao começar a medir as métricas para a nova navegação suave dessas métricas de longa duração, elas precisarão ser "redefinidas" ou "reinicializadas" e tratadas como novas métricas, sem memória dos valores definidos para as "páginas" anteriores. Ou seja, o entendimento do que é a "maior" exibição, a Interaction to Next Paint ou a mudança de layout é redefinido para permitir uma nova medição do zero.
Como o conteúdo que permanece o mesmo entre as navegações deve ser tratado?
A LCP para navegações suaves (calculada com base em interaction-contentful-paint) vai medir apenas as novas pinturas e somente as pinturas associadas à interação que causou a navegação. Isso pode resultar em uma LCP diferente de um carregamento a frio dessa navegação flexível para um carregamento flexível.
Por exemplo, considere uma página que inclui uma imagem do banner grande que é o elemento LCP, mas o texto abaixo dela muda a cada navegação suave. O carregamento de página inicial vai sinalizar a imagem do banner como o elemento da LCP e basear o tempo da LCP nela. Para as próximas navegações suaves, o texto abaixo será o maior elemento pintado após a navegação suave e será o novo elemento da LCP. No entanto, se a página for carregada com um link direto para o URL de navegação flexível, a imagem do banner será uma nova pintura e, portanto, poderá ser considerada como o elemento LCP.
Da mesma forma, uma animação pode estar atualizando parte da página continuamente, sem relação com qualquer navegação flexível que aconteça. As novas pinturas devido a essa animação em segundo plano não seriam consideradas para a LCP da nova navegação flexível. No entanto, eles podem ser considerados para a LCP se a página for recarregada desse URL.
Como esses exemplos mostram, o elemento LCP para a navegação flexível pode ser informado de maneira diferente dependendo de como a página é carregada, da mesma forma que carregar uma página com um link fixo mais abaixo pode resultar em um elemento LCP diferente para navegações rígidas.
Como medir o TTFB?
O Time to First Byte (TTFB) para um carregamento de página convencional representa o tempo que os primeiros bytes da solicitação original levam para serem retornados.
Para uma navegação suave, essa é uma pergunta mais complicada. Devemos medir a primeira solicitação feita para a nova página? E se todo o conteúdo já existir no app e não houver outras solicitações? E se essa solicitação for feita com antecedência usando uma pré-busca? E se uma solicitação não estiver relacionada à navegação flexível da perspectiva do usuário (por exemplo, se for uma solicitação de análise)?
Um método mais simples é informar um TTFB de 0 para navegações suaves, de maneira semelhante ao que recomendamos para restaurações de cache de avanço e retorno. Esse é o método que a biblioteca web-vitals usa para navegações suaves e o que recomendamos para essa métrica no momento.
Você deve medir as Core Web Vitals com as duas metodologias?
Embora essas novas APIs sejam limitadas apenas a navegadores baseados no Chromium, os sites podem querer medir as duas opções, dividindo por navegações suaves e continuando a dividir em navegações rígidas. Isso permitiria a comparação entre navegadores e tendências históricas.
Para a LCP, isso significa considerar apenas as entradas largest-contentful-paint para o método atual e as entradas largest-contentful-paint e interaction-contentful-paint para o novo método.
Para CLS e INP, isso significa medir essas métricas em todo o ciclo de vida da página, como é o caso do método atual, e dividir a linha do tempo por navegações suaves para medir valores separados de CLS e INP para o novo.
As métricas precisariam ser sinalizadas e armazenadas duas vezes para análise.
Usar a biblioteca web-vitals para medir as Core Web Vitals em navegações suaves
A maneira mais fácil de considerar todas as nuances é usar a biblioteca JavaScript web-vitals, que tem suporte para navegações suaves a partir da v6.0.0. Isso pode ser medido da seguinte maneira (substituindo doTraditionalProcessing e doSoftNavProcessing conforme apropriado):
import {
onTTFB,
onFCP,
onLCP,
onCLS,
onINP,
} from 'https://unpkg.com/web-vitals@soft-navs/dist/web-vitals.js?module';
function doTraditionalProcessing(callback) {
...
}
function doSoftNavProcessing(callback) {
...
}
onTTFB(doTraditionalProcessing);
onFCP(doTraditionalProcessing);
onLCP(doTraditionalProcessing);
onCLS(doTraditionalProcessing);
onINP(doTraditionalProcessing);
onTTFB(doSoftNavProcessing, {reportSoftNavs: true});
onFCP(doSoftNavProcessing, {reportSoftNavs: true});
onLCP(doSoftNavProcessing, {reportSoftNavs: true});
onCLS(doSoftNavProcessing, {reportSoftNavs: true});
onINP(doSoftNavProcessing, {reportSoftNavs: true});
A biblioteca web-vitals também garante que você informe as métricas em relação ao URL correto, conforme observado anteriormente, já que elas incluem o navigationId e um navigationURL nas entradas fornecidas ao callback.
A biblioteca web-vitals informa as seguintes métricas para navegações suaves:
| Métrica | Detalhes |
|---|---|
| TTFB | Informado como 0. |
| First Contentful Paint (FCP) | O tempo da First Contentful Paint, em relação ao horário de início da navegação suave, da interação que acionou a navegação suave. As pinturas existentes da navegação anterior ou não associadas à interação não são consideradas. |
| LCP | O tempo da maior exibição de conteúdo, em relação ao horário de início da navegação suave, da interação que acionou a navegação suave. As pinturas existentes da navegação anterior não estão associadas à interação e não são consideradas. Como de costume, isso pode continuar sendo atualizado até que a página (ou a navegação flexível) seja fechada, já que só então a LCP pode ser finalizada. |
| INP | A INP entre os tempos de navegação. Como de costume, isso pode continuar sendo atualizado até que a página (ou a navegação flexível) seja fechada, já que só então a INP pode ser finalizada. Um valor 0 não será informado se não houver interações. A interação que causa uma navegação flexível geralmente está associada à navegação anterior (de onde se navega), e não à nova navegação (para onde se navega), já que a primeira exibição é necessária para causar a navegação flexível. Isso é semelhante às navegações completas, em que um clique em um link pode ter uma INP, mas que seria associada à página em que o clique ocorreu. |
| CLS | A maior janela de mudanças entre os horários de navegação. Como de costume, isso pode continuar sendo atualizado até que a página (ou a navegação flexível) seja fechada, já que só então a CLS pode ser finalizada. A CLS associada ao evento de navegação pode ser excluída (se ocorrer em até 500 ms da interação), pode ser associada à navegação anterior (se a mudança ocorrer antes da atualização do URL) ou pode ser associada à nova navegação (se a mudança ocorrer após a finalização da navegação suave). |
Essas mudanças vão fazer parte das medições das Core Web Vitals?
O objetivo final é fornecer um meio de medir melhor o desempenho conforme as experiências de usuários reais. Portanto, sim, o objetivo é incluir essas métricas nas medições das Core Web Vitals, conforme exposto por todas as ferramentas após o lançamento da API.
Como as navegações suaves serão informadas no CrUX?
Lançamos versões experimentais das métricas Core Web Vitals no CrUX. Elas encerram as métricas CLS e INP de "navegação completa" após a primeira navegação parcial e também incluem medições adicionais de LCP, CLS e INP para cada navegação parcial. Planejamos transformar essas métricas experimentais em métricas estáveis em maio de 2027. Para mais informações, consulte a postagem do blog Métricas experimentais de navegação suave já disponíveis no CrUX.
Como lidar com navegações suaves em outros navegadores?
As navegações suaves são difíceis de detectar de forma programática em navegadores que não oferecem suporte à API, e é por isso que trabalhamos nela.
É possível usar a API Navigation para monitorar mudanças de URL, o que pode permitir a divisão da INP por URL (e, de forma semelhante, da CLS, embora ela seja exclusiva do Chromium no momento, então não seria medida de qualquer maneira). No entanto, isso não resolve as métricas de pintura (FCP e LCP), que só podem ser aproximadas.
Ao mesmo tempo, acreditamos que os insights oferecidos por essa API são valiosos demais para serem ignorados, tanto para medir o tempo das navegações suaves quanto para atribuir as métricas à navegação correta. Recomendamos o uso dessa nova API, apesar da falta de suporte entre navegadores no momento. Assim como no lançamento dos Core Web Vitals, os problemas identificados e as soluções de desempenho provavelmente vão afetar todos os navegadores, mesmo que a visibilidade esteja limitada apenas aos navegadores baseados no Chromium por enquanto.
Vamos continuar trabalhando no processo de padronização e interagindo com outros fornecedores de navegadores para mostrar a importância dessa API.
Feedback
Estamos buscando feedback sobre essa API nos seguintes locais:
- O feedback sobre a API deve ser enviado como problemas no GitHub.
- Os bugs na implementação do Chromium precisam ser registrados no Issue Tracker do Chrome, se ainda não estiverem entre os problemas conhecidos.
- Para enviar feedback geral sobre as Web Vitals, use o endereço web-vitals-feedback@googlegroups.com.
Se tiver dúvidas, não se preocupe. Preferimos receber o feedback em qualquer um dos lugares e vamos analisar os problemas em ambos os locais e redirecioná-los para o local correto.
Registro de alterações
Durante o desenvolvimento dessa API, várias mudanças foram feitas, mais do que com as APIs estáveis. Confira o registro de alterações de navegações suaves para mais detalhes.
Conclusão
O recurso de navegações suaves é uma abordagem interessante de como a iniciativa Core Web Vitals pode evoluir para medir um padrão comum na Web moderna que está ausente nas nossas métricas. Recebemos muitos comentários da comunidade da Web em geral e estamos animados com o potencial dessa API.
Agradecimentos
Imagem em miniatura por Jordan Madrid no Unsplash
Este trabalho é uma continuação do trabalho iniciado por Yoav Weiss quando ele estava no Google. Agradecemos a Yoav pelos esforços nessa API.