En mai 2022, les équipes Aurora et Angular ont annoncé qu'elles collaboreraient sur une directive d'image pour Angular. La directive a récemment été publiée en version Preview développeur dans Angular v14.2. Cet article explique comment la nouvelle directive d'image, NgOptimizedImage
, prend en charge l'optimisation des images dans Angular.
Contexte
Les images sont un élément courant et essentiel de l'expérience utilisateur sur le Web.99, 9% des pages Web génèrent des requêtes pour une ou plusieurs images. Les images sont également le facteur le plus important du poids des pages, représentant une valeur médiane de 982 ko par page.
En raison de leur nombre et de leur taille croissants, les images peuvent nuire aux performances des pages Web et affecter les métriques Core Web Vitals. En 2021, une image était l'élément LCP (Largest Contentful Paint) pour 79,4% des pages pour ordinateur. La recherche d'images optimisées est donc devenue une tâche constante pour beaucoup d'entre nous.
L'équipe Aurora s'appuie sur la puissance des frameworks pour fournir des solutions intégrées aux défis courants des développeurs. Leur première incursion dans l'optimisation des images a été le composant d'image Next.js. Ils ont considéré ce composant comme un terrain d'essai pour déterminer si l'amélioration de l'expérience de développement de l'optimisation des images pouvait améliorer les performances de davantage d'applications utilisant des frameworks.
Le premier ensemble de résultats de l'utilisateur Next.js Leboncoin a été encourageant. Leboncoin a constaté une amélioration significative du LCP (de 2,4 s à 1,7 s) après avoir commencé à utiliser next/image
. L'adoption ultérieure de next/image
dans la communauté a contribué à l'augmentation du nombre d'origines Next.js répondant aux seuils de LCP. Des demandes de fonctionnalités similaires ont rapidement été formulées dans d'autres frameworks, dont Angular.
Aurora a donc consulté Angular et Nuxt pour créer des prototypes de composants d'image pour ces frameworks. Le composant Image Nuxt a été publié l'année dernière. La directive d'image Angular (NgOptimizedImage
) est désormais disponible pour apporter les valeurs par défaut d'optimisation des images à Angular.
Opportunité
Angular est l'un des principaux frameworks JavaScript utilisés par les développeurs aujourd'hui. Il est utilisé par plus de 50 000 origines explorées par HTTPArchive sur mobile et enregistre presque trois millions de téléchargements hebdomadaires sur NPM.
En examinant les scores Core Web Vitals, le pourcentage d'origines Angular qui atteignent les seuils de LCP "Bon" doit encore être amélioré. Seuls 18,74% des sites Angular avaient un LCP correct sur mobile en juin 2022. Étant donné que les images sont l'élément LCP de plus de 70% des pages Web sur mobile et sur ordinateur, les images LCP non optimisées peuvent être l'une des principales causes d'un LCP inférieur sur les sites Web Angular.
La directive d'image Angular a été conçue pour améliorer ces chiffres.
Version minimale viable de la directive NgOptimizedImage
Le MVP de la directive d'image Angular s'appuie sur les enseignements tirés des composants d'image qu'Aurora a créés à ce jour, tout en adaptant la conception à l'expérience de rendu côté client d'Angular. De nombreux problèmes d'optimisation d'images standards ont été résolus par:
- Fournir des valeurs par défaut sécurisées
- Générer des erreurs ou des avertissements pour vous assurer de respecter les bonnes pratiques
Voici les points forts de la conception:
Chargement différé intelligent
Les images invisibles pour l'utilisateur lors du chargement de la page (par exemple, les images en dessous de la ligne de flottaison ou les images de carrousel masquées) doivent idéalement être chargées de manière différée. Le chargement paresseux libère les ressources du navigateur pour charger d'autres éléments textuels, multimédias ou scripts critiques. La plupart des images ne sont pas essentielles et doivent être chargées de manière différée, mais seulement 7,8% des pages utilisaient le chargement différé natif en 2021.
Par défaut, la directive d'image Angular charge de manière paresseuse les images non critiques et ne charge de manière anticipée que les images spécialement marquées comme
priority
. Cela garantit que la plupart des images présentent un comportement de chargement optimal.Priorisation des images critiques
Ajout d'optimisations de ressources (par exemple,
preload
oupreconnect
) pour prioriser le chargement des images critiques est une bonne pratique recommandée. Cependant, la plupart des applications ne les utilisent pas. Selon l'Almanach Web 2021, seuls 12,7% des pages mobiles utilisent des hints de préconnexion et 22,1% seulement utilisent des hints de préchargement.La directive image agit sur deux fronts lorsque les images sont marquées comme prioritaires.
- Il définit la priorité de récupération de l'image sur
"high"
afin que le navigateur sache qu'il doit télécharger l'image en priorité. - En mode développement, une vérification d'exécution confirme qu'une indication de ressource
preconnect
a été incluse correspondant à l'origine de l'image.
En mode développement, la directive utilise également l'API PerformanceObserver pour vérifier que l'image du LCP a été marquée
priority
comme prévu. Si elle n'est pas marquéepriority
, une erreur est générée, indiquant au développeur d'ajouter l'attributpriority
à l'image du LCP.En fin de compte, cette combinaison d'automatisation et de conformité garantit que l'image LCP comporte un indice
preconnect
, une valeur d'attributfetchpriority
dehigh
et qu'elle n'est pas chargée de manière différée.- Il définit la priorité de récupération de l'image sur
Configuration optimisée pour les outils d'image populaires
Nous recommandons aux applications Angular d'utiliser des CDN d'images, qui fournissent souvent des services d'optimisation par défaut.
Cette directive encourage l'utilisation de CDN d'images en offrant une expérience de développement (DX) particulièrement attrayante pour les configurer dans l'application. Elle est compatible avec une API de chargeur qui vous permet de définir le fournisseur de CDN et votre URL de base dans votre configuration. Une fois la configuration effectuée, il vous suffit de définir le nom de l'asset dans le balisage. Par exemple,
// in module providers: provideImgixLoader('https://mysite.net/assets/') // in markup <img ngSrc="image.png" > <img ngSrc="image2.png" >
Cela équivaut à inclure les balises d'image suivantes et réduit le balisage que les développeurs doivent inclure pour chaque image.
<img src="https://mysite.net/assets/image.png"> <img src="https://mysite.net/assets/image2.png">
La directive image fournit des chargeurs intégrés avec une configuration optimale pour les CDN d'images les plus populaires. Ces chargeurs formatent automatiquement les URL des images pour s'assurer que les paramètres de compression et de format d'image recommandés sont utilisés pour chaque CDN.
Erreurs et avertissements intégrés
En plus des optimisations intégrées ci-dessus, la directive comporte également des vérifications intégrées pour s'assurer que les développeurs ont suivi les bonnes pratiques recommandées dans le balisage des images. La directive image effectue les vérifications suivantes.
Images non redimensionnées:la directive image génère une erreur si la balise de l'image n'a pas défini de largeur et de hauteur explicites. Les images non redimensionnées peuvent entraîner des décalages de mise en page, ce qui affecte la métrique CLS (Cumulative Layout Shift) de la page. Pour éviter cela, nous vous recommandons de spécifier les attributs
width
etheight
pour les images.Format:la directive image génère une erreur pour indiquer aux développeurs si le format de
width
:height
défini dans le code HTML n'est pas proche du format réel de l'image affichée. L'image peut alors sembler déformée à l'écran. Cela peut se produire dans les cas suivants :- Vous avez défini par erreur les mauvaises dimensions (largeur ou hauteur) ;
- Si vous avez défini une dimension en pourcentage dans votre CSS, mais pas l'autre (par exemple,
width: 100%
a besoin deheight: auto
pour que l'image augmente dans les deux dimensions).
Images surdimensionnées:si l'image ne définit pas de
srcset
et que l'image intrinsèque est nettement plus grande que l'image affichée, la directive affiche un avertissement suggérant d'utiliser les attributssrcset
etsizes
.Densité d'image:la directive génère une erreur si vous essayez d'inclure une image dans
srcset
avec une densité de pixels supérieure à3x
. Les descripteurs supérieurs à2x
ne sont généralement pas recommandés, car ils ont pour conséquence involontaire de forcer les appareils mobiles haute résolution à télécharger des images énormes. De plus, l'œil humain ne peut pas vraiment faire la différence au-delà d'un zoom 2x.
Défis
L'adaptation des stratégies d'optimisation des images à un framework côté client a été le principal défi lors de la conception de NgOptimizedImage
. L'expérience de rendu par défaut sur Next.js est le rendu côté serveur (SSR) ou la génération de site statique (SSG), tandis que celle sur Angular est le rendu côté client (CSR). Même si Angular est compatible avec une bibliothèque SSR (angular/universal), la plupart des applications Angular (environ 60%) utilisent le CSR.
La directive image est entièrement conçue pour le CSR afin de s'adapter au cas d'utilisation typique des applications Angular. Cela a entraîné des contraintes supplémentaires, et l'équipe a dû repenser la façon de créer des optimisations spécifiques pour les applications CSR.
Voici quelques-uns des défis rencontrés:
Conseils sur les ressources associées
Le préchargement des composants critiques permet au navigateur de les découvrir plus tôt. Toutefois, l'inclusion d'indices de ressources dans les applications Angular est complexe, car:
Ajout manuel: il est difficile pour les développeurs d'ajouter manuellement l'indice de ressource
preload
. Angular utilise un fichier index.html partagé pour l'ensemble du projet ou pour tous les chemins du site Web. Par conséquent, l'<head>
du document est le même pour chaque itinéraire (au moins au moment de la diffusion). Ajouter une indicationpreload
à<head>
signifie que la ressource sera préchargée pour toutes les routes, même si ce n'est pas nécessaire. Par conséquent, l'ajout manuel d'indicespreload
n'est pas recommandé.Ajout automatique lors du rendu:l'utilisation du framework pour ajouter des indices de préchargement à l'en-tête du document lors du rendu dans une application CSR ne vous aidera pas. Étant donné que l'affichage se produit après le téléchargement et l'exécution du code JavaScript, l'
<head>
sera affiché trop tard pour être utile.Pour la première version de la directive, une combinaison d'indices
preconnect
etfetchpriority
permet de hiérarchiser l'image au lieu d'unpreload
. Cependant, Aurora travaille actuellement avec l'équipe Angular CLI pour permettre l'injection automatique d'indices de ressources au moment de la compilation. Tenez-vous prêt !Optimiser la taille et le format des images sur le serveur
Étant donné que les applications Angular sont généralement affichées côté client, les images du système de fichiers ne peuvent pas être compressées au moment de la requête et sont diffusées telles quelles. Pour cette raison, nous vous recommandons d'utiliser des CDN d'images pour compresser les images et les convertir en formats modernes tels que WebP ou AVIF à la demande.
Bien que la directive n'impose pas l'utilisation de CDN d'images, nous vous recommandons vivement de les utiliser avec la directive. Ses chargeurs intégrés garantissent que les options de configuration appropriées sont utilisées.
Impact
La démonstration suivante montre l'impact de la directive d'image Angular sur les performances des images. Il compare deux sites Web:
Site Web 1:utilise des éléments <img>
natifs avec des images diffusées via le CDN Imgix (avec les options de configuration par défaut).
Deuxième site Web:utilisez la directive image pour toutes les images. Il inclut également les optimisations recommandées directement par les avertissements ou les erreurs générés par la directive.
L'équipe a travaillé avec des partenaires pour valider l'impact des performances de la directive d'image sur des applications Angular d'entreprise réelles.
Land's End en faisait partie. Son site devait servir de bon cas de test pour les résultats que des applications réelles pourraient obtenir.
Des tests Lighthouse en laboratoire ont été effectués sur leur environnement de contrôle qualité avant et après l'utilisation de la directive image. Sur ordinateur, leur LCP médian est passé de 12 secondes à 3 secondes, soit une amélioration de 75 %. Sur mobile, le LCP médian est passé de 20,2 s à 12,0 s (amélioration de 40,6 %).
Feuille de route future
Il ne s'agit que de la première partie de la conception de la directive d'image Angular. De nombreuses autres fonctionnalités sont prévues pour les futures versions, dont les suivantes:
Compatibilité améliorée avec les images responsives :
NgOptimizedImage
accepte actuellement l'utilisation desrcset
, mais les attributssrcset
etsizes
doivent être fournis manuellement pour chaque image. À l'avenir, la directive pourra générer automatiquement les attributssrcset
etsizes
.Injection automatique d'indices de ressources
Il est possible d'intégrer la CLI Angular pour générer des tags de préconnexion et de préchargement pour les images LCP critiques.
Compatibilité avec le SSR Angular
La version MVP est conçue en tenant compte des contraintes de CSR Angular, mais il sera également important d'explorer des solutions d'optimisation des images pour le SSR Angular (angular/universal).
Améliorations de l'expérience des développeurs
NgOptimizedImage
nécessite que les attributswidth
etheight
soient spécifiés pour chaque image. Toutefois, spécifier ces éléments pour chaque image peut être fastidieux pour certains développeurs. Nous pouvons améliorer l'expérience des développeurs lors de la prochaine itération comme suit:- Prise en charge d'un mode supplémentaire (similaire à l'option de mise en page d'image "
fill
" dans Next.js) qui ne nécessite pas de définir explicitement la largeur/hauteur. - Utilisation de l'intégration de la CLI pour définir automatiquement la largeur et la hauteur des images locales en déterminant les dimensions réelles de l'image.
- Prise en charge d'un mode supplémentaire (similaire à l'option de mise en page d'image "
Conclusion
La directive d'image Angular sera disponible pour les développeurs par étapes, à partir de la version preview développeur v14.2.0. Essayez NgOptimizedImage
et envoyez-nous vos commentaires.
Un merci spécial à Katie Hempenius et Alex Castle pour leur contribution.