Atualizado em 19/06/2026
Toda vez que você precisa adicionar um arquivo CSS ou JavaScript a um site WordPress, existe uma forma certa e várias erradas. A forma certa é enfileirar (do inglês enqueue): registrar o arquivo no sistema do WordPress e deixá-lo decidir quando e como imprimir a tag. A forma errada — colar um <script> ou <link> direto no cabeçalho do tema — funciona à primeira vista e quebra silenciosamente depois, em conflitos de jQuery duplicado, ordem de carregamento bagunçada e cache que não atualiza. Este guia explica o porquê de cada decisão e mostra o código atual, incluindo a estratégia de carregamento defer/async introduzida no WordPress 6.3.
1. Por que enfileirar em vez de colar a tag no template
O sistema de enfileiramento existe porque um site WordPress não é controlado por uma pessoa só: o núcleo, o tema e dezenas de plugins adicionam assets ao mesmo tempo. Enfileirar resolve quatro problemas que a tag manual não resolve:
- Dependências. Você declara que o seu script precisa do jQuery, e o WordPress garante que o jQuery seja impresso antes — sem você ter que controlar a ordem na mão.
- Deduplicação. Cada asset tem um handle (um nome único). Se dois plugins enfileiram a mesma biblioteca com o mesmo handle, ela é carregada uma única vez.
- Versionamento / cache-busting. O parâmetro de versão entra na URL, permitindo invalidar o cache do navegador e da CDN quando o arquivo muda.
- Sem conflitos e desativável. Outro código pode remover ou substituir o seu asset de forma limpa, via
wp_dequeue_script()— algo impossível com uma tag colada no template.
2. As funções e suas assinaturas
As duas funções centrais são wp_enqueue_style() e wp_enqueue_script(). Vale conhecer cada parâmetro:
<?php
// wp_enqueue_style( $handle, $src, $deps, $ver, $media )
// wp_enqueue_script( $handle, $src, $deps, $ver, $args )
// $handle nome único do asset (string)
// $src URL do arquivo
// $deps array de handles dos quais este depende (ordem de carga)
// $ver versão para cache-busting (string | null | false)
// $media (estilo) 'all', 'screen', 'print'...
// $args (script) booleano in_footer OU array de estratégia (WP 6.3+)
3. Os hooks corretos — e por que não enfileirar fora deles
Enfileirar nunca acontece "solto". Você sempre engancha a sua função de enfileiramento em um hook específico, e o hook depende de onde o asset deve aparecer:
| Hook de enqueue | Contexto |
|---|---|
wp_enqueue_scripts | Front-end (o site público) |
admin_enqueue_scripts | Painel administrativo (wp-admin) |
login_enqueue_scripts | Tela de login (wp-login.php) |
Apesar do nome, wp_enqueue_scripts é o hook para scripts e estilos do front-end — você enfileira CSS nele também. Por que não enfileirar fora desses hooks? Porque eles disparam no momento exato em que o WordPress está preparado para coletar assets e sabe em que ponto da página imprimir as tags. Chamar wp_enqueue_script() cedo demais (no carregamento do arquivo, ou em init) significa fazê-lo antes de a fila estar pronta — o asset some ou sai fora de ordem.
4. Exemplo completo: estilo + script com dependência, versão e defer
Este é o padrão de produção. Note três coisas: o uso de filemtime() como versão (cache-busting automático a cada alteração do arquivo), a dependência array( 'jquery' ) e o array de estratégia com 'strategy' => 'defer', novidade do WordPress 6.3:
<?php
add_action( 'wp_enqueue_scripts', 'dwp_assets_front' );
function dwp_assets_front() {
$dir = get_stylesheet_directory(); // caminho no disco
$uri = get_stylesheet_directory_uri(); // URL pública
// Estilo: handle, URL, deps, versão (filemtime), media
wp_enqueue_style(
'dwp-estilo',
$uri . '/assets/css/app.css',
array(),
filemtime( $dir . '/assets/css/app.css' ),
'all'
);
// Script: handle, URL, deps, versão, e ARRAY de estratégia (WP 6.3+)
wp_enqueue_script(
'dwp-app',
$uri . '/assets/js/app.js',
array( 'jquery' ), // jQuery já vem com o WP
filemtime( $dir . '/assets/js/app.js' ),
array(
'strategy' => 'defer', // ou 'async'
'in_footer' => true, // substitui o antigo booleano
)
);
}
Sobre o $ver: uma string define a versão manualmente; null faz o WordPress não anexar nenhuma versão à URL; e false usa a versão do próprio WordPress (útil para assets do núcleo, perigoso para os seus, pois o cache só invalida quando o WP for atualizado). Em desenvolvimento, filemtime() é o mais prático: muda sozinho a cada salvamento.
5. Registrar agora, enfileirar depois
Às vezes você quer declarar um asset uma vez e decidir condicionalmente quando carregá-lo. Para isso existem wp_register_script()/wp_register_style(): registram sem imprimir. Mais tarde, wp_enqueue_script( 'handle' ) com apenas o handle marca para impressão. Isso é útil em bibliotecas que vários trechos do código podem precisar.
6. Passar dados do PHP para o JavaScript
Seu JS quase sempre precisa de dados do servidor: a URL do admin-ajax.php, um nonce de segurança, o ID do post. Há duas formas, e vale entender a diferença. A clássica é wp_localize_script(), criada para i18n mas amplamente usada para dados; a moderna e mais flexível é wp_add_inline_script():
<?php
// Forma clássica: cria um objeto JS global (window.dwpDados)
wp_localize_script( 'dwp-app', 'dwpDados', array(
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'dwp_acao' ),
'postId' => get_the_ID(),
) );
// Forma moderna: injeta JS bruto ANTES do script (mais adequada p/ dados)
$dados = array(
'ajaxUrl' => admin_url( 'admin-ajax.php' ),
'nonce' => wp_create_nonce( 'dwp_acao' ),
);
wp_add_inline_script(
'dwp-app',
'const dwpDados = ' . wp_json_encode( $dados ) . ';',
'before'
);
Note o wp_json_encode(): ele serializa os dados com escape seguro para inseri-los no HTML. Tanto o localize quanto o inline dependem de o script (dwp-app) já ter sido enfileirado ou registrado — o dado é "anexado" àquele handle. O uso típico desses dados é a comunicação AJAX.
7. Carregamento condicional: só carregue onde precisa
Carregar todo o CSS e JS em todas as páginas é um erro de performance clássico. Se um script só é usado na página de contato, enfileire-o só ali. As tags condicionais do WordPress (is_page(), is_singular(), is_front_page()) tornam isso trivial:
<?php
add_action( 'wp_enqueue_scripts', 'dwp_assets_contato' );
function dwp_assets_contato() {
// Só carrega o validador de formulário na página de contato
if ( ! is_page( 'contato' ) ) {
return;
}
$uri = get_stylesheet_directory_uri();
wp_enqueue_script(
'dwp-form-contato',
$uri . '/assets/js/form-contato.js',
array(),
'1.0.0',
array( 'strategy' => 'defer', 'in_footer' => true )
);
}
Carregar JavaScript desnecessário é uma das maiores causas de lentidão e de notas ruins no PageSpeed/Core Web Vitals. Cada script extra é tempo de download, parse e execução. A regra é simples: enfileire o mínimo, na página em que ele é usado, e use defer para tirar o JS do caminho crítico de renderização.
8. Remover assets de um plugin ou tema (dequeue / deregister)
Plugins frequentemente carregam CSS/JS em todo o site, mesmo onde não é necessário. Você pode removê-los com wp_dequeue_script() (tira da fila de impressão) e wp_deregister_script() (remove o registro por completo). A chave é rodar isso em uma prioridade alta, depois de o plugin ter enfileirado:
<?php
// Prioridade 100: roda DEPOIS do plugin enfileirar (que costuma usar 10)
add_action( 'wp_enqueue_scripts', 'dwp_remove_assets_desnecessarios', 100 );
function dwp_remove_assets_desnecessarios() {
// Tira da fila de impressão nesta requisição
wp_dequeue_style( 'plugin-x-css' );
wp_dequeue_script( 'plugin-x-js' );
// Remove o registro de vez (impede reenfileiramento por dependência)
wp_deregister_script( 'plugin-x-js' );
}
Funciona da mesma forma para estilos, com wp_dequeue_style() e wp_deregister_style(). Cuidado ao "desregistrar" algo que outros scripts declaram como dependência — você pode quebrá-los; nesse caso, prefira apenas o dequeue.
Armadilhas comuns (e como evitar)
| Sintoma | Causa provável | Correção |
|---|---|---|
| "$ is not a function" | Carregou uma segunda cópia do jQuery | Não enfileire seu próprio jQuery; use array( 'jquery' ) como dep. |
| Asset não aparece | Enfileirou fora do hook correto | Use wp_enqueue_scripts / admin_ / login_ |
| Cache não atualiza | Versão fixa (ou false) sem mudar | Use filemtime() ou bump manual do $ver |
| Script roda antes da dependência | Dependências não declaradas em $deps | Liste os handles necessários no array $deps |
| defer não funciona | Passou booleano antigo em vez do array | Use array( 'strategy' => 'defer' ) (WP 6.3+) |
wp_dequeue sem efeito | Rodou antes de o plugin enfileirar | Use prioridade alta (ex.: 100) |
Boas práticas
- Use handles únicos e prefixados (ex.:
dwp-app) para não colidir com outros plugins. - Aproveite as bibliotecas que o núcleo já registra (jQuery e outras) em vez de embarcar cópias próprias.
- Enfileire de forma condicional: só a página que usa o asset deve carregá-lo.
- Versione com
filemtime()em desenvolvimento; em produção, com a versão real do tema/plugin. - Use
deferpara o JS sair do caminho crítico e melhorar os Core Web Vitals. - Passe dados ao JS com
wp_add_inline_script()+wp_json_encode()em vez de imprimir variáveis cruas no HTML.
Enfileirar corretamente é um dos hábitos que mais separam um site WordPress sólido de um cheio de conflitos. Tudo isso vive em hooks — enfileirar é, no fim, um action ganchado no momento certo.
Perguntas frequentes
Por que não posso simplesmente colar uma tag <script> no template?
Porque você perde tudo o que o sistema de enfileiramento resolve por você. Ao colar a tag manualmente, você não tem controle de dependências (garantir que o jQuery carregue antes do seu script), arrisca duplicar uma biblioteca que outro plugin já carregou, fica sem versionamento para invalidar o cache e cria conflitos. Com wp_enqueue_script() e wp_enqueue_style(), o WordPress monta a ordem certa, deduplica por handle e ainda permite que outros desativem o seu asset de forma limpa.
Em qual hook devo enfileirar meus arquivos?
Depende do contexto. No front-end, use wp_enqueue_scripts. No painel administrativo, admin_enqueue_scripts. Na tela de login, login_enqueue_scripts. Enfileirar fora desses hooks (por exemplo, direto no carregamento do arquivo, ou em init) é errado: as funções de fila podem ainda não estar prontas, e o WordPress não saberá em que momento imprimir as tags — o resultado costuma ser o asset não aparecer ou aparecer no lugar errado.
O jQuery já vem com o WordPress?
Sim. O núcleo registra o jQuery (e várias outras bibliotecas) com o handle jquery. Por isso você nunca deve baixar e enfileirar a sua própria cópia: basta declarar array( 'jquery' ) como dependência do seu script e o WordPress carrega a versão dele, na ordem certa, uma única vez. Carregar uma segunda cópia é uma das causas mais comuns de conflito de JavaScript em sites WordPress.
Para que serve o parâmetro de versão ($ver)?
Para cache-busting: a versão vira um parâmetro na URL do arquivo (?ver=1.2.3), então mudar a versão força navegadores e CDNs a baixarem a cópia nova. Os valores especiais importam: uma string define a versão; null faz o WordPress não anexar versão alguma; e false usa a versão do próprio WordPress. Em desenvolvimento, usar filemtime() do arquivo como versão garante que cada alteração invalide o cache automaticamente.
Qual a diferença entre wp_localize_script e wp_add_inline_script?
wp_localize_script() nasceu para internacionalização (passar strings traduzidas ao JS), mas acabou virando o jeito clássico de injetar dados do PHP — ele cria um objeto JavaScript global com os valores. wp_add_inline_script() é mais recente e flexível: adiciona um trecho de JS bruto antes ou depois de um script já enfileirado, o que o torna mais adequado para passar dados e para pequenos snippets, sem o "molde" de objeto que o localize impõe. Para dados novos, o wp_add_inline_script() costuma ser a melhor escolha.
Como faço meu script carregar com defer no WordPress 6.3+?
A partir do WordPress 6.3, o último parâmetro de wp_enqueue_script() aceita um array em vez do antigo booleano in_footer. Você passa array( 'strategy' => 'defer', 'in_footer' => true ) e o WordPress adiciona o atributo defer (ou async) à tag, respeitando as dependências entre scripts. É o jeito oficial e seguro de adiar a execução de JavaScript sem quebrar a ordem de carregamento.