Ottimizzazione delle immagini con la direttiva Angular Image

Kara Erickson
Kara Erickson
Leena Sohoni
Leena Sohoni

A maggio 2022, i team di Aurora e Angular hanno annunciato che avrebbero collaborato a una direttiva per le immagini per Angular. La direttiva è stata rilasciata di recente per la preview per sviluppatori nell'ambito di Angular v14.2. Questo post spiega in che modo la nuova direttiva immagine NgOptimizedImage supporta l'ottimizzazione delle immagini in Angular.

Sfondo

Le immagini sono un componente comune e fondamentale dell'esperienza utente web, con il 99,9% delle pagine web che generano richieste di una o più immagini. Le immagini sono anche il fattore più significativo per il peso della pagina, costituendo una media di 982 kilobyte per pagina.

A causa del loro numero e delle loro dimensioni in crescita, le immagini possono ostacolare il rendimento delle pagine web e influire sulle metriche di Segnali web essenziali. Nel 2021, per il 79,4% delle pagine desktop, un'immagine era l'elemento Largest Contentful Paint (LCP). La ricerca di immagini ottimizzate è quindi diventata un'attività costante per molti di noi.

Il team di Aurora crede nell'utilizzo della potenza dei framework per fornire soluzioni integrate alle sfide comuni degli sviluppatori. Il loro primo approccio allo spazio di ottimizzazione delle immagini è stato il componente immagine Next.js. Hanno considerato questo componente un banco di prova per verificare se il miglioramento dell'esperienza degli sviluppatori (DX) dell'ottimizzazione delle immagini potesse portare a un miglioramento delle prestazioni per un maggior numero di app che utilizzano i framework.

La prima serie di risultati dell'utente Next.js Leboncoin è stata incoraggiante. Leboncoin ha registrato un miglioramento significativo dell'LCP (da 2,4 a 1,7 secondi) dopo aver iniziato a utilizzare next/image. L'adozione successiva di next/image nella community ha contribuito all'aumento delle origini Next.js che soddisfano le soglie LCP. Ben presto sono arrivate richieste di funzionalità simili in altri framework, tra cui Angular.

Di conseguenza, Aurora ha consultato Angular e Nuxt per realizzare il prototipo dei componenti immagine per questi framework. Il componente immagine Nuxt è stato rilasciato lo scorso anno. Ora è stata rilasciata la direttiva immagine Angular (NgOptimizedImage) per portare le impostazioni predefinite di ottimizzazione delle immagini ad Angular.

Opportunità

Angular è uno dei principali framework JavaScript utilizzati oggi dagli sviluppatori. Viene utilizzato da più di 50.000 origini sottoposte a scansione da HTTPArchive su dispositivi mobili e vanta quasi 3 milioni di download settimanali su NPM.

LCP per i siti web Angular nell'ultimo anno.

Se guardiamo ai punteggi Core Web Vitals, la percentuale di origini Angular che soddisfano le soglie LCP "buone" deve ancora essere migliorata. A giugno 2022, solo il 18,74% dei siti Angular aveva un buon LCP su dispositivi mobili. Poiché le immagini sono l'elemento LCP per oltre il 70% delle pagine web su dispositivi mobili e computer, le immagini LCP non ottimizzate potrebbero essere una delle cause principali di un LCP peggiore sui siti web Angular.

La direttiva di immagine Angular è stata progettata per contribuire a migliorare questi numeri.

MVP per la direttiva NgOptimizedImage

L'MVP della direttiva immagine di Angular si basa sulle lezioni apprese dai componenti immagine che Aurora ha creato finora, adattando al contempo il design all'esperienza di rendering lato client di Angular. Molti dei problemi di ottimizzazione delle immagini standard sono stati risolti:

  • Fornire impostazioni predefinite efficaci.
  • Generare errori o avvisi per garantire la conformità alle best practice.

I punti salienti del design sono i seguenti:

  1. Caricamento lento intelligente

    Le immagini invisibili all'utente al caricamento della pagina (ad esempio le immagini sotto la piega o le immagini del carosello nascoste) dovrebbero idealmente essere caricate in modo lazy. Il caricamento lento libera le risorse del browser per caricare altri testi, contenuti multimediali o script critici. La maggior parte delle immagini non è critica e dovrebbe essere caricata in modo lazy, ma solo il 7,8% delle pagine ha utilizzato il caricamento lazy nativo nel 2021.

    La direttiva immagine Angular carica in modo lazy le immagini non critiche per impostazione predefinita e carica in modo eager solo le immagini contrassegnate appositamente come priority. In questo modo, la maggior parte delle immagini presenta un comportamento di caricamento ottimale.

  2. Assegnazione della priorità alle immagini critiche

    Aggiunta di suggerimenti per le risorse (ad es. preload o preconnect) per dare la priorità al caricamento delle immagini critiche è una best practice consigliata. Tuttavia, la maggior parte delle app non le utilizza. Secondo l'Almanacco del web 2021, solo il 12,7% delle pagine mobile utilizza i suggerimenti di preconnessione e solo il 22,1% delle pagine mobile utilizza i suggerimenti di precaricamento.

    La direttiva image agisce su due fronti quando le immagini sono contrassegnate come prioritarie.

    • Imposta fetchpriority dell'immagine su "high" in modo che il browser sappia che deve scaricare l'immagine con una priorità elevata.
    • In modalità di sviluppo, un controllo di runtime conferma che è stato incluso un suggerimento della risorsa preconnect corrispondente all'origine dell'immagine.

    In modalità di sviluppo, la direttiva utilizza anche l'API PerformanceObserver per verificare che l'immagine LCP sia stata contrassegnata come priority come previsto. Se non è contrassegnato come priority, viene generato un errore che indica allo sviluppatore di aggiungere l'attributo priority all'immagine LCP.

    In definitiva, questa combinazione di automazione e conformità garantisce che l'immagine LCP abbia un suggerimento preconnect, un valore dell'attributo fetchpriority pari a high e non sia caricata in modo lazy.

  3. Configurazione ottimizzata per gli strumenti di elaborazione delle immagini più diffusi

    Per le applicazioni Angular è consigliabile utilizzare CDN di immagini, che spesso forniscono servizi di ottimizzazione per impostazione predefinita.

    La direttiva incoraggia l'utilizzo delle CDN di immagini fornendo un'esperienza utente (DX) particolarmente accattivante per configurarle nell'app. Supporta un'API loader che ti consente di definire il provider CDN e l'URL base nella configurazione. Una volta configurato, devi solo definire il nome della risorsa nel markup. Ad esempio,

    // in module providers:
    provideImgixLoader('https://mysite.net/assets/')
    
    // in markup
    <img ngSrc="image.png" >
    <img ngSrc="image2.png" >
    

    Ciò equivale a includere i seguenti tag immagine e riduce il markup che gli sviluppatori devono includere per ogni immagine.

    <img src="https://mysite.net/assets/image.png">
    <img src="https://mysite.net/assets/image2.png">
    

    La direttiva image fornisce caricatori integrati con una configurazione ottimale per le CDN di immagini più utilizzate. Questi caricatori formattano automaticamente gli URL delle immagini per garantire che vengano utilizzate le impostazioni di compressione e formato delle immagini consigliate per ogni CDN.

  4. Errori e avvisi integrati

    Oltre alle ottimizzazioni integrate sopra indicate, la direttiva include anche controlli integrati per garantire che gli sviluppatori abbiano seguito le best practice consigliate nel markup delle immagini. La direttiva image esegue i seguenti controlli.

    1. Immagini senza dimensioni: l'istruzione image genera un errore se il markup dell'immagine non ha definito una larghezza e un'altezza esplicite. Le immagini senza dimensioni possono causare variazioni del layout, che influiscono sulla metrica Variazione layout cumulativa (CLS) della pagina. La best practice consigliata per evitare questo problema è specificare gli attributi width e height per le immagini.

    2. Proporzioni: la direttiva image genera un errore per informare gli sviluppatori se le proporzioni di width:height definite in HTML non sono vicine alle proporzioni effettive dell'immagine visualizzata. Ciò può causare la distorsione dell'immagine sullo schermo. Ciò può accadere se

      1. Per errore hai definito le dimensioni sbagliate (larghezza o altezza) o
      2. Se hai definito una dimensione in base alla percentuale nel CSS, ma non l'altra (ad esempio, width: 100% ha bisogno di height: auto per garantire che l'immagine cresca in entrambe le dimensioni).
    3. Immagini di grandi dimensioni: se l'immagine non definisce un attributo srcset e l'immagine intrinseca è notevolmente più grande dell'immagine visualizzata, la direttiva mostrerà un avviso che suggerisce l'utilizzo degli attributi srcset e sizes.

    4. Densità delle immagini: la direttiva restituirà un errore se provi a includere un'immagine in srcset con una densità di pixel superiore a 3x. In genere, i descrittori superiori a 2x non sono consigliati perché hanno la conseguenza indesiderata di costringere i dispositivi mobili ad alta risoluzione a scaricare immagini enormi. Inoltre, l'occhio umano non riesce a distinguere una grande differenza oltre il doppio.

Sfide

L'adattamento delle strategie di ottimizzazione delle immagini per il funzionamento in un framework lato client è stata una delle principali sfide durante la progettazione di NgOptimizedImage. L'esperienza di rendering predefinita su Next.js è il rendering lato server (SSR) o la generazione di siti statici (SSG), mentre su Angular è il rendering lato client (CSR). Anche se Angular supporta una libreria SSR (angular/universal), la maggior parte delle app Angular (circa il 60%) utilizza CSR.

La direttiva image è interamente creata per il CSR in modo da allinearsi al caso d'uso tipico nelle app Angular. Ciò ha imposto vincoli aggiuntivi e il team ha dovuto ripensare a come creare ottimizzazioni specifiche per le app CSR.

Di seguito sono riportate alcune delle difficoltà riscontrate:

  1. Suggerimenti per le risorse di supporto

    Il precaricamento degli asset critici consente al browser di rilevarli prima. Tuttavia, l'inclusione di suggerimenti sulle risorse nelle app Angular è complicata perché:

    Aggiunta manuale: per gli sviluppatori è difficile aggiungere manualmente l'indicazione della risorsa preload. Angular utilizza un file index.html condiviso per l'intero progetto o per tutte le route del sito web. Pertanto, il valore <head> del documento è lo stesso per ogni percorso (almeno al momento della pubblicazione). L'aggiunta di un qualsiasi suggerimento preload a <head> comporterà il precaricamento della risorsa per tutti i percorsi anche se non è richiesta. Pertanto, l'aggiunta manuale di suggerimenti preload non è consigliata.

    Aggiunta automatica durante il rendering: l'utilizzo del framework per aggiungere suggerimenti di precaricamento all'intestazione del documento durante il rendering in un'app CSR non è utile. Poiché il rendering avviene dopo il download ed esecuzione di JavaScript, <head> verrà visualizzato troppo tardi per avere valore.

    Per la prima versione della direttiva, una combinazione di suggerimenti preconnect e fetchpriority serve per dare la priorità all'immagine al posto di un preload. Tuttavia, Aurora sta attualmente collaborando con il team di Angular CLI per abilitare l'iniezione automatica dei suggerimenti sulle risorse in fase di compilazione. Continua a seguirci.

  2. Ottimizzazione delle dimensioni e del formato delle immagini sul server

    Poiché le app Angular vengono in genere visualizzate lato client, le immagini sul file system non possono essere compresse al momento della richiesta e vengono pubblicate così come sono. Per questo motivo, è consigliabile utilizzare CDN di immagini per comprimere le immagini e convertirle in formati moderni come WebP o AVIF su richiesta.

    Sebbene la direttiva non imponga l'utilizzo di CDN di immagini, ti consigliamo vivamente di utilizzarle con la direttiva e i relativi caricatori integrati per assicurarti che vengano utilizzate le opzioni di configurazione corrette.

Impatto

La seguente demo mostra la differenza che la direttiva image di Angular può fare sul rendimento delle immagini. Mette a confronto due siti web:

Sito web 1: utilizza elementi <img> nativi con immagini pubblicate tramite la CDN Imgix (con le opzioni di configurazione predefinite).

Secondo sito web: utilizza la direttiva image per tutte le immagini. Sono incluse anche le ottimizzazioni consigliate direttamente dagli avvisi o dagli errori generati dalla direttiva.

Confronto della sequenza di immagini: sito web 1 con tag immagine nativi e sito web 2 con la direttiva image di Angular.

Il team ha collaborato con i partner per convalidare l'impatto delle prestazioni della direttiva immagine sulle applicazioni Angular aziendali reali.

Uno di questi partner era Land's End. Ci si aspettava che il suo sito fosse un buon caso di test per i risultati che potrebbero essere visualizzati dalle applicazioni reali.

I test di Lighthouse Lab sono stati eseguiti nell'ambiente di QA prima e dopo l'utilizzo della direttiva delle immagini. Su computer, il valore LCP mediano è diminuito da 12,0 secondi a 3,0 secondi, con un miglioramento del 75%. Sui dispositivi mobili, il valore mediano LCP è diminuito da 20,2 secondi a 12 secondi (miglioramento del 40,6%).

Roadmap futura

Questa è solo la prima parte del design della direttiva di immagine Angular. Sono previste molte altre funzionalità per le versioni future, tra cui:

  • Migliore supporto per le immagini adattabili:

    Al momento NgOptimizedImage supporta l'utilizzo di srcset, ma gli attributi srcset e sizes devono essere forniti manualmente per ogni immagine. In futuro, la direttiva potrebbe generare automaticamente gli attributi srcset e sizes.

  • Inserimento automatico di suggerimenti per le risorse

    Potrebbe essere possibile eseguire l'integrazione con Angular CLI per generare tag preconnect e di precaricamento per le immagini LCP critiche.

  • Supporto di Angular SSR

    La versione MVP è progettata tenendo conto dei vincoli di Angular CSR, ma sarà anche importante esplorare le soluzioni di ottimizzazione delle immagini per Angular SSR (angular/universal).

  • Miglioramenti all'esperienza degli sviluppatori

    NgOptimizedImage richiede che gli attributi width e height siano specificati per ogni immagine. Tuttavia, specificarli per ogni immagine potrebbe essere faticoso per alcuni sviluppatori. Nella prossima iterazione, è possibile migliorare l'esperienza degli sviluppatori nel seguente modo:

    1. Supporta una modalità aggiuntiva (simile all'opzione di layout delle immagini"fill" in Next.js) che non richiede la definizione di larghezza/altezza esplicite.
    2. Utilizzo dell'integrazione della CLI per impostare automaticamente la larghezza e l'altezza delle immagini locali determinando le dimensioni effettive dell'immagine.

Conclusione

La direttiva di immagine Angular sarà disponibile per gli sviluppatori in più fasi, a partire dalla versione di anteprima per sviluppatori nella v14.2.0. Prova NgOptimizedImage e lascia un feedback.

Un ringraziamento speciale a Katie Hempenius e Alex Castle per il loro contributo.