web performance, rocket car

Un site WordPress performant grâce à la séparation des Styles et JavaScript

Web Performance

Notre parti pris au Petit Garage est de développer et délivrer des sites performants. 

Nous avons pour cela mis en place au fur et à mesure de nos projets un workflow technique sous WordPress pour atteindre cet objectif ! 

Quelques avantages d’un site web performant : 

  • Une meilleure expérience utilisateur.
  • Une réponse instantanée à l’interface qui améliore la confiance des visiteurs en votre service.
  • Un crawl plus efficace des robots d’indexation. 
  • La pérennité du site web. Un site performant est un site robuste techniquement qui durera dans le temps.

Il y en a bien sûr beaucoup d’autres !

Un site performant sous WordPress ?

En premier lieu, le choix de WordPress en tant que CMS n’est plus à défendre. Utilisé par 43% des sites web, sa simplicité d’utilisation et de prise en main par les développeurs et les utilisateurs n’est plus à démontrer. S’il était reconnu comme étant “lent” par le passé, ce n’est plus le cas depuis les dernières versions où de nombreuses améliorations ont été apportées au core.


Le développement de thème sur-mesure a l’avantage de pouvoir partir d’une feuille blanche, c’est-à-dire qu’on n’embarque pas de dette technique à l’instant zéro. 

En effet, partir d’un thème premium ou d’un builder aura forcément une dette technique plus élevée qu’un thème vierge. On parle ici de dette technique de par les plugins installés, du poids des scripts et des styles chargés sur les pages, du temps de chargement du thème au niveau du serveur… 

Beaucoup d’éléments de performances sont couverts par de très bons articles et relèvent de bonnes pratiques du développement front-end en général.

La séparation des fichiers de styles et de scripts, en quoi cela consiste ?

👉 Ici nous allons explorer un point plus particulier qui est la séparation des fichiers de styles et de scripts au sein du développement d’un thème sur mesure.

Il s’agit de diviser le code CSS et JavaScript en fichiers distincts et à les charger uniquement lorsque nécessaire. Plutôt que d’inclure l’ensemble du code dans chaque page, la séparation permet de ne charger que le code requis pour une page spécifique. Cela réduit la taille des fichiers et accélère le temps de chargement.

Stack de développement frontend

Nous utilisons Gulp pour automatiser nos tâches de développement front. 

Ces tâches Gulp sont assez classiques, elles servent à compiler nos fichiers de style SCSS et nos fichiers de Scripts.

Styles

Nous utilisons SASS pour compiler nos feuilles de styles et simplifier le développement. Le problème courant est que ces styles fragmentés sont compilés dans un seul fichier de style. 

Ce fichier monolithique, coûteux en termes de poids est problématique dans le sens où : 

  • Le navigateur va prendre du temps à le télécharger, le décoder, et appliquer les styles
  • Il contient du code qui ne concerne pas la page courante qui est consultée. Ceci est est souvent pointé par les outils d’analyse de performance. (Voir la métrique “Remove unused CSS” et “Eliminate render-blocking ressources”)

Pour pallier à ce problème, nous isolons les styles spécifiques à chaque template ou modèle de page dans des fichiers SCSS séparés :

/**
 *  Tache Gulp - CSS
 *  SourceMaps + Sass + ( PostCSS - Autoprefixer - minify (si prod) )
 **/
function styles() {
	return gulp
		.src("src/styles/**/*.scss")
		.pipe($.plumber({ errorHandler: onError }))
		.pipe($.sourcemaps.init())
		.pipe(sass())
		.pipe($.postcss(POSTCSS_CONFIG))
		.pipe($.if(!isProduction, $.sourcemaps.write(".")))
		.pipe(gulp.dest(`${CONFIG.DIR.DEST}/css`))
		.pipe($.if(!isProduction, browserSync.stream()));
}

Dans l’import de nos styles dans notre thème WordPress, nous conditionnons le chargement de ces styles seulement dans le modèle de page qui utilise ce style. 

Pour rentrer un peu plus dans le détail, on vérifie si un fichier .css a le même nom que le modèle de page ou template et s’il est présent dans notre dossier de style. Si oui, alors on l’inclut dans la page.

👉 Par exemple, cela évite de charger les styles du formulaire de contact sur la homepage !

Côté WordPress, nous ajoutons un filtre sur le « template_include » afin de récupérer le nom du fichier du template chargé. Nous la stockons dans une variable globale que nous récupérons dans la fonction « enqueue_styles« .
Il nous suffit juste à charger le fichier .css correspondant au nom du template seulement si il existe !

<?php 
class Assets
{
    public function __construct()
	{
		// FRONT
		add_action('wp_enqueue_scripts', array($this, 'enqueue_styles'));

		// Ajoute un filtre pour récupérer le nom du template courant
		add_filter('template_include', array($this, 'var_template_include'));
	}

    public static function enqueue_styles($content)
	{

// CSS principale
wp_register_style('Main_css', get_template_directory_uri() . '/assets/css/main.css', false, WP_SCRIPTS_VERSION, "all");
		wp_enqueue_style('Main_css');

		// Récupérer le nom du template 
		$template = Assets::get_current_template();

		// Supprimer l'extension '.php'
		$template = str_replace(".php", "", $template);
		$template_style_file = get_template_directory(). '/assets/css/pages/'. $template .'.css';
		$template_style_path = get_template_directory_uri() . '/assets/css/pages/'. $template .'.css';

		// Charger le fichier css seulement si il existe
		if (file_exists($template_style_file)) {
			wp_enqueue_style($template . '_css', $template_style_path, false, $version, "all");
		}

    }

// Filtre pour définir le template actuel dans une variable globale
	public static function var_template_include($t)
	{
		$GLOBALS['current_theme_template'] = basename($t);
		return $t;
	}

// Récupérer le nom du template 
	public static function get_current_template()
	{
		if (!isset($GLOBALS['current_theme_template'])) {
			return false;
		} else {
			return $GLOBALS['current_theme_template'];
		}
	}

}

Il faut noter aussi que depuis l’apparition de l’éditeur Gutenberg, WordPress permet d’inclure les styles spécifiques à chaque bloc seulement lorsqu’ils sont utilisés.


Scripts 

Nous utilisons Webpack pour bénéficier de la compilation des scripts en modules.
Notre stratégie est, comme pour les Styles, de ne charger que les scripts nécessaires à chaque template de page. Le code est quasiment le même que pour les styles.

Pour économiser sur la taille des fichiers compilés, on évite toute inclusion de plugin externe si il n’est pas nécessaire !

Il faut aussi veiller à charger tout plugin seulement sur le template de page sur lequel il est utilisé, et pas globalement sur tout le site.

👉 Par exemple, sur la page de carte de notre projet récent Dualsun, nous ne chargeons que les scripts et les styles de MapBox sur cette page.

Bien sûr, on évite toute utilisation de jQuery ou de plugin pour de toutes petites fonctionnalités.

Wp Rocket, pour l’optimisation finale

Wp-Rocket est le plugin ultime pour la performance avec WordPress.
Il permet la mise en cache des pages. Cela veut dire que le plugin va générer des versions dites “statiques” des pages au format HTML. 

✨ Le serveur n’a plus besoin de consulter la base de données, et d’exécuter le code PHP nécessaire à l’affichage de la page mais servir directement le résultat visuel au navigateur.

⏩ On a vu des temps de réponse du serveur 10 fois plus rapide après l’activation de Wp-Rocket, passant de 500ms à 50ms. 

Il propose d’autres options de performance comme

  • Minifier les fichiers JS et CSS
  • Reporter le chargement des scripts à l’interaction utilisateur
  • Générer le critical CSS pour chaque page…

Il est donc indispensable d’utilisation pour répondre aux exigences de performance actuelles.

Des performances maximisées avec cette technique

Nous avons constaté une réelle amélioration du score de nos sites produits depuis la mise en place de ce workflow.

Pouvoir modulariser les CSS et JS spécifiques des templates de page nous a permis d’être plus flexibles lors du développement et d’optimiser très finement le chargement de ces ressources.

Avec l’aide de Wp-Rocket, on peut atteindre maintenant les mêmes performances que celles des générateurs de sites statiques tout en conservant WordPress en tant que CMS !


Un autre article pour la route ?