Comment supprimer les blocages de styles CSS pour le Pagespeed SEO avec WordPress ? [MàJ]

Mathieu Chartier Référencement 1 commentaire

Les performances web représentent un enjeu important dans la gestion d'un site web, que ce soit pour des critères purement marketing, pour l'expérience utilisateur (UX, ergonomie), pour l'éco-conception (écologie du web) ou encore pour le référencement web (SEO). Nous allons insister essentiellement sur ce dernier point dans cet article, même si l'objectif reste d'améliorer les performances globales d'un site créé avec WordPress (le même type de programme pour être créé pour d'autres outils, dans la même logique).

Google a mis en place plusieurs outils pour mesurer les performances web, les deux plus connus d'entre eux étant Pagespeed Insights (équivalent à web.dev) et Lighthouse (présent notamment dans les outils de développement de Chrome). Tous sont basés sur la technologie Lighthouse pour analyser les performances web et les critères UX de Page Experience de Google, et permettent de restituer une idée des performances relatives à un site web. Rappelons toutefois qu'avoir une bonne note (sur 100) au Pagespeed ne garantit pas une excellente position dans les pages de résultats, c'est juste un micro-boost avec d'autres bénéfices (notamment pour l'indexation et le crawl budget, etc.). De même, le Pagespeed n'analyse pas la vitesse de chargement en soi, mais des critères d'optimisation précis qui devraient engendrer une meilleure vitesse. La nuance est forte ! ^^

Pourquoi les blocages des ressources CSS et JS posent problème ?

Lors d'une analyse avec Pagespeed Insights ou un outil équivalent, il est fréquent d'obtenir une note en deçà de nos attentes, notamment en ce qui concerne les performances pures. Certains critères reviennent régulièrement et nuisent clairement à l'amélioration des performances.

Parmi eux, un des critères les plus complexes à soigner est "Éliminer les ressources qui bloquent le rendu", qui contiennent à la fois des ressources Javascript et CSS (voir capture ci-dessous). Ce critère analyse le chargement du DOM et du CSSOM, à savoir les structures HTML et CSS, mais en espérant que ces derniers ne soient pas ralentis ("bloqués") par des ressources précises. Or, par défaut, le chargement des ressources externes (fichiers Javascript ou feuilles de style CSS) est synchrone, donc bloquant lors du chargement du DOM par exemple (pour faire simple, au lieu de lire un fichier HTML simple, le navigateur doit faire des allers-retours client-serveur pour récupérer au fur et à mesure le contenu des fichiers externes, ralentissant le chargement de la structure DOM).

Le blocage du rendu des contenus à cause de ressources externes qui ralentissent le chargement est un critère complexe à soigner, notamment dans le cadre de sites réalisées avec WordPress ou d'autres CMS. Plusieurs optimisations (conjointes ou non) peuvent être réalisées pour lever ce critère négatif malgré tout :

  1. Passer toutes les ressources en "inline" : cela revient à ne plus faire appel à des ressources externes, mais bien à copier le contenu des ressources JS dans des balises <script>...</script> et CSS dans des balises <style>...</style>. Cela devient complexe dans le cadre de WordPress à cause des nombreux scripts et CSS chargés dynamiquement à partir d'extensions ou des thèmes Premium, etc. Nous verrons comment procéder pour charger le fichier style.css d'un thème WordPress sur ce principe (ce qui pourrait s'appliquer à d'autres styles si besoin).
  2. Précharger les ressources de tout type : l'objectif est d'utiliser des balises <link rel="preload".../> pour éviter le chargement direct des ressources critiques. En général, l'attribut "preload" est utilisé pour préchargé les polices de caractères ou des ressources CSS. Nous verrons un code pour les CSS dans WordPress.
  3. Charger les scripts JS en asynchrone automatiquement : il existe plusieurs techniques pour réussir à charger des ressources JS automatiquement de manière asynchrone, en outrepassant les limites natives des attributs HTML async et defer. Nous ne traitons pas ce cas ici car il ne concerne pas le CSS évoqué dans cet article.

Les critères d'optimisation du Pagespeed sont presque tous traités en détails dans le dernier livre d'Alexandra Martin et moi-même, Techniques de référencement web : audit et suivi SEO, avec des codes à l'appui, notamment pour l'asynchronisme des fichiers JS. Nous ne traitons ici que le cas des ressources CSS qui n'ont pas connu d'explications aussi détaillées dans la dernière version de l'ouvrage en 2021.

Vous pouvez télécharger dès à présent les codes qui seront présentés plus bas dans cet article :

Télécharger “WordPress : meilleurs chargements des ressources CSS critiques”style-wordpress-pagespeed.zip – Téléchargé 101 fois – 1,16 Ko

Exemples de critères bloquants les performances web dans Pagespeed Insights

Comment précharger les feuilles de style CSS dans WordPress ?

Le préchargement des ressources avec "preload" se fait relativement facilement avec un site WordPress, il faut passer par le hook style_loader_tag qui permet de lister tous les fichiers CSS chargés avec la fonction wp_enqueue_style(). Pour les CSS chargés "manuellement", il faut alors ajouter soi-même les balises de préchargement bien entendu...

Le code suivant est à ajouter dans le fichier functions.php et s'occupe de générer automatiquement les balises de préchargement CSS pour l'ensemble des styles (souvent à l'exception du fichier style.css, qu'il est recommandé d'exclure puisqu'il ne s'agit pas d'une ressource "critique" au sens propre).

// CSS préchargés (preload) pour éviter les chargements critiques
function preload_stylesheet_css($html, $handle, $href, $media) {
    if(is_admin()) {
        return $html;
    }
    return '<link rel="preload" href="'.$href.'" as="style" id="'.$handle.'" media="'.$media.'" onload="this.onload=null;this.rel=\'stylesheet\'">';
}
add_filter('style_loader_tag', 'preload_stylesheet_css', 10, 4);

Ce simple code peut vous permettre de diminuer drastiquement la liste des ressources CSS qui bloquent le rendu dans Pagespeed Insights (et pour les navigateurs web bien entendu).

 Le cas des thèmes avec des fichiers CSS structurants chargés via wp_enqueue_style()

Dans certains thèmes, le fichier style.css est vidé de sa substance et ne conserve que les commentaires CSS utiles pour pouvoir charger le thème dans le back-office. Dans ce cas, d'autres fichiers styles servent à mettre en forme les pages du site mais sont appelés avec la fonction wp_enqueue_style(). Dans ce cas, ils vont être préchargés par la fonction présentée précédemment, alors que ça ne serait pas toujours judicieux (chaque cas est différent, difficile de vous donner une règle générale ici). Si tel est le cas pour votre site, il faudrait rajouter quelques lignes au code précédent pour exclure les "tags" des scripts en question, afin qu'ils ne soient pas pris en compte dans le préchargement.

Comment passer des feuilles de style CSS en ligne (inline) dans WordPress ?

Bien que l'on arrive à précharger les ressources CSS dynamiquement, il reste en général quelques feuilles de style récalcitrantes dans la liste des "ressources qui bloquent le rendu" de Pagespeed Insights ou Lighthouse. Si le thème est bien conçu, il est fort probable que seul le fichier style.css demeure dans la liste, mais cela nous empêche de bénéficier de meilleures performances. Pour contrecarrer ce problème, l'idéal est de faire charger ce fichier (ou d'autres) directement dans le code HTML, à la volée, et donc d'éviter le blocage (avec un aller-retour client-serveur évitable).

La règle générale est d'annuler le chargement originel du fichier style.css, que ce soit dans une balise <link rel="stylesheet" href="<?php bloginfo('stylesheet_url'); ?>"/> (souvent dans le fichier header.php) ou avec la fonction wp_enqueue_style() (en général dans le fichier functions.php). Ce sera via la fonction suivante que la feuille de style sera chargée en inline, donc il est inutile de la charger deux fois... ^^

Si votre site web charge dynamiquement d'autres feuilles de style pour la mise en forme du thème avec la fonction wp_enqueue_style() ou directement avec des balises <link/>, il faudra effectuer quelques modifications au code pour que ces fichiers ne soient plus chargés ainsi (en d'autres termes, commentez les lignes concernées dans les codes sources)...

Le code qui permet de charger le fichier style.css en ligne (inline) est relativement simple. Sachez que la fonction suivante apporte plusieurs bénéfices :

  1. Peut concaténer plusieurs feuilles de style : notre exemple ne porte que sur un seul fichier mais il est possible de fournir une liste de feuilles de style à charger en inline d'un seul tenant...
  2. Compresse les feuilles de style CSS qui ne le seraient pas : une partie de la fonction ne sert qu'à compresser les fichiers. Si cela est inutile pour vous, vous pouvez supprimer la portion de code concernée...
  3. Charge en inline à partir d'un fichier CSS externe : vous ne travaillerez pas votre mise en forme CSS dans le code HTML comme dans les années 1990, mais bien dans vos fichiers CSS habituels. La fonction va récupérer dynamiquement le contenu des fichiers pour les afficher en inline. Ainsi, vous pouvez continuer de travailler comme avant, seule la méthode de chargement change...

Sans plus attendre, voici l'exemple du code pour le fichier style.css, adaptable selon vos besoins :

// Charge le CSS général en inline
function load_style_css_inline() {
    // N'applique la fonction qu'au front-end
    if(is_admin()) {
        return;
    }
    /*======================*/
    /*=== Chargement CSS ===*/
    /*======================*/
    // Chargement des styles à rendre "inline"
    $fusion = "";
    $css_array = array(get_bloginfo('stylesheet_url'), // Style par défaut du thème);

    // On parcoure le tableau et indente les CSS
    foreach($css_array as $css) {
        $fusion.= file_get_contents($css);
    }

    /*=======================*/
    /*=== Compression CSS ===*/
    /*=======================*/
    // Suppression automatique des commentaires
    $fusion = preg_replace('!/\*[^*]*\*+([^/][^*]*\*+)*/!', '', $fusion);

    // Suppression des espaces avec les propriétés CSS
    $fusion = str_replace("('", "(", $fusion);
    $fusion = str_replace("')", ")", $fusion);
    $fusion = str_replace('("', '(', $fusion);
    $fusion = str_replace('")', ')', $fusion);
    $fusion = str_replace(' {', '{', $fusion);
    $fusion = str_replace('} ', '}', $fusion);
    $fusion = str_replace(': ', ':', $fusion);
    $fusion = str_replace('; ', ';', $fusion);

    // Suppression des espaces doubles, sauts de lignes, etc.
    $fusion = str_replace(array("\n", "\t", "\r", ' ', ' ', ' '), '', $fusion);

    // Suppression des derniers points-virgules (inutiles)
    $fusion = str_replace(';}', '}', $fusion);

    /*======================*/
    /*=== Adaptation URL ===*/
    /*======================*/
    // Rétablit les bons chemins d'URL quand c'est possible
    preg_match_all("|url\(([^)]+)\)|i", $fusion, $out);
    foreach($out[1] as $url) {
	if(substr($url, 0, 1) == "/") {
	    $url = substr($url, 1);
	}

	if(preg_match("|(wp-content/theme)|i", $url) == false) {
	    $fusion = str_replace($url, get_stylesheet_directory_uri().'/'.$url, $fusion);
	}
    }

    /*========================*/
    /*=== Affichage inline ===*/
    /*========================*/
    echo '<style>'.$fusion.'</style>';
}
add_action('wp_head', 'load_style_css_inline');

Quels résultats en termes de performances web ?

Côté Pagespeed Insights, l'application des 2 fonctions présentées ici a permis de faire gagner parfois jusqu'à 40 points sur 100 au Pagespeed Score de Google. Cela est bien entendu à relaviser selon le site concerné et les optimisations déjà en place, mais dans tous les cas vous ne devriez pas perdre de points ni de performances... ^^

Pour ce blog, la page d'accueil qui contient beaucoup de photos et de scripts obtient une note en moyenne autour de 80/100 au Pagespeed avec ces optimisations et d'autres (asynchronisme JS, lazy loading, cache, compression des ressources...). Il s'agit globalement de la page la moins performante du site. Le critère "Éliminer les ressources qui bloquent le rendu" a disparu de la liste des problèmes...

Exemple de suppression des ressources CSS critiques dans un site WordPress pour le Pagespeed SEO