Cómo agregar la etiqueta defer="defer" en los javascripts de plugins

9 ene 2012, 09:59:34
Vistas: 40.9K
Votos: 31

No pude agregar la etiqueta defer en los javascripts del plugin. La prueba de velocidad de Google Developer me sugiere agregar la etiqueta defer en los javascripts de Contact Form 7.

Así es como Contact Form 7 incluye javascript en el encabezado.

add_action( 'wp_enqueue_scripts', 'wpcf7_enqueue_scripts' );

function wpcf7_enqueue_scripts() {
    // jquery.form.js originalmente incluido con WordPress está desactualizado y obsoleto
    // por lo que necesitamos anular su registro y volver a registrar la última versión
    wp_deregister_script( 'jquery-form' );
    wp_register_script( 'jquery-form', wpcf7_plugin_url( 'jquery.form.js' ),
        array( 'jquery' ), '2.52', true );

    $in_footer = true;
    if ( 'header' === WPCF7_LOAD_JS )
        $in_footer = false;

    wp_enqueue_script( 'contact-form-7', wpcf7_plugin_url( 'scripts.js' ),
        array( 'jquery', 'jquery-form' ), WPCF7_VERSION, $in_footer );

    do_action( 'wpcf7_enqueue_scripts' );
}

¿Ahora cómo agregar la etiqueta defer="defer" en el código anterior?

2
Comentarios

Ticket relevante: http://core.trac.wordpress.org/ticket/12009

scribu scribu
9 ene 2012 19:15:15

Buena pregunta @Viruthagiri.

Ramkumar M Ramkumar M
2 feb 2012 15:30:47
Todas las respuestas a la pregunta 2
6
63

A partir de WordPress 4.1 existe un filtro: script_loader_tag. Puedes usarlo para encontrar el script correcto:

add_filter( 'script_loader_tag', function ( $tag, $handle ) {

    if ( 'contact-form-7' !== $handle )
        return $tag;

    return str_replace( ' src', ' defer="defer" src', $tag );
}, 10, 2 );

Respuesta antigua

No hay un filtro dedicado disponible... al menos no puedo ver uno. Pero...

  • wp_print_scripts() llama a WP_Scripts->do_items()
  • que llama a WP_Scripts->do_item()
  • que usa esc_url()
  • que ofrece un filtro: 'clean_url'.

Y aquí vamos:

function add_defer_to_cf7( $url )
{
    if ( FALSE === strpos( $url, 'contact-form-7' )
      or FALSE === strpos( $url, '.js' )
    )
    { // no es nuestro archivo
        return $url;
    }
    // ¡Debe ser una ', no "!
    return "$url' defer='defer";
}
add_filter( 'clean_url', 'add_defer_to_cf7', 11, 1 );

Advertencia: no probado, solo una idea. :)

Actualización

He escrito y probado un plugin con este código.

9 ene 2012 13:56:46
Comentarios

Esto es perfecto también para usar con data-main en requirejs

Nicola Peluchetti Nicola Peluchetti
6 jun 2012 18:07:47

¡Ese es un buen truco, y tan simple! Creo que también sería útil para agregar charset='utf-8' cuando sea necesario.

webaware webaware
16 ene 2013 10:16:09

Genial, pero ¿por qué: Debe ser un ', no "! ?

henrywright henrywright
1 feb 2014 04:09:52

@henrywright WordPress añade ' en ambos lados de la cadena devuelta, un " resultaría en HTML inválido.

fuxia fuxia
1 feb 2014 12:54:48

Probablemente sea una buena idea en caso de que alguien quiera adaptar esto para que funcione con otros scripts, validar su uso solo en el front-end usando algo como if( ! is_admin() ){}. Plugins populares como ACF podrían darte dolores de cabeza.

crissoca crissoca
28 abr 2015 05:09:37

@crissoca, gracias compañero. Lo había olvidado hasta que TinyMCE no hizo lo que debía (faltaban qtags y demás :-D ). Así que sí, ¡usa esto SOLO en el front-end!

Charles Charles
12 jun 2015 15:46:31
Mostrar los 1 comentarios restantes
0

La respuesta aceptada es correcta, pero quería hacer algunas mejoras/actualizaciones para un caso más general, para cualquiera que, incluyendo mi yo futuro, llegue a esto mientras busca una respuesta. Para casos generales que no estén relacionados con el plugin contact-form-7, donde estés agregando el atributo defer a todos los scripts, probablemente quieras excluirlo de las páginas de administración, porque estas dependen de que los scripts se ejecuten en un orden específico. Además, para las páginas que no son de administración, querrás excluir jQuery, porque jQuery probablemente debería cargarse en el head antes que cualquier otra cosa. También, en lugar de manipular la cadena de texto del tag, una mejor manera de hacerlo sería cargarla en un objeto DOMDocument, manipularlo y luego convertirlo de vuelta a una cadena. Además, las versiones más recientes de PHP tienen verificación de tipos, por lo que probablemente deberías agregar los tipos de parámetros y retorno en tu llamada de función.

<?php

    add_filter('script_loader_tag', function (string $tag, string $handle, string $src):string {
        if (is_admin()) {
            return $tag;
        }
        if (in_array($handle, array('jquery-core', 'jquery-migrate'))) {
            return $tag;
        }
        $dom = new \DomDocument();
        $dom->loadHTML($tag, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD);
        $dom->getElementsByTagName('script')[0]->setAttribute("defer", "defer");
        $tag = $dom->saveHTML();
        return $tag;
    }, 10, 3);

?>
6 jun 2023 01:05:52