Saat ini, batu sandungan utama di jalan menuju situs pemuatan kecepatan tinggi adalah gambar. Ini terutama berlaku untuk proyek-proyek e-commerce. Gambar di atasnya, biasanya cukup "berat", membuat sebagian besar konten halaman. Ini, sebagai suatu peraturan, mengarah pada fakta bahwa untuk menunjukkan kepada pengguna suatu halaman, browser-nya perlu mengunduh beberapa megabita data grafik. Bagaimana mempercepat pemuatan halaman dalam situasi ini? Jawaban untuk pertanyaan ini dikhususkan untuk materi, terjemahan yang kami terbitkan hari ini.

Ketentuan Umum
Pertimbangkan, misalnya, halaman awal Departemen
Dalam Negeri di Walmart.
Halaman dengan banyak gambarBerikut adalah informasi tentang berapa banyak gambar yang dimuat untuk membentuk halaman ini:
Gambar dimuat selama pembentukan halamanSeperti yang Anda lihat, ada 137 gambar! Ini berarti bahwa lebih dari 80% data yang diperlukan untuk menampilkan halaman dan dikirim melalui jaringan disajikan sebagai file grafik.
Sekarang kami menganalisis permintaan jaringan yang dieksekusi ketika halaman dimuat:
Permintaan jaringan dieksekusi selama pembentukan halamanDalam hal ini, file yang dihasilkan dari pemisahan kode proyek diunduh lebih lambat dari yang semestinya. Ini karena Anda harus memuat bundel utama
cp_ny.bundle
. Bundel ini dapat diunduh lebih cepat jika tidak terganggu oleh 18 gambar yang saling bersaing untuk mendapatkan bandwidth.
Bagaimana cara memperbaikinya? Bahkan, untuk benar-benar "memperbaiki" ini tidak akan berhasil, tetapi Anda dapat melakukan banyak hal untuk mengoptimalkan pemuatan gambar. Ada banyak pendekatan untuk mengoptimalkan gambar yang digunakan pada halaman web. Diantaranya adalah penggunaan berbagai format file grafik, kompresi data, penggunaan teknik animasi blur, penggunaan CDN. Saya ingin membahas apa yang disebut "pemuatan malas" gambar (lazy loading). Secara khusus, kita akan berbicara tentang bagaimana menerapkan teknik ini di situs Bereaksi, tetapi karena didasarkan pada mekanisme JavaScript, itu dapat diintegrasikan ke dalam proyek web apa pun.
Proyek percontohan
Mari kita mulai dengan komponen
Image
React yang sangat sederhana:
class Image extends PureComponent { render() { const { src } = this.props; return <img align="center" src={src} />; } }
Dibutuhkan, sebagai properti, URL, dan menggunakannya untuk merender elemen
img
HTML.
Berikut adalah kode JSFiddle yang relevan. Gambar berikut menunjukkan halaman yang mengandung komponen ini. Harap dicatat bahwa untuk melihat gambar yang ditampilkan olehnya, Anda perlu menggulir konten halaman.
Halaman dengan komponen yang menampilkan gambarUntuk menerapkan teknik pemuatan gambar yang malas di komponen ini, Anda perlu melakukan tiga langkah berikut:
- Jangan membuat gambar segera setelah mengunduh.
- Siapkan alat untuk mendeteksi tampilan gambar di area tampilan konten halaman.
- Tampilkan gambar setelah terdeteksi bahwa itu jatuh ke area tampilan.
Mari kita lihat langkah-langkah ini.
Langkah 1
Pada langkah ini, gambar segera setelah pemuatan tidak ditampilkan.
render() { return <img />; }
Langkah 2
Di sini kita mengkonfigurasi mekanisme yang memungkinkan kita mendeteksi saat gambar memasuki area tampilan.
componentDidMount() { this.observer = new IntersectionObserver(() => { // }, { root: document.querySelector(".container") }); this.observer.observe(this.element); } .... render() { return <img ref={el => this.element = el} />; }
Mari kita menganalisis kode ini. Inilah yang telah dilakukan di sini:
- Atribut ref telah ditambahkan ke elemen
img
. Ini memungkinkan Anda untuk memperbarui tautan gambar di src
tanpa harus merender ulang komponen tersebut. - Sebuah instance baru dari
IntersectionObserver
(kita akan membicarakan ini di bawah). - Objek
IntersectionObserver
diminta untuk mengamati gambar menggunakan konstruksi observe(this.element)
.
Apa itu
IntersectionObserver
? Menimbang bahwa kata "persimpangan" diterjemahkan sebagai "persimpangan" dan "pengamat" adalah "pengamat", orang sudah bisa menebak peran objek ini. Jika Anda mencari informasi tentang hal itu di
MDN , Anda dapat mengetahui bahwa Intersection Observer API memungkinkan aplikasi web untuk secara asinkron memantau perubahan di persimpangan elemen dengan induknya atau ruang lingkup dokumen viewport.
Pada pandangan pertama, karakteristik API ini mungkin tampak tidak terlalu dapat dimengerti, tetapi pada kenyataannya, strukturnya sangat sederhana. Contoh
IntersectionObserver
melewati beberapa parameter. Secara khusus, kami menggunakan parameter
root
, yang memungkinkan kami untuk mengatur elemen DOM root, yang kami anggap sebagai wadah, tentang persimpangan elemen dengan perbatasan yang perlu kami ketahui. Secara default, ini adalah area di mana fragmen yang terlihat dari halaman (viewport) berada, tetapi saya secara eksplisit mengaturnya untuk menggunakan wadah yang terletak di elemen
iframe
dari JSFiddle. Ini dilakukan untuk, kemudian, mempertimbangkan satu kemungkinan yang tidak dirancang untuk menggunakan elemen
iframe
.
Alasan yang menggunakan
IntersectionObserver
untuk menentukan kapan suatu item menjadi terlihat lebih populer daripada metode yang lebih tradisional, seperti menggunakan
onScroll
dan
getBoundingClientRect()
bersamaan, karena mekanisme
IntersectionObserver
berjalan di luar utas utama. Namun, panggilan balik yang dipanggil setelah
IntersectionObserver
mendeteksi persimpangan elemen dengan wadah dijalankan secara alami di utas utama, sehingga kodenya tidak boleh terlalu berat.
Langkah 3
Sekarang kita perlu mengkonfigurasi callback yang dipanggil ketika mendeteksi persimpangan elemen
target
(elemen ini dalam kasus kami) dengan wadah
root
(dalam kasus kami, ini adalah elemen
div
.container
).
.... this.observer = new IntersectionObserver( entries => { entries.forEach(entry => { const { isIntersecting } = entry; if (isIntersecting) { this.element.src = this.props.src; this.observer = this.observer.disconnect(); } }); }, { root: document.querySelector(".container") } ); ....
Ketika persimpangan terdeteksi, array
entries
ditransfer ke
entries
, yang menyerupai sekumpulan snapshot status semua elemen target yang terdeteksi persimpangan perbatasan yang ditentukan. Properti
isIntersecting
menunjukkan arah persimpangan. Jika item yang dipantau berada di luar elemen root, itu
true
. Jika suatu elemen meninggalkan elemen root, maka itu
false
.
Jadi, ketika ternyata elemen telah menyeberang dengan batas bawah wadah, saya secara manual mengatur properti
src
dan mematikan pemantauan untuknya, yang tidak lagi diperlukan.
Langkah 4 (rahasia)
Sekarang, pada langkah rahasia keempat dari pekerjaan kami, Anda dapat mengagumi hasilnya dan menikmati kesuksesan. Berikut adalah
kode yang mengumpulkan apa yang baru saja kita bicarakan.
Hasil penerapan teknik pemuatan gambar malasNamun, jika Anda melihat lebih dekat apa yang kita miliki, ternyata di sini Anda dapat menemukan sesuatu yang tidak terlalu baik. Untuk melihat ini, saya dengan cepat menggulir halaman, sambil memperlambat kecepatan koneksi jaringan.
Perilaku halaman saat bergulir dengan cepat dan memperlambat kecepatan koneksi jaringanKarena kita memuat gambar hanya setelah telah mencapai area di mana seharusnya sudah terlihat, pengguna tidak memiliki kesempatan untuk menelusuri halaman dan melihat area yang ditempati oleh gambar, dan, tentu saja, gambar itu sendiri, sebelum memuatnya. Ketika situs melihat dari komputer biasa yang terhubung ke Internet cepat, ini tidak menimbulkan masalah. Tetapi banyak pengguna modern mengunjungi situs dari ponsel mereka, kadang-kadang mereka menggunakan jaringan 3G atau, lebih buruk lagi, koneksi EDGE.
Benar, menangani masalah ini tidak begitu sulit. Ini dapat dilakukan karena fakta bahwa Intersection Observer API memberi pengembang kemampuan untuk memperluas atau mempersempit batasan elemen root (dalam kasus kami, ini adalah elemen
.container
). Untuk menggunakan kesempatan ini, cukup tambahkan satu baris kode ke tempat wadah root dikonfigurasi:
rootMargin: "0px 0px 200px 0px"
Di properti
rootMargin
, tulis baris yang strukturnya sesuai dengan aturan CSS yang digunakan untuk mengonfigurasi lekukan elemen. Dalam kasus kami, kami memberi tahu sistem bahwa batas bawah yang digunakan untuk mendeteksi persimpangan elemen dengan wadah perlu ditingkatkan 200 piksel. Ini berarti bahwa panggilan balik yang sesuai akan dipanggil ketika elemen jatuh ke area yang 200 piksel di bawah batas bawah elemen root (nilai defaultnya adalah 0).
Berikut adalah kode yang mengimplementasikan teknik ini.
Memperbaiki teknik pemuatan gambar yang malasHasilnya, ternyata ketika kita menggulir halaman hanya ke elemen ke-4 dari daftar, gambar dimuat di area yang 200 piksel di bawah area yang terlihat dari halaman.
Sekarang, tampaknya, semua yang dibutuhkan sudah selesai. Tapi ini tidak benar.
Masalah ketinggian gambar
Jika Anda dengan cermat mempelajari ilustrasi GIF di atas, maka Anda mungkin memperhatikan bahwa bilah gulir βmelompatβ setelah memuat gambar. Untungnya, masalah ini mudah ditangani. Alasannya adalah bahwa elemen yang menampilkan gambar pada awalnya memiliki ketinggian 0, yang, setelah memuat gambar, ternyata 300 piksel. Oleh karena itu, untuk memperbaiki masalah, cukup untuk mengatur elemen ke ketinggian tetap dengan menambahkan atribut
height={300}
ke gambar.
Tentang hasil pengoptimalan
Apa hasil yang kami dapatkan di Walmart setelah menerapkan pemuatan gambar yang malas di halaman
ini ? Bahkan, hasil spesifik sangat bervariasi tergantung pada banyak keadaan, di antaranya kita dapat mencatat kecepatan koneksi jaringan klien, ketersediaan CDN, jumlah gambar pada halaman dan aturan untuk mendeteksi persimpangan dengan elemen root yang diterapkan padanya. Dengan kata lain, bagi Anda, untuk menilai dampak pemuatan gambar yang malas pada proyek Anda sendiri, yang terbaik adalah menerapkan dan memverifikasi sendiri. Tetapi jika Anda masih tertarik untuk melihat apa yang diberikan pemuatan gambar secara malas kepada kami, berikut adalah beberapa laporan Lighthouse. Yang pertama dibentuk sebelum optimasi, yang kedua - setelah.
Laporan mercusuar dihasilkan sebelum pengoptimalanLaporan mercusuar dihasilkan setelah optimasiRingkasan
Hari ini kami melihat teknik untuk mengoptimalkan halaman web menggunakan pemuatan gambar yang malas. Jika halaman situs Anda penuh dengan gambar, maka, sangat mungkin, teknik ini akan berguna bagi Anda.
Pembaca yang budiman! Bagaimana Anda mengoptimalkan gambar dan pemuatannya?