Recursos que bloqueiam a renderização: o que bloqueia mesmo, e porque o async não é a solução

  • vuetelemetry
  • Guias
  • 8 min de leitura

O Lighthouse nomeia a auditoria e lista os ficheiros. Não explica que um script sem atributo para o analisador de imediato, que o async continua a bloquear a renderização ao executar, nem que o CSS bloqueia por uma razão totalmente diferente.

«Eliminar os recursos que bloqueiam a renderização» é a auditoria mais frequente de um relatório do Lighthouse, e a menos explicada. Nomeia os ficheiros e fica por aí. Por trás dessa única linha escondem-se dois mecanismos diferentes, que exigem correções diferentes.

Os scripts: o que faz mesmo cada atributo

Pessoas em fila junto a um passeio, vistas de cima, com marcações rodoviárias no alcatrão ao lado. Um script que bloqueia faz o mesmo ao analisador: tudo o que vem atrás espera, por ordem, que o da frente termine.
Pessoas em fila junto a um passeio, vistas de cima, com marcações rodoviárias no alcatrão ao lado. Um script que bloqueia faz o mesmo ao analisador: tudo o que vem atrás espera, por ordem, que o da frente termine.

**Um script clássico sem atributo para o analisador.** A MDN di-lo sem rodeios: os scripts sem `async`, `defer` ou `type="module"` são *«obtidos e executados imediatamente, antes de o navegador continuar a analisar a página»*. O navegador está a construir o seu documento, encontra a etiqueta e para: descarregar, executar, e só depois seguir. Tudo o que está abaixo espera.

**O `defer` é a resposta na maioria dos casos.** O atributo indica que o script *«deve ser executado depois de o documento ter sido analisado, mas antes de disparar o DOMContentLoaded»*. A análise continua sem interrupção, e os scripts diferidos *«executam pela ordem em que aparecem no documento»*: um script que depende de outro continua a obtê-lo.

**O `async` é o que se usa mal.** É obtido *«em paralelo com a análise e avaliado assim que estiver disponível»*, o que soa estritamente melhor. O que se omite é a frase logo a seguir: *«assim que o descarregamento estiver completo, o script executa, o que impede a página de ser renderizada»*.

Portanto o async elimina o bloqueio durante o **descarregamento**, não durante a **execução**. Um script grande carregado com async chega quando chega, a meio da análise, e bloqueia a renderização nesse momento. E como a ordem de execução segue a de chegada, a MDN avisa que não há *«qualquer garantia de que os scripts corram numa ordem específica»*, o que parte tudo o que tenha dependências.

A regra curta: **defer para os seus próprios scripts, async só para terceiros verdadeiramente independentes**, como um sinalizador de analítica que não fala com ninguém.

O CSS bloqueia por outra razão

**O CSS bloqueia por outra razão, e a correção não é um atributo.** Uma folha de estilos não para o analisador de HTML, mas o navegador não pinta enquanto não tiver o CSS de que precisa, porque pintar primeiro e reestilizar depois mostraria um clarão de conteúdo sem estilo. É um bloqueio da renderização, não da análise.

  • Sem atributo: obtido e executado de imediato, a análise para
  • defer: executa após a análise, pela ordem do documento, antes do DOMContentLoaded
  • async: sem bloqueio no descarregamento, mas a execução bloqueia a renderização, e a ordem não é garantida
  • CSS: não bloqueia a análise, bloqueia a pintura - limite o âmbito com media
  • As etiquetas de terceiros são normalmente a maior fatia da auditoria

Aqui a alavanca é o âmbito, não o momento. Uma folha que só se aplica a um contexto pode levar um atributo `media`, e o navegador obtê-la-á sem a deixar bloquear a primeira pintura - `media="print"` é o caso conhecido. Resta o CSS de que o primeiro ecrã precisa mesmo, e é esse que vale a pena manter pequeno.

Aqui a alavanca é o âmbito, não o momento. Uma folha que só se aplica a um contexto pode levar um atributo `media`, e o navegador obtê-la-á sem a deixar bloquear a primeira pintura - `media="print"` é o caso conhecido. Resta o CSS de que o primeiro ecrã precisa mesmo, e é esse que vale a pena manter pequeno.

- vuetelemetry

Onde está o peso, e como confirmá-lo

**As etiquetas de terceiros costumam ser o peso real.** O seu próprio bundle está à vista e acaba otimizado; o gestor de etiquetas, o widget de conversa e o banner de consentimento chegam como scripts que não escreveu, muitas vezes a carregar outros por sua conta. Auditar o que custam de facto - e se cada um o merece - move o número muito mais do que raspar kilobytes ao seu código.

**E depois meça no campo, não no relatório.** O Lighthouse diz-lhe que um recurso bloqueava a renderização; não lhe diz se retirá-lo mudou alguma coisa para os seus visitantes. Essa diferença entre uma auditoria de laboratório e utilizadores reais é [um assunto à parte](/pt/articles/dados-de-campo-vs-dados-de-laboratorio), e é ela que decide se o trabalho valeu a pena.

FAQ

O que significa «eliminar os recursos que bloqueiam a renderização»?

É uma auditoria do Lighthouse que lista scripts e folhas de estilo que atrasam a primeira pintura. Por trás há dois mecanismos distintos: um script clássico sem atributo para por completo o analisador de HTML, ao passo que uma folha de estilos deixa a análise continuar mas impede a pintura até estar carregada. Exigem correções diferentes, e por isso a auditoria sozinha não chega para agir.

Devo usar async ou defer?

defer para os seus próprios scripts, async só para terceiros verdadeiramente independentes. O defer executa depois da análise, pela ordem do documento, pelo que as dependências continuam a funcionar. O async executa assim que o descarregamento termina, o que bloqueia a renderização nesse instante, e a MDN avisa que não há garantia quanto à ordem de execução.

O async torna um script não bloqueante?

Não inteiramente, e é a leitura errada mais comum. O async elimina o bloqueio durante o descarregamento: o script é obtido em paralelo com a análise. Mas a MDN indica que, concluído o descarregamento, o script executa e essa execução impede a página de ser renderizada. Um script async grande limita-se a bloquear num momento imprevisível em vez de um previsível.

Porque é que o CSS bloqueia a renderização?

Porque pintar antes de a folha de estilos chegar mostraria conteúdo sem estilo, que teria de ser refeito. Por isso o navegador espera. Ao contrário de um script, o CSS não para o analisador de HTML: para a pintura. A correção não é um atributo mas o âmbito - uma folha limitada por um atributo media é obtida sem reter a primeira pintura.

Como sei se a correção ajudou?

Não pelo relatório do Lighthouse, que só lhe diz que um recurso bloqueava a renderização. Se a alteração chegou aos seus visitantes vê-se nos dados de campo, no percentil 75 sobre 28 dias. Uma auditoria de laboratório identifica o candidato; só o campo confirma o resultado.

Stack relacionado