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-baru ini dirilis untuk pratinjau developer sebagai bagian dari Angular v14.2. Postingan ini membahas cara 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 yang menghasilkan permintaan untuk satu atau beberapa gambar. Gambar juga merupakan kontributor terbesar terhadap ukuran 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 adalah elemen Largest Contentful Paint (LCP) pada tahun 2021. Oleh karena itu, upaya untuk mendapatkan gambar yang dioptimalkan telah menjadi upaya yang terus-menerus bagi banyak orang.

Tim Aurora percaya pada pemanfaatan kekuatan framework untuk memberikan solusi bawaan bagi tantangan umum developer. Langkah pertama mereka dalam bidang pengoptimalan gambar adalah komponen gambar Next.js. Mereka menganggap komponen ini sebagai tempat pengujian untuk mengetahui apakah meningkatkan pengalaman developer (DX) pengoptimalan gambar dapat meningkatkan performa 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. Penerapan next/image berikutnya di komunitas berperan dalam peningkatan origin Next.js yang memenuhi nilai minimum LCP. Segera setelah itu, ada permintaan untuk fitur serupa di framework lain, salah satunya adalah Angular.

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

Peluang

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

LCP untuk situs Angular selama satu tahun terakhir.

Melihat skor Core Web Vitals, persentase origin Angular yang memenuhi nilai minimum LCP "baik" masih perlu ditingkatkan. 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 dari perintah gambar Angular dibuat berdasarkan pelajaran dari komponen gambar yang telah dibuat Aurora hingga saat ini sambil menyesuaikan 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 kepatuhan terhadap praktik terbaik.

Sorotan desainnya adalah sebagai berikut:

  1. Pemuatan lambat cerdas

    Gambar yang tidak terlihat oleh pengguna saat halaman dimuat (misalnya, gambar di bawah lipatan atau gambar carousel tersembunyi) idealnya harus dimuat lambat. Pemuatan lambat 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 lambat gambar non-kritis secara default dan hanya memuat dengan cepat gambar yang ditandai secara khusus sebagai priority. Hal ini memastikan bahwa sebagian besar gambar menunjukkan perilaku pemuatan yang optimal.

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

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

    • Fungsi ini menetapkan fetchpriority gambar ke "high" sehingga browser tahu bahwa browser harus mendownload gambar dengan prioritas tinggi.
    • Dalam mode pengembangan, pemeriksaan runtime 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 priority, error akan ditampilkan, yang menginstruksikan developer untuk menambahkan atribut priority ke gambar LCP.

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

  3. Konfigurasi yang dioptimalkan untuk alat gambar populer

    Sebaiknya aplikasi Angular menggunakan CDN gambar, yang sering kali 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" >
    

    Hal ini setara 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 image menyediakan loader bawaan dengan konfigurasi optimal untuk CDN gambar yang paling populer. Loader ini akan memformat URL gambar secara otomatis untuk memastikan bahwa setelan kompresi dan format gambar 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 melakukan pemeriksaan berikut.

    1. Gambar tanpa ukuran: Perintah gambar menampilkan error jika markup gambar belum menentukan lebar dan tinggi yang eksplisit. Gambar tanpa ukuran 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 dalam 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 telah menentukan dimensi (lebar atau tinggi) yang salah secara tidak sengaja 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 bertambah di kedua dimensi).
    3. Gambar berukuran besar: Jika gambar tidak menentukan srcset dan gambar intrinsik jauh lebih besar daripada gambar yang dirender, perintah akan menampilkan peringatan yang menyarankan penggunaan atribut srcset dan sizes.

    4. Kepadatan gambar: Perintah akan menampilkan error jika Anda mencoba menyertakan gambar di 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 sebenarnya tidak dapat melihat perbedaan yang signifikan di atas 2x.

Tantangan

Menyesuaikan strategi pengoptimalan gambar agar berfungsi dalam framework sisi klien adalah tantangan utama saat mendesain NgOptimizedImage. Pengalaman rendering default di Next.js adalah Rendering Sisi Server (SSR) atau Pembuatan Situs Statis (SSG), sedangkan 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 batasan tambahan, dan tim harus memikirkan kembali cara membuat pengoptimalan tertentu 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 di aplikasi Angular itu 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 penayangan). Menambahkan petunjuk preload ke <head> berarti resource akan dipramuat untuk semua rute meskipun tidak diperlukan. Oleh karena itu, penambahan petunjuk preload secara manual tidak direkomendasikan.

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

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

  2. Mengoptimalkan ukuran dan format gambar di server

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

    Meskipun perintah ini tidak mewajibkan penggunaan CDN gambar, sebaiknya gunakan CDN gambar dengan perintah ini dan loader bawaannya untuk memastikan bahwa opsi konfigurasi yang benar digunakan.

Dampak

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

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

Situs Kedua: Menggunakan perintah gambar untuk semua gambar. Laporan ini juga mencakup pengoptimalan yang direkomendasikan langsung oleh peringatan atau error yang ditampilkan oleh perintah.

Perbandingan filmstrip: Situs Satu dengan tag gambar native versus Situs Dua dengan perintah gambar Angular.

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

Salah satu partner ini adalah Land's End. Situs mereka diharapkan akan menjadi kasus pengujian yang baik untuk hasil yang mungkin dilihat oleh aplikasi sebenarnya.

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

Roadmap Mendatang

Ini hanyalah bagian pertama dari 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. Di masa mendatang, perintah ini dapat membuat atribut srcset dan sizes secara otomatis.

  • Injeksi petunjuk resource secara otomatis

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

  • Dukungan untuk SSR Angular

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

  • Peningkatan pengalaman developer

    NgOptimizedImage mewajibkan atribut width dan height ditentukan untuk setiap gambar. Namun, menentukannya 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 menetapkan lebar dan tinggi secara otomatis untuk gambar lokal dengan menentukan dimensi gambar yang sebenarnya.

Kesimpulan

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

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