Poco più di un anno fa, il team di Chrome Aurora ha lanciato la direttiva Angular NgOptimizedImage. La direttiva si concentra principalmente sul miglioramento del rendimento, misurato dalle metriche Core Web Vitals. Raggruppa le ottimizzazioni comuni delle immagini e le best practice in un'API rivolta agli utenti non molto più complicata di un elemento <img>
standard.
Nel 2023 abbiamo migliorato l'directive con nuove funzionalità. Questo post descrive le più significative di queste nuove funzionalità, sottolineando perché abbiamo scelto di dare la priorità a ciascuna funzionalità e spiegando come possono contribuire a migliorare le prestazioni delle applicazioni Angular.
Nuove funzionalità
NgOptimizedImage è migliorato notevolmente nel tempo, incluse le nuove funzionalità elencate di seguito.
Modalità di riempimento
Il dimensionamento delle immagini indicando gli attributi width
e height
è un'ottimizzazione estremamente importante per ridurre la variazione del layout, poiché i browser devono conoscere le proporzioni dell'immagine per poter risparmiare spazio. Tuttavia, la regolazione delle dimensioni delle immagini comporta un lavoro aggiuntivo per gli sviluppatori di applicazioni e non ha senso per alcuni casi d'uso delle immagini.
A risolvere questo problema contribuisce la prima funzionalità principale aggiunta al componente immagine dopo l'anteprima per sviluppatori: la modalità di riempimento. In questo modo, gli sviluppatori possono includere le immagini senza specificarne esplicitamente le dimensioni e senza che si verifichi uno spostamento del layout.
Con la modalità di riempimento, il requisito relativo alle dimensioni dell'immagine viene disattivato e l'immagine viene stilizzata automaticamente per riempire l'elemento contenitore. In questo modo, le proporzioni di un'immagine vengono disaccoppiate dallo spazio che occupa nella pagina e hai un maggiore controllo su come le immagini si inseriscono nel layout della pagina.
La modalità di riempimento utilizza NgOptimizedImage come alternativa con un rendimento migliore alla proprietà CSS background-image
. Posiziona un'immagine all'interno dell'elemento <div>
o di un altro elemento che avrebbe avuto lo stile background-image
, quindi attiva la modalità di riempimento, come mostrato nell'esempio di codice precedente. Utilizza le proprietà CSS object-fit
e object-position
in <div>
per controllare il posizionamento dell'immagine sullo sfondo.
// Height and width are required
<img ngSrc="example.com" height="300" width="400">
// Unless you use fill mode!
<div style="width: 100vw; height: 50em; position: relative">
<img ngSrc="example.com" fill>
</div>
Generazione di srcset
Una delle tecniche di ottimizzazione delle immagini più efficaci è l'utilizzo dell'attributo srcset
per assicurarsi che vengano scaricate immagini con dimensioni adeguate per qualsiasi dispositivo che accede alla tua applicazione. L'utilizzo di srcset
in tutta l'app può impedirti di sprecare larghezza di banda e migliorare notevolmente il LCP Core Web Vital.
Lo svantaggio dell'attributo srcset
è che può essere complicato da implementare. La scrittura manuale dei valori srcset
comporta l'aggiunta di più righe di markup a ogni elemento immagine dell'app, con più URL personalizzati per ogni srcset
. Devi anche decidere un insieme di breakpoint, il che è complicato, in quanto possono rappresentare sia le densità dello schermo sia le dimensioni dell'area visibile dei dispositivi comuni.
Ecco perché l'aggiunta della generazione automatica di srcset alla direttiva NgOptimizedImage è stata un traguardo importante dopo il lancio. Con questa aggiunta, qualsiasi applicazione che utilizza una CDN che supporta il ridimensionamento delle immagini può avere srcset completi e personalizzabili aggiunti automaticamente a ogni immagine generata con la direttiva NgOptimizedImage.
Abbiamo incluso un'API semplificata per l'impostazione della proprietà sizes
, che viene utilizzata per assicurarsi che a ogni immagine venga assegnato il tipo corretto di sizes
.srcset
Se non includi un attributo sizes
, sappiamo che l'immagine deve essere di dimensioni fisse e dovrebbe avere un srcset dipendente dalla densità, come il seguente:
<img src="www.example.com/image.png" srcset="www.example.com/image.png?w=400 1x, www.example.com/image.png?w=800 2x" >
Questo tipo di srcset garantisce che le immagini vengano pubblicate in dimensioni che tengano conto della densità di pixel del dispositivo dell'utente.
Se invece includi la proprietà sizes
, NgOptimizedImage
genera un attributo srcset responsive che include i breakpoint per molti dispositivi e dimensioni delle immagini comuni, utilizzando questo elenco predefinito di breakpoint:
[16, 32, 48, 64, 96, 128, 256, 384, 640, 750, 828, 1080, 1200, 1920, 2048, 3840]
Generazione di preconnect
Per migliorare la funzionalità LCP, è importante ridurre il tempo impiegato dagli utenti per scaricare l'immagine LCP. Nella sezione precedente hai visto come srcset
può aiutarti trasferendo file immagine più piccoli, ma un'ottimizzazione altrettanto importante è avviare il trasferimento il prima possibile. Un modo per farlo è utilizzare i tag link rel="preconnect"
per avviare la connessione al dominio delle immagini.
Fin dall'inizio, NgOptimizedImage ha emesso un avviso se non riesci a eseguire la preconnessione al dominio dell'immagine LCP, ma l'avviso non è la soluzione ideale: preferiamo risolvere il problema per te. Ed è esattamente ciò che fa ora NgOptimizedImage, con la generazione automatica di preconnect.
Per supportare questa funzionalità, utilizziamo l'analisi statica del codice per tentare di rilevare i domini immagine nei loader NgOptimizedImage e generare automaticamente tag link di preconnessione per questi domini. In alcuni casi sono comunque necessari link di preconnessione manuali, ma per la maggior parte degli utenti la preconnessione automatica comporta un passaggio in meno per ottenere un buon rendimento delle immagini.
Supporto migliorato per i caricatori personalizzati
Un elemento chiave di NgOptimizedImage è l'architettura di caricamento, che consente alla direttiva di generare automaticamente URL adattati alla CDN immagine dell'applicazione. È incluso un insieme di caricatori integrati per le CDN di uso comune. Forniamo inoltre l'utilizzo di caricatori personalizzati, che ti consentono di integrare NgOptimizedImage con quasi tutte le soluzioni di hosting di immagini.
Al momento del lancio, questi caricatori personalizzati avevano un ambito limitato e potevano leggere solo l'attributo width
dall'elemento immagine. In risposta al feedback degli utenti, abbiamo aggiunto il supporto di una struttura di dati loaderParams
personalizzabile, che consente di passare dati arbitrari dall'elemento immagine al caricatore personalizzato. Con l'espansione, i caricatori personalizzati possono essere semplici o complessi, a seconda delle esigenze dell'infrastruttura di immagini di un'applicazione.
L'esempio seguente mostra come un semplice caricatore personalizzato potrebbe utilizzare l'API loaderParams
per scegliere tra due domini di immagini alternativi:
const myCustomLoader = (config: ImageLoaderConfig) => {
if (config.loaderParams?.alternateDomain) {
return `https://alternate.domain.com/images/${config.src}`
}
return `https://primary.domain.com/images/${config.src}`;
};
Un esempio di caricatore personalizzato più complesso è disponibile nella documentazione di Angular.
Indicazioni estese per il rendimento delle immagini
Fino a questo momento, tutti gli avvisi sul rendimento delle immagini che abbiamo aggiunto ad Angular facevano parte della direttiva NgOptimizedImage. Se non utilizzi la direttiva nell'app, non riceverai indicazioni sui problemi di prestazioni delle immagini.
In Angular 17, stiamo ampliando l'ambito delle indicazioni sul rendimento delle immagini per includere tutte le app Angular. Ora, se rileviamo pattern di immagini che sappiamo essere errori che influiscono sulle prestazioni, ad esempio il caricamento lento dell'immagine LCP o il download di un file troppo grande per la pagina, te lo comunicheremo, anche se non utilizzi NgOptimizedImage.
Il rendimento delle immagini è importante per tutte le app e siamo lieti di continuare a creare guardrail per contribuire a evitare errori comuni nelle app Angular.
Cordiali saluti
Stiamo già lavorando per sviluppare il prossimo insieme di funzionalità per NgOptimizedImage. Anche se le prestazioni delle immagini rimangono la nostra preoccupazione principale, vorremmo anche aggiungere funzionalità che migliorano l'esperienza degli sviluppatori, per garantire che NgOptimizedImage rimanga un'opzione allettante per includere immagini nelle applicazioni Angular.
Una funzionalità che per noi è una priorità è quella dei segnaposto per le immagini. Questi vengono spesso utilizzati per migliorare la visualizzazione del caricamento delle immagini nelle applicazioni web, ma possono influire negativamente sul rendimento se implementati in modo errato. Ci auguriamo di creare un sistema di segnaposto delle immagini incentrato sulle prestazioni in NgOptimizedImage. Continua a seguirci sul nostro blog per altri annunci.