Novità dell'istruzione Angular NgOptimizedImage

Alex Castle
Alex Castle

Poco più di un anno fa, il team di Chrome Aurora ha lanciato la direttiva Angular NgOptimizedImage. La direttiva è incentrata principalmente sul miglioramento delle prestazioni, secondo quanto 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'istruzione con nuove funzionalità. Questo post descrive le più significative di queste nuove funzionalità, sottolineando perché abbiamo scelto di dare 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, il dimensionamento delle immagini è un lavoro aggiuntivo per gli sviluppatori di applicazioni e non ha senso in alcuni casi d'uso di immagini.

La prima funzionalità importante aggiunta all'anteprima post-sviluppatore del componente immagine: la modalità di riempimento contribuisce a risolvere questo problema. Questo consente agli sviluppatori di includere le immagini senza ridimensionarle esplicitamente e senza incorrere in variazioni del layout.

Con la modalità di riempimento, il requisito delle dimensioni delle immagini viene disattivato e l'immagine viene adattata automaticamente per riempire l'elemento che la contiene. In questo modo le proporzioni di un'immagine vengono disaccoppiate dallo spazio che occupa sulla pagina e puoi controllare meglio il modo in cui le immagini si adattano al layout della pagina.

La modalità di riempimento utilizza NgOptimizedImage come alternativa con prestazioni migliori alla proprietà CSS background-image. Posiziona un'immagine all'interno di <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 SRcset

Una delle tecniche di ottimizzazione delle immagini più efficaci è l'utilizzo dell'attributo srcset per garantire che vengano scaricate le immagini di dimensioni corrette per qualsiasi dispositivo che accede alla tua applicazione. L'uso di srcset nell'app può evitare di sprecare larghezza di banda e migliorare notevolmente il tuo valore LCP Core Web Vital.

Lo svantaggio dell'attributo srcset è che può essere complicato da implementare. Scrivere manualmente i valori srcset significa aggiungere più righe di markup a ogni elemento immagine nella tua app, complete di più URL personalizzati per ogni srcset. Devi anche decidere un insieme di punti di interruzione, che è complicato poiché 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'importante pietra miliare dopo il lancio. Con questa aggiunta, qualsiasi applicazione che utilizza una CDN che supporta il ridimensionamento delle immagini può essere aggiunta automaticamente a srcset completi e personalizzabili a ogni immagine generata con la direttiva NgOptimizedImage.

Abbiamo incluso un'API semplificata per impostare la proprietà sizes, che viene utilizzata per garantire che ogni immagine riceva il tipo corretto di 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 a una dimensione che tenga conto della densità dei pixel del dispositivo dell'utente.

Se invece includi la proprietà sizes, NgOptimizedImage genera un srcset adattabile che include punti di interruzione per molte dimensioni comuni di dispositivi e immagini, utilizzando questo elenco predefinito di punti di interruzione:

[16, 32, 48, 64, 96, 128, 256, 384, 640, 750, 828, 1080, 1200, 1920, 2048, 3840]

Generazione di preconnessione

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 rapidamente la connessione con il dominio della tua immagine.

Fin dall'inizio, NgOptimizedImage ha avvisato se non riesci a preconnetterti al dominio dell'immagine LCP, ma l'avviso non è la soluzione ideale: vorremmo risolvere il problema al tuo posto. Ed è esattamente ciò che ora fa NgOptimizedImage con la generazione automatica di preconnessione.

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 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. Per le reti CDN più utilizzate è incluso un set di caricatori integrati. Forniamo inoltre l'utilizzo di caricatori personalizzati, che 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 il trasferimento di dati arbitrari dall'elemento immagine al caricatore personalizzato. Con l'espansione, i caricatori personalizzati possono essere semplici o complessi, come richiesto dall'infrastruttura di immagini di un'applicazione.

L'esempio seguente mostra in che modo un caricatore personalizzato semplice potrebbe utilizzare l'API loaderParams per selezionare 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 Angolare.

Indicazioni estese per il rendimento delle immagini

Finora, tutti gli avvisi sulle prestazioni delle immagini che abbiamo aggiunto ad Angular facevano parte dell'istruzione NgOptimizedImage. Se non utilizzi l'istruzione nell'app, non riceverai alcuna indicazione sui problemi di prestazioni delle immagini.

In Angular 17, stiamo ampliando l'ambito delle indicazioni sulle prestazioni delle immagini per includere tutte le app Angular. Ora, se rileviamo pattern delle immagini che risultano essere errori che compromettono le prestazioni, come il caricamento lento dell'immagine LCP o il download di un file troppo grande per la pagina, te lo comunicheremo, anche se non stai utilizzando NgOptimizedImage.

Le prestazioni delle immagini sono importanti per tutte le app e siamo entusiasti di continuare a creare sistemi di protezione per evitare errori comuni nelle app Angular.

Prospettive future

Ci stiamo già adoperando per sviluppare il prossimo set 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 delle nostre priorità sono i segnaposto per le immagini. Vengono comunemente utilizzati per migliorare il caricamento delle immagini nelle applicazioni web, ma possono peggiorare le prestazioni se vengono implementati in modo errato. Speriamo di creare in NgOptimizedImage un sistema di segnaposto per le immagini incentrato sulle prestazioni. Segui il nostro blog per ulteriori annunci.