Otimizar a latência na primeira entrada

Como responder mais rapidamente às interações do usuário.

Cliquei, mas nada aconteceu! Por que não consigo interagir com esta página? 😢

Primeira exibição de conteúdo (FCP, na sigla em inglês) e Maior exibição de conteúdo (LCP, na sigla em inglês) são métricas que medem o tempo necessário para o conteúdo renderizar visualmente (pintura) em uma página. Embora seja importante, os tempos de exibição não capturam a capacidade de responsividade do carregamento ou a rapidez com que uma página responde à interação do usuário.

A latência na primeira entrada (FID, na sigla em inglês) é uma métrica das Core Web Vitals que captura a primeira impressão de um usuário sobre a interatividade e a capacidade de resposta de um site. Ela mede o tempo entre a interação de um usuário com a página e o momento em que o navegador pode responder a essa interação. A FID é uma métrica de campo e não pode ser simulada em um ambiente de laboratório. É necessária uma interação real do usuário para medir o atraso de resposta.

Os valores de fid bons são de 2,5 segundos, os valores ruins são maiores do que 4,0 segundos e qualquer valor entre eles precisa ser melhorado

Para ajudar a prever a FID no laboratório, recomendamos o Tempo total de bloqueio (TBT, na sigla em inglês). Elas medem coisas diferentes, mas as melhorias no TBT geralmente correspondem a melhorias na FID.

A principal causa de uma FID ruim é a execução pesada do JavaScript. A otimização da forma como o JavaScript analisa, compila e executa na sua página da Web reduz diretamente a FID.

Execução intensa de JavaScript

O navegador não pode responder à maioria das entradas do usuário enquanto executa JavaScript na linha de execução principal. Em outras palavras, o navegador não pode responder às interações do usuário enquanto a linha de execução principal está ocupada. Para melhorar isso:

Dividir tarefas longas

Se você já tentou reduzir a quantidade de JavaScript carregada em uma única página, divida o código de longa duração em tarefas menores e assíncronas.

Tarefas longas são períodos de execução do JavaScript em que os usuários podem perceber que a interface não responde. Qualquer parte do código que bloqueie a linha de execução principal por 50 ms ou mais pode ser caracterizada como uma tarefa longa. Tarefas longas são um sinal de possível sobrecarga do JavaScript, ou seja, carregar e executar mais do que o usuário pode precisar no momento. A divisão de tarefas longas pode reduzir o atraso de entrada no site.

Tarefas longas no Chrome DevTools
O Chrome DevTools visualiza tarefas longas no painel "Desempenho"

A FID deve melhorar de forma perceptível à medida que você adota práticas recomendadas, como divisão de código e divisão de tarefas longas. Embora o TBT não seja uma métrica de campo, ele é útil para verificar o progresso para melhorar o tempo até a interação (TTI, na sigla em inglês) e a FID.

Otimize sua página para que esteja pronta para interação

Há várias causas comuns de pontuações baixas de FID e TBT em apps da Web que dependem muito de JavaScript:

A execução de scripts próprios pode atrasar a prontidão da interação

  • A sobrecarga de tamanho do JavaScript, os tempos de execução pesados e a divisão ineficiente podem atrasar o tempo necessário para uma página responder à entrada do usuário e afetar a FID, TBT e TTI. O carregamento progressivo de código e recursos pode ajudar a espalhar esse trabalho e melhorar a prontidão para a interação.
  • Os apps renderizados do lado do servidor podem parecer que estão pintando pixels na tela rapidamente, mas tenha cuidado com as interações do usuário bloqueadas por grandes execuções de script (por exemplo, re-hidratação para conectar listeners de eventos). Isso pode levar várias centenas de milissegundos, às vezes até mesmo segundos, se a divisão de código com base em rota estiver sendo usada. Considere mudar mais lógica do lado do servidor ou gerar mais conteúdo estaticamente durante o tempo de build.

Confira abaixo as pontuações de TBT antes e depois de otimizar o carregamento de scripts próprios de um aplicativo. Ao remover o carregamento caro do script (e a execução) de um componente não essencial do caminho crítico, os usuários puderam interagir com a página muito mais cedo.

Melhorias na pontuação de TBT no Lighthouse após otimizar o script próprio.

A busca de dados pode afetar muitos aspectos da prontidão para interação

  • A espera por uma cascata de buscas em cascata (por exemplo, buscas de JavaScript e de dados para componentes) pode afetar a latência da interação. Tentar minimizar a dependência de buscas de dados em cascata.
  • Grandes armazenamentos de dados inline podem adiar o tempo de análise do HTML e afetar as métricas de pintura e interação. Tente minimizar a quantidade de dados que precisam ser pós-processados no lado do cliente.

A execução de scripts de terceiros também pode atrasar a latência da interação

  • Muitos sites incluem análises e tags de terceiros que podem manter a rede ocupada e fazer com que a linha de execução principal não responda periodicamente, afetando a latência da interação. Explorar o carregamento sob demanda de código de terceiros (por exemplo, talvez não carregue os anúncios abaixo da dobra até que eles estejam mais perto da janela de visualização).
  • Em alguns casos, scripts de terceiros podem antecipar os próprios em termos de prioridade e largura de banda na linha de execução principal, atrasando o momento em que uma página fica pronta para interação. Tente priorizar o carregamento do que você acredita que oferece mais valor aos usuários.

Usar um Web worker

Uma linha de execução principal bloqueada é uma das principais causas de atraso na entrada. Os Web workers possibilitam a execução de JavaScript em uma linha de execução em segundo plano. A migração de operações que não são da interface para uma linha de execução de worker separada pode reduzir o tempo de bloqueio da linha de execução principal e, consequentemente, melhorar a FID.

Considere o uso das seguintes bibliotecas para facilitar o uso de web workers no seu site:

  • Comlink: uma biblioteca auxiliar que abstrai postMessage e facilita o uso.
  • Workway: um exportador de worker da Web de uso geral
  • Workerize: mova um módulo para um worker da Web.

Reduzir o tempo de execução do JavaScript

Limitar a quantidade de JavaScript na sua página reduz o tempo que o navegador precisa gastar na execução de códigos JavaScript. Isso acelera a velocidade com que o navegador pode começar a responder a qualquer interação do usuário.

Para reduzir a quantidade de JavaScript executado na sua página:

  • Adiar JavaScript não utilizado
  • Minimizar polyfills não usados

Adiar JavaScript não utilizado

Por padrão, todo JavaScript bloqueia a renderização. Quando o navegador encontra uma tag de script vinculada a um arquivo JavaScript externo, ele precisa pausar o que está fazendo e fazer o download, analisar, compilar e executar esse JavaScript. Portanto, carregue apenas o código necessário para a página ou que responda à entrada do usuário.

A guia Cobertura do Chrome DevTools pode informar quanto JavaScript não está sendo usado na sua página da Web.

A guia "Cobertura".

Para reduzir o JavaScript não utilizado:

  • Dividir seu pacote em várias partes de código
  • Adie qualquer JavaScript não crítico, incluindo scripts de terceiros, usando async ou defer.

A divisão de código é o conceito de dividir um único pacote JavaScript grande em pedaços menores que podem ser carregados condicionalmente (também conhecido como carregamento lento). A maioria dos navegadores mais recentes é compatível com a sintaxe de importação dinâmica, que permite a busca de módulos sob demanda:

import('module.js').then((module) => {
  // Do something with the module.
});

A importação dinâmica de JavaScript em determinadas interações do usuário (como a mudança de uma rota ou a exibição de um modal) garante que o código não usado para o carregamento inicial da página seja buscado apenas quando necessário.

Além do suporte geral a navegadores, a sintaxe de importação dinâmica pode ser usada em muitos sistemas de compilação diferentes.

  • Se você usa webpack, Rollup ou Parcel como um bundler de módulo, aproveite a compatibilidade com importação dinâmica.
  • Os frameworks do lado do cliente, como React, Angular e Vue, fornecem abstrações para facilitar o carregamento lento no nível do componente.

Além da divisão de código, sempre use async ou adiar para scripts que não sejam necessários para o caminho crítico ou conteúdo acima da dobra.

<script defer src="…"></script>
<script async src="…"></script>

A menos que haja um motivo específico para não fazer isso, todos os scripts de terceiros precisam ser carregados com defer ou async por padrão.

Minimizar polyfills não usados

Se você criar o código usando sintaxe JavaScript moderna e referenciar APIs de navegadores modernos, será necessário transcompilar e incluir polyfills para que ele funcione em navegadores mais antigos.

Uma das principais preocupações com o desempenho da inclusão de polyfills e código transcompilado no seu site é que os navegadores mais recentes não precisam fazer o download desses arquivos se não forem necessários. Para reduzir o tamanho em JavaScript do aplicativo, minimize ao máximo os polyfills não usados e restrinja o uso deles aos ambientes em que são necessários.

Para otimizar o uso do polyfill no seu site, faça o seguinte:

  • Se você usar o Babel como transpilador, use @babel/preset-env para incluir apenas os polyfills necessários para os navegadores que você planeja segmentar. No Babel 7.9, ative a opção bugfixes para reduzir ainda mais os polyfills desnecessários.
  • Use o padrão module/nomodule para enviar dois pacotes separados (@babel/preset-env também oferece suporte a isso via target.esmodules).

    <script type="module" src="modern.js"></script>
    <script nomodule src="legacy.js" defer></script>
    

    Muitos recursos mais recentes do ECMAScript compilados com o Babel já são aceitos em ambientes compatíveis com módulos JavaScript. Ao fazer isso, você simplifica o processo de garantir que apenas o código transcompilado seja usado para navegadores que realmente precisam dele.

Ferramentas para desenvolvedores

Várias ferramentas estão disponíveis para medir e depurar a FID:

  • O Lighthouse 6.0 não inclui suporte à FID, já que é uma métrica de campo. No entanto, o Tempo total de bloqueio (TBT, na sigla em inglês) pode ser usado como um proxy. As otimizações que melhoram o TBT também precisam melhorar a FID no campo.

    Lighthouse 6.0

  • O Chrome User Experience Report fornece valores de FID reais agregados no nível da origem

Agradecimentos a Philip Walton, Kayce Basques, Ilya Grigorik e Annie Sullivan pelas avaliações.