web-dev-qa-db-fra.com

Comment différer ou asynciser cet extrait de code JavaScript WordPress à charger en dernier pour des temps de chargement plus rapides?

J'ai plusieurs javascripts qui sont des plugins nécessaires dans l'un de mes domaines WordPress, et je sais d'où provient le fichier php.

Je prends toutes les mesures possibles pour accélérer les temps de chargement des pages , et chaque testeur de vitesse sur le Web recommande de différer les javascripts si possible.

J'ai lu sur les fonctions defer = 'différer' et les fonctions async en javascript et je pense que l'une d'entre elles permettra d'accomplir ce que j'essaie d'accomplir. Mais je ne comprends pas comment je le ferais dans un fichier php.

Par exemple, voici un extrait du fichier php d'un plugin particulier dans lequel le fichier javascript est appelé:

function add_dcsnt_scripts() {

    wp_enqueue_script( 'jquery' );
    wp_enqueue_script( 'dcsnt', dc_jqsocialtabs::get_plugin_directory() . '/js/jquery.social.media.tabs.1.7.1.min.js' );

}

J'ai lu qu'il est préférable de faire quelque chose comme ceci pour des temps de chargement de page plus rapides:

<script defer async src="..."></script>

Mais je ne sais pas comment accomplir cela dans un fichier php. Je veux faire cela avec tous mes fichiers javascript.

Comment pourrais-je effectuer le report ou l'asynchronisation de cet extrait de code javascript jusqu'à la fin du chargement et l'accélération du temps de chargement des pages ? Quel serait le moyen idéal pour augmenter les temps de chargement de page sur tous les navigateurs? Merci pour tous les conseils que tout le monde peut offrir!

45
Jason Weber

This blog post liens vers deux plugins d’intérêt:

Javascript asynchrone
Améliore les performances de chargement des pages en chargeant javascript de manière asynchrone à l'aide de head.js

WP Javascripts différés
Diffère le chargement de tous les javascripts ajoutés avec wp_enqueue_scripts, à l'aide de LABJS (une bibliothèque javascript asynchrone).

Je ne les ai pas testées, mais j'ai vérifié le code et elles font des choses assez sophistiquées avec le processus de mise en file d'attente des scripts WordPress.

Mais ensuite WPSE vient au secours :

// Adapted from https://Gist.github.com/toscho/1584783
add_filter( 'clean_url', function( $url )
{
    if ( FALSE === strpos( $url, '.js' ) )
    { // not our file
        return $url;
    }
    // Must be a ', not "!
    return "$url' defer='defer";
}, 11, 1 );
26
brasofilo

Ou de manière plus universelle:

function add_async_forscript($url)
{
    if (strpos($url, '#asyncload')===false)
        return $url;
    else if (is_admin())
        return str_replace('#asyncload', '', $url);
    else
        return str_replace('#asyncload', '', $url)."' async='async"; 
}
add_filter('clean_url', 'add_async_forscript', 11, 1);

afin que vous puissiez ajouter un code asynchrone à n'importe quel script sans modification du code, ajoutez simplement #asyncload à l'URL du script en tant que

wp_enqueue_script('dcsnt', '/js/jquery.social.media.tabs.1.7.1.min.js#asyncload' )
40
bestlion

En essayant de garder les choses quelque peu modulaires et globales, l’approche suivante choisit dynamiquement l’incorporation de la balise avec les attributs async ou différés en ajoutant simplement un petit identifiant au nom du descripteur $:

/**
* Add async or defer attributes to script enqueues
* @author Mike Kormendy
* @param  String  $tag     The original enqueued <script src="...> tag
* @param  String  $handle  The registered unique name of the script
* @return String  $tag     The modified <script async|defer src="...> tag
*/
// only on the front-end
if(!is_admin()) {
    function add_asyncdefer_attribute($tag, $handle) {
        // if the unique handle/name of the registered script has 'async' in it
        if (strpos($handle, 'async') !== false) {
            // return the tag with the async attribute
            return str_replace( '<script ', '<script async ', $tag );
        }
        // if the unique handle/name of the registered script has 'defer' in it
        else if (strpos($handle, 'defer') !== false) {
            // return the tag with the defer attribute
            return str_replace( '<script ', '<script defer ', $tag );
        }
        // otherwise skip
        else {
            return $tag;
        }
    }
    add_filter('script_loader_tag', 'add_asyncdefer_attribute', 10, 2);
}

Exemple d'utilisation:

function enqueue_my_scripts() {

    // script to load asynchronously
    wp_register_script('firstscript-async', '//www.domain.com/somescript.js', '', 2, false);
    wp_enqueue_script('firstscript-async');

    // script to be deferred
    wp_register_script('secondscript-defer', '//www.domain.com/otherscript.js', '', 2, false);
    wp_enqueue_script('secondscript-defer');


    // standard script embed
    wp_register_script('thirdscript', '//www.domain.com/anotherscript.js', '', 2, false);
    wp_enqueue_script('thirdscript');
}
add_action('wp_enqueue_scripts', 'enqueue_my_scripts', 9999);

Les sorties:

<script async type='text/javascript' src='//www.domain.com/somescript.js'></script>
<script defer type='text/javascript' src='//www.domain.com/otherscript.js'></script>
<script type='text/javascript' src='//www.domain.com/anothercript.js'></script>

Merci à @MattKeys @crissoca pour avoir inspiré ma réponse ici.

18
Mike Kormendy

Une autre solution utilisant un filtre différent, qui peut être utilisée pour cibler un descripteur de script spécifique:

function frontend_scripts()
{
    wp_enqueue_script( 'my-unique-script-handle', 'path/to/my/script.js' );
}
add_action( 'wp_enqueue_scripts', 'frontend_script' );

function make_script_async( $tag, $handle, $src )
{
    if ( 'my-unique-script-handle' != $handle ) {
        return $tag;
    }

    return str_replace( '<script', '<script async', $tag );
}
add_filter( 'script_loader_tag', 'make_script_async', 10, 3 );
13
Matt Keys

Une méthode simplifiée. Ajoutez à votre fichier functions.php pour rendre JavaScript asynchrone dans Wordpress.

// Make JavaScript Asynchronous in Wordpress
add_filter( 'script_loader_tag', function ( $tag, $handle ) {    
    if( is_admin() ) {
        return $tag;
    }
    return str_replace( ' src', ' async src', $tag );
}, 10, 2 );
10
TheRealJAG

Pour avoir le contrôle sur les fichiers js à différer et éviter les conflits, vous pouvez ajouter une variable à l'URL dans la fonction wp_register_script comme ci-dessous.

wp_register_script( 'menu', get_template_directory_uri() . '/js/script.js?defer', array('jquery'), '1.0', true );

Puis changez la ligne: 

if ( FALSE === strpos( $url, '.js' ))

À: 

if ( FALSE === strpos( $url, '.js?defer' ))

Le nouveau filtre ressemble à ceci.

add_filter( 'clean_url', function( $url )
{
    if ( FALSE === strpos( $url, '.js?defer' ) )
    { // not our file
    return $url;
    }
    // Must be a ', not "!
    return "$url' defer='defer";
}, 11, 1 );
5
Nathan Friend

Très peu de code de modification Mike Kormendy , ce qui vous permet d’ajouter 2 attributs à la fois:

// Async load
function add_asyncdefer_attribute($tag, $handle)
{
    $param = '';
    if ( strpos($handle, 'async') !== false ) $param = 'async ';
    if ( strpos($handle, 'defer') !== false ) $param .= 'defer ';
    if ( $param )
        return str_replace('<script ', '<script ' . $param, $tag);
    else
        return $tag;
}

Résultat:

<script async defer type='text/javascript' src='#URL'></script>
4
Marina Lebedeva

Je crois que c’est une mauvaise pratique de reporter/asynciser WordPress jQuery Une meilleure solution consisterait à exclure jQuery du filtre:

if (!is_admin()) {
    add_filter( 'script_loader_tag', function ( $tag, $handle ) {    
        if ( strpos( $tag, "jquery.js" ) || strpos( $tag, "jquery-migrate.min.js") ) {
            return $tag;
        }
        return str_replace( ' src', ' async src', $tag );
    }, 10, 2 );
}

Vous pouvez utiliser defer au lieu de async

2
Abukwaik

Quelque chose à ajouter à la solution de filtre clean_url, assurez-vous de ne l'utiliser que sur la fin de la police, en utilisant éventuellement des plugins if( ! is_admin() ){} tels que ACF, qui pourraient vous donner mal à la tête.

Mettre à jour

Voici ma version modifiée de la solution:

if( ! is_admin() ){
  add_filter( 'clean_url', 'so_18944027_front_end_defer', 11, 1 );
  function so_18944027_front_end_defer( $url ) {
    if ( FALSE === strpos( $url, '.js' ) )
    { // not our file
        return $url;
    }
    // Must be a ', not "!
    return "$url' defer='defer";
  }
}
1
crissoca

Incorporez l'attribut async aux scripts pour qu'ils ne soient chargés qu'une fois la page entière chargée

<script type="text/javascript">
    function ngfbJavascript( d, s, id, url ) {
        var js, ngfb_js = d.getElementsByTagName( s )[0];
        if ( d.getElementById( id ) ) return;
        js = d.createElement( s );
        js.id = id;
        js.async = true;
        js.src = url;
        ngfb_js.parentNode.insertBefore( js, ngfb_js );
    };
</script>

Source: ici

1
Anz Joy