Praktik terbaik pemuatan lambat

Meskipun pemuatan lambat gambar dan video memiliki manfaat performa yang positif dan terukur, ini bukanlah tugas yang bisa dianggap enteng. Jika Anda salah, ada konsekuensi yang tidak diinginkan. Oleh karena itu, Anda harus memperhatikan hal-hal berikut.

Hati-hati dengan {i>fold<i}

Anda mungkin tergoda untuk memuat lambat setiap resource media di halaman dengan JavaScript, tetapi Anda harus melawan godaan ini. Apa pun yang berada di paruh atas tidak boleh dimuat dengan lambat. Resource tersebut harus dianggap sebagai aset penting, sehingga harus dimuat secara normal.

Pemuatan lambat menunda pemuatan resource hingga DOM selesai interaktif saat skrip selesai dimuat dan memulai eksekusi. Untuk gambar paruh bawah, hal ini tidak masalah, tetapi resource penting di paruh atas harus dimuat dengan elemen <img> standar agar ditampilkan sesegera mungkin.

Tentu saja, di mana letak lipatan tidak begitu jelas saat ini ketika {i>website<i} dilihat di begitu banyak layar dengan berbagai ukuran. Apa yang ada di paruh atas laptop mungkin diletakkan di bawah perangkat seluler. Tidak ada saran ampuh untuk mengatasi ini secara optimal dalam setiap situasi. Anda harus melakukan inventarisasi aset penting halaman, dan memuat gambar tersebut dengan cara biasa.

Selain itu, sebaiknya jangan terlalu ketat tentang garis lipatan sebagai batas untuk memicu pemuatan lambat. Sebaiknya buat zona buffer agak jauh di paruh bawah, sehingga gambar mulai dimuat jauh sebelum pengguna men-scroll-nya ke area tampilan. Misalnya, Intersection Observer API memungkinkan Anda menentukan properti rootMargin dalam objek opsi saat membuat instance IntersectionObserver baru. Cara ini secara efektif memberikan elemen buffering, yang memicu perilaku pemuatan lambat sebelum elemen berada di area tampilan:

let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
  // lazy-loading image code goes here
}, {
  rootMargin: "0px 0px 256px 0px"
});

Jika nilai untuk rootMargin terlihat mirip dengan nilai yang akan Anda tentukan untuk properti margin CSS, hal itu karena memang demikian. Dalam hal ini, margin bawah elemen yang diamati (area pandang browser secara default, tetapi dapat diubah menjadi elemen tertentu menggunakan properti root) diperluas sebesar 256 piksel. Artinya, fungsi callback akan dieksekusi saat elemen gambar berada dalam jarak 256 piksel area tampilan dan gambar akan mulai dimuat sebelum pengguna benar-benar melihatnya.

Untuk mendapatkan efek yang sama di browser yang tidak mendukung Intersection Observation, gunakan kode penanganan peristiwa scroll dan sesuaikan pemeriksaan getBoundingClientRect untuk menyertakan buffer.

Pergeseran tata letak dan placeholder

Media pemuatan lambat dapat menyebabkan pergeseran tata letak jika placeholder tidak digunakan. Perubahan ini dapat membingungkan pengguna dan memicu operasi tata letak DOM yang mahal yang menggunakan resource sistem dan berkontribusi pada jank. Setidaknya, pertimbangkan untuk menggunakan placeholder warna solid yang menempati dimensi yang sama dengan gambar target, atau teknik seperti LQIP atau SQIP yang mengisyaratkan konten item media sebelum dimuat.

Untuk tag <img>, src awalnya harus mengarah ke placeholder hingga atribut tersebut diperbarui dengan URL gambar final. Gunakan atribut poster dalam elemen <video> untuk mengarah ke gambar placeholder. Selain itu, gunakan atribut width dan height pada tag <img> dan <video>. Hal ini memastikan bahwa transisi dari placeholder ke gambar akhir tidak akan mengubah ukuran elemen yang dirender saat media dimuat.

Penundaan decoding gambar

Memuat gambar berukuran besar dalam JavaScript dan melepaskannya ke DOM dapat mengikat thread utama, menyebabkan antarmuka pengguna tidak responsif untuk waktu singkat saat decoding terjadi. Mendekode gambar secara asinkron menggunakan metode decode sebelum memasukkannya ke DOM dapat mengurangi jank semacam ini, tetapi berhati-hatilah: Karena ini belum tersedia di mana saja, dan akan menambah kompleksitas pada logika pemuatan lambat. Jika ingin menggunakannya, Anda harus memeriksanya. Di bawah ini menunjukkan cara menggunakan Image.decode() dengan penggantian:

var newImage = new Image();
newImage.src = "my-awesome-image.jpg";

if ("decode" in newImage) {
  // Fancy decoding logic
  newImage.decode().then(function() {
    imageContainer.appendChild(newImage);
  });
} else {
  // Regular image load
  imageContainer.appendChild(newImage);
}

Buka link CodePen ini untuk melihat penerapan kode yang mirip dengan contoh ini. Jika sebagian besar gambar Anda cukup kecil, hal ini mungkin tidak banyak membantu Anda, tetapi tentu dapat membantu mengurangi jank saat memuat gambar besar secara lambat dan memasukkannya ke DOM.

Saat sesuatu tidak dimuat

Terkadang resource media gagal dimuat karena satu atau beberapa alasan dan terjadi error. Kapan hal ini dapat terjadi? Tergantung, ada satu skenario hipotesis untuk Anda: Anda memiliki kebijakan penyimpanan dalam cache HTML untuk jangka waktu singkat (misalnya, lima menit), dan pengguna mengunjungi situs atau pengguna membiarkan tab lama tetap terbuka untuk jangka waktu yang lama (misalnya, beberapa jam) dan kembali untuk membaca konten Anda. Pada titik tertentu dalam proses ini, deployment ulang terjadi. Selama deployment ini, nama resource gambar akan berubah karena pembuatan versi berbasis hash, atau dihapus sama sekali. Pada saat pengguna memuat gambar secara lambat, resource tidak tersedia, sehingga gagal.

Meskipun kejadian ini relatif jarang terjadi, Anda mungkin harus memiliki rencana cadangan jika pemuatan lambat gagal. Untuk gambar, solusi tersebut mungkin terlihat seperti ini:

var newImage = new Image();
newImage.src = "my-awesome-image.jpg";

newImage.onerror = function(){
  // Decide what to do on error
};
newImage.onload = function(){
  // Load the image
};

Apa yang Anda putuskan untuk dilakukan jika terjadi error bergantung pada aplikasi Anda. Misalnya, Anda dapat mengganti area placeholder gambar dengan tombol yang memungkinkan pengguna mencoba memuat gambar lagi, atau cukup menampilkan pesan error di area placeholder gambar.

Skenario lain juga bisa muncul. Apa pun yang Anda lakukan, bukanlah hal yang buruk untuk memberi tahu pengguna saat terjadi error, dan mungkin memberi mereka tindakan untuk diambil jika terjadi kesalahan.

Ketersediaan JavaScript

Jangan berasumsi bahwa JavaScript selalu tersedia. Jika Anda akan memuat gambar dengan lambat, pertimbangkan untuk menawarkan markup <noscript> yang akan menampilkan gambar jika JavaScript tidak tersedia. Contoh penggantian paling sederhana yang mungkin melibatkan penggunaan elemen <noscript> untuk menayangkan gambar jika JavaScript dinonaktifkan:

Aku adalah sebuah gambar!

Jika JavaScript dinonaktifkan, pengguna akan melihat gambar placeholder dan gambar yang berisi elemen <noscript>. Untuk menyiasatinya, tempatkan class no-js pada tag <html> seperti berikut:

<html class="no-js">

Kemudian, tempatkan satu baris skrip inline di <head> sebelum lembar gaya apa pun diminta melalui tag <link> yang menghapus class no-js dari elemen <html> jika JavaScript aktif:

<script>document.documentElement.classList.remove("no-js");</script>

Terakhir, gunakan beberapa CSS untuk menyembunyikan elemen dengan class lambat saat JavaScript tidak tersedia:

.no-js .lazy {
  display: none;
}

Hal ini tidak mencegah pemuatan gambar placeholder, tetapi hasilnya lebih diinginkan. Pengguna yang menonaktifkan JavaScript akan mendapatkan hal yang lebih dari sekadar gambar placeholder, yang lebih baik daripada placeholder dan tidak memiliki konten gambar yang berarti sama sekali.