Performance

Site lento por JavaScript: como identificar e reduzir o peso

Imagens e fontes carregam-se otimizam-se com plugins. JavaScript, não. JavaScript é o problema que sobra depois de tudo o resto resolvido, e em 2026 é o maior responsável por sites lentos em mobile, scores baixos no PageSpeed, e INP acima de 200ms.

Este guia ataca o problema: como descobrir o que está a pesar, como reduzir sem partir funcionalidade, e como evitar que volte a crescer.

Porque é que o JavaScript dói mais do que as imagens

Uma imagem pesada custa bandwidth, demora a descarregar. Mas depois de descarregada, não pesa mais.

JavaScript custa três coisas:

  1. Descarga, bytes a transferir.
  2. Parse + compile, o navegador tem de interpretar e converter em código executável (custa CPU).
  3. Execução, corre. Bloqueia a main thread. Atrasa interação.

Em telemóveis de gama média (Android 200-400€, que é o que a maioria dos clientes em Portugal usa), 500 KB de JavaScript pode demorar 3-5 segundos a parse+execute. A página visualmente "está lá" mas não responde a clicks. É exatamente isso que o Google mede em INP.

Diagnosticar: as 3 ferramentas que importam

PageSpeed Insights, o resumo

Vai a pagespeed.web.dev com o teu URL. Procura especificamente:

  • "Reduce unused JavaScript", quanto código foste obrigado a descarregar e nunca foi executado.
  • "Eliminate render-blocking resources", scripts no <head> sem defer/async.
  • "Minimize main-thread work", quanto tempo a CPU passou só com JavaScript.
  • "Reduce JavaScript execution time", o que executou e quanto demorou.

Se algum destes ultrapassa 1.5s em mobile, tens problema sério. Detalhe completo no guia do PageSpeed Insights.

Chrome DevTools → Coverage

Abre o teu site no Chrome. F12 → Cmd+Shift+P → "Show Coverage". Recarrega. Para cada ficheiro JS verás quanto código foi carregado vs quanto foi realmente executado. Razão típica em sites de PME: 70-90% de JS não usado.

Chrome DevTools → Performance

Grava 5 segundos de carregamento. Procura as "Long Tasks" (tarefas >50ms) na main thread. Cada uma é um momento em que o utilizador clicou e nada aconteceu. Identifica que script as causa.

Os 7 culpados mais comuns

Em centenas de auditorias a sites WordPress de PME portuguesa, os mesmos suspeitos voltam:

  1. Google Tag Manager mal configurado, carrega 30 tags em vez das 5 necessárias.
  2. Plugins de slider (Revolution Slider, Smart Slider), 200-500 KB por slider, mesmo onde não há slider.
  3. Plugins de chat (Tawk, Tidio, Crisp), carregam síncronos no head.
  4. Page builders (Elementor, WPBakery), JS para animações que ninguém pediu.
  5. Form builders pesados (WPForms premium, Gravity Forms com 12 add-ons).
  6. Bibliotecas duplicadas, tema carrega jQuery 1.x, plugin carrega jQuery 3.x.
  7. Tracking scripts sem consentimento gated (Meta Pixel, Hotjar, Clarity) a competir por main thread.

A boa notícia: identificar cada um leva 5 minutos com Chrome DevTools. Cortar cada um vale 100-500ms.

Defer vs async vs nada

Por defeito, um <script src="..."> no HTML bloqueia o navegador, pára de renderizar até descarregar e executar. Os atributos resolvem isso:

<!-- Bloqueia. Evitar. -->
<script src="grande.js"></script>

<!-- Descarrega em paralelo, executa logo que descarregado (pode interromper) -->
<script src="analytics.js" async></script>

<!-- Descarrega em paralelo, executa só depois do HTML pronto -->
<script src="ui.js" defer></script>

Regras práticas:

  • defer para scripts da página (UI, formulários). Mantém ordem de execução.
  • async para scripts independentes que não dependem nem afetam o resto (analytics, pixels).
  • Sem atributo só para scripts realmente críticos acima da dobra (raríssimo).

Em WordPress, plugins como Autoptimize ou Async JavaScript automatizam isto. Em Next.js, a tag <Script> tem strategy="afterInteractive" ou "lazyOnload".

Tag Manager: o assassino silencioso

Google Tag Manager é prático, mas vira pesadelo rápido. Cada tag adicional é JavaScript de terceiros a competir por main thread.

Auditoria mínima a fazer uma vez por trimestre:

  1. Abre o GTM. Lista todas as tags ativas.
  2. Para cada uma, pergunta: ainda usamos esta? Há quanto tempo?
  3. Apaga as inativas/desconhecidas. A maioria das contas tem 40% de tags mortas.
  4. Verifica triggers, tags a disparar em "All Pages" quando deviam estar em páginas específicas.
  5. Move o GTM para gated por consentimento de cookies (RGPD + performance).

Resultado típico: GTM passa de 250 KB de overhead para 80 KB. INP cai 100ms.

Plugins WordPress: matar primeiro, fazer cocó depois

Métrica simples: cada plugin ativo custa, em média, 30-80 ms de TTFB e 20-150 KB de JS/CSS frontend. Multiplica por 25 plugins (típico) e tens 1-2 segundos de custo.

Tratamento:

  • Listar todos os plugins. Para cada um, classificar: essencial / útil / esquecido.
  • Desativar os esquecidos. Se não notas nada 7 dias, apaga.
  • Substituir os pesados por leves. Slider Revolution → Swiper.js direto (10x mais leve). Contact Form 7 com add-ons → WPForms Lite ou um custom.
  • Lazy load de scripts não-críticos com plugin como FlyingScripts.

Lazy load de JavaScript de terceiros

Scripts como chat widgets, mapas embedded, players de vídeo, podem esperar pela primeira interação:

// Pseudo-código: carrega o chat só depois do utilizador interagir
['scroll', 'mousemove', 'touchstart'].forEach(e =>
  document.addEventListener(e, loadChat, { once: true })
);

Plugins WordPress como FlyingScripts ou Perfmatters fazem isto sem código. Resultado: o LCP cai imediatamente, e o chat continua a aparecer quando o utilizador interage.

Code splitting (para sites custom)

Para Next.js, React, ou framework moderno, o code splitting acontece automaticamente, cada página carrega só o JS dessa rota. Mas há erros comuns:

  • Importar bibliotecas pesadas no _app.tsx (vai para todas as páginas).
  • Usar import em vez de dynamic import para módulos só usados em modais.
  • Não tree-shake bibliotecas (importar lodash inteiro em vez de lodash/get).

next/dynamic resolve estes em 5 minutos.

Métricas-alvo realistas

Para PME portuguesa típica em 2026:

MétricaBomAceitávelMau
Total JS (transfer)< 200 KB200-400 KB> 400 KB
Tempo execução JS (mobile)< 1s1-2s> 2s
Long tasks0-23-5> 5
INP (p75)< 200 ms200-500 ms> 500 ms

Sites WordPress com Elementor + 5 plugins de marketing tendem a ficar na coluna "mau" sem esforço. Sites custom bem feitos ficam no "bom" sem esforço.

O que NÃO fazer

  • Minificar não é otimização. Reduz ~20% de bytes mas não muda parse+execute. Faz-se mas não conta como solução.
  • Não acreditar em plugin de "cache" mágico. Cache HTML serve a página pronta, não reduz JS no browser do utilizador.
  • Não substituir GTM por "tags hardcoded no tema". Perdes controlo, ganhas marginalmente.
  • Não migrar para framework "rápido" sem identificar o problema. Se o problema é Elementor + 5 chat widgets, mudar para Next.js sem mudar o resto piora.

Service Workers, vale a pena?

Service Workers (a base das Progressive Web Apps) permitem cachear JS no browser para visitas repetidas. Para um site institucional, o ganho é marginal, utilizadores típicos visitam uma vez por mês.

Para lojas online com utilizadores que voltam várias vezes por semana, faz diferença: o JS principal já está em cache local na segunda visita, TTFB para "carregar a app" cai a 0ms.

Em WordPress, plugins como PWA for WP simplificam. Em Next.js, next-pwa cobre o caso. Para PME pequena, vai à frente das tuas necessidades. Para loja com 5.000 visitantes/mês, considera.

Métrica em campo vs em laboratório

Quando otimizas JS, há duas realidades:

  • Lab (Lighthouse, PageSpeed Insights), simula CPU 4x slower e rede 3G. Conservador. Bom para detetar regressões em PR.
  • Field (CrUX, RUM próprio), visitantes reais com hardware real. É o que o Google rankeia.

Diferenças típicas: Lab diz INP 350ms. Campo diz INP 220ms (utilizadores reais têm dispositivos médios variados, alguns em desktop). Não confundas: otimiza para Lab passar limites, mas valida em campo antes de declarar vitória.

O ciclo de auditoria recomendado

Para PME que quer manter performance ao longo do tempo, não basta otimizar uma vez. Recomendação:

  1. Mensal, verificar Search Console Core Web Vitals. Se grupo de páginas piorou, investigar.
  2. Trimestral, auditoria de plugins WordPress: o que se acrescentou? O que se pode tirar?
  3. Semestral, Tag Manager: lista de tags ativas, comparar com o que se está mesmo a usar.
  4. Anual, auditoria completa: PageSpeed em 5 páginas-chave, comparar com ano anterior.

Sem este ciclo, sites bem otimizados degradam-se em 12-18 meses. Plugins acumulam, tags adicionam-se, ninguém limpa.

Em resumo

JavaScript pesado é hoje a maior causa de sites lentos em mobile e de INP fora dos limites. O problema é cumulativo: GTM com tags mortas, plugins esquecidos, sliders gigantes, chats síncronos, bibliotecas duplicadas. Diagnostica com PageSpeed Insights + Chrome DevTools Coverage (vais ver 70-90% de código não usado). Ataca em camadas: defer/async no que sobra, lazy load em scripts de terceiros, auditoria trimestral do Tag Manager, e substituição de plugins pesados por alternativas leves. Alvo realista para PME: <200 KB de JS, <1s de execução em mobile, INP <200ms. Maioria dos sites lá chega com 4-8 horas de trabalho, não com refactor de meses.


No sitesfixe.pt entregamos sites com JS auditado por defeito, defer/async corretos, sem bibliotecas duplicadas, com tracking gated por consentimento. Se o teu site WordPress tem INP acima de 500ms e ninguém sabe porquê, fala connosco. Sites desde 1.500€.

Lê também:

Fontes

Precisas de um site ou loja online?

Agência digital em Portugal. Sites e lojas online rápidos, otimizados para o Google e feitos para destacar a tua empresa e vender mais.

Pedir orçamento

Ver todos os artigos de Performance

A agência digital que o teu negócio procurava. Sites e lojas online para mais presença, mais contactos e menos improviso.