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é leur collaboration sur une directive pour les images pour Angular. Cette directive a été récemment publiée en version Preview développeur dans la version 14.2 d'Angular. Cet article explique comment la nouvelle directive d'image, NgOptimizedImage, prend en charge l'optimisation des images dans Angular.

Contexte

Les images sont un composant courant et essentiel de l'expérience utilisateur sur le Web.En effet, 99,9% des pages Web génèrent des demandes pour une ou plusieurs images. Les images contribuent également de manière significative au poids des pages, avec une médiane de 982 kilo-octets par page.

En raison de leur nombre et de leur taille croissants, les images peuvent nuire aux performances des pages Web et avoir une incidence sur les métriques Core Web Vitals. Pour 79,4% des pages pour ordinateur, une image constituait l'élément LCP (Largest Contentful Paint) en 2021. Pour beaucoup d'entre nous, la recherche d'images optimisées est donc devenue un effort constant.

L'équipe d'Aurora est convaincue qu'il est important d'exploiter la puissance des frameworks pour fournir des solutions intégrées aux défis courants des développeurs. Ils ont fait leur première incursion dans le domaine de l'optimisation des images avec le composant image Next.js. Elle a considéré ce composant comme un terrain d'essai pour savoir si l'amélioration de l'expérience développeur (DX) de l'optimisation des images pouvait améliorer les performances d'un plus grand nombre 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 augmenté le nombre d'origines Next.js qui atteignent les seuils du LCP. Très vite, des demandes ont été faites pour des fonctionnalités similaires dans d'autres frameworks, dont Angular.

Aurora a donc collaboré avec Angular et Nuxt pour prototyper des composants d'image pour ces frameworks. Le composant Image Nuxt est sorti l'année dernière. La directive d'image Angular (NgOptimizedImage) a été publiée pour utiliser Angular par défaut pour l'optimisation des images.

Opportunité

Angular est actuellement l'un des principaux frameworks JavaScript utilisés par les développeurs. Il est utilisé par plus de 50 000 origines explorées par HTTPArchive sur mobile et peut être téléchargé près de 3 millions chaque semaine sur NPM.

LCP des sites Web Angular au cours de l'année écoulée.

Si l'on considère les scores Core Web Vitals, le pourcentage d'origines Angular qui atteignent les seuils LCP d'un "bon" seuil doit encore être retravaillé. En juin 2022, seulement 18,74% des sites Angular affichaient un bon LCP sur mobile. É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 produit minimum viable de la directive d'image Angular s'appuie sur les leçons tirées 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 solides.
  • Générer des erreurs ou des avertissements pour garantir le respect des bonnes pratiques

Les points forts de la conception sont les suivants:

  1. Chargement différé intelligent

    Les images qui ne sont pas visibles par l'utilisateur lors du chargement de la page (par exemple, les images en dessous de la ligne de flottaison ou les images masquées du carrousel) doivent idéalement être chargées de manière différée. Le chargement différé libère des ressources du navigateur pour permettre le chargement d'autres textes, contenus multimédias ou scripts essentiels. La plupart des images ne sont pas critiques et devraient être chargées en différé.Toutefois, en 2021, seules 7,8% des pages utilisaient le chargement différé natif.

    Par défaut, la directive d'image Angular charge les images non critiques de manière différée et ne charge que hâtivement les images spécialement marquées comme priority. Cela garantit que le comportement de chargement de la plupart des images est optimal.

  2. Hiérarchisation des images critiques

    Ajouter des indices 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, seules 12,7% des pages mobiles utilisent des indications de préconnexion et seulement 22,1% des pages mobiles utilisent des indications de préchargement.

    La directive d'image agit sur deux fronts lorsque les images sont marquées comme prioritaires.

    • Il définit la valeur fetchPriority de l'image sur "high" afin que le navigateur sache qu'il doit télécharger l'image avec une priorité élevée.
    • En mode développement, une vérification de l'environnement d'exécution confirme qu'un indicateur de ressource preconnect a été inclus 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 comme priority, une erreur est générée, demandant au développeur d'ajouter l'attribut priority à l'image LCP.

    En fin de compte, cette combinaison d'automatisation et de conformité garantit que l'image LCP comporte une indication preconnect, une valeur d'attribut fetchpriority définie sur high et qu'elle n'est pas chargée de manière différée.

  3. Configuration optimisée pour les outils d'images courants

    Il est recommandé aux applications Angular d'utiliser des CDN pour les images, qui fournissent souvent des services d'optimisation par défaut.

    Cette directive encourage l'utilisation des CDN d'images en offrant une expérience de développement (DX) particulièrement attrayante pour les développeurs afin de les configurer dans l'application. Elle est compatible avec une API de chargement 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 aux chargeurs intégrés une configuration optimale pour les CDN d'images les plus courants. 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 des vérifications intégrées qui permettent de s'assurer que les développeurs ont suivi les bonnes pratiques recommandées concernant le balisage des images. La directive "image" effectue les vérifications suivantes.

    1. Images non dimensionnées:la directive "image" génère une erreur si le balisage d'image n'a pas défini de largeur et de hauteur explicites. Les images non dimensionnées peuvent entraîner des décalages de mise en page, qui affectent la métrique CLS (Cumulative Layout Shift) de la page. Pour éviter cela, il est recommandé de spécifier les attributs width et height des images.

    2. Format:la directive d'image génère une erreur pour indiquer aux développeurs si le format de la valeur width:height définie dans le code HTML n'est pas proche du format réel de l'image affichée. L'image peut alors être déformée à l'écran. Cela peut se produire si

      1. Vous avez défini des dimensions incorrectes (largeur ou hauteur) par erreur.
      2. Si vous avez défini une dimension en pourcentage dans votre code CSS, mais pas l'autre (par exemple, width: 100% a besoin de height: auto pour que l'image s'agrandit 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 dans le fichier srcset une image dont la densité en pixels est supérieure à 3x. Les descripteurs supérieurs à 2x ne sont généralement pas recommandés, car cela a pour conséquence involontaire de forcer les appareils mobiles haute résolution à télécharger des images très volumineuses. De plus, l'œil humain ne peut pas vraiment distinguer une différence au-delà de deux fois plus.

Difficultés

Lors de la conception de NgOptimizedImage, l'un des principaux défis consistait à adapter les stratégies d'optimisation des images pour qu'elles fonctionnent dans un framework côté client. L'expérience d'affichage par défaut sur Next.js est le rendu côté serveur (SSR) ou la génération de sites statiques (SSG), tandis que sur Angular, il s'agit du rendu côté client (CSR, Client Side Rendering). Même si Angular est compatible avec une bibliothèque SSR (angulaire/universelle), la plupart des applications Angular (environ 60%) utilisent la requête de signature de certificat.

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. Compatibilité avec les indices de ressources

    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'indicateur de ressource preload. Angular utilise un fichier index.html partagé pour l'ensemble du projet ou pour toutes les routes 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). Si vous ajoutez une suggestion preload à <head>, la ressource sera préchargée pour toutes les routes, même si elle n'est pas requise. Par conséquent, l'ajout manuel d'indicateurs preload n'est pas recommandé.

    Ajout automatique pendant 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 a lieu après le téléchargement et l'exécution de JavaScript, le <head> s'affiche trop tard pour avoir une valeur quelconque.

    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. C'est pourquoi nous vous recommandons d'utiliser des CDN pour les images afin de compresser les images et de les convertir dans des 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 permettent de s'assurer que les options de configuration appropriées sont utilisées.

Impact

La démonstration suivante montre la différence que la directive d'image Angular peut apporter aux 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 des 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 tags d&#39;image natifs et site Web 2 avec la directive d&#39;image Angular.

L'équipe a collaboré avec des partenaires pour valider l'impact de la directive "Image" sur les performances sur des applications Angular d'entreprise réelles.

Land's End était l'un de ces partenaires. On s'attendait à ce que ce site constitue un bon scénario de test pour des résultats que des applications réelles pourraient obtenir.

Des tests en laboratoire phare ont été effectués dans l'environnement de contrôle qualité avant et après l'utilisation de la directive sur les images. Sur les ordinateurs, son LCP médian est passé de 12 s à 3 s, ce qui représente une amélioration de 75% du LCP. Sur les mobiles, le LCP médian est passé de 20,2 s à 12 s (amélioration de 40,6 %).

Feuille de route future

Ce n'est que la première étape de la conception de la directive d'image Angular. De nombreuses autres fonctionnalités sont prévues pour les versions futures, parmi lesquelles:

  • Meilleure compatibilité avec les images responsives:

    NgOptimizedImage est actuellement compatible avec l'utilisation de srcset, mais les attributs srcset et sizes doivent être fournis manuellement pour chaque image. À l'avenir, la directive pourrait générer automatiquement les attributs srcset et sizes.

  • Injection automatique d'indices de ressources

    Il est possible d'intégrer la CLI Angular afin de générer des tags de préconnexion et de préchargement pour les images LCP critiques.

  • Compatibilité avec Angular SSR

    La version MVP est conçue en tenant compte des contraintes CSR Angular, mais il sera également important d'explorer les solutions d'optimisation des images pour Angular SSR (angulaire/universel).

  • Améliorations de l'expérience pour les 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. Dans la prochaine itération, l'expérience des développeurs pourrait être améliorée, comme suit:

    1. Prise en charge d'un mode supplémentaire (semblable à l'option de mise en page d'image "fill" dans Next.js) qui ne nécessite pas de définir une largeur et une hauteur explicites.
    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 laissez un commentaire !

Nous remercions tout particulièrement Katie Hempenius et Alex Castle pour leur contribution.