Kode acara gulir berebut waktu thread utama: setiap acara menjadwalkan pembacaan tata letak, dan seratus pendengar membuat satu gulir jank. IntersectionObserver menggantikan keseluruhan genre: browser memberi tahu Anda, secara asinkron, saat elemen memasuki area pandang.

const io = new IntersectionObserver((entries) => {
  for (const e of entries) {
    if (!e.isIntersecting) continue;
    const img = e.target;
    img.src = img.dataset.src;
    io.unobserve(img); // one-shot work: stop watching after first hit
  }
}, { rootMargin: "200px" });

document.querySelectorAll("img[data-src]")
  .forEach((img) => io.observe(img));

Aturan yang menjaganya tetap waras

  • Satu pengamat per penggunaan, bukan per elemen: batalkan pengamatan setelah pekerjaan sekali pakai seperti pemuatan lambat; pengamat berumur panjang bertahan untuk hal-hal seperti widget pelacakan tempel.
  • rootMargin dimuat sebelumnya sebelum kedatangan: 200 piksel ke depan untuk gambar, lebih banyak untuk penyematan video.
  • Jangan pernah mengurai tata letak dalam gaya panggilan balik: panggilan balik akan mengaktifkan loop utama, jadi pertahankan pekerjaannya tetap kecil dan tidak menghalangi.
  • Desain untuk pengamat tidak pernah aktif: tanpa skrip, pemuatan biasa=malas pada gambar, dan tidak ada konten tersembunyi yang menjadi sandaran halaman Anda.

Tabel keputusan gambar malas

  1. Foto pahlawan di paro atas: tidak ada pemuatan lambat yang diamati, tidak ada pemuatan=malas; ambilprioritas=kemenangan tinggi di sana.
  2. Semuanya diukur di paro bawah: pemuatan asli=malas dulu; hampir tidak ada proyek yang membutuhkan lebih banyak.
  3. Widget di luar DOM (penyematan tweet, peta): pola pengamat di atas, sehingga iframe hanya dimuat saat didekati.

Situs ini tidak menemukan apa pun: pahlawan mendapatkan prioritas pengambilannya, gambar tubuh memuat pemuatan=malas, dan skrip ditunda setelah dicat. Pengamat menyelesaikan cerita itu tepat ketika atribut biasa tidak lagi cukup, cakupannya sangat gacor.