Guidelines : Performances

Statut : Working Draft (WD)

Bonnes pratiques de Performance Web appliquées par l'agence web Alsacreations.fr, évoluant dans le temps et adaptées à chaque nouveau projet.


Bonnes pratiques HTTP

Valable pour HTTP/1.x, plus forcément pour HTTP/2 et HTTP/2 qui permettent le multiplexing et diverses optimisations natives.

  • Minifier les ressources texte (css, js, html)
    • Vue/Nuxt/React : déjà optimisé de base
    • WordPress : utiliser une extension
  • Compresser les ressources texte (css, js, html) par exemple avec gzip/deflate
  • Réduire le nombre de requêtes HTTP
  • Exploiter les en-têtes de cache (Cache-Control, Expires)

Core Web Vitals

Les Core Web Vitals regroupent des mesures de performance et d'expérience utilisateur. Google considère que ces indices sont essentiels pour la performance et l'expérience utilisateur et les intègre dans son algorithme de Ranking depuis 2021.

Les métriques mesurées sont :

  • Largest Contentful Paint (LCP) : mesure la vitesse de chargement de page. L'indice porte sur le temps de chargement et d'affichage de la plus grande image ou du plus grand bloc de contenu visible dans le viewport. Le critère est "Good" lorsque ce temps est inférieur ou égal à 2.5 secondes.
  • First Input Delay (FID) : mesure l'interactivité. Calcule le temps nécessaire au navigateur pour offrir une première interaction avec le visiteur (clic sur un lien, un bouton, interagir avec un formulaire) L'expérience est considérée réussie si ce délai est inférieur ou égal à 100 millisecondes.
  • Cumulative Layout Shift (CLS) : mesure la stabilité visuelle (l'ensemble des repositionnements, redimensionnements, décalages intempestifs des contenus pendant la durée de vie d'une page web). La métrique mesure la quantité de contenu qui se déplace, ainsi que la distance de déplacement. Le CLS doit être égal ou inférieur à 0.1.

Les sections suivantes de ce document indiquent comment améliorer les Web Core Vitals dans le détail :

  • Bonnes pratiques générales
  • Modes de positionnement CSS
  • Aides au pré-chargement de ressources
  • Images
  • Polices
  • Icônes

Voir aussi Our top Core Web Vitals recommendations for 2023

Bonnes pratiques générales

On veillera à respecter des critères communs de performance :

  • Limiter le nombre de ressources différentes exploitées et donc de requêtes HTTP (images, feuilles de styles, scripts, fonts).
  • Minifier les ressources texte (CSS, JavaScript, JSON...)
  • Utiliser des formats de fichiers modernes (WEBP, Avif, WOFF2)
  • Différer les requêtes moins importantes (lazy loading) (en JavaScript ou avec l'attribut natif loading)
  • Utiliser les attributs qui confèrent des indications de pré-chargement (async, defer, rel=preload ou fetchpriority)
  • Établir un budget de performance pour Lighthouse

Plus de détails sur ces généralités dans les parties détaillées suivantes.

Modes de positionnement CSS

Les modes de positionnement CSS ne sont pas tous égaux en ce qui concerne les Layout Shifts.

  • Flexbox : Conçu pour s'adapter aux contenus. Designé pour être fluide par défaut. Plus sensible aux Layout Shifts
  • Grid Layout : Conçu pour englober les contenus. Grid Layout est designé pour être rigide par défaut. Globalement moins sensible aux Layout Shifts.

De manière générale :

  • Nous utilisons Grid Layout en priorité tant que possible, et Flexbox si nécessaire.
  • Nous tentons de limiter les valeurs automatiques, dépendantes du contenu (auto, flex-grow, flex-shrink, 1fr, min-content, max-content, stretch)
  • grid-template-columns: 1fr 1fr 1fr; est conseillé par rapport à grid-auto-flow: column;
  • flex: 1; est conseillé par rapport à flex-grow: 1;
  • flex: 1; min-width: 0 est conseillé par rapport à flex: 1;
  • grid-template-columns: minmax(0,1fr) est conseillé par rapport à grid-template-columns: 1fr

Plus d'info : https://http203-playlist.netlify.app/videos/avoiding-layout-shift-by-putting-the-css-in-charge/

Aides au pré-chargement de ressources

Le parseur HTML du navigateur est bloqué par deux types de ressources :

  • les éléments <link>
  • les éléments <script> qui ne disposent pas d'attributs async ni defer

Depuis 2008, un second mécanisme parallèle entre en jeu sur l'ensemble des navigateurs : celui du "Preload Scanner". Ce second parseur agit lorsque le parseur HTML est bloqué sur une ressource et pré-charge les ressources suivantes indiquées dans le markup HTML.

Cela signifie que certains éléments placés hors HTML ne participeront pas à cette recherche anticipée : c'est le cas des polices et des images de fond appelées dans les fichiers CSS, mais également des liens ou ressources situées dans des scripts.

Ce mécanisme est automatique, mais il est possible de l'influencer en proposant le pré-chargement de certaines ressources en priorité en agissant sur les "Priority Hints" tels que async, defer, rel=preload ou fetchpriority

async et defer

Ces attributs sont liés au chargement des scripts. Dans les deux cas, ces attributs rendent le chargement asynchrone et ne bloquent pas le paseur HTML :

  • async est exécuté dès que le navigateur en a la possibilité, les ressources sont potentiellement chargées dans n'importe quel ordre.
  • defer est exécuté lorsque tout le DOM est parsé, les ressources sont chargées dans l'ordre dans lequel elles sont placées dans le DOM.

async est prioritaire sur defer.

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

rel=preload

Cette déclaration demande au navigateur de découvrir et charger une ressource en priorité avant que le parseur ne l'atteigne. Elle est également particulièrement utile pour tous les assets non indiqués dans le markup HTML.

Exemple de pré-chargement de police :

<!-- Dans le <head> après
     la feuille de styles pour ne pas la bloquer -->
<link rel="preload" as="font" href="kiwi.woff2" 
      type="font/woff2" crossorigin="anonymous">

(Note : ici crossorigin="anonymous" n'est utile que si la police n'est pas auto-hébergée)

Exemple de pré-chargement d'image :

<link rel="preload" as="image" href="hero.webp">

Priorité "Mandatory" (obligatoire) : cette fonctionnalité doit être traitée en priorité par le navigateur.

fetchpriority

L'attribut fetchpriority informe le navigateur du degré de priorité du pré-chargement d'une ressource. Il est possible de l'appliquer sur l'élément <link> mais aussi directement sur <img>, <script> et <iframe>.

Les valeurs possibles sont "high" (haute priorité), "low" (basse priorité) et "auto" (valeur par défaut).

Quelques exemples :

<!-- Ce script doit être pré-chargé 
     mais d'autres ressources sont prioritaires -->
<link rel="preload" href="script.js" as="script" fetchpriority="low">

<!-- Cette image de fond critique 
     est hautement prioritaire -->
<link rel="preload" as="image" href="hero.webp" fetchpriority="high">

<!-- Cette image doit être pré-chargée
     mais n'est pas vraiment critique -->
<img src="sausage.svg" alt="je ne suis pas importante" fetchpriority="low">

Avec l'exemple d'images d'un carousel :

<ul class="carousel">
  <img src="img/carousel-1.jpg" fetchpriority="high">
  <img src="img/carousel-2.jpg" fetchpriority="low">
  <img src="img/carousel-3.jpg" fetchpriority="low">
  <img src="img/carousel-4.jpg" fetchpriority="low">
</ul>

(source de l'exemple : https://web.dev/priority-hints/)

Priorité "Hint" (indice) : cette fonctionnalité est une simple indication pour le navigateur.

preconnect et dns-prefetch

Ces attributs sont liés au chargement des ressources externes (non hébergées localement).

  • rel="preconnect" informe le navigateur que l'on souhaite établir une connexion le plus rapidement possible à une autre plateforme.
  • rel="dns-prefetch" ne fait que résoudre le nom de domaine sans toutefois atteindre la ressource indiquée.
<link rel="preconnect" href="https://example.com">
<link rel="dns-prefetch" href="https://example.com">

Pour en savoir plus sur l'usage de ces attributs : Optimisation des pré-chargements avec prefetch, dns-prefetch et prerender

Priorité "Hint" (indice) : cette fonctionnalité est une simple indication pour le navigateur.

Lazyloading

L'attribut loading permet de ne charger que les images situées au dessus de la ligne de flottaison. Les autres images ne sont alors chargées que lorsque cela devient nécessaire, au fur et à mesure que l'utilisateur scrolle (défile). On améliore ainsi le temps de chargement initial de la page.

Les valeurs de loading sont les suivantes :

  • eager : l'image est chargée immédiatement, qu'elle soit située dans ou hors de la fenêtre visible (valeur par défaut),
  • lazy : le chargement est retardé jusqu'à ce que l'usager scrolle et s'approche du bas de la fenêtre du navigateur.
<img src="image.webp" loading="lazy" width="" height="" alt="">
<iframe src="video-player.html" loading="lazy" title=""></iframe>

Quelques ressources :

Images

Voici nos préconisations concernant les performances des images :

  • Toujours indiquer les dimensions initiales de l'image (width et height) dans le HTML pour que le navigateur puisse calculer le ratio et éviter des Layout Shifts.
  • Utiliser des formats d'images modernes et plus légers (Webp, Avif) à condition que le processus d'encodage/décodage soit lui-même rapide.
  • max-width: 100% pour que l'image s'adapte en largeur à son conteneur (images fluides).
  • height: auto pour que le navigateur applique le ratio systématiquement.
  • background-color sur l'image pour indiquer visuellement l'espace qui sera occupé quand elle sera chargée (placeholder).

Code recommandé

<!-- Dimensions initiales de l'image -->
<img src="(chemin)" alt="" width="2000" height="1000">
img {
  max-width: 100%; /* largeur fluide */
  height: auto; /* ratio préservé */
  background: gray; /* placeholder en attendant */
}

Outils d'optimisation d'images

Outils d'optimisation vidéo et audio

Polices

Autant que possible, privilégier le chargement de polices légères et respectueuses des performances, indiquées notamment sur Google Web Fonts. Limiter le nombre de ces polices à 2, voire 3 grand maximum.

Recommandations générales

  • Privilégier la police système system-ui pour les textes de contenus (raison : performance + UX + Layout Shifts)
  • Privilégier le format .woff2 (et .woff en alternative)
  • Limiter à 2 ou 3 fichiers de police au maximum (regular, bold, italic), sinon préférer une Variable Font
  • Utiliser la directive <link rel="preload"> pour charger les polices de manière asynchrone.
  • Ajouter font-display: swap; au sein de la règle @font-face pour éviter les effets de FOIT. Si la police est pré-chargée, font-display: optional; est alors recommandé.
  • Héberger la police sur son propre serveur (voir l'outil "Google Webfont Helper")

Code recommandé

Voici un exemple de chargement de police conseillé (cas de deux fichiers de police regular et bold) :

<!-- Dans le <head> après
     la feuille de styles pour ne pas la bloquer -->
<link rel="preload" as="font" href="kiwi.woff2" 
      type="font/woff2" crossorigin="anonymous">

⚠️ Noter ci-dessous que le nom de la font-family est toujours le même ("kiwi") et qu'il ne faut pas confondre avec le nom du fichier

@font-­face {
  font-­family: "kiwi";
  src: url("kiwi.woff2") format("woff2"), 
    url("kiwi.woff") format("woff"); /* dans cet ordre */
  font-weight: normal;
  font-style: normal;
  font-display: optional; /* on évite les layout shifts */
}
@font-­face {
  font-­family: "kiwi";
  src: url("kiwi-bold.woff2") format("woff2"), 
    url("kiwi-bold.woff") format("woff");
  font-weight: bold;
  font-style: normal;
  font-display: optional;
}

Ressource : Google Webfont Helper

L'application web Google Webfont Helper est une excellente ressource permettant d'optimiser finement les fichiers :

  • choisir le bon subset (latin, latin-ext, etc.)
  • choisir les styles nécessaires au projet (normal, bold, italic, etc.)
  • copier le code CSS prévu pour les navigateurs modernes (woff2 et woff)
  • télécharger les fontes de Google Fonts aux formats woff2 et woff

Il est conseillé de récupérer les fontes via cette ressource si cela est possible.

Icônes

Voir le document spécifique des Guidelines Icônes.

Hébergement

Outils d'audit de performance

Autres checklists et ressources

Cache serveur