Ao longo dos anos, a comunidade da Web acumulou muitos conhecimentos sobre a otimização de desempenho da Web. Embora uma otimização possa melhorar o desempenho de muitos sites, todas elas ao mesmo tempo podem ser esmagadoras e, realisticamente, apenas algumas delas são aplicáveis a um determinado site.
A menos que a performance da Web seja seu trabalho diário, provavelmente não é óbvio quais otimizações terão o maior impacto no seu site. Você provavelmente não terá tempo para todas elas, então é importante se perguntar quais são as otimizações de maior impacto que você pode escolher para melhorar o desempenho para seus usuários?
A verdade sobre otimizações de desempenho: você não pode julgá-las somente por seus méritos técnicos. Você também precisa considerar os fatores humanos e organizacionais que influenciam a probabilidade de implementar uma determinada otimização. Algumas melhorias de desempenho podem ter um impacto enorme na teoria, mas, na realidade, poucos desenvolvedores terão o tempo ou os recursos para implementá-las. Por outro lado, pode haver práticas recomendadas de desempenho altamente impactantes que quase todo mundo já está seguindo. Este guia identifica otimizações de desempenho da Web que:
- Têm o maior impacto no mundo real
- São relevantes e aplicáveis à maioria dos sites
- São realistas para a maioria dos desenvolvedores implementar
Juntas, essas são as maneiras mais realistas e eficazes de melhorar as métricas das Core Web Vitals. Se você for iniciante em desempenho da Web ou se ainda estiver decidindo qual oferecerá o maior retorno do investimento, esse é o melhor lugar para começar.
Interaction to Next Paint (INP)
Como a métrica mais recente das Core Web Vitals, a Interaction to Next Paint (INP) tem algumas das maiores oportunidades de melhoria. No entanto, como muitos menos sites estão atendendo ao limite para experiências "boas" em comparação com o antecessor descontinuado, você pode estar entre os muitos desenvolvedores que estão aprendendo a otimizar a capacidade de resposta de interação pela primeira vez. Comece com estas técnicas indispensáveis para saber as maneiras mais eficazes de melhorar a INP.
1. Rendem-se com frequência para dividir tarefas longas
As tarefas são qualquer trabalho discreto que o navegador executa, incluindo renderização, layout, análise, compilação ou execução de scripts. Quando uma tarefa excede 50 milissegundos de duração, ela se torna uma tarefa longa. Tarefas longas são problemáticas porque podem impedir que a linha de execução principal responda rapidamente às interações do usuário.
É necessário sempre fazer o mínimo de trabalho possível em JavaScript, mas você pode ajudar a linha de execução principal dividindo tarefas longas. Para isso, retorne com frequência para a linha de execução principal, para que as atualizações de renderização e outras interações do usuário possam acontecer mais rapidamente.
A API Scheduler permite enfileirar o trabalho usando um sistema de prioridades. Especificamente, a API scheduler.yield() divide tarefas longas, garantindo que as interações possam ser processadas sem perder o lugar na fila de tarefas.
Ao dividir tarefas longas, você dá ao navegador mais oportunidades de se encaixar em trabalhos críticos que bloqueiam o usuário.
2. Evitar JavaScript desnecessário
Os sites estão enviando mais JavaScript do que nunca, e a tendência não parece mudar. Quando você envia muito JavaScript, cria um ambiente em que as tarefas competem pela atenção da linha de execução principal. Isso pode afetar a capacidade de resposta do site, especialmente durante esse período crucial de inicialização.
No entanto, esse não é um problema sem solução, e você tem opções:
- Use os recursos da Referência, amplamente disponíveis na plataforma da Web, em vez de implementações redundantes baseadas em JavaScript.
- Use a ferramenta de cobertura no Chrome DevTools para encontrar códigos não usados nos scripts. Ao reduzir o tamanho dos recursos necessários durante a inicialização, você garante que as páginas passem menos tempo analisando e compilando códigos, o que proporciona uma experiência inicial mais tranquila ao usuário.
- Use a divisão de código para criar um pacote separado para códigos não necessários para a renderização inicial, mas que ainda será usado posteriormente.
- Se você usa um gerenciador de tags, otimizar suas tags periodicamente. As tags mais antigas com código não utilizado podem ser removidas para reduzir o impacto do Gerenciador de tags no JavaScript.
3. Evite atualizações de renderização grandes
A execução do JavaScript é apenas uma coisa que afeta a capacidade de resposta do seu site. A renderização é um tipo de trabalho caro em si e, durante grandes atualizações de renderização, seu site pode responder ainda mais lentamente às interações do usuário.
Otimizar o trabalho de renderização não é um processo simples e depende do que você está tentando alcançar. Mesmo assim, veja o que você pode fazer para garantir que as tarefas de renderização não se tornem longas:
- Reorganize as leituras e gravações do DOM no código JavaScript para evitar o layout forçado e a a troca frequente de layouts.
- Mantenha os tamanhos do DOM pequenos. O tamanho do DOM e a intensidade do trabalho de layout estão correlacionados. Quando o renderizador precisa atualizar o layout de um DOM muito grande, o trabalho necessário para recalcular o layout pode aumentar significativamente.
- Use a contenção do CSS para renderizar de maneira lenta o conteúdo do DOM fora da tela. Isso nem sempre é simples, mas isolar áreas com layouts complexos evita trabalhos desnecessários de layout e renderização.
Maior exibição de conteúdo (LCP)
O Largest Contentful Paint (LCP) é a Core Web Vital com que os desenvolvedores têm mais dificuldade. 40% dos sites no Relatório de UX do Chrome não atendem ao limite recomendado de LCP para uma boa experiência do usuário. A equipe do Chrome recomenda as técnicas a seguir como as maneiras mais eficazes de melhorar o LCP.
1. Garanta que o recurso LCP seja detectável na origem HTML e priorizado
A equipe do Chrome notou o seguinte em relação ao LCP na Web:
- De acordo com o Almanaque da Web de 2022 do HTTP Archive, 72% das páginas para dispositivos móveis têm uma imagem como elemento LCP.
- Uma análise de dados de usuários reais do Chrome mostra que a maioria das origens com LCP ruim gasta menos de 10% do tempo de LCP p75 fazendo o download da imagem de LCP.
- Entre as páginas com LCP ruim, o carregamento das imagens de LCP tem um atraso de 1.290 milissegundos no cliente no percentil 75, o que é mais da metade do orçamento para uma experiência rápida.
- Das páginas em que o elemento LCP era uma imagem, 39% delas tinham URLs de origem que não eram detectáveis na resposta HTML inicial (como
<img src="...">
ou<link rel="preload" href="...">
), o que permitiria que o scanner de pré-carregamento do navegador as detectasse o mais rápido possível. - De acordo com o Web Almanac, apenas 0,03% das páginas qualificadas usavam o atributo HTML
fetchpriority
para dar mais prioridade aos recursos, incluindo aqueles que poderiam melhorar a LCP de uma página com relativamente pouco esforço.
Essas estatísticas mostram que os desenvolvedores têm uma grande oportunidade de reduzir o atraso no carregamento de recursos e a duração do carregamento de recursos para imagens de LCP.
Quando o atraso no carregamento de recursos é o problema, é importante lembrar que pode ser tarde demais para alcançar um bom LCP se uma página precisar esperar que o CSS ou o JavaScript sejam totalmente carregados antes que as imagens comecem a carregar. Além disso, a duração do carregamento de recursos de uma imagem de LCP pode ser reduzida priorizando-a para que ela receba mais largura de banda e carregue mais rapidamente usando o atributo HTML fetchpriority
.
Se o elemento LCP for uma imagem, o URL dela precisa ser detectável na resposta HTML para reduzir o atraso no carregamento de recursos. Confira algumas dicas para fazer isso:
- Carregue a imagem usando um elemento
<img>
com o atributosrc
ousrcset
. Não use atributos não padrão, comodata-src
, que exigem JavaScript para a renderização, porque eles sempre são mais lentos. 9% das páginas ocultam a imagem da LCP atrás dedata-src
. - Prefira a renderização do lado do servidor (SSR) em vez da renderização do lado do cliente (CSR), já que a SSR implica que a marcação completa da página (incluindo a imagem) está presente na origem do HTML. As soluções CSR exigem que o JavaScript seja executado antes que a imagem possa ser descoberta.
- Se a imagem precisar ser referenciada em um arquivo CSS ou JS externo, ainda será possível incluí-la na origem HTML usando uma tag
<link rel="preload">
. As imagens referenciadas por estilos inline não são detectáveis pelo scanner de pré-carregamento do navegador. Portanto, mesmo que sejam encontradas na origem HTML, a detecção delas ainda pode ser bloqueada no carregamento de outros recursos. O pré-carregamento pode ajudar nesses casos.
Além disso, é possível reduzir a duração do carregamento de um recurso garantindo que o recurso LCP seja carregado antecipadamente e em alta prioridade:
- Adicione o atributo
fetchpriority="high"
à tag<img>
ou<link rel="preload">
da imagem do LCP. Isso aumenta a prioridade do recurso de imagem para que ele comece a ser carregado antes. - Remova o atributo
loading="lazy"
da tag<img>
da imagem do LCP. Isso evita o atraso de carregamento causado pela confirmação de que a imagem aparece na viewport ou perto dela. - Adie recursos não críticos quando possível. Mover esses recursos para o final do documento, carregar imagens de forma lenta ou iframes ou carregá-los de forma assíncrona usando JavaScript vai ajudar a abrir caminho para que recursos mais importantes, como a imagem do LCP, sejam carregados mais rapidamente.
2. Tenha como objetivo navegações instantâneas
A experiência ideal do usuário é nunca ter que esperar o carregamento de uma página. As otimizações de LCP, como a capacidade de descoberta e priorização de recursos, são eficazes para reduzir o tempo que um usuário espera para que o elemento LCP seja carregado e renderizado. No entanto, há um limite físico para a rapidez com que esses bytes são carregados pela rede e renderizados em uma página. Antes de chegar a esse limite, é necessário um esforço proibitivamente alto para reduzir apenas alguns milissegundos. Portanto, para conseguir navegações instantâneas, precisamos adotar uma abordagem radicalmente diferente.
As navegações instantâneas tentam carregar e renderizar a página antes de o usuário começar a navegar até ela. Dessa forma, a página pré-renderizada pode ser mostrada imediatamente com uma LCP próxima de zero. Restaurações e especulações são duas maneiras de fazer isso. Quando um usuário volta ou avança para uma página visitada anteriormente, ela pode ser restaurada rapidamente do cache na memória, aparecendo exatamente como o usuário a deixou. Como alternativa, os aplicativos da Web podem tentar prever para onde um usuário vai em seguida. Quando estiver correto, a próxima página já terá sido carregada e renderizada quando o usuário navegar até ela.
O cache de avanço e retorno (bfcache) permite restaurar páginas visitadas anteriormente. Para usá-lo, verifique se as páginas atendem aos critérios de qualificação do bfcache. Os motivos mais comuns para as páginas não se qualificarem para o bfcache são a veiculação de diretivas de armazenamento em cache no-store
ou os listeners de eventos unload
.
Restaurar páginas renderizadas melhora não apenas o desempenho de carregamento, mas também a estabilidade do layout. Saiba mais sobre o bfcache e como ele é eficaz para melhorar o CLS na seção Garantir que as páginas estejam qualificadas para o bfcache.
Compatibilidade com navegadores
A pré-renderização da próxima página que um usuário visita é outra maneira eficaz de melhorar drasticamente a performance do LCP, e isso é possível com a API Speculation Rules. No entanto, para conseguir esses ganhos, verifique se as páginas corretas são renderizadas previamente. Especulações incorretas desperdiçam recursos no servidor e no cliente, o que pode prejudicar o desempenho. Portanto, quanto menos confiante você estiver em relação à próxima página, mais conservador será o processo de pré-renderização. Em caso de dúvida, seus dados de análise podem dar a você a confiança para pré-renderizar mais prontamente as páginas com maior probabilidade de serem acessadas na próxima vez.
3. Usar um CDN para otimizar o TTFB
A recomendação anterior tinha como foco as navegações instantâneas, que oferecem a melhor experiência possível aos usuários, mas pode haver situações em que as técnicas de bfcache e de carregamento especulativo não são aplicáveis. Considere um usuário que segue um link entre origens para seu site em que a resposta inicial do documento HTML bloqueia efetivamente a LCP. O navegador não pode começar a carregar nenhum subrecurso até receber o primeiro byte da resposta. Quanto mais cedo isso acontecer, mais cedo tudo vai começar a acontecer.
Esse tempo é conhecido como Tempo para o primeiro byte (TTFB, na sigla em inglês). As melhores maneiras de reduzir o TTFB são:
- Exiba seu conteúdo o mais perto possível dos usuários geograficamente.
- Armazene esse conteúdo em cache para que ele possa ser exibido rapidamente se for solicitado novamente em breve.
A melhor maneira de fazer isso é usando uma CDN. As CDNs distribuem seus recursos para servidores de borda em todo o mundo, limitando a distância que esses recursos precisam percorrer para chegar aos usuários. As CDNs também costumam ter controles refinados de armazenamento em cache que podem ser ajustados às necessidades do site.
Os CDNs também podem armazenar e armazenar em cache documentos HTML, mas, de acordo com o Web Almanac, apenas 29% das solicitações de documentos HTML foram atendidas por um CDN. Isso significa que há uma oportunidade significativa para os sites economizarem mais.
Estas são algumas dicas para configurar CDNs:
- Armazene em cache documentos HTML estáticos, mesmo por um curto período. Por exemplo, é importante que o conteúdo seja sempre atualizado? Ou pode ficar alguns minutos desatualizados?
- Verifique se é possível mover a lógica dinâmica em execução no servidor de origem para a borda, que é um recurso da maioria das CDNs modernas.
Sempre que você puder veicular conteúdo diretamente da borda e evitar uma viagem ao servidor de origem, vai ganhar desempenho. Mesmo nos casos em que você precisa fazer a jornada até a origem, as CDNs geralmente são otimizadas para fazer isso mais rapidamente.
Cumulative Layout Shift (CLS)
O Cumulative Layout Shift (CLS) é uma medida da estabilidade visual de uma página da Web. Embora a CLS seja a métrica em que a maioria dos sites costuma se sair bem, cerca de um quarto deles ainda não atende ao limite recomendado. Portanto, ainda há uma grande oportunidade para muitos sites melhorarem a experiência do usuário.
1. Definir tamanhos explícitos em qualquer conteúdo carregado da página
As mudanças de layout geralmente acontecem quando o conteúdo existente é movido depois que outro conteúdo termina de carregar. A principal maneira de melhorar a CLS é reservar o espaço necessário com antecedência o máximo possível.
A melhor maneira de corrigir mudanças de layout causadas por imagens sem tamanho é definir explicitamente os atributos width
e height
ou as propriedades CSS equivalentes. 72% das páginas têm pelo menos uma imagem sem tamanho. Sem um tamanho explícito, essas imagens têm uma altura inicial de 0px
, o que pode causar mudanças no layout quando elas são carregadas e o navegador descobre as dimensões. Isso representa uma grande oportunidade para a Web coletiva, e essa oportunidade exige menos esforço do que algumas das outras recomendações sugeridas neste guia.
As imagens não são os únicos fatores que contribuem para o CLS. As mudanças de layout podem ser causadas por outro conteúdo que normalmente é carregado após a renderização inicial da página, incluindo anúncios de terceiros ou vídeos incorporados. A propriedade aspect-ratio
pode ajudar. É um recurso CSS de referência amplamente disponível que permite aos desenvolvedores definir explicitamente uma proporção em imagens e elementos que não são imagens. Isso permite definir um width
dinâmico (por exemplo, com base no tamanho da tela) e fazer com que o navegador calcule automaticamente a altura adequada, da mesma forma que faz para imagens com dimensões.
No entanto, nem sempre é possível saber o tamanho exato do conteúdo dinâmico. Mesmo que você não saiba o tamanho exato, ainda é possível reduzir a gravidade das mudanças de layout. Definir um min-height
razoável é quase sempre melhor do que permitir que o navegador use a altura padrão de 0px
para um elemento vazio. Usar uma min-height
também costuma ser uma correção simples, já que ela ainda permite que o contêiner cresça até a altura do conteúdo final, se necessário. Ela apenas reduziu essa quantidade de crescimento a um nível mais tolerável.
2. Garantir que as páginas estejam qualificadas para o bfcache
Como mencionado anteriormente neste guia, o cache de avanço e retorno (bfcache) carrega instantaneamente uma página anterior ou posterior no histórico do navegador usando um snapshot de memória. Embora o bfcache seja uma otimização significativa de desempenho no nível do navegador que melhora a LCP, ele também elimina totalmente as mudanças de layout. Na verdade, a introdução do bfcache em 2022 foi responsável pela maior melhoria na CLS que observamos naquele ano.
Apesar disso, um número significativo de sites não estão qualificados para o bfcache e, portanto, não estão aproveitando essa vantagem de desempenho da Web sem custo. A menos que a página esteja carregando informações sensíveis que você não quer que sejam restauradas da memória, verifique se ela está qualificada para usar o bfcache.
Os proprietários de sites precisam verificar se as páginas estão qualificadas para o bfcache e corrigir os motivos de não estarem. O Chrome tem um teste de bfcache no DevTools, e você também pode usar a API Not Restored Reasons para detectar motivos de inelegibilidade no campo.
3. Evite animações e transições que usam propriedades CSS que induzem o layout
Outra fonte comum de mudanças de layout é quando os elementos são animados. Por exemplo, banners de cookies ou outros banners de notificação que deslizam de cima para baixo ou de baixo para cima geralmente contribuem para a CLS. Isso é particularmente problemático quando esses banners empurram outros conteúdos para fora do caminho, mas mesmo quando não o fazem, a animação deles ainda pode afetar o CLS.
Embora os dados do HTTP Archive não conectem conclusivamente as animações às mudanças de layout, eles mostram que as páginas que animam qualquer propriedade CSS que pode afetar o layout têm 15% menos probabilidade de ter um CLS "bom" do que as páginas em geral. Algumas propriedades têm uma CLS pior do que outras. Por exemplo, as páginas que animam as larguras margin
ou border
têm CLS "ruim" quase duas vezes mais do que as páginas em geral são avaliadas como ruins.
Isso talvez não seja surpreendente, porque sempre que você faz a transição ou anima qualquer propriedade CSS que induz o layout, isso resulta em mudanças de layout. Se essas mudanças de layout não ocorrerem em 500 milissegundos após uma interação do usuário, elas vão afetar a CLS.
O que pode surpreender alguns desenvolvedores é que isso é verdade mesmo nos casos em que o elemento é levado para fora do fluxo normal do documento. Por exemplo, elementos posicionados de forma absoluta que animam top
ou left
causam mudanças no layout, mesmo que não estejam empurrando outro conteúdo. No entanto, se, em vez de animar top
ou left
, você animar transform:translateX()
ou transform:translateY()
, o navegador não vai atualizar o layout da página, evitando mudanças no layout.
Há muito tempo, a preferência pela animação de propriedades CSS que podem ser atualizadas na linha de execução de composição do navegador é uma prática recomendada de desempenho, porque move esse trabalho do thread principal para a GPU. Além de ser uma prática recomendada de desempenho geral, ela também pode ajudar a melhorar a CLS.
Como regra geral, nunca anime ou faça a transição de propriedades CSS que exijam que o navegador atualize o layout da página, a menos que você faça isso em resposta a um toque do usuário ou ao pressionamento de uma tecla (mas não hover
). Sempre que possível, prefira transições e animações usando a propriedade CSS transform
.
A auditoria do Lighthouse Evitar animações não compostas avisa quando a animação de propriedades CSS potencialmente lentas em uma página.
Conclusão
Melhorar a performance da página pode parecer assustador, especialmente porque há muitas orientações na Web para considerar. No entanto, ao se concentrar nesta lista curta das práticas recomendadas mais eficazes, você pode abordar o problema com um foco renovado e, com sorte, melhorar os Core Web Vitals do seu site.
Se quiser ir além das otimizações listadas aqui, leia estes guias para mais informações:
Apêndice: registro de alterações
As principais alterações feitas neste documento serão rastreadas aqui para ajudar a explicar quando e por que as principais recomendações foram alteradas.
Outubro de 2024
Atualização de 2024:
- INP
- Mudamos essa métrica de FID para INP de acordo com o lançamento da INP como uma métrica Core Web Vital e a tornamos a principal métrica da lista.
- Revertemos nossa recomendação de usar a API
isInputPending
como parte da divisão de tarefas longas. Saiba mais sobre nosso raciocínio no artigo Otimizar tarefas longas.
- LCP
- Combinamos as recomendações de descoberta e priorização em uma.
- Adicionamos uma nova recomendação para oferecer navegações instantâneas.
Janeiro de 2023
Esta é a lista inicial de recomendações:
- LCP
- Verifique se o recurso de LCP é detectável na origem HTML
- Priorizar o recurso LCP
- Usar uma CDN para otimizar o TTFB de documentos e recursos
- CLS
- Definir tamanhos explícitos em qualquer conteúdo carregado da página
- Garantir que as páginas estejam qualificadas para o bfcache
- Evite animações e transições que usam propriedades CSS que induzem o layout
- FID
- Evite ou divida tarefas longas
- Evitar JavaScript desnecessário
- Evite atualizações de renderização grandes
Você também pode assistir esta apresentação do Google I/O 2023 para conferir um resumo em vídeo.