Optimiser les images avec la directive Angular Image

Kara Erickson
Kara Erickson
Leena Sohoni
Leena Sohoni

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.

LCP pour les sites Web Angular au cours de la dernière année

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:

  1. 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.

  2. Hiérarchisation des images critiques

    Ajout d'optimisations de ressources (par exemple, preload ou preconnect) 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ée priority, une erreur est générée, indiquant au développeur d'ajouter l'attribut priority à 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'attribut fetchpriority de high et qu'elle n'est pas chargée de manière différée.

  3. 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.

  4. 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.

    1. 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 et height pour les images.

    2. 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 :

      1. Vous avez défini par erreur les mauvaises dimensions (largeur ou hauteur) ;
      2. Si vous avez défini une dimension en pourcentage dans votre CSS, mais pas l'autre (par exemple, width: 100% a besoin de height: auto pour que l'image augmente dans les deux dimensions).
    3. 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 attributs srcset et sizes.

    4. 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:

  1. 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 indication preload à <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'indices preload 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 et fetchpriority permet de donner la priorité à l'image au lieu d'une preload. 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é !

  2. 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.

Comparaison de la pellicule: site Web 1 avec des balises d&#39;image natives et site Web 2 avec la directive d&#39;image Angular.

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 de srcset, mais les attributs srcset et sizes doivent être fournis manuellement pour chaque image. À l'avenir, la directive pourra générer automatiquement les attributs srcset et sizes.

  • 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 attributs width et height 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:

    1. 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.
    2. 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.

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.