Praktik terbaik pemuatan lambat

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

Pikirkan lipatan

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

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

Tentu saja, letak lipatan yang tidak begitu jelas akhir-akhir ini ketika situs web dilihat di begitu banyak layar dengan berbagai ukuran. Apa yang ada di paruh atas laptop mungkin terletak 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 yang umum.

Selain itu, Anda mungkin tidak ingin terlalu ketat tentang garis lipatan sebagai nilai minimum untuk memicu pemuatan lambat. Mungkin lebih ideal jika Anda ingin membuat zona buffer dengan jarak di paruh bawah, sehingga gambar mulai dimuat dengan baik sebelum pengguna men-scrollnya ke area pandang. Misalnya, Intersection Observer API memungkinkan Anda menentukan properti rootMargin dalam objek opsi saat membuat instance IntersectionObserver baru. Tindakan ini secara efektif memberikan buffer kepada elemen, 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 adalah karena adanya. Dalam hal ini, margin bawah elemen yang diamati (area pandang browser secara default, tetapi ini dapat diubah menjadi elemen tertentu menggunakan properti root) akan diperluas sebesar 256 piksel. Hal itu berarti fungsi callback akan dijalankan ketika elemen gambar berada dalam 256 piksel dari 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 Anda untuk menyertakan buffer.

Pergeseran tata letak dan placeholder

Media pemuatan lambat dapat menyebabkan pergeseran tata letak jika placeholder tidak digunakan. Perubahan ini dapat membingungkan bagi pengguna dan memicu operasi tata letak DOM yang mahal dan 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 menunjukkan konten item media sebelum dimuat.

Untuk tag <img>, src pada awalnya harus mengarah ke placeholder hingga atribut tersebut diperbarui dengan URL gambar akhir. Gunakan atribut poster dalam elemen <video> untuk menunjuk 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 besar dalam JavaScript dan melepaskannya ke DOM dapat mengaitkan thread utama, yang menyebabkan antarmuka pengguna tidak responsif dalam waktu singkat saat decoding terjadi. Mendekode gambar secara asinkron menggunakan metode decode sebelum memasukkannya ke DOM dapat mengurangi jank seperti ini, tetapi berhati-hatilah: Kode ini belum tersedia di mana-mana, dan 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);
}

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

Saat sesuatu tidak dimuat

Terkadang resource media gagal dimuat karena satu atau beberapa alasan dan error terjadi. Kapan hal ini terjadi? Tergantung, tetapi berikut satu skenario hipotesis: Anda memiliki kebijakan caching HTML untuk jangka waktu yang singkat (misalnya, lima menit), dan pengguna mengunjungi situs atau pengguna membiarkan tab tidak berlaku lagi 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 berubah karena pembuatan versi berbasis hash, atau dihapus sama sekali. Pada saat pengguna memuat lambat gambar, resource tidak tersedia, sehingga gagal.

Meskipun ini adalah kejadian yang relatif jarang, Anda mungkin harus memiliki rencana cadangan jika pemuatan lambat gagal. Untuk gambar, solusi tersebut dapat 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 bila 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, sebaiknya Anda memberi tahu pengguna saat terjadi error, dan mungkin memberi mereka tindakan yang dapat dilakukan 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 yang paling sederhana adalah menggunakan elemen <noscript> untuk menyajikan gambar jika JavaScript dinonaktifkan:

Aku ini gambar!

Jika JavaScript dinonaktifkan, pengguna akan melihat gambar placeholder dan gambar yang berisi elemen <noscript>. Untuk mengatasi hal ini, 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 gambar placeholder dimuat, tetapi hasilnya lebih diinginkan. Pengguna yang menonaktifkan JavaScript mendapatkan sesuatu yang lebih dari sekadar gambar placeholder, yang lebih baik daripada placeholder dan tidak memiliki konten gambar yang berarti sama sekali.