Est-ce si horrible d’optimiser son site ?

On aime tous un beau site rapide, qui charge sans latence et sans faire apparaître un joli bouton « Acheter » sous la souris juste au moment où on allait cliquer sur « Partir ». Mais en tant que développeur, comment faire pour développer ce genre de site ?

La 5G arrive, ce que beaucoup vont retenir c’est : « Pourquoi je devrais perdre du temps à rendre mon site fluide et rapide alors qu’avec les processeurs et la bande passante d’aujourd’hui, nos téléphones peuvent faire des super story en direct depuis Mars ? »

C’est donc un article complètement obsolète que j’écris. Ne vous embêtez pas pour vos utilisat·eurs·ices en 3G moyenne au fin fond de la campagne bretonne1, ou pour ces pauvres bougres coincés dans une tour à la Défense à partager une antenne avec 15 000 personnes !

Les octets sont en Black Friday, Papa Noël fait pleuvoir la bande passante !

Plus sérieusement, une grande part des interwebs sont visités par des connexions moyennes, sur un navigateur obsolète (de moins en moins vrai) avec 67 onglets ouverts en arrière plan et une application de jeu qui mange la moitié des ressources. Et quand on développe, on a l’habitude de tester majoritairement sur un ordinateur (potentiellement assez puissant), en local, avec une connexion Ethernet, sur un réseau fibre, éventuellement en responsive, mais on s’intéresse finalement assez peu à la performance du site en situation « réelle ».

Au quotidien, pour faire une passe d’optimisation, je m’y prends (prenais ?) un peu au doigt mouillé (attention au clavier). Tiens, je vais mettre ce truc en cache, je vais limiter certains appels réseau, etc.

Mais je me place rarement, voire jamais, du côté utilisat·eur·rice pour prendre en compte :

  • Comment ça se passe si l’utilisat·eur·rice a une mauvaise connexion ?
  • Que doit-on voir en priorité ?
  • À partir de quand mon site réagit-il aux entrées utilisat·eurs·rices ?
  • Tout cela n’est-il finalement pas un peu trop compliqué ?
  • A‑t-on vraiment besoin de consulter mon site en rentrant dans un train bondé de monde un vendredi soir ?
  • Dois-je mettre un vigile de la qualité réseau à l’entrée de mon site ?
  • Dois-je fuir dans le Larzac élever des chèvres ?

Alors, tout d’abord, non, n’allez pas élever des chèvres, conseil d’ami.

Préférez plutôt utiliser les superbes outils mis à disposition sur l’internet pour vous aider à dégrossir le travail et rendre agréable la navigation sur votre site, même avec une connexion hasardeuse et un mobile fabriqué avec une pomme de terre et deux noix de cajou.

Trois bonnes raisons d’optimiser les performances de son site

1) Les utilisat·eurs·rices.

Ah les chenapans, il veulent acheter sur votre site, ou tout simplement faire du lèche-vitrine virtuel. Ils devraient être votre plus grande motivation, vous incitant à observer le comportement de votre site dans une situation non idéale. Il se dit même que les performances d’un site affectent le taux de rebond2 (les utilisat·eurs·rices quitteraient les pages mettant trop de temps à se charger !).

2) Le SEO.

Bon on va pas se mentir, c’est un peu le mal de notre siècle mais tout le monde veut être en haut de la page de résultats Google (et bing aussi bien sûr monsieur portails !). Et pour bien se placer dans les résultats de recherche, la performance compte³.

3) La charge du serveur.

On ne parle bien évidemment pas de la course poursuite effrenée au café du coin après un verre de trop. Mais plutôt de votre serveur qui, à chaque requête, travaille dur pour récupérer du contenu et l’envoyer à l’utilisat·eur·rice. Qui va potentiellement utiliser de sa très chère bande passante pour transmettre une magnifique image de plusieurs mégaoctets à un utilisat·eur·rice ingrat sur Nokia 3310, qui ne verra pas la moitié des pixels reçus.

ordinateur chargeant quelque chose

Quels outils ?

Il y en a de nombreux, des outils payants, des outils gratuits, des outils qui font le café pendant que vous attendez le résultat des tests, et des outils qui se concentrent sur l’essentiel. Je vais vous présenter deux outils que je juge complémentaires. Pour commencer, un rapide tour sur les différents indicateurs que les outils de performance web reprennent plus ou moins tous.

Les indicateurs

Comme pour tout développement, il faut savoir ce que l’on cherche à obtenir avant de commencer à développer. Se définir des objectifs (parce que l’optimisation peut être « sans fin ») et des raisons pour choisir ses batailles. Voici une liste des indicateurs clés, mis en place par les grands du web, qui permettent de mesurer concrètement le « score » d’une page.

  • Le First Contentful Paint. Sobrement surnommé FCP, on dirait le sigle d’un parti communiste d’une obscure région de France mais c’est en fait le temps qu’il faut à votre page pour afficher autre chose qu’un gros paté blanc.
  • Le Speed Index. Aka SI. Une mesure phare pour le référencement car elle est directement utilisée dans le pagerank, mais aussi pour la réactivité utilisat·eur·rice. Elle mesure le temps que prend la page, au-dessus de la ligne de flottaison, avant d’arrêter de trop bouger. Ce qui équivaut, quand vous visitez un site, à : « C’est bon, la page est chargée, je peux cliquer tranquillement ! ».
  • Largest Contentful Paint. Aka LCP. Le pendant « taille » du FCP. Combien de temps le plus gros élément de la page met-il à se charger ? Vous avez maintenant la réponse.
  • Time To Interactive. Aka TTI. C’est le temps que prend votre page à répondre rapidement aux entrées utilisat·eur·rice tout en ayant chargé la plupart de la page.
  • Total Blocking Time.TBT. L’idée est de déceler les tâches consommatrices de ressources retardant le TTI.
  • Cumulative Layout shift. CLS. L’objectif derrière cet indicateur est de vous aider à faire des pages ou les contenus ne bougent pas trop au fur et à mesure du chargement de la page.

Dans les solutions que je vais proposer dans la suite de l’article, j’essaierai de définir quelle mesure on essaye d’améliorer avec chaque changement. Je vous invite à aller lire la documentation des métriques, le calcul du score, etc. sur le site de Google web.dev. C’est très instructif !

Google Lighthouse

logo google lighthouse
« Un phare dans la nuit de votre médiocrité ». Google a fait fort sur ce coup.

Intégré à Chrome (dans les outils de développement, sous l’onglet « Lighthouse ») ou disponible en ligne, il peut fonctionner sans connexion internet. Les sections sont claires et utiles. On peut sélectionner ce que l’on veut évaluer. Il permet de choisir la taille de l’écran ainsi que la rapidité du réseau. Ce qui permet de tester comme si l’on était un habitant de la campagne au sud de Rennes alors qu’on ne l’est pas réellement (qui voudrait habiter dans un endroit sans connexion fibre franchement ?). Je vous conseille pour vos test de prendre un appareil représentatif des visites de votre site et de brider les performances réseau pour un résultat plus stable.

résultats test lighthouse sur web.dev
LH sur le site web.dev (qui explique l’algorithme dudit logiciel), un excellent score très difficile à obtenir sur une page avec pas mal de JavaScript.

Plusieurs catégories

  • Performance : teste la réactivité générale du chargement de la page
  • Progressive web app : teste les fonctionnalités PWA (mode déconnecté, etc.)
  • Best practices : teste si les bonnes pratiques web sont bien respéctées
  • Accessibility : teste le site en prenant en compte les utilisat·eurs·rices qui rencontrent des difficultés sur le web (daltoniens, etc.)
  • SEO : teste les bonnes pratiques du référencement (mots-clés)

Et comme vous avez pu le deviner, nous allons nous concentrer sur la catégorie Lighthouse “Performance”.

Webpagetest.org

logo webpagetest.org

Bon, je n’ai pas envie de faire de la pub pour Google tout au long de cet article. Je vous présente donc une alternative qui a ses avantages et ses inconvénients par rapport à LightHouse. La grosse différence c’est que ce n’est pas en local dans le navigateur déjà. Une plateforme en ligne donc, plus indépendante. On peut choisir la région pour ceux qui ont un site international et veulent s’assurer que leurs optimisations fonctionnent, même à huit fuseaux horaires d’ici. L’autre avantage de cet outil est qu’il permet d’être lancé sur des navigateurs différents.

Pour propulser son petit localhost sur le net interglobal, rien de mieux que “Ngrok”, un outil qui, telle une petite taupe virtuelle, construit un tunnel entre un port de votre machine et le reste du monde. Il mériterait aussi un article dans les 24 jours du web tant il peut être utile (démos, tests à distance, etc.) et pratique d’utilisation. Mais cet article n’est pas son article.

cloud link
Ngrok permet de créer un tunnel entre sa machine et le reste du monde. Pratique pour tester son site sur les outils en ligne !

On peut également y paramétrer tout un tas de choses comme la rapidité de la connexion, la configuration du navigateur, la capture des étapes de chargement de la page, et nombre d’autres choses qui permettent de mieux comprendre ce qui impacte la fluidité du chargement de la page.

À titre personnel je l’utilise en complément de LightHouse, une fois les optimisations faites, pour vérifier que WebPageTest les détecte aussi, et que le score augmente ici aussi.

Il dispose des mêmes indicateurs que LightHouse. Il lui manque juste le TTI. La note est représentée de A à F (A = “Awesome” et F = “Freaking Bad” ou quelque chose du genre).

Résultats de web page test.org sur leur propre site
L’interface de WPT est moins ergonomique mais très détaillée. Le score de leur propre site en terme de performance n’est pas mal du tout sauf pour le petit C du premier octet reçu.

Comment s’y prendre ?

Je crois que je vous ai suffisamment fait attendre. J’espère avoir éveillé votre curiosité et pouvoir vous décevoir pleinement dans cette partie ! En vrai, le web est un monde compliqué, chaque site possède ses spécificités, ses difficultés. Les optimisations techniques sont un domaine vaste et rempli de fausses promesses, de déceptions, un peu comme ce repas de noël, qu’on attend chaque année avec impatience (ou pas !), et qui cette année se fera en visio, masqués, à 1m50 de l’ordinateur avec une dinde désinfectée au gel hydroalcoolique.

Je vais vous raconter ce parcours de développement, récemment vécu, qui nous a permis d’améliorer le ressenti sur notre site web.

Avant de commencer

Haha je vous ai bien eu·e·s, aller une dernière chose avant de commencer :

  • Sélectionnez les pages que vous souhaitez optimiser en priorité : si c’est le SEO qui vous intéresse vous allez commencer par les pages que vous mettez en avant sur vos campagnes de publicités, celles sur lesquelles les utilisat·eurs·rices débarquent, et surtout celles qui sont indexées dans les moteurs de recherche et qui ont de l’importance pour vous. Pour notre cas, nous avions sélectionné 3 pages. De haut en bas : la page d’accueil car elle concerne une grande majorité d’utilisateurs, notre page d’aide car elle est simple et permet de constater les évolutions efficacement, et une page produit, qui contient beaucoup de logique métier et de script et qui possédait des performances assez mauvaises.

performance accueil avant optimisation performances aide avant optimisation performance produit avant optimisation

  • Choisissez les métriques et les valeurs attendues en fonction de vos priorités. Si vous souhaitez optimiser le référencement, commencez par le speed index, si c’est l’experience utilisat·eur·rice qui vous intéresse, concentrez vous sur le LCP, le TTI et les mesures qui font que votre page paraît stable pour l’utilisat·eur·rice. Nous avons choisi de nous concentrer sur le speed index, qui aggrège un peu les autres métriques et notre objectif était de passer sous la barre des 3s.
  • Définissez un plan de test stable. Pour ma part je relance plusieurs fois les outils et je prends la meilleur mesure. Je le fais dans une configuration de développement stable en sélectionnant toujours le même viewport (résolution d’écran) et en bridant la connexion du test à « mid-tier mobile » dans la dropbox « online », et en faisant tou cela dans une fenêtre de navigation privée pour éviter que vos extensions ne perturbent les tests.

plan de test pour lighthouse

Exemple de plan de test pour avoir des résultats qui ne changent pas trop à chaque test.

La configuration de votre serveur

robot serveur

Le cache

Du cache, du cache, et encore du cache. Faut pas se le cacher, ça fait gagner du temps à tout le monde. C’est une des premières optimisations à réaliser si ce n’est pas déjà fait ! Si une même ressource doit être utilisée plusieurs fois, elle doit être en cache quelque part. Bon, l’armoire de grand-mère n’est pas une solution dans ce cas précis. On parle plutôt d’un disque dur ou de mémoire vive, ceux de votre serveur ou ceux de votre utilisat·eur·rice.

Le cache serveur : il indique que la donnée est stockée dans le serveur.

Il peut s’agir de données que l’on utilise sur son site, qui changent peu et sont coûteuses a récupérer (la liste des produits en vente, les avis, etc) ou carrément de pages entières (un WordPress qui affiche un article n’a pas besoin de repasser sur tout le code qui permet de générer la page à chaque fois. Il sauvegardera une copie en mémoire et sera capable de la renvoyer beaucoup plus rapidement.). Le cache serveur permet d’économiser les ressources du serveur en gardant en mémoire un travail déjà effectué.

Le cache client : il va stocker la donnée dans la mémoire du navigateur directement.

Il s’agit généralement d’images, de scripts ou de fichiers de ressources. Mais grâce à l’entête Cache-control, on peut aussi demander au navigateur de sauvegarder une copie html de la page pour éviter de la redemander à la prochaine visite.

Le cache du code HTML de votre page permettra de réduire le first byte Time. L’utilisat·eur·rice reçoit plus rapidement la page (soit parce qu’une version est déjà en mémoire, soit parce que le serveur ne perd pas du temps à reconstruire la réponse mais la sort de son chapeau).

Le cache client des ressources permettra au fil de la navigation d’un·e utilisat·eur·rice d’optimiser le FCP et le LCP en évitant le temps de chargement des ressources depuis le serveur.

De notre côté, le cache était déjà bien en place mais nous avons pu remarquer grâce aux suggestions de Google LightHouse qu’il en manquait sur certaines ressources car chargées un peu différemment, et surtout que la durée du cache pouvait être très courte sur certaines ressources.

Les images

Réduire, compresser des images. Autre optimisation assez facile généralement. L’idée est de faire en sorte que les images prennent moins de place pour qu’elles transitent plus rapidement. On peut compresser l’image en utilisant des logiciels, et on peut réduire leur taille en regardant à celle à laquelle elles vont réellement s’afficher sur le navigateur (il faut faire attention aux différentes résolutions d’écrans).

On sait que vous êtes supers fier·e·s du logo à 4,58 € que votre jeune cousin vous a photoshopé. Mais pas besoin de l’intégrer en super résolution 4k ultra max digital double HDR si il s’affichera toujours dans un espace de 24 pixels de long et de large.

Cette optimisation accélère le FCP et le LCP en permettant au navigateur d’afficher plus rapidement la page.

De notre côté, nous avions déjà compressé la plupart de nos images, mais en repassant les ressources au peigne fin, nous en avons trouvé d’autres !

Compression GZip

GZip. C’est comme WinZip mais pour les serveurs . En général pas activé de base pour des raisons historiques, désormais bien supporté, activez le. Ca paraît tout bête mais ça libère pas mal de bande passante pour votre serveur et les informations arrivent plus vite, toujours plus vite ! Pour cette optimisation c’est encore le FCP qui est concerné.

De notre côté, c’était très simple à activer et n’a posé aucun problème une fois en production. Certaines ressources mettaient moitié moins de temps à charger.

Minification des ressources

Toujours la même idée, réduire la taille des ressources à télécharger. Cette fois-ci on supprime tous les caractères inutiles pour réduire au maximum la taille du fichier tout en ayant le même comportement.

« J’ai très sincèrement autre chose à faire que d’aller relire tous mes noms de variables pour les rapetisser, monsieur ! ». Vous, en lisant cette partie.

Bien entendu, des tas de logiciels font ça, intégrez les dans votre usine de build ou directement dans votre interface d’édition de code tabarnak !

De notre côté, les ressources étaient pour la plupart déjà minifiées, il en manquait certaines. Assez facile à détécter grâce aux recommendations LightHouse.

Utiliser un CDN pour ses ressources

« Pourquoi faire vous même ce que les autres peuvent faire pour vous ? ». On dirait le slogan d’un parti capitaliste.

Les CDN ou Content Delivery Network, sont des plateformes qui servent des fichiers, dans notre cas, si on utilise jQuery sur son site, on peut le charger directement depuis leur CDN plutôt que depuis son serveur.

Il y a des avantages à servir soi-même des fichiers de ressources :

  • Être sûr·e·s du fichier desservi.
  • L’empaqueter avec ses autres ressources.

Et il y a des avantages à le faire servir par un CDN :

  • L’utilisat·eur·rice peut avoir une version en cache parce qu’il a visité un autre site qui utilisait le même CDN.
  • Ce n’est pas la bande passante de votre serveur qui est consommée.

Je vous laisse faire votre choix en fonction de ce qui fonctionne le mieux pour vous.

De notre côté, nous avons fait le choix de nous appuyer sur libman pour utiliser les CDN de nos librairies externes. En ajoutant un fallback pour le developpement local sur les fichiers versionnés. Les temps de chargement étaient divisés par 2 ce qui est non négligeable.

Les optimisations qui ne nécessitent pas trop de changement dans le code

Lazy loading

Ou bien, dans la langue de Benoît Poelvoorde, « chargement faignant ». Il s’agit de décaler au maximum le chargement des ressources qui ne sont pas nécessaires pour afficher le contenu qui se trouve au dessus de la ligne de flottaison (le bas de votre navigateur). Tant que l’image n’est pas proche de cette ligne, on ne la charge pas, ce qui laisse des ressources pour charger plus rapidement le reste. Les images sont chargées au fur et à mesure de la navigation. Il existe des librairies Javascript qui le font très bien, ou un attribut au niveau de l’image mais ce n’est pas encore très bien supporté par tous les navigateurs.

L’idée est toujours d’optimiser les métriques FCP et LCP en se concentrant sur les ressources primordiales

De notre côté, nous avions déjà du lazy loading et nous l’avons étendu à tout notre site en nous appuyant sur une librairie JS existante.

Packager ses fichiers js en bundles

Les serveurs HTTP sont désormais capables de faire plusieurs choses à la fois ! Avec HTTP2, rassembler ses ressources en paquets n’est plus tellement une nécessité car désormais le navigateur peut charger de multiples ressources simultanément plus efficacement. Mais, de façon marginale, empaqueter plusieurs fichiers en un seul et le minifier peut simplifier le travail du navigateur et réduire la surcharge des multiples requêtes HTTP.

De notre côté, ces optimisations étaient là depuis longtemps et on a tenté au maximum de les conserver mais on a surtout découpé nos paquets historiques en plus petits morceaux adaptés à des situations de navigations. On peut aller plus loin en ne chargeant que les scripts nécessaires en utilisant des systèmes tels que le lazy loading de scripts sur React et autre, mais cela rend la migration plus coûteuse.

Réorganiser le chargement de ses ressources

Organiser les priorités de chargement des ressources n’est pas toujours une tâche facile, mais on peut assez simplement :

  • Descendre l’exécution des scripts avec peu d’importance plus bas dans son code
  • Charger en priorité les éléments structurant la page, et plus précisément le haut de page (toujours penser à la ligne de flottaison).
exemple de page HTML
Les ressources sont téléchargées et exécutées dans l’ordre de déclaration. Déplacer un script plus bas dans son code peut avoir un impact sur a peu près toutes les métriques de performance (permettre au reste du contenu de s’afficher plus vite, réduire le blockage utilisateur, etc.).

C’est un travail super important et même si il est assez consommateur de temps il permet de vraiment restructurer son site pour charger de manière efficace les ressources nécessaires.

De notre côté, nous avons pu limiter les ressources chargées, certaines étaient chargées sur des pages pour lesquelles elles n’étaient pas utiles, d’autres pouvait être chargées à la toute fin de la page (validation de formulaire, suivi de session, etc.), et d’autres étaient charées tardivement alors qu’elles impactaient l’écran au dessus de la ligne de flottaison. Tout cela a un impact sur la façon dont est percue la page et sur les scores de performance. C’est un peu comme si Netflix chargeait la fin du film avant le début.

quoi ?
Quand je lance mon film et que la plateforme de streaming commence par charger la fin.

Les optimisations qui nécessitent pas mal de changements

Définir des espaces pour ses images et ses contenus qui éviteront au site de bouger

Ce qui perturbe aussi pas mal les utilisat·eurs·rices c’est quand les éléments de la page n’arrêtent pas de bouger au fur et à mesure du chargement. Un bon moyen de régler cela est de prévoir à l’avance les espaces dans lesquels vont s’afficher les différents éléments et leurs tailles. Ça dépend vraiment de la configuration de vos pages mais c’est souvent un travail fastidieux et à tester dans de nombreuses résolutions d’écran. C’est sur le CLS que cette optimisation a le plus d’impact.

De notre côté, c’est quelque chose que nous avons finalement peu mis en place sauf pour certaines images critiques.

Réduire les dépendances

Ah quel bonheur de trouver la librairie parfaite pour résoudre un petit problème de code. Mais quand on embarque plusieurs kilo octets de surcharge sur chaque page pour éviter quelques lignes de code maison, cela peut s’avérer contre productif.

De notre côté, c’est underscorejs et knockoutjs qui étaient chargés sur toutes les pages alors qu’en modifiant un peu le code on a pu se débarrasser de ces dépendances sur la plupart de nos pages et surtout sur 2 de nos pages choisies pour les tests. Un gain de plusieurs kilo octets mais aussi de temps de parsing des scripts qui a permis de pas mal faire grimper le score.

Utilisation d’async et defer

Pour vous présenter ces 2 mots clés, une petite explication technique s’impose. Lors du chargement des pages, le navigateur respecte l’ordre d’inclusion des ressources. Sauf si l’on spécifie un de ces 2 attributs. À chaque fois qu’il rencontre une balise <script> ou <link>, il va télécharger la ressource, la parser (exécuter dans le cadre du JS ou inclure les styles dans le cadre d’un CSS), puis il reprendra le traitement du document HTML là où il s’était arrêté.

Async va indiquer au navigateur, charge et exécute ce script quand tu en as le loisir. Il doit être réservé aux scripts n’ayant pas d’impact au dessus de la ligne de flottaison et dont aucun autre script ne dépend. Car on ne peut prévoir ni quand il sera chargé, ni quand il sera exécuté par le navigateur. Il faut tout de même déclarer ces scripts en bas de page afin que le navigateur ne se mette pas à les traiter avant d’autres potentiellement.

Defer va permettre au navigateur de savoir que l’éxécution de ce script, même si elle doit respecter l’ordre de déclaration au sein du document HTML, n’a pas besoin d’être faite immédiatement après le téléchargement de la ressource mais peut être faite plus tard.

C’est donc des mots clés très puissants qui même si ils ne sont pas toujours faciles à implémenter peuvent aider grandement les performances de votre page en chargeant et exécutant dans le bonne ordre de priorité les scripts en fonction de leur importance.

De notre côté, très peu de scripts ont pu passer en async, mais on a réussi à « defer » la plupart des autres. Le score a bien grimpé, notamment le LCP, car le navigateur pouvait allouer des ressources en priorité au traitement du document HTML et au téléchargement des images du haut de la page.

Pour aller plus loin

D’autres techniques existent pour améliorer les performances d’un page. Il faut savoir parfois choisir entre la complexité de l’architecture technique, la simplicité de développement, le temps et les performances.

On a évalué la possibilité de construire un fichier CSS par page, avec seulement les styles utilisés en haut de page. Mais cette technique s’avérait coûteuse en intégration et assez peu différentiante en termes de performances.

performance accueil après optimisations performances aide après optimisations Performances produit après optimisations

De haut en bas, toujours les mêmes lascars, accueil, aide et produit. On remarque que le score global a bien évolué, le pari est presque réussi sauf pour le speed index de notre fiche produit que l’on n’a pas réussi à faire passer sous la barre des 3s.

Pour conclure

L’amélioration des performances d’un site est un travail qui peu être coûteux et laborieux mais pas nécessairement, certaines optimisations sont à portée de clic. Mais c’est un travail nécessaire car dans la course à la « nouvelle feature » une pause s’impose parfois pour prendre en compte les conditions de navigation. D’autant plus que dans certains domaines c’est un facteur différentiant. De notre côté, les choses se sont plutôt bien passées, suite à cela un ensemble de bonnes pratiques ont été mises en place au sein de l’équipe et l’on suit régulièrement les performances de notre site pour vérifier qu’elles ne se dégradent pas !

nicolas cage est satisfait des optimisations de son site

Quand je vois pour la première fois mes optimisations me faire basculer du côté « vert » des performances.