Experimento com a medição de navegações suaves

Publicado em: 1º de fevereiro de 2023. Última atualização: 30 de março 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 sobre como ele é criado ou carregado. As três métricas do Core Web Vitals foram criadas como métricas centradas no usuário, uma evolução em relação às métricas técnicas atuais, como DOMContentLoaded ou load, que mediam tempos geralmente não relacionados à percepção dos usuários sobre a performance 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 popular de aplicativo de página única nunca foi totalmente compatível com as métricas Core Web Vitals. Em vez de carregar páginas da Web distintas e individuais enquanto 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 por JavaScript. Nesses aplicativos, a ilusão de uma arquitetura de página da Web convencional é mantida alterando o URL e enviando os URLs anteriores no histórico do navegador para permitir que os botões "Voltar" e "Avançar" funcionem como o usuário espera.

Muitos frameworks 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", a medição sempre foi difícil: onde está a linha entre uma interação na página atual e considerar isso como uma página nova?

A equipe do Chrome está considerando esse desafio há algum tempo e quer padronizar uma 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 API com base no feedback dos desenvolvedores para o último teste de origem e agora pedimos que eles testem a iteração mais recente e enviem feedback sobre a abordagem antes do lançamento. Estamos confiantes de que a API chegou a um bom ponto ao longo dessas iterações e pretendemos lançá-la ainda este ano, sujeito a feedback sobre o último teste de origem.

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 visível de URL para o usuário.
  • A interação resulta em uma renderização visível.

Para alguns sites, essas heurísticas podem levar a falsos positivos (que os usuários não considerariam uma "navegação") ou falsos negativos (em que o usuário considera uma "navegação" mesmo que ela não atenda a esses critérios). Queremos saber sua opinião sobre as heurísticas no repositório de especificações de navegação suave.

Suporte das DevTools para navegações leves

Adicionamos suporte para navegações suaves ao painel de desempenho do DevTools na visualização de rastreamento:

Um marcador de navegação suave no painel "Performance" com um rastreamento de youtube.com.

Você pode ver marcadores para navegações suaves e LCP, ambos marcados com um * para ajudar a diferenciá-los das entradas de navegação completa comuns. Ela é ativada por padrão e é separada das mudanças na API de performance que vamos discutir a seguir. É uma maneira rápida de testar se o experimento de navegações suaves funciona corretamente no seu site.

Por enquanto, isso mostra apenas a navegação suave e os carimbos de data/hora do LCP na visualização de rastreamento. Outras métricas (por exemplo, LCP) e suporte na visualização Métricas em tempo real serão adicionados mais tarde.

Como o Chrome implementa navegações suaves para desenvolvedores da Web?

Depois que as heurísticas de navegação suave forem ativadas (mais detalhes na próxima seção), o Chrome vai mudar a forma como informa algumas métricas de desempenho:

  • Um evento soft-navigation PerformanceTiming será emitido após cada navegação suave detectada.
  • Essa entrada de soft-navigation vai incluir um navigationId, o novo URL no atributo name e um interactionId da interação inicial.
  • Uma ou mais entradas interaction-contentful-paint serão emitidas após interações que causam uma renderização significativa. Isso pode ser usado para medir o Largest Contentful Paint (LCP) em navegações suaves quando a interação emite uma navegação suave.
  • 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, event e layout-shift). Isso corresponde à entrada de navegação em que o evento foi emitido. Observe que, quando essas entradas abrangem navegações suaves, elas podem conter o navigationId anterior ou seguinte, dependendo de quando a entrada foi emitida. Saiba mais sobre isso na seção Informar as métricas no URL adequado.
  • O soft-navigation vai incluir uma entrada largestInteractionContentfulPaint com a maior entrada interaction-contentful-paint emitida como parte da navegação. Isso pode ser usado como o LCP inicial para essa navegação, que pode ser atualizado à medida que mais entradas interaction-contentful-paint para essa interação são observadas.
  • É possível que algumas entradas de interaction-contentful-paint tenham ocorrido antes da navegação suave (se a atualização do URL não acontecer até depois dessas renderizações). Nesses casos, a maior entrada de largestInteractionContentfulPaint evita a necessidade de buffer e de analisar entradas antigas. O largestInteractionContentfulPaint é uma cópia exata da maior entrada interaction-contentful-paint. Portanto, essa entrada usou o navigationId anterior, já que foi quando a pintura ocorreu. No entanto, essas pinturas devem ser medidas em relação ao novo navigationId.
  • A entrada soft-navigation também vai incluir paintTime e presentationTime como o FCP dessa navegação.
  • As entradas interaction-contentful-paint também serão emitidas após outras interações, mas o LCP de um URL deve ser restrito às entradas interaction-contentful-paint que correspondem às navegações suaves interactionId para excluir essas entradas.

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, mas há algumas nuances que precisam ser consideradas.

Quais são as implicações de ativar as navegações suaves no Chrome?

Confira algumas das mudanças que os proprietários de sites precisam considerar depois de ativar esse recurso:

  • O monitoramento das entradas soft-navigation permite "dividir" as entradas de performance em cada "navegação".
  • As métricas CLS e INP já podem ser segmentadas a seu critério, em vez de serem medidas durante todo o ciclo de vida da página. No entanto, a API Soft Navigation oferece uma medida padronizada de quando isso acontece, independente da tecnologia usada.
  • A entrada largest-contentful-paint é finalizada em uma interação (necessária para iniciar uma navegação suave). Portanto, ela só pode ser usada para medir o LCP da navegação "difícil" inicial. Isso significa que ela não vai mudar quando as navegações suaves forem medidas. Assim, o LCP do carregamento de página inicial e de navegação completa pode ser medido como sempre foi.
  • A nova entrada interaction-contentful-paint emitida pelas interações pode ser usada para medir o LCP em navegações suaves, mas há algumas considerações sobre como usar essa entrada que vamos discutir neste artigo.
  • Observe que nem todos os usuários são compatíveis com essa API de navegação suave, principalmente em versões mais antigas do Chrome e em outros navegadores. Alguns usuários podem não informar métricas baseadas em navegação suave, mesmo que informem métricas de Core Web Vitals.
  • Como um novo recurso experimental que não é ativado por padrão, os sites precisam testar essa funcionalidade para verificar se há efeitos colaterais não intencionais.

Verifique com seu provedor de RUM se ele oferece suporte à medição das Core Web Vitals por navegação suave. Muitas pessoas estão planejando testar esse novo padrão e vão levar em consideração 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 "Medir as Core Web Vitals por navegação suave".

Como faço para ativar as navegações suaves no Chrome?

As navegações suaves não são ativadas por padrão no Chrome, mas estão disponíveis para testes. Basta ativar o recurso explicitamente.

Para desenvolvedores, isso pode ser ativado ao ativar a flag em chrome://flags/#soft-navigation-heuristics. Como alternativa, ele pode ser ativado usando os argumentos de linha de comando --enable-features=SoftNavigationHeuristics ao iniciar o Chrome. Ativar a flag chrome://flags/#enable-experimental-web-platform-features também ativa as navegações suaves.

Para um site que quer ativar isso para todos os visitantes e ver o impacto, haverá um teste de origem em execução no Chrome 147. Para participar, basta se inscrever e incluir um elemento meta com o token do teste de origem no cabeçalho HTML ou HTTP. Consulte a postagem Começar a usar os testes de origem para mais informações.

Os proprietários de sites podem incluir o teste de origem nas páginas para todos ou apenas para um subconjunto de usuários. Considere a seção de implicações anterior para saber como isso muda a forma como suas métricas podem ser informadas, principalmente se você ativar o teste de origem para uma grande proporção de usuários. A CrUX vai continuar informando as métricas da maneira atual, independente dessa configuração de navegação suave, e não será afetada por essas implicações. Também é importante observar que os testes de origem são limitados à ativação de recursos experimentais em um máximo de 0,5% de todos os carregamentos de página do Chrome como uma mediana em 14 dias, mas isso só deve ser um problema para sites muito grandes.

Recurso que detecta a compatibilidade com a 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
}

Observe que supportedEntryTypes é congelado no primeiro uso. Portanto, se o suporte a navegações suaves for adicionado dinamicamente por um token de teste de origem injetado na página, isso poderá retornar o valor original, antes da ativação do recurso.

A seguinte alternativa pode ser usada nesse caso enquanto as navegações suaves ainda não são compatíveis por padrão e estão nesse estado de transição:

if ('SoftNavigationEntry' in window) {
  // Monitor Soft Navigations
}

Como posso medir navegações suaves?

Depois que o experimento de navegações suaves for ativado, as métricas serão informadas usando a API PerformanceObserver, assim como 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 navegações suaves. Confira um exemplo de snippet de código que registra entradas de navegação suave no console, incluindo navegações suaves 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.

Gerar relatórios sobre as métricas em relação ao URL adequado

Quando uma navegação suave é detectada, as Core Web Vitals da página anterior precisam ser finalizadas e informadas para o URL anterior. Em seguida, um novo monitoramento precisa ser iniciado para o novo URL.

O atributo name da entrada soft-navigation adequada vai conter o novo URL para informar as métricas, 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 pode ser pesquisado com a API PerformanceEntry:

const softNavEntry =
  performance.getEntriesByType('soft-navigation').filter(
    (entry) => entry.navigationId === navigationId
  )[0];
const hardNavEntry = performance.getEntriesByType('navigation')[0];
const navEntry = softNavEntry || hardNavEntry;
const pageUrl = navEntry?.name;

Denunciar o URL correto de interaction-contentful-paint

São necessárias outras considerações para calcular o LCP das 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-paint podem ser emitidas antes da navegação suave se uma renderização ocorrer antes da atualização do URL. Nesses casos, o navigationId será do URL antigo. Se o URL for atualizado primeiro, a renderização vai concluir a navegação suave. Nesse caso, a entrada soft-navigation será emitida primeiro, e a interaction-contentful-paint terá o novo URL.
  • O segundo problema é que interaction-contentful-paint, as entradas vão continuar sendo emitidas para interações mais recentes, já que o escopo dessa métrica de performance vai além do LCP para navegações suaves. Queremos considerar apenas as renderizações para o carregamento de navegação suave do LCP, e não as das interações subsequentes.

Portanto, o interactionId, e não o navigationId, deve ser usado para mapear entradas interaction-contentful-paint para soft-navigation-entries e obter 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 o LCP.

Além disso, considere processar a entrada largestInteractionContentfulPaint das entradas soft-navigation também para facilitar o processamento de entradas interaction-contentful-paint que ocorrem antes da emissão de soft-navigation entries.

Como conseguir o startTime de navegações suaves

Todos os tempos de desempenho, incluindo os de navegações suaves, e as entradas usadas para calcular as métricas das Core Web Vitals são informados como um tempo desde a navegação inicial "completa" da página. Portanto, o tempo de início da navegação suave precisa ser subtraído dos tempos de métricas de carregamento de navegação suave (por exemplo, LCP) para que sejam informados em relação a esse tempo de navegação suave.

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 suave. Isso é um pouco diferente das "navegações completas", em que o "tempo de início" é quando a nova página é "confirmada" para o navegador e depois que parte do código do manipulador de eventos é executada. Os tempos de início de navegação suave também incluem esse código do manipulador de eventos, já que medimos a partir do tempo de início da interação.

Medir as Core Web Vitals por navegação suave

Para medir as Core Web Vitals, ouça as entradas soft-navigation e redefina as métricas ao recebê-las. O FCP pode ser emitido com base no presentationTime, e o LCP pode ser inicializado como largestInteractionContentfulPaint. INP e CLS precisam ser inicializados como 0, assim como em um carregamento de página.

O LCP, o INP e o CLS podem ser medidos e monitorados como de costume, exceto quando se usa interaction-contentful-paint para LCP, desde que o interactionId corresponda. Os interactionId e navigationId podem ser usados 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 "completa" original. Portanto, para calcular o LCP de uma navegação suave, por exemplo, você precisa usar a marcação de tempo interaction-contentful-paint e subtrair o horário de início da navegação suave adequado, conforme detalhado anteriormente, para ter um tempo relativo à navegação suave.

Algumas métricas são medidas ao longo da vida útil da página. Por exemplo, o LCP pode mudar até que uma interação ocorra. O CLS e o INP podem ser atualizados até que a página seja deixada, independentemente das interações. Portanto, as métricas da navegação anterior precisam ser finalizadas a cada nova navegação suave. Isso significa que as métricas de navegação "difíceis" iniciais 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 "páginas" anteriores. Ou seja, o entendimento do que é a "maior" exibição, interação até a próxima exibição ou mudança de layout é redefinido para permitir a medição novamente do zero.

Como o conteúdo que permanece o mesmo entre navegações deve ser tratado?

O LCP para navegações suaves (calculado com base em interaction-contentful-paint) mede apenas novas renderizações e apenas as associadas à interação que causou a navegação. Isso pode resultar em um LCP diferente, por exemplo, de um carregamento a frio dessa navegação suave para um carregamento suave.

Por exemplo, uma página que inclui uma imagem de 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 LCP e basear o tempo da LCP nisso. Para as próximas navegações suaves, o texto abaixo será o maior elemento renderizado após a navegação suave e será o novo elemento LCP. No entanto, se a página for carregada com um link direto no URL de navegação suave, a imagem do banner será uma nova renderização e, portanto, poderá ser considerada o elemento LCP.

Da mesma forma, uma animação pode atualizar parte da página continuamente, sem relação com qualquer navegação suave que aconteça. Novas renderizações devido a essa animação de plano de fundo não seriam consideradas para o LCP da nova navegação suave. No entanto, eles podem ser considerados para o LCP se a página for recarregada desse URL.

Como mostram esses exemplos, o elemento LCP para a navegação suave pode ser informado de maneira diferente, dependendo de como a página é carregada. Da mesma forma, carregar uma página com um link fixo mais abaixo pode resultar em um elemento LCP diferente para navegações completas.

Como medir o TTFB?

O Time to First Byte (TTFB) para um carregamento de página convencional representa o tempo em que os primeiros bytes da solicitação original são retornados.

Para uma navegação suave, essa é uma questão 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 um pré-busca? E se uma solicitação não relacionada à navegação suave do ponto de vista do usuário (por exemplo, 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 do 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?

Durante esse experimento, recomendamos que você continue medindo as Core Web Vitals da maneira atual, com base em navegações "difíceis" na página, já que a nova implementação pode ter problemas ou mudar antes de ser lançada. Isso também vai corresponder ao que a CrUX mede por enquanto (mais sobre isso depois).

As navegações suaves precisam ser medidas além dessas para que você veja como elas podem ser medidas no futuro e para que você possa enviar feedback à equipe do Chrome sobre como essa implementação funciona na prática. Isso vai ajudar você e a equipe do Chrome a moldar a API no futuro.

Para o LCP, isso significa considerar apenas entradas largest-contentful-paint para a maneira atual e entradas largest-contentful-paint e interaction-contentful-paint para a nova maneira.

Para CLS e INP, isso significa medir essas métricas em todo o ciclo de vida da página, no estado em que se encontra, e dividir separadamente a linha do tempo por navegações suaves para medir valores separados de CLS e INP para a nova.

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 experimental para navegações leves em um soft-navs branch separado (também disponível em npm e unpkg). Isso pode ser medido da seguinte forma (substituindo doTraditionalProcessing e doSoftNavProcessing conforme necessário):

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 as métricas sejam informadas no URL correto conforme observado anteriormente, já que 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 primeira exibição de conteúdo, em relação ao horário de início da navegação suave, da interação que a acionou. As renderizações 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 renderizações existentes da navegação anterior ou não associadas à interação não são consideradas. Como de costume, isso será informado em uma interação ou quando a página for colocada em segundo plano, já que só então o LCP poderá ser finalizado.
CLS A maior janela de turnos entre os horários de navegação. Como de costume, isso acontece quando a página é colocada em segundo plano, pois só então o CLS pode ser finalizado. Um valor 0 será informado se não houver turnos.
INP O INP entre os tempos de navegação. Como de costume, isso será informado em uma interação ou quando a página for colocada em segundo plano, já que só então o INP poderá ser finalizado. Um valor 0 não será informado se não houver interações.

Essas mudanças vão fazer parte das medições de Core Web Vitals?

Queremos avaliar as heurísticas e verificar se elas refletem com mais precisão a experiência do usuário antes de decidir se isso será integrado à iniciativa Core Web Vitals. O objetivo final é fornecer um meio de medir melhor a performance como experiências de usuários reais. Portanto, o objetivo é incluir essas métricas nas medições das Core Web Vitals, conforme exposto por todas as ferramentas, caso o experimento seja bem-sucedido.

Valorizamos o feedback dos desenvolvedores da Web sobre o experimento, as heurísticas usadas e se você acha que ele reflete melhor a experiência. O repositório do GitHub de navegação suave é o melhor lugar para enviar feedback. No entanto, bugs individuais com a implementação do Chrome devem ser informados no rastreador de problemas do Chrome.

Como as navegações suaves serão informadas no CrUX?

Ainda não se sabe como as navegações suaves serão informadas no CrUX se esse experimento for bem-sucedido. Não é necessariamente uma certeza que eles serão tratados da mesma forma que as navegações "rígidas" atuais.

Em algumas páginas da Web, as navegações suaves são quase idênticas aos carregamentos de página completa para o usuário, e o uso da tecnologia de aplicativo de página única é apenas um detalhe de implementação. Em outros, eles podem ser mais parecidos com um carregamento parcial de conteúdo adicional.

Por isso, podemos decidir informar essas navegações suaves separadamente no CrUX ou ponderá-las ao calcular as Core Web Vitals de uma determinada página ou grupo de páginas. Também podemos excluir totalmente a navegação suave de carregamento parcial à medida que a heurística evolui.

A equipe está se concentrando na implementação heurística e técnica, o que nos permitirá julgar o sucesso desse experimento. Portanto, nenhuma decisão foi tomada nessas frentes.

Feedback

Estamos buscando feedback sobre esse experimento nos seguintes lugares:

Se estiver em dúvida, não se preocupe muito. Preferimos receber o feedback em qualquer um dos lugares e vamos analisar os problemas nos dois locais e redirecionar para o local correto.

Registro de alterações

Como essa API está em fase experimental, ela passa por várias mudanças, mais do que as APIs estáveis. Consulte o registro de mudanças das heurísticas de navegação suave para mais detalhes.

Conclusão

O experimento de navegações suaves é uma abordagem interessante para a evolução da iniciativa Core Web Vitals, que pode medir um padrão comum na Web moderna que não está presente nas nossas métricas. Embora esse experimento ainda esteja em fase inicial e haja muito a ser feito, disponibilizar o progresso até agora para a comunidade da Web experimentar é uma etapa importante. Coletar o feedback desse experimento é outra parte crucial dele. Por isso, incentivamos muito os interessados nesse desenvolvimento a aproveitar essa oportunidade para ajudar a moldar a API e garantir que ela represente o que esperamos medir com ela.

Agradecimentos

Imagem em miniatura de 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.