Mengoptimalkan Gambar dengan Angular Image Directive

Kara Erickson
Kara Erickson
Leena Sohoni
Leena Sohoni

Pada Mei 2022, tim Aurora dan Angular mengumumkan bahwa mereka akan berkolaborasi dalam perintah gambar untuk Angular. Perintah ini baru saja dirilis untuk pratinjau developer sebagai bagian dari Angular v14.2. Postingan ini membahas bagaimana perintah gambar baru, NgOptimizedImage, mendukung pengoptimalan gambar di Angular.

Latar belakang

Gambar adalah komponen umum dan penting dari pengalaman pengguna web, dengan 99,9% halaman web menghasilkan permintaan untuk satu atau beberapa gambar. Gambar juga merupakan kontributor yang paling signifikan terhadap berat halaman, dengan rata-rata 982 kilobyte per halaman.

Karena jumlah dan ukurannya yang terus bertambah, gambar dapat menghambat performa halaman web dan memengaruhi metrik Data Web Inti. Untuk 79,4% halaman desktop, gambarnya dianggap sebagai elemen Largest Contentful Paint (LCP) pada tahun 2021. Oleh karena itu, pencarian gambar yang dioptimalkan telah menjadi upaya yang konstan bagi banyak dari kita.

Tim Aurora meyakini manfaat framework untuk memberikan solusi siap pakai untuk tantangan umum developer. Upaya pertama mereka ke ruang pengoptimalan gambar adalah komponen gambar Next.js. Mereka menganggap komponen ini sebagai ajang pengujian apakah meningkatkan pengalaman developer (DX) pengoptimalan gambar dapat menghasilkan performa yang memuaskan untuk lebih banyak aplikasi yang menggunakan framework.

Kumpulan hasil pertama dari pengguna Next.js Leboncoin sangat menggembirakan. Leboncoin mengalami peningkatan LCP yang signifikan (dari 2,4 detik menjadi 1,7 detik) setelah mereka mulai menggunakan next/image. Adopsi next/image selanjutnya dalam komunitas berperan dalam peningkatan origin Next.js yang memenuhi nilai minimum LCP. Tak lama kemudian ada permintaan untuk fitur serupa di framework lain, salah satunya Angular.

Oleh karena itu, Aurora berkonsultasi dengan Angular dan Nuxt untuk membuat prototipe komponen gambar bagi framework ini. Komponen image Nuxt dirilis tahun lalu. Sekarang perintah gambar Angular (NgOptimizedImage) telah dirilis untuk memberikan setelan default pengoptimalan gambar ke Angular.

Opportunity

Angular adalah salah satu framework JavaScript terkemuka yang digunakan oleh developer saat ini. URL ini digunakan oleh lebih dari 50 ribu origin yang di-crawl oleh HTTPArchive di perangkat seluler dan menawarkan hampir 3 juta download mingguan di NPM.

LCP untuk situs Angular selama satu tahun terakhir.

Dengan melihat skor Data Web Inti, persentase asal Angular yang memenuhi nilai minimum LCP "baik" masih memerlukan perbaikan. Hanya 18,74% situs Angular yang memiliki LCP yang baik di perangkat seluler pada Juni 2022. Karena gambar adalah elemen LCP untuk lebih dari 70% halaman web di perangkat seluler dan desktop, gambar LCP yang tidak dioptimalkan dapat menjadi salah satu penyebab utama LCP yang lebih buruk di situs Angular.

Perintah gambar Angular dirancang untuk membantu meningkatkan jumlah ini.

MVP untuk perintah NgOptimizedImage

MVP perintah gambar Angular dibuat berdasarkan pelajaran dari komponen gambar yang telah dibuat Aurora hingga saat ini sambil mengadaptasikan desain dengan pengalaman rendering sisi klien Angular. Banyak masalah pengoptimalan gambar standar telah diatasi dengan:

  • Memberikan default yang kuat.
  • Menampilkan error atau peringatan untuk memastikan kesesuaian dengan praktik terbaik.

Sorotan desain adalah sebagai berikut:

  1. Pemuatan lambat cerdas

    Gambar yang tidak terlihat oleh pengguna saat halaman dimuat (misalnya, gambar paruh bawah atau gambar carousel tersembunyi) idealnya harus dimuat dengan lambat. Pemuatan lambat akan mengosongkan resource browser untuk memuat teks, media, atau skrip penting lainnya. Sebagian besar gambar tidak penting dan harus dimuat lambat, tetapi hanya 7,8% halaman yang menggunakan pemuatan lambat native pada tahun 2021.

    Perintah gambar Angular memuat gambar yang tidak penting secara default dan hanya memuat gambar yang ditandai khusus sebagai priority dengan segera. Hal ini memastikan sebagian besar gambar menampilkan perilaku pemuatan yang optimal.

  2. Penentuan prioritas gambar kritis

    Menambahkan petunjuk resource (misalnya, preload atau preconnect) untuk memprioritaskan pemuatan gambar penting adalah praktik terbaik yang direkomendasikan. Namun, sebagian besar aplikasi tidak menggunakannya. Menurut Web Almanac tahun 2021, hanya 12,7% halaman seluler yang menggunakan petunjuk preconnect dan hanya 22,1% halaman seluler yang menggunakan petunjuk pramuat.

    Perintah gambar bertindak di dua sisi saat gambar ditandai sebagai prioritas.

    • Ini menetapkan prioritas pengambilan gambar ke "high" sehingga browser mengetahui bahwa browser harus mendownload gambar dengan prioritas tinggi.
    • Dalam mode pengembangan, pemeriksaan runtime mengonfirmasi bahwa petunjuk resource preconnect telah disertakan yang sesuai dengan asal gambar.

    Dalam mode pengembangan, perintah ini juga menggunakan PerformanceObserver API untuk memverifikasi bahwa gambar LCP telah ditandai priority seperti yang diharapkan. Jika tidak ditandai priority, error akan muncul, yang memerintahkan developer untuk menambahkan atribut priority ke gambar LCP.

    Pada akhirnya, kombinasi otomatisasi dan kesesuaian ini memastikan bahwa gambar LCP memiliki petunjuk preconnect, nilai atribut fetchpriority high, dan tidak dimuat dengan lambat.

  3. Konfigurasi yang dioptimalkan untuk alat gambar populer

    Sebaiknya aplikasi Angular menggunakan CDN gambar, yang sering menyediakan layanan pengoptimalan secara default.

    Perintah ini mendorong penggunaan CDN gambar dengan memberikan pengalaman developer (DX) yang sangat menarik untuk mengonfigurasinya di aplikasi. Perintah ini mendukung API loader yang memungkinkan Anda menentukan penyedia CDN dan URL dasar dalam konfigurasi. Setelah dikonfigurasi, Anda hanya perlu menentukan nama aset dalam markup. Misalnya,

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

    Ini sama dengan menyertakan tag gambar berikut dan mengurangi yang harus disertakan developer markup untuk setiap gambar.

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

    Perintah gambar menyediakan loader bawaan dengan konfigurasi optimal untuk CDN gambar yang paling populer. Loader ini akan memformat URL gambar secara otomatis untuk memastikan bahwa format gambar dan setelan kompresi yang direkomendasikan digunakan untuk setiap CDN.

  4. Error dan peringatan bawaan

    Selain pengoptimalan bawaan di atas, perintah ini juga memiliki pemeriksaan bawaan untuk memastikan bahwa developer telah mengikuti praktik terbaik yang direkomendasikan dalam markup gambar. Perintah gambar melakukan pemeriksaan berikut.

    1. Gambar tidak berukuran: Perintah gambar menampilkan error jika markup gambar tidak menentukan lebar dan tinggi yang eksplisit. Gambar yang tidak berukuran dapat menyebabkan pergeseran tata letak, yang memengaruhi metrik Pergeseran Tata Letak Kumulatif (CLS) halaman. Praktik terbaik yang direkomendasikan untuk mencegah hal ini adalah gambar harus memiliki atribut width dan height yang ditentukan.

    2. Rasio aspek: Perintah gambar menampilkan error untuk memberi tahu developer jika rasio aspek width:height yang ditentukan di HTML tidak mendekati rasio aspek sebenarnya dari gambar yang dirender. Hal ini dapat menyebabkan gambar terlihat terdistorsi di layar. Hal ini dapat terjadi jika

      1. Anda tidak sengaja menentukan dimensi (lebar atau tinggi) atau
      2. Jika Anda telah menentukan satu dimensi berdasarkan persentase di CSS, tetapi tidak menentukan dimensi lainnya (misalnya, width: 100% memerlukan height: auto untuk memastikan gambar tumbuh di kedua dimensi).
    3. Gambar besar: Jika gambar tidak menentukan srcset dan gambar intrinsik secara signifikan lebih besar daripada gambar yang dirender, perintah akan menampilkan peringatan yang menyarankan penggunaan atribut srcset dan sizes.

    4. Kepadatan gambar: Perintah ini akan menampilkan error jika Anda mencoba menyertakan gambar dalam srcset dengan kepadatan piksel lebih dari 3x. Deskripsi yang lebih tinggi dari 2x umumnya tidak direkomendasikan karena memiliki konsekuensi yang tidak diinginkan, yaitu memaksa perangkat seluler beresolusi tinggi mendownload gambar yang besar. Selain itu, mata manusia sebenarnya tidak dapat menunjukkan banyak perbedaan di atas 2x.

Tantangan

Menyesuaikan strategi pengoptimalan gambar agar berfungsi dalam framework sisi klien merupakan tantangan utama saat mendesain NgOptimizedImage. Pengalaman rendering default di Next.js adalah Rendering Sisi Server (SSR) atau Pembuatan Situs Statis (SSG), sedangkan yang ada di Angular adalah Rendering Sisi Klien (CSR). Meskipun Angular mendukung library SSR - angular/universal - sebagian besar aplikasi Angular (~60%) menggunakan CSR.

Perintah gambar sepenuhnya dibuat untuk CSR agar selaras dengan kasus penggunaan umum di aplikasi Angular. Hal ini menetapkan kendala tambahan, dan tim harus memikirkan kembali cara membangun pengoptimalan khusus untuk aplikasi CSR.

Beberapa tantangan yang dihadapi adalah sebagai berikut:

  1. Petunjuk referensi pendukung

    Pramuat aset penting membantu browser menemukannya lebih awal. Namun, menyertakan petunjuk resource dalam aplikasi Angular rumit karena:

    Penambahan Manual: Developer sulit menambahkan petunjuk resource preload secara manual. Angular menggunakan satu file index.html bersama untuk seluruh project atau untuk semua rute di situs. Dengan demikian, <head> dokumen sama untuk setiap rute (setidaknya pada waktu inferensi). Menambahkan petunjuk preload ke <head> berarti resource akan dipramuat untuk semua rute bahkan saat tidak diperlukan. Oleh karena itu, penambahan petunjuk preload secara manual tidak direkomendasikan.

    Penambahan otomatis selama render: Menggunakan framework untuk menambahkan petunjuk pramuat ke bagian head dokumen selama rendering dalam aplikasi CSR tidak membantu. Karena rendering terjadi setelah JavaScript didownload dan dijalankan, <head> akan terlambat dirender menjadi nilai apa pun.

    Untuk versi pertama perintah ini, kombinasi petunjuk preconnect dan petunjuk fetchpriority berfungsi untuk memprioritaskan gambar sebagai pengganti preload. Namun, saat ini Aurora bekerja sama dengan tim Angular CLI untuk mengaktifkan injeksi otomatis petunjuk resource pada waktu build. Nantikan kabar terbarunya.

  2. Mengoptimalkan ukuran dan format gambar di server

    Karena aplikasi Angular biasanya dirender sisi klien, gambar pada sistem file tidak dapat dikompresi pada waktu permintaan dan ditayangkan sebagaimana adanya. Oleh karena itu, sebaiknya gunakan CDN gambar untuk mengompresi gambar dan mengonversinya menjadi format modern seperti WebP atau AVIF sesuai permintaan.

    Meskipun perintah tersebut tidak memberlakukan penggunaan CDN gambar, sangat disarankan untuk menggunakannya dengan perintah dan loader bawaannya untuk memastikan bahwa opsi konfigurasi yang benar digunakan.

Dampak

Demo berikut menunjukkan perbedaan yang dapat dihasilkan perintah gambar Angular terhadap performa gambar. Laporan ini membandingkan dua situs:

Website One: Menggunakan elemen <img> native dengan gambar yang disajikan melalui Imgix CDN (dengan opsi konfigurasi default).

Situs Dua: Gunakan perintah gambar untuk semua gambar. Hal ini juga mencakup pengoptimalan yang direkomendasikan secara langsung oleh peringatan atau error yang ditampilkan oleh perintah.

Perbandingan setrip film: Situs One dengan tag gambar native versus Situs Dua dengan perintah gambar Angular.

Tim ini bekerja sama dengan partner untuk memvalidasi dampak performa perintah gambar pada aplikasi Angular perusahaan yang sebenarnya.

Salah satu partner tersebut adalah Land's End. Diharapkan bahwa situs mereka akan menjadi kasus pengujian yang baik untuk hasil yang dapat dilihat oleh aplikasi nyata.

Pengujian lab Lighthouse dilakukan di lingkungan UM (Uji Mutu) mereka sebelum dan sesudah menggunakan perintah gambar. Di desktop, LCP mediannya menurun dari 12,0 detik menjadi 3,0 detik, dengan peningkatan LCP sebesar 75%. Di perangkat seluler, median LCP menurun dari 20,2 dtk menjadi 12,0 dtk (peningkatan 40,6%).

Roadmap Masa Mendatang

Ini adalah bagian pertama desain untuk perintah gambar Angular. Ada banyak fitur lain yang direncanakan untuk versi mendatang, termasuk:

  • Dukungan yang lebih baik untuk gambar responsif:

    NgOptimizedImage saat ini mendukung penggunaan srcset, tetapi atribut srcset dan sizes harus disediakan secara manual untuk setiap gambar. Di masa mendatang, perintah tersebut dapat membuat atribut srcset dan sizes secara otomatis.

  • Injeksi otomatis petunjuk resource

    Anda mungkin dapat berintegrasi dengan Angular CLI untuk menghasilkan tag prakoneksi dan pramuat untuk gambar LCP yang penting.

  • Dukungan untuk SSR Angular

    Versi MVP dirancang dengan mempertimbangkan batasan CSR Angular, tetapi juga penting untuk mengeksplorasi solusi pengoptimalan gambar untuk Angular SSR (angular/universal).

  • Peningkatan pengalaman developer

    NgOptimizedImage mengharuskan atribut width dan height ditentukan untuk setiap gambar. Namun, menentukan nilai ini untuk setiap gambar mungkin melelahkan bagi sebagian developer. Ada potensi untuk meningkatkan pengalaman developer di sini pada iterasi berikutnya sebagai berikut:

    1. Mendukung mode tambahan (mirip dengan opsi tata letak gambar "fill" di Next.js) yang tidak memerlukan lebar/tinggi eksplisit untuk ditentukan.
    2. Menggunakan integrasi CLI untuk menyetel lebar dan tinggi gambar lokal secara otomatis dengan menentukan dimensi gambar yang sebenarnya.

Kesimpulan

Perintah gambar Angular akan tersedia untuk developer secara bertahap, dimulai dengan versi pratinjau developer di v14.2.0. Cobalah NgOptimizedImage dan berikan masukan.

Dengan ucapan terima kasih khusus kepada Katie Hempenius dan Alex Castle atas kontribusinya.