Diferir los scripts en WordPress

Cómo diferir

Diferir un script que se encuentra en la cabecera del index es pasar de esto:

<script type='text/javascript' src='https://jquery.min.js' id='jquery-core'></script>

A esto:

<script defer type='text/javascript' src='https://jquery.min.js' id='jquery-core'></script>

Se le ha agregado al link el parámetro <defer>.

Qué hace <defer>

Una muy buena explicación sobre defer y async se puede leer en el artículo sobre ello de javascript.info.

Pero en pocas palabras lo que va a hacer es decirle al navegador que no ejecute ese código, que puede continuar con la carga del DOM sin esperar por él, pero sí que lo descargue en paralelo y luego cuando termine con el DOM, justo antes del evento DOMContentLoaded, lea y ejecute el script. De hecho si todavía no se ha descargado, el navegador espera por él.

Defer también va a indicarle al navegador que debe respetar el orden de prioridad, si un archivo javascrip se solicitó primero que otro, entonces así el segundo se descargue primero y el DOM haya terminado y solo esté a espera para ejecutar el DOMContentLoaded, igual va a esperar por el primero para ejecutar el segundo.

Debido a esto es que se hace innecesario colocar los scripts al final del cuerpo, porque el parámetro <defer> hace lo mismo. No tengo claro exactamente por qué los temas de WordPress colocan los scripts al final del <body> pero creo que las razones están dentro de estas:

  • Algunas versiones de navegadores no están actualizadas para reconocer <defer> o <async>.
  • Dejan el diferir archivos de script a decisión de los usuarios.
  • La función wp_enqueue_script no permite dentro de sus variables la opción de agregar parámetros.

Cómo se hace

Con un código que hace esas modificaciones sin necesidad de quitar el script del registro y volverlo a registrar. No se del todo como funciona, lo tomé de un artículo en wpshout.com por el amigo David Hayes.

add_filter( 'script_loader_tag', 'wsds_defer_scripts', 10, 3 );
function wsds_defer_scripts( $tag, $handle, $src ) {

	// The handles of the enqueued scripts we want to defer
	$defer_scripts = array( 
		'prismjs',
		'admin-bar',
		'et_monarch-ouibounce',
		'et_monarch-custom-js',
		'wpshout-js-cookie-demo',
		'cookie',
		'wpshout-no-broken-image',
		'goodbye-captcha-public-script',
		'devicepx',
		'search-box-value',
		'page-min-height',
		'kamn-js-widget-easy-twitter-feed-widget',
		'__ytprefs__',
		'__ytprefsfitvids__',
		'jquery-migrate',
		'icegram',
		'disqus',
	);

    if ( in_array( $handle, $defer_scripts ) ) {
        return '<script src="' . $src . '" defer="defer" type="text/javascript"></script>' . "\n";
    }
    
    return $tag;
} 

El return luego del condicional final es el que me va a arrojar la etiqueta <script> completa, lo único que es variable es $src.

Yo he modificado el return final por:

return '<script type="text/javascript" defer src="' . $src . '" id="' . $handle . '" ></script>' . "\n";

Lo he dejado solo en defer porque de esa manera el navegador toma el valor predeterminado que es defer=defer. Y le he agregado el id con el valor de la variable $handle para mantener la identificación del script.

De esa manera el scrip ya queda diferido.

Entiendo muchas cosas sobre el script anterior, esta muy bien explicado, pero si quieres más detalles te invito a que lo visites, para yo no repetir lo mismo.

Leave a comment

Your email address will not be published. Required fields are marked *