Skip to content

Todo para WordPress, el desarrollo web — y mucho más

🛠 Inclusión correcta de JavaScript en temas de WordPress

🛠 Inclusión correcta de JavaScript en temas de WordPress

Su galería de WordPress dejó de funcionar después de una actualización. ¿Le suena familiar?

Casi siempre la causa es JavaScript enlazado directamente en header.php, sin hooks, sin dependencias, sin tener en cuenta que un plugin de caché puede alterar el orden de carga. Un plugin carga jQuery, otro carga su propia versión de jQuery y su script queda en medio y falla con $ is not defined.

En la práctica, una sola llamada a wp_enqueue_script en el lugar correcto basta para olvidarse de los conflictos para siempre. A continuación encontrará un desglose completo: desde los errores de principiante hasta las estrategias defer/async y las opciones de ajuste que aparecieron en WordPress 6.6.

💡 Resumen rápido:

  • No inserte etiquetas script directamente en header.php ni en footer.php: esto genera conflictos con plugins y rompe los temas hijo
  • Encole JavaScript mediante wp_enqueue_script en functions.php con el hook wp_enqueue_scripts: WordPress colocará las etiquetas en head o antes de /body por sí mismo
  • Para código inline breve use wp_add_inline_script, no una etiqueta script suelta: preserva el orden de ejecución y da a los plugins la oportunidad de interceptar el código
  • En WordPress 6.3+ especifique una estrategia defer o async directamente en los parámetros de la llamada y, a partir de 6.6, también fetchpriority
  • Desencole scripts de terceros mediante wp_dequeue_script si un plugin ralentiza su sitio: la prioridad del hook decide

Cómo se añade JavaScript incorrectamente en WordPress

Escenario típico: necesita cargar su custom.js y el desarrollador inserta esta línea en header.php:

1<script src="<?php echo get_template_directory_uri(); ?>/js/custom.js"></script>

Parece funcionar. Pero este enfoque crea tres problemas.

Conflictos con plugins. Un plugin de caché combina los scripts en un orden diferente, un plugin de minificación renombra el archivo y rompe la ruta. Si otro plugin ya cargó jQuery y usted lo carga de nuevo, doble carga y errores en consola.

No se puede sobrescribir desde un tema hijo. Al usar un tema hijo, header.php rara vez se copia. Si el script está incrustado directamente en el header.php del tema padre, el tema hijo no puede desencolarlo ni reemplazarlo sin copiar el archivo completo, y esto implica que las ediciones se perderán cuando el tema padre se actualice.

Sin dependencias. El navegador carga su script antes que jQuery y obtiene $ is not defined. El script se carga en todas las páginas, incluso donde no se necesita, y las peticiones extra ralentizan el sitio.

La forma correcta: wp_enqueue_script

WordPress proporciona un sistema de cola para scripts y estilos. Usted no inserta <script> manualmente, sino que registra el script mediante PHP, especifica dependencias y ubicación de carga. WordPress coloca las etiquetas en <head> o antes de </body> por sí mismo.

Ejemplo mínimo funcional para el functions.php de su tema:

1/**
2 * Enqueue the main theme script.
3 */
4function mytheme_enqueue_scripts() {
5 wp_enqueue_script(
6 'mytheme-main', // $handle — unique name
7 get_template_directory_uri() . '/js/main.js', // $src — file path
8 array( 'jquery' ), // $deps — dependencies
9 '1.0.0', // $ver — version for cache busting
10 true // $in_footer — load in footer
11 );
12}
13add_action( 'wp_enqueue_scripts', 'mytheme_enqueue_scripts' );

La función wp_enqueue_script acepta cinco parámetros. $handle, un identificador único: si otro plugin ya registró un script con el mismo handle, no habrá carga duplicada. $deps, un array de handles de dependencias: WordPress cargará los scripts requeridos antes que el suyo. $in_footer con valor true coloca la etiqueta <script> antes de </body>, lo que acelera la renderización de la página.

Nota: get_template_directory_uri() apunta a la carpeta del tema padre. En un tema hijo use get_stylesheet_directory_uri(), la URL apuntará a la carpeta del tema hijo y su script no se perderá cuando el tema padre se actualice.

Estrategias de carga: defer, async y fetchpriority

A partir de WordPress 6.3, el parámetro $args acepta un array con configuraciones adicionales:

1wp_enqueue_script(
2 'mytheme-main',
3 get_template_directory_uri() . '/js/main.js',
4 array( 'jquery' ),
5 '1.0.0',
6 array(
7 'in_footer' => true,
8 'strategy' => 'defer',
9 )
10);

La estrategia defer le dice al navegador: «carga el script en paralelo, ejecútalo después de construir el DOM». El orden de ejecución está garantizado, los scripts con defer se ejecutan en el orden en que se añadieron al DOM. La estrategia async significa «ejecuta en cuanto se cargue», el orden no está garantizado. Para scripts del tema que dependen del DOM, elija defer.

A partir de WordPress 6.6, el array $args ganó dos parámetros más. fetchpriority controla la prioridad de carga ('high' o 'low'), útil para scripts críticos que deben cargar antes que otros. module_dependencies acepta un array de IDs de módulo para importación dinámica, esto es para escenarios avanzados con módulos ES. Importante: al especificar module_dependencies el script debe cargar en el footer (in_footer => true) o con la estrategia defer, de lo contrario el mapa de importación de módulos no estará listo cuando el script se ejecute.

Qué scripts ya están en WordPress

WordPress registra docenas de librerías JavaScript de serie: jQuery, jQuery UI, Backbone, wp-api, MediaElement.js y otras. Lista completa en la documentación oficial.

La regla principal: nunca cargue jQuery desde un CDN como Google o cdnjs si su tema funciona en el ecosistema WordPress. El propio WordPress proporciona jQuery con el handle jquery. Para usarlo, simplemente especifique array( 'jquery' ) en las dependencias, WordPress cargará su propia versión probada para compatibilidad con todo el núcleo.

Puede comprobar si una librería está registrada mediante wp_script_is():

1if ( wp_script_is( 'jquery-ui-datepicker', 'registered' ) ) {
2 // Library is available — just add to $deps
3}

Uso del hook wp_enqueue_scripts

El hook wp_enqueue_scripts se dispara en el frontend. Es dentro de este hook donde se envuelven las llamadas a wp_enqueue_script. No llame a la función directamente en el cuerpo de functions.php sin un hook, el script podría cargarse antes de que WordPress registre las librerías del sistema.

Para el área de administración use un hook separado:

1add_action( 'admin_enqueue_scripts', 'mytheme_admin_scripts' );
2function mytheme_admin_scripts( $hook_suffix ) {
3 // $hook_suffix contains the current admin page
4 if ( 'post.php' !== $hook_suffix ) {
5 return; // load script only on the post edit page
6 }
7 wp_enqueue_script( 'mytheme-admin', get_template_directory_uri() . '/js/admin.js', array(), '1.0', true );
8}

La carga condicional ahorra recursos: un script para una página de opciones no debería cargarse en todas las páginas de administración. El parámetro $hook_suffix lo pasa automáticamente WordPress, utilícelo.

Si un script se necesita tanto en el frontend como en administración, enganche una función a ambos:

1add_action( 'wp_enqueue_scripts', 'mytheme_global_scripts' );
2add_action( 'admin_enqueue_scripts', 'mytheme_global_scripts' );

Cómo añadir JavaScript inline: wp_add_inline_script

No todo el código merece ir en un archivo separado. Para fragmentos cortos, contadores, variables de configuración, manejadores rápidos, WordPress proporciona wp_add_inline_script:

1function mytheme_inline_config() {
2 wp_enqueue_script( 'mytheme-main', get_template_directory_uri() . '/js/main.js', array(), '1.0', true );
3 wp_add_inline_script(
4 'mytheme-main',
5 'const MYTHEME_AJAX_URL = "' . admin_url( 'admin-ajax.php' ) . '";',
6 'before'
7 );
8}
9add_action( 'wp_enqueue_scripts', 'mytheme_inline_config' );

El tercer parámetro, 'before' o 'after', determina dónde se inserta el código en relación con el script especificado. Esto es conveniente para pasar variables PHP a JavaScript: la URL del manejador AJAX, la clave nonce de seguridad, el ID del post actual.

Detalle importante: wp_add_inline_script solo funciona con un script registrado. Si pasa un handle que no está en la cola, el código no se emitirá. Así que primero wp_enqueue_script, luego wp_add_inline_script.

Alternativa para temas hijo: wp_head y wp_footer

Si trabaja en un tema hijo y no quiere crear un archivo separado, puede emitir código directamente a través de los hooks wp_head (en <head>) o wp_footer (antes de </body>):

1add_action( 'wp_footer', function() { ?>
2 <script>
3 ( function( $ ) {
4 'use strict';
5 $( function() {
6 // Your code here — DOM is already ready
7 } );
8 } ( jQuery ) );
9 </script>
10<?php } );

Este método es más corto pero menos flexible que wp_enqueue_script: sin dependencias, versionado ni capacidad de desencolar el script desde un tema hijo. Úselo para pequeños arreglos cuando no quiera crear un archivo separado.

Cómo desencolar un script añadido por un plugin o tema

A veces un plugin carga un script innecesario en todas las páginas y ralentiza el sitio. Puede eliminarlo mediante wp_dequeue_script:

1function mytheme_dequeue_plugin_scripts() {
2 if ( ! is_page( 'contacts' ) ) {
3 wp_dequeue_script( 'plugin-handle' );
4 }
5}
6add_action( 'wp_enqueue_scripts', 'mytheme_dequeue_plugin_scripts', 20 );

La prioridad 20 (tercer argumento de add_action) coloca su función después del registro del plugin, de lo contrario el handle aún no estará en la cola. Puede encontrar el handle de un script a través de la consola del navegador: abra el código fuente de la página y busque el atributo id en la etiqueta <script>, el handle generalmente coincide con el id sin el sufijo -js.

Si necesita reemplazar completamente un script, primero desregistre el antiguo mediante wp_deregister_script y luego registre el nuevo:

1function mytheme_replace_script() {
2 wp_deregister_script( 'old-handle' );
3 wp_enqueue_script( 'old-handle', get_template_directory_uri() . '/js/replacement.js', array(), '2.0', true );
4}
5add_action( 'wp_enqueue_scripts', 'mytheme_replace_script', 20 );

Antes de tales operaciones haga una copia de seguridad completa del sitio. Reemplazar scripts de plugins es un camino directo a funcionalidades rotas si no prueba en un entorno de staging.

El video de arriba muestra un desglose paso a paso del encolado de CSS y JavaScript en un tema WordPress mediante wp_enqueue_script y wp_enqueue_style. Si es nuevo en hooks, comience por él y luego vuelva a esta guía escrita para los detalles.

⁉️🤔 Preguntas frecuentes

¿Es obligatorio usar wp_enqueue_script para cada archivo js?

En la práctica, sí, para todos los scripts cargados globalmente. Para un script que funciona en una sola página y se genera dinámicamente, es aceptable insertar <script> directamente en la plantilla. Pero en cuanto tenga dos o más scripts, la cola mediante wp_enqueue_script le ahorra horas de depuración.

¿En qué se diferencia wp_register_script de wp_enqueue_script?

wp_register_script solo registra un script en el sistema (establece handle, ruta, dependencias) pero no emite la etiqueta en la página. wp_enqueue_script registra Y encola inmediatamente para su salida. La separación es útil cuando el script no siempre se necesita: regístrelo una vez en functions.php y llame a wp_enqueue_script('my-handle') solo en las páginas requeridas.

¿Puedo cargar scripts desde un CDN externo?

Técnicamente, sí, pase la URL completa como segundo parámetro. Pero para jQuery y otras librerías del núcleo de WordPress esto es una mala práctica: WordPress ya las incluye y prueba su compatibilidad. Un CDN externo se justifica para servicios de terceros como Google Analytics, reCAPTCHA, widgets de chat. En ese caso especifique la URL tal cual.

¿Cómo verifico que un script se cargó realmente?

Abra las herramientas de desarrollador (F12), pestaña Network, filtre por JS y refresque la página. Su archivo debería aparecer en la lista con un código de estado 200. Si el script falta, compruebe que el hook wp_enqueue_scripts se dispara en esta página y que la ruta del archivo es correcta. Para depurar, emita get_template_directory_uri() por separado y compare la URL.

¿Qué debo hacer si los scripts dejan de funcionar tras una actualización del tema?

Lo más probable es que la actualización haya sobrescrito su functions.php. La solución es un tema hijo: cree uno, mueva sus funciones allí y actívelo. Después de eso, las actualizaciones del tema padre dejarán su código intacto.

¿Qué significa el error "$ is not defined" al usar jQuery?

WordPress carga jQuery en modo noConflict, la variable $ no está ocupada por jQuery para evitar conflictos con otras librerías. Use el nombre completo jQuery en lugar de $ o envuelva el código en una función autoinvocada: (function($) { ... })(jQuery);.

¿Vale la pena molestarse con wp_enqueue_script para un par de scripts?

Si tiene más de un plugin en el sitio, vale la pena. La cola de scripts de WordPress está diseñada de modo que un plugin que carga jQuery directamente rompe medio sitio en el momento en que instala un plugin de caché. wp_enqueue_script elimina toda esta clase de problemas.

Para un tema de cinco archivos, use wp_enqueue_script. Para un fragmento corto en una página específica, wp_add_inline_script o el hook wp_footer servirán. Pero en cuanto tenga dos o más scripts, vuelva a la cola. Una hora invertida en un encolado correcto ahora le ahorra una tarde de depuración tras la próxima actualización de WordPress.