Como otimizar JavaScript, CSS e HTML para melhorar o tempo de carregamento
Para melhorar LCP, INP e TTFB, foque em: menos bytes, menos blocos na renderização e menos trabalho no main thread. Abaixo, um guia prático com exemplos prontos para produção (e WordPress).Índice
- Metas e prioridades de rede
- JavaScript: reduzir, adiar e dividir
- CSS: critical, não-bloqueante e minificado
- HTML: entrega, hints e semântica
- Cache, compressão e entrega
- Scripts de terceiros sem travar a página
- WordPress: configurações seguras
- Testes, métricas e automação
- Checklist final
- FAQ
- Tags
1) Metas e prioridades de rede
| Métrica | Meta | Foco |
|---|---|---|
| LCP | < 2.5s | Imagem/hero + CSS crítico + TTFB baixo |
| INP | < 200ms | Menos JS, dividir bundles, remover trabalho síncrono |
| CLS | < 0.1 | Reservar dimensões de imagens/iframes, evitar injeções tardias |
Regra: carregue o essencial primeiro (HTML + CSS crítico + hero). O resto vai depois.
2) JavaScript: reduzir, adiar e dividir
- Remova dependências desnecessárias. Troque libs grandes por nativas.
- Divida bundles por rota/funcionalidade (code‑splitting).
- Carregue JS não crítico com
deferoutype="module". - Evite
document.write,alerte handlers pesados no carregamento.
Tags de script recomendadas
<!-- JS próprio crítico, mas não bloqueante -->
<script src="/js/app.min.js" defer></script>
<!-- Módulos ES com pré-carregamento -->
<link rel="modulepreload" href="/js/home.mjs">
<script type="module">
import init from '/js/home.mjs';
init();
</script>
<!-- Carregar terceiro só quando ocioso -->
<script>
'requestIdleCallback' in window
? requestIdleCallback(()=>import('/js/analytics.js'))
: setTimeout(()=>import('/js/analytics.js'), 2000);
</script>
Build rápido (esbuild)
# Empacotar + minificar + split
esbuild src/index.ts --bundle --minify --sourcemap --splitting --format=esm \
--outdir=public/js --target=es2019
# Gerar também um legado opcional (nomes hipotéticos)
esbuild src/legacy.ts --bundle --minify --outfile=public/js/legacy.js --target=es5
Evitar trabalho pesado no main thread
// Mova tarefas custosas para Web Worker
const worker = new Worker('/js/heavy.worker.js');
worker.postMessage({payload});
worker.onmessage = (e) => { render(e.data) };
3) CSS: critical, não-bloqueante e minificado
- Inline o CSS crítico para above‑the‑fold.
- Carregue o restante de forma não‑bloqueante.
- Remova CSS não utilizado de forma segura (testar em staging).
Padrão de critical CSS + load assíncrono
<!-- No <head> -->
<style>/* critical.css gerado por ferramenta */
html{scroll-behavior:smooth} header{min-height:56px} .hero{display:grid}
</style>
<!-- CSS restante de forma não-bloqueante -->
<link rel="preload" href="/css/styles.min.css" as="style">
<link href="/css/styles.min.css" rel="stylesheet" media="print" onload="this.media='all'">
<noscript><link rel="stylesheet" href="/css/styles.min.css"></noscript>
Purge + minificação (PostCSS/LightningCSS)
# Exemplo com LightningCSS (rápido e seguro)
npx lightningcss -m -o public/css/styles.min.css src/styles.css
Cuidado: “remover CSS não utilizado” pode quebrar componentes dinâmicos. Liste whitelists/safelist para classes geradas via JS.
4) HTML: entrega, hints e semântica
- Minifique HTML (sem remover espaços relevantes).
- Use resource hints:
preload,preconnect,dns-prefetch. - Garanta dimensões em imagens/iframes e
loading="lazy"para abaixo da dobra.
Hints de rede
<link rel="preconnect" href="https://cdn.exemplo.com" crossorigin>
<link rel="dns-prefetch" href="//cdn.exemplo.com">
<link rel="preload" as="image" href="/img/hero-960.avif" imagesrcset="/img/hero-480.avif 480w, /img/hero-960.avif 960w" imagesizes="(max-width:600px) 96vw, 960px">
Imagem com dimensões (evita CLS)
<img src="/img/card.webp" width="360" height="240" loading="lazy" alt="Exemplo">
5) Cache, compressão e entrega
- HTTP/2 ou HTTP/3 ativos no servidor/CDN.
- Compressão: Brotli (estático) > Gzip.
- Cache agressivo para assets versionados (hash no nome).
Nginx (Brotli + cache longo)
brotli on;
brotli_comp_level 6;
brotli_types text/html text/css application/javascript image/svg+xml;
gzip on;
gzip_types text/css application/javascript image/svg+xml;
location ~* \.(css|js|mjs|png|jpg|webp|avif|svg|woff2)$ {
add_header Cache-Control "public, max-age=31536000, immutable";
}
Apache (.htaccess) equivalente
<IfModule mod_brotli.c>AddOutputFilterByType BROTLI_COMPRESS text/html text/css application/javascript image/svg+xml</IfModule>
<IfModule mod_deflate.c>AddOutputFilterByType DEFLATE text/html text/css application/javascript image/svg+xml</IfModule>
<FilesMatch "\.(css|js|mjs|png|jpg|webp|avif|svg|woff2)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
6) Scripts de terceiros sem travar a página
- Carregue por consentimento (CMP) e sob demanda.
- Use Subresource Integrity (SRI) e
crossoriginquando for CDN. - Substitua widgets pesados por APIs + renderização sob demanda.
Exemplo de SRI
<script src="https://cdn.exemplo.com/lib.min.js"
integrity="sha384-BASE64AQUI..."
crossorigin="anonymous" defer></script>
7) WordPress: configurações seguras
- Um plugin de cache/otimização (LiteSpeed Cache, WP Rocket ou FlyingPress). Evite sobreposição.
- JS: ative defer para scripts próprios; teste “adiar JS” com lista de exclusões para scripts críticos de tema.
- CSS: gere critical CSS automático; carregue o restante de forma não‑bloqueante.
- Fontes: hospede localmente,
preloadda fonte principal efont-display: swap. - Limpeza: desative módulos/plugins que injetam JS/CSS em todas as páginas (ex.: sliders em páginas que não usam).
Functions.php — mover script para footer e adicionar defer
<?php
function tema_scripts() {
wp_enqueue_script('app', get_stylesheet_directory_uri().'/js/app.min.js', [], '1.0', true); // true = footer
}
add_action('wp_enqueue_scripts','tema_scripts');
// Adicionar defer globalmente (com cuidado e exceções)
function add_defer_to_scripts($tag, $handle) {
$defer = ['app','galeria','loja']; // handles que podem receber defer
if (in_array($handle, $defer)) {
return str_replace(' src', ' defer src', $tag);
}
return $tag;
}
add_filter('script_loader_tag','add_defer_to_scripts',10,2);
?>
8) Testes, métricas e automação
- PageSpeed Insights (dados de campo e laboratório) para cada template chave.
- WebPageTest (4G/CPU limitada) para ver waterfall e bloqueios.
- CrUX/GSC para monitorar CWV reais ao longo do tempo.
- CI/CD: quebre o build se o bundle JS > X KB ou se LCP simulado > Y s.
Auditoria rápida com cURL
# Ver headers úteis
curl -sI https://www.seusite.com.br/ | grep -Ei "HTTP/|content-encoding|cache-control|server|link|age"
# Ver cadeia de redirecionamentos
curl -s -I -L https://www.seusite.com.br/ | grep -i "^location"
# Tamanho dos bundles
curl -s https://www.seusite.com.br/js/app.min.js | wc -c
9) Checklist final
- JS mínimo, dividido por rota, carregado com
deferoutype="module". - CSS crítico inline + restante não‑bloqueante; dimensões reservadas.
- HTML minificado, hints de
preload/preconnectconfigurados. - Assets versionados com cache
immutable+ Brotli ativo. - Scripts de terceiros sob consentimento e carregamento tardio.
- Sem cadeias de 301; HTTP/2 ou HTTP/3 habilitado.
- Monitoramento contínuo de LCP/INP/CLS em dados de campo.
FAQ
1) Devo usar async ou defer?
defer para scripts que dependem da ordem e do DOM; async para scripts independentes (ex.: anúncios). type="module" já é defer‑like.
2) Critical CSS sempre ajuda?
Quase sempre. Ele acelera o first render. Em sites muito pequenos, pode bastar um único CSS no head minificado.
3) Inline de CSS/JS prejudica cache?
Inline em excesso reduz cache entre páginas. Use inline só para o crítico; o restante fica em arquivos versionados.
4) Prefetch, preload e preconnect: qual usar?
preconnect abre conexões cedo; preload baixa o recurso essencial; prefetch prepara navegação futura.
5) Posso unir todos os JS num arquivo só no HTTP/2?
Empacotar demais pode piorar cache e INP. Prefira code‑split por rota e componentes críticos.
6) “Remover CSS não utilizado” é seguro?
Só com safelist e testes. Classes geradas dinamicamente podem desaparecer e quebrar a UI.
7) Como melhorar INP de forma prática?
Corte JS, delegue eventos, use idle callbacks, mova cálculos para Web Workers e evite long tasks (>50ms).
8) Fontes web pesam muito?
Sim. Subset, WOFF2, preload na principal e font-display: swap. Hospede localmente.
9) Posso carregar Analytics depois?
Sim. Carregue após interação ou ociosidade. Use gtag/GA4 com consent mode quando aplicável.
10) Otimizações valem para SPAs?
Sim. Considere SSR/SSG, islands e hidratação parcial para reduzir JS inicial.
Tags
JavaScript CSS HTML Core Web Vitals LCP INP CLS Preload Preconnect Brotli HTTP/3 WordPress Code‑splitting Critical CSS Minificação
“É necessário construir frases curtas. Toda otimização dividirá em, no mínimo, duas frases.”



