Un petit peu d'optimisation de ce site

Un petit peu de travail pour optimiser le chargement de ce site et obtenir le “Saint Gral” : 100/100 au test Google Page Speed Insights, que ce soit sur mobile ou sur navigateur classique.

C’est désormais chose faite. Pour y parvenir, voici les étapes que j’ai franchies.

J’utilise un thème Hugo pré-construit (coder). Comme de nombreux thèmes, celui-ci s’appuie énormément sur les CDN pour servir les ressources habituelles :

  • font-awesome
  • polices chez Google

La partie facile : tout ramener en local et ne plus dépendre des CDN externes

La premère étape a été de tout rappatrier en local pour éviter de faire un trop grand nombre de requêtes sur de nombreux sites différents. Cela peut paraitre contre-intuitif, car l’objet de ces CDN est bien d'éviter à chacun de télécharger toujours les mêmes ressources à de multiples reprises, dans les faits, on n’y gagne pas tant que cela (tout le monde utilise des versions différentes) et surtout on dépend très fortement de ces CDN !

Ainsi, très facile de télécharger en local les CSS concernés et de changer le chemin vers elles dans le template. Mais cette recette n’est pas adaptée pour les ressources plus complexes telles que les polices de caractères (Google Fonts et Font-Awesome), il faut faire quelques petits efforts suppplémentaires.

font-awesome

font-awesome est une combinaison (complexe) de feuilles de style, de javascript, de polices et d’images… Tout ça pour quelques utilisations rares sur ce site.

Sur leur blog on trouve tout de même de quoi faire le travail espéré :

  • il faut télécharger le dossier “free” et le dézipper en local
  • sélectonner ce dont vous avez besoin uniquement, en général :
    • le fichier all.css qui est indipensable
    • le dossier webfonts qui est le minimum que j’utilise. Ce dossier est à placer à la racine de votre site, tout est référencé dans la CSS en mode /webfonts

Une fois cela réalisé, vous servez font-awesome depuis votre site !

Google Fonts

J’ai trouvé l’article How to Self-Host Google Fonts on Your Own Server qui résume parfaitement les étapes à faire pour y parvenir. Pour chaque police dont vous dépendez :

  • rendez-vous sur google-webfonts-helper
  • recherchez votre police
  • sélectionnez les tailles demandées pour votre police. Par exemple, dans mon thème, il y avait la ligne suivante :
    • <link href="https://fonts.googleapis.com/css?family=Lato:400,700%7CMerriweather:300,700%7CSource+Code+Pro:400,700&display=swap" rel="stylesheet">
    • dans cette ligne, on lit pour la police Lato les tailles 400 et 700
  • copiez la CSS proposée (j’ai choisi la version normale non optimisée pour supporter les anciens navigateurs) dans une feuille de style dédiée
  • téléhargez et dézippez la police et placez-là par exemple dans un dossier fonts à la racine de votre site

J’ai donc fait un feuille de style fonts.css et j’y ai ajouté toutes les polices de Google.

Je vous invite également à lire Should you self-host Google Fonts? qui est très complet sur le sujet (je ne l’ai trouvé que plus tard) :

To answer the question in the title of this post: yes it’s better to self-host as the performance gains are substantial.

Il nous reste encore un peu de chemin à parcourir pour obtenir la note parfaite.

Optimiser le chargement de la page

En s’appuyant sur les recommandations proposées par Google Page Speed Insights, on se rend vite compte qu’on peut gagner quelques points facilement :

  • diminuer le nombre de requêtes HTTP
  • diminuer la taille des resources statiques
  • ne pas faire de rendu bloquant

Voyons voir comment je m’y suis pris…

Diminuer le nombre de requêtes HTTP

Le pluis simple pour réaliser cela, c’est de mettre toutes vos CSS dans un seul fichier ; attention cela peut avoir un impact négatif si vous avez de nombreux styles qui bloquent le rendu. Le sujet est vaste, on ne va pas l’aborder ici.

J’ai pour ma part 3 CSS que je voulais charger dans un seul fichier. J’utilise Hugo pour générer ce site, j’ai eu quelques difficultés à comprendre comment fonctionnait la fonction resources.Get.

En effet, comme les CSS sont des fichiers statiques, ils doivent se trouver dans le dossier static et hugo les recopie à la racine du sité généré, tels quels.

Pour combiner plusieurs fichiers statiques, il faut considérer ces fichiers comme des ressources pour que Hugo réalise un traitement dessus. Pour que hugo les voit, ces fichiers doivent être présents dans un dossier assets. Après les avoir déplacés, ils sont accessibles par leur nom avec resources.Get. Ainsi, on charge chaque CSS dans une variable avec resources.Get, ensuite on les combine ensemble avec resources.Concat :

{{- $fontCss := resources.Get "css/fonts.css" }}
{{- $normalizeCss := resources.Get "css/normalize-8.0.1.css" }}
{{- $customCss := resources.Get "css/custom.css" }}
{{- $css := slice $fontCss $normalizeCss $customCss | resources.Concat "css/mytheme.css" }}
<link rel="stylesheet" href="{{ $css.Permalink }}" media="screen"/>

On passe ainsi de 3 requêtes à une seule. On peut faire de même pour les fichiers javascript également.

Diminuer la taille des resources statiques

Hugo permet de minifier les contenus qu’il génère :

  • pour tout le site, à la construction, avec l’option hugo --minify qui va compresser tous les fichiers générés (HTML, json, XML)
  • pour les ressources statiques avec le pipe resources.Minify qu’il suffit d’ajouter à la création de la variable $css : {{- $css := slice $fontCss $normalizeCss $customCss | resources.Concat "css/mytheme.css" | resources.Minify }}

On peut aller plus ploin et en profiter pour faire du fingerprinting et du SRI de nos ressources statiques avec le pipe resources.Fingerprint. Cela nous donne le template suivant :

{{- $fontCss := resources.Get "css/fonts.css" }}
{{- $normalizeCss := resources.Get "css/normalize-8.0.1.css" }}
{{- $customCss := resources.Get "css/custom.css" }}
{{- $css := slice $fontCss $normalizeCss $customCss | resources.Concat "css/mytheme.css" | resources.Minify | resources.Fingerprint "sha512" }}
<link rel="stylesheet" href="{{ $css.Permalink }}" integrity="{{ $css.Data.Integrity }}" crossorigin="anonymous" media="screen"/>

La code généré dans la page HTML est le suivant :

<link rel=stylesheet 
    href=https://jp.caruana.fr/css/mytheme.min.48d62b9e7e906ff0bfd3b5e106f8d66d8c89924348bd360f2bde5455abdd74c60884498e89d3b75708cd183e9f195f148074ee33375453adb3b3d5b816453564.css
    integrity="sha512-SNYrnn6Qb/C/07XhBvjWbYyJkkNIvTYPK95UVavddMYIhEmOidO3VwjNGD6fGV8UgHTuMzdUU62zs9W4FkU1ZA=="
    crossorigin=anonymous 
    media=screen>

Eviter les rendus bloquants

Je me suis rendu-compte que le chargement des polices pouvoit bloquer le rendu. L’option CSS font-display: swap permet de dire au navigateur de dessiner les mots sur la page avant la fin du téléchargement de toutes les polices, quitte à changer l’affichage final de manière un peu brutale (on peut observer un effet de clignotement). Pour que cela fonctionne, il faut bien sûr utiliser les bonnes pratiques du web en préciser à chaque fois un famille de police de plus en plus générale, par exemple : text-font-family: Merriweather, Georgia, serif;

 @font-face {
  ...
  font-display: swap;
 }

Enfin, le chargement de font-awesome pesait lourd dans le rendu, j’ai donc choisi de la déplacer en fin de document, hors de la balise <head>, juste avant la balise </body>.

Avec toutes ces mesures, j’ai pu atteindre la note maximale :