Skip to content

Tudo para WordPress, desenvolvimento web — e não só

⚡ Contact form 7 - carregamento diferido de scripts e estilos para acelerar o WordPress

⚡ Contact form 7 - carregamento diferido de scripts e estilos para acelerar o WordPress

Como o CF7 torna o seu site mais lento e porque pode resolver isso em 5 minutos

O Contact Form 7 está instalado em mais de 5 milhões de sites WordPress. O plugin é fiável, flexível e gratuito, e os formulários de contacto criados com ele funcionam em praticamente todos os sites. Mas esta conveniência tem um lado negativo: por predefinição, o CF7 carrega o seu CSS e JavaScript em todas as páginas do seu site, mesmo quando não há nenhum formulário por perto.

Para a página inicial, blogue, páginas de destino e dezenas de outras páginas, isto é peso morto: pedidos extra, aumento do DOM Content Loaded, tamanho de página inchado. Em números, cerca de 10 a 30 KB de tráfego comprimido e 1 a 2 pedidos bloqueantes sem motivo algum. O PageSpeed Insights não perdoa estas coisas.

Isto pode ser resolvido de três formas, desde um simples defer de duas linhas até ao carregamento condicional cuidadoso e «within the book» do criador do plugin. Vamos abordar cada uma, com código e sem palha.

💡 Visão geral rápida:

  • Desative o carregamento global do CF7 através das constantes WPCF7_LOAD_JS e WPCF7_LOAD_CSS no wp-config.php, o método oficial mais limpo.
  • Reative os scripts e estilos, mas apenas nas páginas com um formulário, através de wpcf7_enqueue_scripts() no modelo de página.
  • Para pacotes personalizados, o pacote lazy-cf7-assets, que encontra automaticamente o formulário na página e carrega o JS dinamicamente.

Método 1: adiar o carregamento do script do CF7 via functions.php

A opção mais rápida e simples é adicionar o atributo defer ao script do Contact Form 7. Isto diz ao navegador: «carrega o ficheiro em segundo plano, mas executa-o quando o DOM estiver pronto». O formulário continua a funcionar, mas o script deixa de bloquear a renderização da página.

Adicione este código ao functions.php no seu tema ativo (ou através do plugin Code Snippets, mais seguro durante as atualizações):

1if ( ! function_exists( 'add_defer_to_cf7' ) ) {
2 function add_defer_to_cf7( $url ) {
3 if (
4 false === strpos( $url, 'contact-form-7' ) ||
5 false === strpos( $url, '.js' )
6 ) {
7 return $url;
8 }
9 return "$url' defer='defer";
10 }
11 add_filter( 'clean_url', 'add_defer_to_cf7', 11, 1 );
12}

A função verifica o URL de cada script registado através do hook clean_url. Se o endereço contiver contact-form-7 e a extensão .js, adiciona defer='defer'. Todos os outros scripts são deixados como estão.

Vantagem: uma solução em 10 linhas que não requer a edição de modelos ou da configuração do plugin. Adequado para temas onde não existe um modelo de página de contacto separado.

Desvantagem: o script continua a carregar em todas as páginas, está apenas a remover o comportamento de bloqueio de renderização. O tráfego e os pedidos ao servidor não são reduzidos. Este método não afeta de todo o CSS do plugin, a folha de estilos carrega como habitualmente.

Método 2: método oficial, carregamento condicional através de constantes

Esta abordagem está descrita na documentação do Contact Form 7 pelo próprio criador do plugin, Takayuki Miyoshi. A ideia tem dois passos: primeiro, desative globalmente os scripts e estilos do CF7 e, depois, reative-os, mas apenas nas páginas onde o formulário é realmente utilizado.

Passo 1: desativar o carregamento em todas as páginas

Adicione duas constantes ao wp-config.php:

1define( 'WPCF7_LOAD_JS', false );
2define( 'WPCF7_LOAD_CSS', false );

Em alternativa, através do functions.php do seu tema:

1add_filter( 'wpcf7_load_js', '__return_false' );
2add_filter( 'wpcf7_load_css', '__return_false' );

Depois disto, o CF7 não carregará uma única linha do seu código em nenhuma página do seu site, incluindo aquelas onde existe um formulário. Sem scripts, o formulário perde a submissão por AJAX e a validação, pelo que o passo 2 é necessário.

Passo 2: restaurar os scripts nas páginas com um formulário

Suponhamos que a sua página de contacto usa o template page-contact.php na pasta do seu tema. Adicione isto a esse template antes de chamar wp_head():

1if ( function_exists( 'wpcf7_enqueue_scripts' ) ) {
2 wpcf7_enqueue_scripts();
3}
4
5if ( function_exists( 'wpcf7_enqueue_styles' ) ) {
6 wpcf7_enqueue_styles();
7}

As funções wpcf7_enqueue_scripts() e wpcf7_enqueue_styles() carregam manualmente os scripts e estilos do CF7 apenas neste template. Todas as outras páginas do seu site permanecem limpas.

Vantagem: o método é «do fabricante», garantido que não se parte durante as atualizações do plugin. Funciona com as versões 5.x e 6.x do CF7, versão atual 6.1.6 em junho de 2026 (lista de versões). Zero carregamentos desnecessários em páginas sem formulário.

Desvantagem: requer a edição dos templates do tema. Se tiver várias páginas com formulários, precisa de se lembrar de adicionar as chamadas a cada template. Se o formulário for inserido via shortcode no conteúdo (em vez de num template), o método não funcionará sem condições adicionais.

Método 3: o pacote lazy-cf7-assets para bundles de JavaScript

Se estiver a construir o seu frontend com um bundler (Webpack, Vite, esbuild) e a usar um tema moderno com um bundle de JavaScript personalizado, existe um pacote npm chamado lazy-cf7-assets. Ele resolve o mesmo problema, mas do lado do cliente: faz scan ao DOM, encontra o formulário do CF7 e só então carrega dinamicamente os scripts do plugin.

Instalação:

1npm install lazy-cf7-assets

Antes de o usar, precisa de desativar o carregamento automático de JS pelo plugin (como no método 2, via wpcf7_load_js):

1add_filter( 'wpcf7_load_js', '__return_false' );

Depois, no seu bundle de JS:

1import lazyform from 'lazy-cf7-assets';
2
3// Initialize after DOM ready
4lazyform.init();

Se os scripts carregarem no <head> em vez de no final do <body>, especifique um caminho absoluto para a imagem GIF de carregamento para que o formulário não «pisque» num estado vazio:

1lazyform.init({
2 gifPath: '/wp-content/themes/my-theme/images/ajax-loader.gif'
3});
Captura de ecrã do repositório lazy-cf7-assets no GitHub

Vantagem: zero intervenção no lado do PHP, sem necessidade de editar templates para cada página com formulário. O pacote deteta automaticamente se existe um shortcode do CF7 na página e carrega os scripts apenas nesse caso. Adequado para sites onde o formulário é apresentado via shortcode no conteúdo (em vez de estar hardcoded num template).

Desvantagem: funciona apenas com JavaScript (o CSS do plugin ainda precisa de ser desativado separadamente). Requer um bundler no projeto. O pacote é mínimo (1 estrela no GitHub), mantido por um único developer; para produção, deve fazer fork e verificar a compatibilidade com as atualizações do CF7.

O que escolher: comparação das três abordagens

Critério

defer via hook

Constantes + template

lazy-cf7-assets

Poupança de tráfego

❌ não

✅ total

✅ total (JS)

Proteção contra atualizações do CF7

✅ sim

✅ sim

requer verificação

Não requer edição de templates

✅ sim

❌ não

✅ sim

Desativa o CSS

❌ não

✅ sim

❌ não

Complexidade de implementação

baixa

média

média

Shortcode do formulário no conteúdo

✅ funciona

❌ dificuldades

✅ funciona

Se o seu formulário reside numa única página, num template separado, use o método 2 (método oficial). Se o site usa um bundler moderno e pode ter vários formulários em locais diferentes, o método 3 (lazy-cf7-assets). Se precisa de uma solução «para já» sem editar templates, o método 1 (defer), mas lembre-se das limitações.

Uma ressalva importante: após qualquer uma destas alterações, certifique-se de verificar que o formulário submete, a validação funciona, o reCAPTCHA não está partido e os estilos não se deslocaram. Abra a página com o formulário em modo anónimo, preencha e submeta uma mensagem de teste antes e depois.

⁉️🤔 Perguntas frequentes

Porque é que o CF7 carrega scripts em todas as páginas, de qualquer forma?

O plugin não sabe, na fase de carregamento do WordPress, se uma página específica contém um shortcode de formulário. O WordPress monta a página mais tarde, quando a fila de scripts já foi formada. O programador Takayuki Miyoshi explica isto na documentação oficial: é tecnicamente impossível detetar a presença de um shortcode antes do hook wp_head. Por isso, foi escolhida uma abordagem conservadora, de carregar sempre. Esta é uma decisão arquitetural deliberada, não um bug: o plugin sacrifica o desempenho em prol da funcionalidade garantida. O ónus da otimização é transferido para o programador do site.

O formulário vai deixar de funcionar depois de desativar o carregamento global?

Não, se reativar cuidadosamente os scripts nas páginas necessárias. O formulário perderá o envio por AJAX e a validação do lado do cliente apenas nas páginas onde os scripts não forem incluídos. É por isso que o passo 2 (restaurar os scripts) é obrigatório, não pare apenas em WPCF7_LOAD_JS = false. Verifique a ordem das chamadas: wpcf7_enqueue_scripts() deve vir antes de wp_head(), e não depois. E certifique-se de que o reCAPTCHA não entra em conflito com o carregamento diferido.

O método das constantes funciona com o CF7 6.x?

Sim, as constantes WPCF7_LOAD_JS e WPCF7_LOAD_CSS são totalmente suportadas na versão atual 6.1.6 (consulte o registo oficial de versões). Ao longo de toda a história do plugin, da versão 3.9 até à atual 6.x, estas constantes nunca foram declaradas como obsoletas. Este é o método mais estável e documentado para gerir o carregamento.

E se eu tiver vários formulários em locais diferentes?

Se os formulários estiverem dispersos por páginas diferentes através de shortcodes no conteúdo (e não em modelos), o método oficial com modelos é inconveniente. Use o lazy-cf7-assets (método 3) ou o plugin Conditionally Load CF7: ele adiciona uma configuração no painel de administração para definir em que páginas ou tipos de conteúdo os scripts devem ser carregados, e funciona sem edição de código.

Três linhas de código contra dezenas de pedidos

O problema de "o CF7 carrega scripts em todo o lado" existe exatamente há tanto tempo quanto o próprio plugin e, ao longo de mais de 10 anos, o programador não alterou o comportamento padrão, porque é um compromisso entre simplicidade e desempenho. Mas um compromisso, não uma sentença.

O caminho mais seguro é o método oficial com constantes e modelos. Ele remove os scripts e estilos do plugin de todas as páginas, exceto daquelas onde são necessários, e não se quebra durante as atualizações. Se o seu site usa uma stack moderna com um bundler, dê uma vista de olhos ao lazy-cf7-assets. Se precisa de algo rápido e sem editar modelos, o carregamento diferido através do hook clean_url dar-lhe-á melhorias nas métricas hoje mesmo.

Verifique o seu site através do PageSpeed Insights antes e depois; reduzir o número de pedidos bloqueantes em 1 ou 2 unidades e poupar 10 a 30 KB por página pode aumentar a pontuação de Desempenho em 2 a 5 pontos, especialmente em dispositivos móveis.