Publicações

Entenda a importância da performance web e do Core Web Vitals

Lorrane De Alkimim
Lorrane De Alkimim Frontend Developer

A performance de um site tem grande impacto na experiência do usuário. Entretanto, pensar em performance web não é uma tarefa muito fácil.

Normalmente nós temos a tendência de pensar na performance do nosso site somente com base em números. Mas, no fim das contas, a percepção do usuário é mais importante do que a velocidade medida.

A boa notícia é que existem técnicas e modelos criados para nos ajudar nessa jornada de mantermos um site performático e agradável para os nossos usuários.

Ao longo desse post, vou te mostrar como é possível otimizar a performance do seu site e como utilizar o Core Web Vitals a seu favor.

Performance Web

Para garantir que o usuário terá uma boa experiência, é necessário que o conteúdo que ele deseja acessar seja rápido para carregar e para responder a uma interação. Esse é o nosso trabalho ao otimizar a performance de um site: fazer com que ele seja mais rápido e, principalmente, fazer com que os processos lentos pareçam rápidos.

Para nos ajudar a pensar na performance do nosso site focando na experiência do usuário, podemos dividir a performance web em algumas áreas principais. Para isso, vamos utilizar o modelo RAIL, proposto pelo Google.

RAIL é um modelo centrado no usuário que se baseia nos quatro aspectos do ciclo de vida de uma aplicação web, são eles: resposta, animação, ociosidade e carregamento.

modelo RAIL

Para cada um desses contextos, os usuários da nossa aplicação tem expectativas diferentes. Por isso, foram definidas metas de desempenho para cada um deles através de um estudo sobre como os usuários percebem atrasos.

Tempo limite para respostas
0 a 16msPara evitar uma percepção ruim de animações travadas no seu site, cada quadro de uma animação deve levar até 16ms para ser renderizado. Pois, os usuários percebem as animações como fluídas desde que elas tenham 60 novos quadros renderizados a cada segundo.
0 a 100msPara dar ao usuário a sensação de que o seu site tem respostas imediatas às ações executadas, é necessário que ele responda dentro de 100ms. Assim, os usuários vão sentir que o resultado é imediato.
100 a 1000msDentro dessa janela de tempo, os usuários percebem as coisas como parte de uma progressão natural e contínua das tarefas. Essa é a faixa de tempo aceitável para uma atividade qualquer em um site, como carregar páginas ou alterar visualizações.
Mais do que 1.000msA partir de 1.000ms (1s), os usuários perdem o foco na tarefa que estão realizando.
Mais do que 10.000msDepois de 10.000ms (10s), os usuários estão frustrados e provavelmente abandonam as tarefas.

Agora que já sabemos os principais aspectos da performance web e já temos uma noção das expectativas do nosso usuário, podemos dizer que nossos objetivos são:

  • Reduzir o tempo total de carregamento do nosso site
  • Tornar o nosso site utilizável o mais rápido possível
  • Tornar as animações suaves e fluídas

Redução do tempo total de carregamento

Para podermos ter uma redução do tempo total de carregamento, precisamos nos fazer a seguinte pergunta:

Quanto tempo leva para que todos os arquivos necessários para apresentar o site sejam baixados no navegador do usuário? Isso pode ser afetado pela latência, pelo tamanho e quantidade dos arquivos, entre outros fatores.

Então, algumas técnicas que podemos usar são:

  • Tornar os arquivos o menor possível, com técnicas como:

    • minificação de arquivos HTML, CSS e JS
    • compressão de imagens
    • compactação de arquivos com Gzip ou Brotli
  • Remover arquivos desnecessários

  • Reduzir o máximo possível o número de solicitações HTTP

  • Utilizar serviços de CDN

  • Configurar cache

  • E empregar técnicas inteligentes de carregamento (como preload) para disponibilizar os arquivos quanto antes.

Essas técnicas devem ser analisadas para cada caso e não é uma regra geral utilizar todas elas em qualquer aplicação web, é preciso testar e ver qual técnica vai fazer sentido para aquilo que precisamos.

Tornar o site utilizável o mais rápido possível

Isso basicamente significa carregar os arquivos do site em uma ordem sensata para que o usuário possa começar a realmente usá-lo rapidamente.

Nesse ponto, precisamos entender um pouco mais sobre como o navegador renderiza as coisas na tela, porque se não soubermos direito como isso é feito, podemos cair em alguns gargalos de performance que vão dar a sensação de que a página não está respondendo ou que ela está lenta.

O que vai ser mais importante aqui é o que acontece nas etapas intermediárias entre o recebimento de bytes de HTML, CSS e JavaScript pelo navegador e o processamento feito para transformar eles em pixels renderizados na tela. Isso é chamado caminho crítico de renderização.

caminho crítico de renderização

Primeiro, para que algo seja renderizado o navegador precisa construir as árvores do DOM (Document Object Model) e do CSSOM (CSS Object Model). Basicamente, o navegador recebe o arquivo HTML do servidor, vai analisar ele transformando as tags HTML em nós. Esses nós vão ser vinculados em uma estrutura de dados em árvore que identifica relacionamentos hierárquicos e isso vai formar o DOM.

árvore DOM

Por enquanto temos somente a marcação HTML, mas não temos nenhum estilo. Por isso, é necessário a criação do CSSOM que referencia o CSS. Enquanto o navegador construía o DOM, ele encontrou uma tag link na seção head (onde são chamados os estilos CSS). O navegador envia uma solicitação desse recurso ao servidor, que é devolvida com o nosso arquivo CSS.

Assim como foi o processo para o HTML, o CSS leva o mesmo tratamento.

árvore CSSOM

Em seguida, as árvores do CSSOM e do DOM são combinadas em uma árvore de renderização, usada para processar o layout dos elementos visíveis. Assim, o resultado dessa árvore de renderização são os nós visíveis com conteúdo e seus estilos processados.

árvore de renderização

Com a árvore de renderização concluída, podemos prosseguir para a fase de layout (também conhecida como reflow). É nessa fase que é calculada a posição e o tamanho exato dos elementos na página. Para definir o tamanho e a posição de cada objeto, o navegador começa analisando na raiz da árvore de renderização e passa por ela toda.

Depois que conhecemos os nós visíveis, seus estilos processados e sua geometria, podemos finalmente passar essas informações para a última fase, que converte cada nó da árvore de renderização em pixels reais na tela. Essa etapa é chamada Paint.

Vamos recapitular as etapas que o navegador executa para renderizar uma página web:

  1. Processa a marcação HTML e cria a árvore do DOM.
  2. Processa a marcação CSS e cria a árvore do CSSOM.
  3. Combina o DOM e o CSSOM em uma árvore de renderização.
  4. Executa o layout na árvore de renderização para calcular a geometria de cada nó.
  5. Pinta os nós individuais na tela.

Esse processo pode parecer bastante simples, mas exige bom tempo de trabalho. Se o DOM ou o CSSOM forem modificados, é preciso repetir o processo para descobrir que pixels precisariam ser renderizados novamente na tela.

A otimização do caminho crítico de renderização é o processo de minimizar o total de tempo gasto em todo esse processo e priorizar a exibição do conteúdo relacionado à ação atual do usuário.

Como o navegador não renderiza nenhum conteúdo processado até que o CSSOM seja construído, o CSS é tratado como um recurso bloqueador de renderização. Se quisermos fazer com que o nosso site renderize mais rápido, devemos carregar o CSS crítico quanto antes e, como alguns estilos CSS são usados somente em determinadas circunstâncias, podemos fazer um carregamento condicional utilizando media query.

<!-- bloqueia a renderização, nada é renderizado até que ele seja baixado e analisado pelo navegador -->
<link rel="stylesheet" href="style.css">

<!-- bloqueia a renderização, pois o media não está apresentando uma condição específica -->
<link rel="stylesheet" href="style.css" media="all">

<!-- não bloqueia a renderização, a menos que a orientação do dispositivo esteja na vertical -->
<link rel="stylesheet" href="style.css" media="orientation:portrait">

<!-- não bloqueia a renderização, a menos que a página esteja em modo de impressão -->
<link rel="stylesheet" href="style.css" media="print">

No caso de precisarmos utilizar JavaScript, que também é um recurso que bloqueia a renderização (por isso deve ser chamado no fim do arquivo HTML), ele deve ser declarado como assíncrono sempre que possível.

<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css">
    <title>Caminho Crítico de Renderização: Script Async</title>
  </head>
  <body>
    <p>Hello world!</p>
    <div><img src="nice-image.jpg"/></div>
    <script src="app.js" async></script>
  </body>
</html>

Quando o navegador encontra uma tag de script, a construção do DOM faz uma pausa até que a execução do script termine. Adicionar a palavra-chave async à tag do script informa ao navegador que ele não deve bloquear a construção do DOM enquanto estiver aguardando o script ser disponibilizado, o que pode melhorar significativamente o desempenho.

Assim, quando carregamos os arquivos em uma ordem estratégica, renderizamos o necessário para que qualquer outro arquivo possa continuar carregando em segundo plano enquanto o usuário continua com as tarefas primárias.

Suavidade e interatividade

Algumas coisas que notamos assim que entramos em um site é se a rolagem é suave, se as animações são fluídas, se os botões são clicáveis e se não for, isso já nos causa uma má impressão.

Existem dois aspectos que causam problemas no desempenho do nosso site, são eles: a main thread ocupada e muitas operações de layout/paint acontecendo no navegador. Esses são os dois principais gargalos que vão impactar na interação e animação do nosso site.

Primeiro, vamos entender o que é a main thread: basicamente, o termo vem da programação concorrente, ao ter uma linha de execução onde é executada uma coisa de cada vez. A main thread é onde o navegador processa os eventos realizados pelo usuário e todas aquelas etapas de renderização da página citadas anteriormente.

O JavaScript é um recurso que bloqueia a main thread. Enquanto o navegador está executando o JavaScript, ele acaba não podendo responder às interações dos usuários.

Isso ocorre porque, por padrão, o navegador executa todo o JavaScript da página na main thread junto com outros processos como cálculos de estilo, layout e paint. Se a execução do JavaScript demorar muito tempo, ela vai bloquear essas outras tarefas, causando possivelmente perda de quadros na animação, ou demorando na resposta de um clique do usuário, por exemplo.

Então nós temos basicamente duas opções que são: dividir esses scripts em blocos menores ou não utilizar a main thread.

Dividir os scripts em blocos menores

A ideia aqui é dividir os scripts pesados em pedaços menores para que ele não ocupe a main thread por um longo período a ponto de travar outras tarefas que o usuário precise fazer. Então nós podemos usar alguns recursos como: requestAnimationFrame, setTimeout e setInterval.

O setTimeout e o setInterval são funções mais básicas que executam determinada ação após um tempo definido ou em um intervalo de tempo definido. O requestAnimationFrame é bem parecido, mas ele deve ser usado mais especificamente para animações, pois ele executa determinada função com uma taxa de quadros adequada — otimizada pelo navegador, o que torna as animações mais suaves. Além disso, usando o requestAnimationFrame, as animações em guias inativas vão parar, permitindo que a CPU esfrie e seja mais amigável à bateria.

Em resumo, esses recursos podem ser usados quando queremos fazer alguma alteração no DOM, nesse caso poderíamos dividir uma grande tarefa em micro-tarefas e usar alguma dessas funções, dependendo da natureza da tarefa.

Não utilizar a main thread

Nessa estratégia, nós podemos mover os scripts de longa duração para uma "thread" separada utilizando Web Workers. Dessa forma, podemos manter a interface atualizada, com bom desempenho e responsiva às interações dos usuários. Entretanto, como os Web Workers não tem acesso ao DOM, é interessante mover para eles os scripts mais voltados para processamento e cálculos.

Outra alternativa muito legal para liberar a main thread e deixar um tempo ocioso para que possam ser ouvidos os eventos realizados pelo usuário, é diminuir os processamentos feitos na CPU com as animações do site. Basicamente, nós podemos transferir a responsabilidade de processamento das nossas animações da main thread para a GPU utilizando propriedades básicas do CSS, como transform e opacity. Essas duas propriedades rodam na GPU e liberam o processamento da main thread, evitando que ela fique ocupada com processos de repaints e reflows.

O objetivo final é maximizar o tempo de ociosidade na main thread, para que assim, ela possa ter uma resposta mais rápida às ações que o usuário precisar executar.

Agora que já vimos como otimizar o carregamento do nosso site, a resposta, a interação e o tempo de ociosidade, é interessante entendermos como o usuário percebe o desempenho do nosso site e se possível, otimizar isso também.

Desempenho percebido

O quão rápido um site parece para o usuário tem um impacto maior na experiência dele, do que a rapidez que o site realmente tem. Mesmo que uma operação leve muito tempo, é possível manter o usuário engajado enquanto espera mostrando, por exemplo, um spinner de carregamento, um Shimmer Effect, como no Facebook e Instagram, ou qualquer outra coisa apropriada para o perfil dos seus usuários.

spinner de carremento

shimmer effect

Essa abordagem é muito melhor do que apenas não mostrar nada, o que pode dar a impressão para o usuário de que está demorando muito mais e, possivelmente, ele vai desistir de esperar e simplesmente vai sair do seu site.

É bom lembrar também que não é necessário carregar todo o site assim que o usuário entrar nele. Mas, é preciso que seja apresentado o essencial para ele poder ter a sensação de que algo está sendo carregado. Isso pode ser feito utilizando a técnica Lazy Load.

lazy load

Core Web Vitals

Medir a performance de um site envolve medir as velocidades reais e percebidas da aplicação, otimizar sempre que possível e, em seguida, monitorar o desempenho, para garantir que o que você otimizou permaneça otimizado.

Existem vários testes de performance e muitas métricas que podem ser aplicadas no seu site dependendo do aspecto de performance que você deseja medir. Nesse post, vamos focar no Core Web Vitals por serem métricas implantadas recentemente pelo Google e que vão ter grande impacto no ranqueamento dos sites.

Core Web Vitals é um conjunto de métricas que mede o desempenho do site focando em aspectos importantes da experiência do usuário. Ele é composto por três métricas principais e seus limites-alvo, que vão nos ajudar a compreender como está a experiência do nosso site pensando nos aspectos de carregamento, interatividade e estabilidade visual.

Largest Contentful Paint

Largest Contentful Paint - LCP (Maior renderização de conteúdo): mede quanto tempo demora para o maior elemento da página ser carregado e renderizado. Ou seja, ela é a métrica que mede a performance de carregamento. Na LCP, será medida a velocidade de carregamento percebida, marcando na linha do tempo do carregamento do site o ponto em que o conteúdo principal da página foi carregado. O tempo ideal definido para essa métrica é de até 2,5 segundos.

First Input Delay

First Input Delay - FID (Primeiro atraso de entrada): basicamente, mede quanto tempo demora para a primeira ação que o usuário executar no site ter uma resposta. Essa é a métrica relacionada à interatividade. No FID, é possível quantificar a experiência que o usuário tem ao interagir com o seu site. O tempo ideal definido para essa métrica é de até 100 milissegundos.

Cumulative Layout Shift

Cumulative Layout Shift - CLS (Deslocamento cumulativo de layout): provavelmente você já entrou em um site que, quando menos esperava, algo mudou de lugar ou algum elemento apareceu na tela sem nenhum aviso. Ou pior ainda, quando vamos tentar clicar em algo e o site parece que não carregou completamente, causando um efeito de layout shift — que é quando, por exemplo, um link ou um botão tem um deslocamento repentino — e acabamos clicando em algo que não queríamos. Para evitar esse tipo de experiência negativa é que essa métrica foi criada. Basicamente, ela mede essas mudanças de layout inesperadas que ocorrem durante a vida útil da página. Um bom princípio para evitar essas mudanças de layout é sempre incluir o tamanho (width e height) nas imagens ou vídeos, reservando os espaços necessários para eles na página.

exemplo de layout shift


Essas técnicas são um bom ponto de partida para melhorar as nossas aplicações e a experiência de quem vai utilizar elas. E como recompensa, sites que tem uma boa pontuação no Core Web Vitals terão também uma classificação melhor nas buscas do Google. Isso é importante para o seu site e para o seu negócio que ao realizar essas otimizações podem ter melhora no tráfego e na conversão.

Para saber mais

Referências

Solução de problemas, melhoria de gestão e aumento de produtividade

Com tecnologias renomadas, aplicamos práticas ágeis e capacitamos sua equipe.

Fale com um consultor