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. Pour beaucoup d'entre nous, la recherche d'images optimisées est donc devenue un effort constant.
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.
Les premiers résultats de Leboncoin, utilisateur de Next.js, étaient encourageants. 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 de next/image
par la communauté a ensuite contribué à augmenter le nombre d'origines Next.js qui atteignent les seuils du 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 constituent l'élément LCP de plus de 70% des pages Web sur mobile et ordinateur, les images LCP non optimisées pourraient en être l'une des principales causes sur les sites Web Angular.
La directive d'image Angular a été conçue pour améliorer ces chiffres.
MVP pour 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. La plupart des problèmes standards d'optimisation des images ont été résolus de l'une des manières suivantes:
- Fournir des valeurs par défaut sécurisées
- Générer des erreurs ou des avertissements pour garantir le respect des 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 les images non critiques de manière différée et ne charge que rapidement les images spécialement marquées comme
priority
. Cela garantit que la plupart des images présentent un comportement de chargement optimal.Hiérarchisation des images critiques
Ajout d'optimisations de ressources (par exemple,
preload
oupreconnect
) pour hiérarchiser 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 LCP a bien été marquée comme
priority
. 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 terminé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 d'image afin de s'assurer que les paramètres de compression et de format 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 beaucoup 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 distinguer une différence au-delà de deux fois plus.
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 d'image est entièrement conçue pour CSR afin de s'aligner sur le 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-unes des difficultés rencontrées:
Conseils sur les ressources associées
Le préchargement des éléments critiques permet au navigateur de les détecter plus tôt. Cependant, l'intégration d'optimisations de ressources dans les applications Angular est compliquée pour les raisons suivantes:
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. Ainsi, la valeur<head>
du document est la même pour chaque route (au moins au moment de la présentation des résultats). 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 de l'affichage:l'utilisation du framework pour ajouter des conseils de préchargement à l'en-tête du document lors de l'affichage dans une application CSR ne permet pas de résoudre le problème. É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 de suggestions
preconnect
etfetchpriority
permet de donner la priorité à l'image au lieu d'unepreload
. Cependant, Aurora travaille actuellement avec l'équipe de CLI Angular pour activer l'injection automatique d'indices de ressources au moment de la compilation. Tenez-vous informé !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).
Site Web 2: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 étape 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
prend actuellement en charge 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
exige que les attributswidth
etheight
soient spécifiés pour chaque image. Toutefois, les spécifier 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.
Nous remercions tout particulièrement Katie Hempenius et Alex Castle pour leur contribution.