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 pada perintah gambar untuk Angular. Perintah ini baru-baru ini 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 median 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, gambar merupakan elemen Largest Contentful Paint (LCP) pada tahun 2021. Sebagian besar dari kita harus berupaya mendapatkan gambar yang dioptimalkan.

Tim Aurora percaya dalam memanfaatkan kekuatan framework guna memberikan solusi bawaan untuk berbagai tantangan developer yang umum. Upaya pertama mereka di ruang pengoptimalan gambar adalah komponen gambar Next.js. Mereka menganggap komponen ini sebagai tempat uji coba apakah peningkatan pengalaman developer (DX) dalam pengoptimalan gambar dapat meningkatkan performa untuk lebih banyak aplikasi yang menggunakan framework.

Beberapa hasil pertama yang diberikan pengguna Next.js, Leboncoin, sangat menggembirakan. Leboncoin memperoleh peningkatan LCP yang signifikan (dari 2,4 detik menjadi 1,7 detik) setelah mereka mulai menggunakan next/image. Penggunaan next/image berikutnya di komunitas berperan dalam meningkatkan jumlah asal Next.js yang memenuhi nilai minimum LCP. Dalam waktu singkat, muncul permintaan untuk fitur serupa di framework lain, salah satunya adalah Angular.

Hasilnya, Aurora berkonsultasi dengan Angular dan Nuxt untuk membuat prototipe komponen gambar bagi framework ini. Komponen image Nusht dirilis tahun lalu. Sekarang perintah gambar Angular (NgOptimizedImage) telah dirilis untuk menghadirkan default pengoptimalan gambar ke Angular.

Peluang

Angular adalah salah satu framework JavaScript terkemuka yang digunakan oleh para developer saat ini. Penyimpanan ini digunakan oleh lebih dari 50 ribu origin yang di-crawl oleh HTTPArchive di perangkat seluler dan memiliki hampir 3 juta download setiap minggu di NPM.

LCP untuk situs Angular selama satu tahun terakhir.

Dengan melihat skor Core Web Vitals, persentase asal Angular yang memenuhi syarat "baik" Nilai minimum LCP masih perlu ditingkatkan. Hanya 18,74% situs Angular yang memiliki LCP yang baik di perangkat seluler pada Juni 2022. Karena gambar merupakan 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 kualitas angka-angka ini.

MVP untuk perintah NgOptimizedImage

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

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

Highlight desain adalah sebagai berikut:

  1. Pemuatan lambat cerdas

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

    Perintah gambar Angular memuat gambar nonkritis dengan lambat secara default dan hanya memuat gambar yang ditandai secara khusus sebagai priority dengan segera. Hal ini memastikan bahwa sebagian besar gambar menunjukkan perilaku pemuatan yang optimal.

  2. Penentuan prioritas gambar penting

    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 2021, hanya 12,7% halaman seluler yang menggunakan petunjuk preconnect dan hanya 22,1% halaman seluler yang menggunakan petunjuk pramuat.

    Perintah gambar berfungsi pada dua aspek ketika gambar ditandai sebagai prioritas.

    • Perintah ini menetapkan prioritas pengambilan gambar ke "high" sehingga browser tahu bahwa gambar harus didownload dengan prioritas tinggi.
    • Dalam mode pengembangan, pemeriksaan runtime akan mengonfirmasi bahwa petunjuk resource preconnect telah disertakan 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 sebagai priority, error akan ditampilkan, yang meminta 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. Solusi ini mendukung API loader yang memungkinkan Anda menentukan penyedia CDN dan URL dasar dalam konfigurasi Anda. 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 markup yang harus disertakan developer 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 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 image akan melakukan pemeriksaan berikut.

    1. Gambar tidak berukuran: Perintah gambar akan menampilkan error jika markup gambar tidak menentukan lebar dan tinggi yang eksplisit. Gambar yang tidak berukuran dapat menyebabkan perubahan 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 bisa terjadi jika

      1. Anda telah salah menentukan dimensi (lebar atau tinggi) yang salah atau
      2. Jika Anda telah menentukan satu dimensi berdasarkan persentase di CSS, tetapi tidak dengan dimensi lain (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 ini 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 untuk mendownload gambar berukuran besar. Selain itu, mata manusia tidak dapat membedakan dengan jelas di atas 2x.

Tantangan

Mengadaptasi strategi pengoptimalan gambar agar berfungsi dalam framework sisi klien merupakan tantangan utama saat mendesain NgOptimizedImage. Pengalaman rendering default di Next.js adalah Server Side Rendering (SSR) atau Static Site Generation (SSG), sedangkan di Angular adalah Client Side Rendering (CSR). Meskipun Angular mendukung library SSR - sudut/universal - sebagian besar aplikasi Angular (~60%) menggunakan CSR.

Perintah gambar sepenuhnya dibangun untuk CSR agar selaras dengan kasus penggunaan umum di aplikasi Angular. Hal ini menimbulkan batasan tambahan, dan tim harus memikirkan kembali cara membangun pengoptimalan spesifik untuk aplikasi CSR.

Beberapa tantangan yang dihadapi adalah sebagai berikut:

  1. Petunjuk resource pendukung

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

    Penambahan Manual: Sulit bagi developer untuk 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> akan berarti bahwa resource akan dipramuat untuk semua rute meskipun tidak diperlukan. Dengan demikian, penambahan manual preload petunjuk tidak direkomendasikan.

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

    Untuk perintah versi pertama, kombinasi petunjuk preconnect dan petunjuk fetchpriority berfungsi untuk memprioritaskan gambar sebagai pengganti preload. Namun, Aurora saat ini 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 dari sisi klien, gambar pada sistem file tidak dapat dikompresi pada waktu permintaan dan ditayangkan apa adanya. Oleh karena itu, sebaiknya gunakan CDN gambar untuk mengompresi gambar dan mengonversinya menjadi format modern seperti WebP atau AVIF on demand.

    Meskipun perintah ini tidak mewajibkan 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 dibuat oleh perintah gambar Angular pada performa gambar. Laporan tersebut membandingkan dua situs:

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

Situs Kedua: Gunakan perintah gambar untuk semua gambar. Ini juga mencakup pengoptimalan yang direkomendasikan langsung oleh peringatan atau error yang ditampilkan oleh perintah.

Perbandingan setrip film: Situs Satu 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 ini adalah Land's End. Diharapkan bahwa situs mereka akan menjadi kasus pengujian yang baik untuk hasil yang dapat dilihat oleh aplikasi sebenarnya.

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

Roadmap Masa Depan

Ini hanyalah 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 diberikan secara manual untuk setiap gambar. Ke depannya, perintah ini dapat menghasilkan atribut srcset dan sizes secara otomatis.

  • Injeksi otomatis petunjuk resource

    Anda dapat berintegrasi dengan Angular CLI untuk menghasilkan tag preconnect dan pramuat untuk gambar LCP penting.

  • Dukungan untuk Angular SSR

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

  • Peningkatan pengalaman developer

    NgOptimizedImage mengharuskan atribut width dan height ditentukan untuk setiap gambar. Namun, menetapkan hal ini untuk setiap gambar mungkin merepotkan bagi sebagian developer. Terdapat 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 menetapkan 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. Coba NgOptimizedImage dan berikan masukan.

Ucapan terima kasih khusus kepada Katie Hempenius dan Alex Castle atas kontribusi mereka.