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.
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:
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.Assegnazione della priorità alle immagini critiche
Aggiunta di suggerimenti per le risorse (ad es.
preload
opreconnect
) 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 comepriority
, viene generato un errore che indica allo sviluppatore di aggiungere l'attributopriority
all'immagine LCP.In definitiva, questa combinazione di automazione e conformità garantisce che l'immagine LCP abbia un suggerimento
preconnect
, un valore dell'attributofetchpriority
pari ahigh
e non sia caricata in modo lazy.- Imposta fetchpriority dell'immagine su
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.
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.
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
eheight
per le immagini.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- Per errore hai definito le dimensioni sbagliate (larghezza o altezza) o
- Se hai definito una dimensione in base alla percentuale nel CSS, ma non l'altra (ad esempio,
width: 100%
ha bisogno diheight: auto
per garantire che l'immagine cresca in entrambe le dimensioni).
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 attributisrcset
esizes
.Densità delle immagini: la direttiva restituirà un errore se provi a includere un'immagine in
srcset
con una densità di pixel superiore a3x
. In genere, i descrittori superiori a2x
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:
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 suggerimentopreload
a<head>
comporterà il precaricamento della risorsa per tutti i percorsi anche se non è richiesta. Pertanto, l'aggiunta manuale di suggerimentipreload
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
efetchpriority
serve per dare la priorità all'immagine al posto di unpreload
. 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.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.
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 disrcset
, ma gli attributisrcset
esizes
devono essere forniti manualmente per ogni immagine. In futuro, la direttiva potrebbe generare automaticamente gli attributisrcset
esizes
.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 attributiwidth
eheight
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:- Supporta una modalità aggiuntiva (simile all'opzione di layout delle immagini"
fill
" in Next.js) che non richiede la definizione di larghezza/altezza esplicite. - Utilizzo dell'integrazione della CLI per impostare automaticamente la larghezza e l'altezza delle immagini locali determinando le dimensioni effettive dell'immagine.
- Supporta una modalità aggiuntiva (simile all'opzione di layout delle immagini"
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.