Dans cet article, je partagerai 8 techniques pour optimiser le chargement des images qui réduisent la bande passante réseau requise et la charge du processeur lorsqu'elles sont affichées à l'écran. Voici quelques exemples de HTML annoté pour vous faciliter la reproduction. Certaines techniques sont connues depuis longtemps et certaines sont apparues relativement récemment. Idéalement, votre mécanisme de publication de documents Web préféré (tel qu'un CMS, un générateur de site statique ou un cadre d'application Web) devrait faire tout cela dès le départ.
Collectivement, les techniques optimisent tous les éléments de Google Core Web Vitals en:
- minimiser les problèmes de contenu majeurs ( Largest Contentful Paint (LCP) ) grâce à la réduction de la taille, la mise en cache et le chargement différé;
- préservation du décalage de mise en page cumulatif nul (décalage de mise en page cumulatif (CLS) );
- réduire le délai de la première entrée ( First Input Delay (FID) ) en réduisant la consommation du processeur (pour le thread principal d'exécution).
Pour voir toutes les techniques en action, jetez un œil au code source pour charger cette image:
https://www.industrialempathy.com/img/remote/ZiClJf.jpg
<img loading="lazy" decoding="async" style="background-size: cover; background-image: none;" src="/img/remote/ZiClJf.avif" alt="Sample image illustrating the techniques outlined in this post." width="4032" height="2268">
Techniques d'optimisation
Mise en page réactive
Cette technique simple permet à l'image d'occuper l'espace horizontal disponible tout en conservant le rapport hauteur / largeur. En 2020, les navigateurs ont appris à réserver la bonne quantité d'espace vertical pour une image avant son chargement si l'élément
img
contient des attributs
width
et
height
. Cela évite le décalage cumulatif de la mise en page.
<style>
img {
max-width: 100%;
height: auto;
}
</style>
<!-- Providing width and height is more important than ever. -->
<img height="853" width="1280" … />
Rendu paresseux
La deuxième technique est plus compliquée. Le nouvel attribut CSS
content-visibility: auto
indique au navigateur de ne pas penser à placer l'image tant qu'elle n'est pas prête. Cette approche présente plusieurs avantages, dont le principal est que tant que le navigateur ne reçoit pas une image d'espace réservé floue ou l'image elle-même, il ne la décodera pas, ce qui économise les ressources du processeur.
Plus besoin de contenir-intrinsèque-taille
Une version antérieure de l'article expliquait comment
contain-intrinsic-size
éviter l'effet CLS lors de l'utilisation
content-visibility: auto
. Mais dans Chromium 88, ce n'est plus nécessaire dans le cas d'images pour lesquelles
width
et
height
. À compter du 27 janvier 2021,
content-visibility: auto
pas encore implémentés dans d'autres moteurs de navigateur , ils suivront probablement l'exemple de Chromium. Alors oui, c'est beaucoup plus facile maintenant!
<style>
/* This probably only makes sense for images within the main scrollable area of your page. */
main img {
/* Only render when in viewport */
content-visibility: auto;
}
</style>
AVIF
AVIF est le format graphique le plus récent pris en charge par les navigateurs. Il est désormais pris en charge dans Chromium et par indicateur dans Firefox. Safari ne fonctionne pas encore avec lui, mais comme Apple fait partie du groupe qui a développé le format, ce navigateur devrait également prendre en charge AVIF à l'avenir.
Ce format est remarquable en ce qu'il est largement supérieur au JPEG. Et cela se compare favorablement au format WebP, dont les images ne sont pas toujours plus petites que JPEG et qui peuvent augmenter la consommation de ressources en raison du manque de prise en charge du chargement progressif.
Pour implémenter une extension progressive pour AVIF, vous pouvez utiliser
picture
.
L'élément est en fait
img
imbriqué dans
picture
... Cela peut être déroutant, car on l'appelle
img
parfois une solution de secours pour les navigateurs qui ne prennent pas en charge
picture
, mais en fait, cet élément ne fait qu'aider à la sélection
src
, et il n'a pas sa propre disposition. L'élément
img
sera dessiné et vous lui appliquerez le style.
Jusqu'à récemment, il était assez difficile d'implémenter des images AVIF côté serveur, mais les versions récentes de bibliothèques comme sharp rendaient cette tâche beaucoup plus facile.
<picture>
<source
sizes="(max-width: 608px) 100vw, 608px"
srcset="
/img/Z1s3TKV-1920w.avif 1920w,
/img/Z1s3TKV-1280w.avif 1280w,
/img/Z1s3TKV-640w.avif 640w,
/img/Z1s3TKV-320w.avif 320w
"
type="image/avif"
/>
<!-- snip lots of other stuff -->
<img />
</picture>
Chargement du nombre correct de pixels
Le code ci-dessus a des attributs
srcset
et
sizes
. Ils utilisent un sélecteur
w
pour indiquer au navigateur quelle URL prendre en fonction du nombre physique de pixels nécessaire pour rendre l'image sur un appareil particulier. Ce montant dépend de la largeur de l'image, qui est calculée en fonction de l'attribut
sizes
(qui est une expression de la requête multimédia).
Cela garantit que le navigateur chargera toujours la plus petite image possible, offrant la meilleure qualité sur un appareil particulier. Alternativement, il peut sélectionner la plus petite image si l'utilisateur a activé le mode de sauvegarde des données.
Solution de secours
Pour les navigateurs qui ne prennent en charge que les anciens formats d'image, vous pouvez
srcset
fournir plus d'éléments bruts à l'aide de:
<source
sizes="(max-width: 608px) 100vw, 608px"
srcset="
/img/Z1s3TKV-1920w.webp 1920w,
/img/Z1s3TKV-1280w.webp 1280w,
/img/Z1s3TKV-640w.webp 640w,
/img/Z1s3TKV-320w.webp 320w
"
type="image/webp"
/>
<source
sizes="(max-width: 608px) 100vw, 608px"
srcset="
/img/Z1s3TKV-1920w.jpg 1920w,
/img/Z1s3TKV-1280w.jpg 1280w,
/img/Z1s3TKV-640w.jpg 640w,
/img/Z1s3TKV-320w.jpg 320w
"
type="image/jpeg"
/>
Mise en cache et URL immuables
Incorporez dans l'URL de l'image un hachage du nombre d'octets que l'image occupe. Dans l'exemple ci-dessus, je l'ai fait avec
Z1s3TKV
. Lorsque vous modifiez l'image, l'URL change également, ce qui signifie que vous pouvez appliquer une mise en cache infinie des images. Les en-têtes de mise en cache doivent ressembler à
cache-control: public,max-age=31536000,immutable
.
immutable
C'est une signification sémantiquement correcte
cache-control
, mais elle a peu de support de navigateur aujourd'hui (je vous regarde, Chrome).
max-age=31536000
- méthode de mise en cache de secours tout au long de l'année.
public
est nécessaire à votre CDN pour mettre en cache l'image et la diffuser à partir du bord du réseau. Mais cette approche ne peut être utilisée que si elle ne viole pas vos politiques de confidentialité.
Chargement paresseux
En ajoutant
loading=«lazy»
à l'élément,
img
nous disons au navigateur de commencer à récupérer l'image uniquement lorsqu'elle est prête à être rendue.
<img loading="lazy" … />
Décryptage asynchrone
En ajoutant
decoding=«async»
à l'élément,
img
nous permettons au navigateur de décrypter l'image en dehors du flux principal afin que cette procédure n'interfère pas avec l'utilisateur. Il ne devrait y avoir aucun défaut notable dans cette solution, sauf qu'elle n'est pas toujours applicable par défaut dans les anciens navigateurs.
<img decoding="async" … />
Talon flou
Un stub flou est une image en ligne qui donne à l'utilisateur une idée d'une image à part entière qui sera chargée plus tard, sans transfert de données sur le réseau.
https://www.industrialempathy.com/img/blurry.svg
Quelques notes de mise en œuvre:
- Le stub est incrusté comme des
background-image
images. Cette technique vous permet de supprimer le deuxième élément HTML en masquant littéralement le stub lorsque l'image principale est chargée, aucun JavaScript n'est nécessaire. - L'URI des données d'image principale est enveloppé dans l'URI des données d'image SVG. Ceci est fait parce que le flou se fait au niveau SVG et sans utiliser de filtre CSS. Autrement dit, le flou est effectué une fois pour chaque image rastérisée par SVG, pas pour chaque mise en page. Cela économise les ressources du processeur.
<img
style="
…
background-size: cover;
background-image:
url('data:image/svg+xml;charset=utf-8,%3Csvg xmlns=\'http%3A//www.w3.org/2000/svg\'
xmlns%3Axlink=\'http%3A//www.w3.org/1999/xlink\' viewBox=\'0 0 1280 853\'%3E%3Cfilter id=\'b\' color-interpolation-filters=\'sRGB\'%3E%3CfeGaussianBlur stdDeviation=\'.5\'%3E%3C/feGaussianBlur%3E%3CfeComponentTransfer%3E%3CfeFuncA type=\'discrete\' tableValues=\'1 1\'%3E%3C/feFuncA%3E%3C/feComponentTransfer%3E%3C/filter%3E%3Cimage filter=\'url(%23b)\' x=\'0\' y=\'0\' height=\'100%25\' width=\'100%25\'
xlink%3Ahref=\'data%3Aimage/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAkAAAAGCAIAAACepSOSAAAACXBIWXMAAC4jAAAuIwF4pT92AAAAs0lEQVQI1wGoAFf/AImSoJSer5yjs52ktp2luJuluKOpuJefsoCNowB+kKaOm66grL+krsCnsMGrt8m1u8mzt8OVoLIAhJqzjZ2tnLLLnLHJp7fNmpyjqbPCqLrRjqO7AIeUn5ultaWtt56msaSnroZyY4mBgLq7wY6TmwCRfk2Pf1uzm2WulV+xmV6rmGyQfFm3nWSBcEIAfm46jX1FkH5Djn5AmodGo49MopBLlIRBfG8yj/dfjF5frTUAAAAASUVORK5CYII=\'%3E%3C/image%3E%3C/svg%3E');
"
…
/>
(Facultatif) Optimisation JavaScript
Les navigateurs peuvent être obligés de pixelliser le stub flou même si l'image est déjà chargée. Le problème peut être résolu en supprimant la pixellisation au démarrage. De plus, si votre image comporte des zones transparentes, cette optimisation devient obligatoire, sinon un stub apparaîtra à travers l'image.
<sript>
document.body.addEventListener(
"load",
(e) => {
if (e.target.tagName != "IMG") {
return;
}
// Remove the blurry placeholder.
e.target.style.backgroundImage = "none";
},
/* capture */ true
);
</sript>
aditionellement
Un outil utile qui implémente toutes les optimisations décrites: onzeventy-high-performance-blog