รูปภาพการโหลดแบบ Lazy Loading

รูปภาพอาจปรากฏในหน้าเว็บเนื่องจากมีการแทรกในบรรทัดใน HTML เป็นองค์ประกอบ <img> หรือเป็นภาพพื้นหลัง CSS ในโพสต์นี้คุณจะพบวิธีโหลดรูปภาพทั้ง 2 ประเภทแบบ Lazy Loading

ภาพในบรรทัด

ตัวเลือกการโหลดแบบ Lazy Loading ที่พบบ่อยที่สุดคือรูปภาพตามที่ใช้ในองค์ประกอบ <img> สำหรับรูปภาพในบรรทัด เรามี 3 ตัวเลือกสำหรับการโหลดแบบ Lazy Loading ซึ่งอาจใช้ร่วมกันเพื่อความเข้ากันได้ที่ดีที่สุดในเบราว์เซอร์ต่างๆ ดังนี้

การใช้การโหลดแบบ Lazy Loading ระดับเบราว์เซอร์

Chrome และ Firefox รองรับการโหลดแบบ Lazy Loading ด้วยแอตทริบิวต์ loading คุณเพิ่มแอตทริบิวต์นี้ลงในองค์ประกอบ <img> และองค์ประกอบ <iframe> ได้ ค่า lazy จะบอกให้เบราว์เซอร์โหลดรูปภาพทันทีหากอยู่ในวิวพอร์ตและดึงข้อมูลรูปภาพอื่นๆ เมื่อผู้ใช้เลื่อนมาใกล้รูปภาพ

ดูช่อง loading ของตารางความเข้ากันได้กับเบราว์เซอร์ของ MDN สำหรับรายละเอียดการสนับสนุนเบราว์เซอร์ หากเบราว์เซอร์ไม่รองรับการโหลดแบบ Lazy Loading ระบบจะไม่สนใจแอตทริบิวต์และรูปภาพจะโหลดทันทีตามปกติ

สำหรับเว็บไซต์ส่วนใหญ่ การเพิ่มแอตทริบิวต์นี้ลงในรูปภาพในบรรทัดจะช่วยเพิ่มประสิทธิภาพและบันทึกผู้ใช้ที่โหลดรูปภาพที่อาจไม่เคยเลื่อนเข้าไปได้ หากคุณมีรูปภาพจำนวนมากและต้องการตรวจสอบว่าผู้ใช้เบราว์เซอร์ที่ไม่รองรับประโยชน์การโหลดแบบ Lazy Loading คุณจะต้องรวมฟีเจอร์นี้เข้ากับวิธีใดวิธีหนึ่งที่จะอธิบายต่อไป

ดูข้อมูลเพิ่มเติมได้ในการโหลดแบบ Lazy Loading ระดับเบราว์เซอร์สำหรับเว็บ

การใช้ Intersection Observer

สำหรับการโหลดแบบ Lazy Loading ขององค์ประกอบ <img> เราจะใช้ JavaScript เพื่อตรวจสอบว่าองค์ประกอบอยู่ในวิวพอร์ตหรือไม่ หากใช่ แอตทริบิวต์ src (และบางครั้งคือ srcset) จะมี URL ไปยังเนื้อหารูปภาพที่ต้องการ

หากเคยเขียนโค้ดการโหลดแบบ Lazy Loading มาก่อน คุณอาจทำงานเสร็จแล้วได้โดยใช้ตัวแฮนเดิลเหตุการณ์ เช่น scroll หรือ resize แม้ว่าวิธีนี้จะเข้ากันได้กับเบราว์เซอร์ต่างๆ มากที่สุด แต่เบราว์เซอร์ที่ทันสมัยก็มีวิธีการที่มีประสิทธิภาพและประสิทธิผลมากกว่าในการตรวจสอบระดับการเข้าถึงองค์ประกอบผ่าน Intersection Observer API

Intersection Observer ใช้งานและอ่านได้ง่ายกว่าโค้ดที่อาศัยตัวแฮนเดิลเหตุการณ์ต่างๆ เนื่องจากคุณเพียงต้องลงทะเบียนผู้สังเกตการณ์เพื่อดูองค์ประกอบเท่านั้น แทนที่จะเขียนโค้ดการตรวจจับองค์ประกอบที่น่าเบื่อ ที่เหลือก็แค่ตัดสินใจว่าต้องทำอะไรเมื่อองค์ประกอบหนึ่งปรากฏขึ้นมา สมมติว่ารูปแบบมาร์กอัปพื้นฐานสำหรับองค์ประกอบ <img> ที่โหลดแบบ Lazy Loading ของคุณมีดังนี้

<img class="lazy" src="placeholder-image.jpg" data-src="image-to-lazy-load-1x.jpg" data-srcset="image-to-lazy-load-2x.jpg 2x, image-to-lazy-load-1x.jpg 1x" alt="I'm an image!">

มาร์กอัปนี้มีส่วนที่เกี่ยวข้อง 3 ส่วนที่คุณควรมุ่งเน้น ดังนี้

  1. แอตทริบิวต์ class ซึ่งเป็นสิ่งที่คุณจะเลือกองค์ประกอบด้วยใน JavaScript
  2. แอตทริบิวต์ src ซึ่งอ้างอิงรูปภาพตัวยึดตำแหน่งที่จะปรากฏขึ้นเมื่อโหลดหน้าเว็บเป็นครั้งแรก
  3. แอตทริบิวต์ data-src และ data-srcset ซึ่งเป็นแอตทริบิวต์ตัวยึดตำแหน่งที่มี URL ของรูปภาพที่คุณจะโหลดเมื่อองค์ประกอบอยู่ในวิวพอร์ต

มาดูวิธีใช้ Intersection Observer ใน JavaScript เพื่อโหลดรูปภาพแบบ Lazy Loading โดยใช้รูปแบบมาร์กอัปนี้

document.addEventListener("DOMContentLoaded", function() {
  var lazyImages = [].slice.call(document.querySelectorAll("img.lazy"));

  if ("IntersectionObserver" in window) {
    let lazyImageObserver = new IntersectionObserver(function(entries, observer) {
      entries.forEach(function(entry) {
        if (entry.isIntersecting) {
          let lazyImage = entry.target;
          lazyImage.src = lazyImage.dataset.src;
          lazyImage.srcset = lazyImage.dataset.srcset;
          lazyImage.classList.remove("lazy");
          lazyImageObserver.unobserve(lazyImage);
        }
      });
    });

    lazyImages.forEach(function(lazyImage) {
      lazyImageObserver.observe(lazyImage);
    });
  } else {
    // Possibly fall back to event handlers here
  }
});

ในเหตุการณ์ DOMContentLoaded ของเอกสาร สคริปต์นี้จะค้นหา DOM สำหรับองค์ประกอบ <img> ทั้งหมดที่มีคลาสเป็น lazy หากมี Intersection Observer ให้สร้างผู้สังเกตการณ์ใหม่ที่เรียกใช้การเรียกกลับเมื่อองค์ประกอบ img.lazy เข้าสู่วิวพอร์ต

Intersection Observer มีให้ใช้งานในเบราว์เซอร์รุ่นใหม่ทั้งหมด ดังนั้นการใช้เป็น Polyfill สำหรับ loading="lazy" จะทำให้ผู้เข้าชมส่วนใหญ่ใช้การโหลดแบบ Lazy Loading ได้

รูปภาพใน CSS

แม้ว่าแท็ก <img> จะเป็นวิธีที่นิยมใช้กันมากที่สุดในการใช้รูปภาพในหน้าเว็บ แต่คุณก็ยังเรียกใช้รูปภาพผ่านพร็อพเพอร์ตี้ CSS background-image (และพร็อพเพอร์ตี้อื่นๆ) ได้ด้วย การโหลดแบบ Lazy Loading ระดับเบราว์เซอร์ใช้ไม่ได้กับภาพพื้นหลัง CSS ดังนั้นคุณต้องพิจารณาวิธีอื่นๆ หากมีภาพพื้นหลังสำหรับการโหลดแบบ Lazy Loading

ลักษณะการโหลดรูปภาพใน CSS จะทำกับการคาดเดามากกว่า ซึ่งต่างจากองค์ประกอบ <img> ที่โหลดโดยไม่คำนึงถึงระดับการมองเห็น เมื่อมีการสร้างโมเดลออบเจ็กต์เอกสารและ CSS รวมถึงแผนผังการแสดงผล เบราว์เซอร์จะตรวจสอบว่าใช้ CSS กับเอกสารอย่างไรก่อนที่จะขอทรัพยากรภายนอก หากเบราว์เซอร์ระบุว่ากฎ CSS ที่เกี่ยวข้องกับทรัพยากรภายนอกไม่ได้ใช้กับเอกสารเนื่องจากมีการสร้างในขณะนี้ เบราว์เซอร์จะไม่ขอกฎดังกล่าว

ลักษณะการทำงานแบบคาดเดานี้ใช้เพื่อเลื่อนการโหลดรูปภาพใน CSS ได้โดยใช้ JavaScript เพื่อระบุเวลาที่องค์ประกอบอยู่ภายในวิวพอร์ต และนำคลาสไปใช้กับองค์ประกอบดังกล่าวซึ่งใช้การจัดรูปแบบที่เรียกใช้ภาพพื้นหลัง ซึ่งจะทำให้รูปภาพดาวน์โหลดในเวลาที่ต้องการแทนการโหลดครั้งแรก ตัวอย่างเช่น ลองพิจารณาองค์ประกอบที่มี ภาพพื้นหลังหลักขนาดใหญ่

<div class="lazy-background">
  <h1>Here's a hero heading to get your attention!</h1>
  <p>Here's hero copy to convince you to buy a thing!</p>
  <a href="/buy-a-thing">Buy a thing!</a>
</div>

โดยปกติแล้วองค์ประกอบ div.lazy-background จะมีภาพพื้นหลังหลักที่ CSS เรียกใช้ อย่างไรก็ตาม ในตัวอย่างการโหลดแบบ Lazy Loading นี้ คุณจะแยกพร็อพเพอร์ตี้ background-image ขององค์ประกอบ div.lazy-background ผ่านคลาส visible ที่เพิ่มลงในองค์ประกอบเมื่อองค์ประกอบอยู่ในวิวพอร์ตได้ ดังนี้

.lazy-background {
  background-image: url("hero-placeholder.jpg"); /* Placeholder image */
}

.lazy-background.visible {
  background-image: url("hero.jpg"); /* The final image */
}

จากที่นี่ ให้ใช้ JavaScript เพื่อตรวจสอบว่าองค์ประกอบอยู่ในวิวพอร์ต (โดยมี Intersection Observer!) หรือไม่ และเพิ่มคลาส visible ลงในองค์ประกอบ div.lazy-background ในขณะนั้น ซึ่งจะโหลดรูปภาพ

document.addEventListener("DOMContentLoaded", function() {
  var lazyBackgrounds = [].slice.call(document.querySelectorAll(".lazy-background"));

  if ("IntersectionObserver" in window) {
    let lazyBackgroundObserver = new IntersectionObserver(function(entries, observer) {
      entries.forEach(function(entry) {
        if (entry.isIntersecting) {
          entry.target.classList.add("visible");
          lazyBackgroundObserver.unobserve(entry.target);
        }
      });
    });

    lazyBackgrounds.forEach(function(lazyBackground) {
      lazyBackgroundObserver.observe(lazyBackground);
    });
  }
});

ผลกระทบต่อการแสดงผลเนื้อหาขนาดใหญ่ที่สุด (LCP)

การโหลดแบบ Lazy Loading คือการเพิ่มประสิทธิภาพที่ยอดเยี่ยมที่ลดทั้งปริมาณการใช้อินเทอร์เน็ตโดยรวมและการแย่งชิงเครือข่ายในระหว่างการเริ่มต้นทำงานโดยเลื่อนการโหลดรูปภาพไปยังเวลาที่ต้องการจริงๆ ซึ่งจะช่วยปรับปรุงเวลาเริ่มต้น และลดการประมวลผลในเทรดหลักโดยลดเวลาที่ต้องใช้ในการถอดรหัสรูปภาพ

อย่างไรก็ตาม การโหลดแบบ Lazy Loading เป็นเทคนิคที่อาจส่งผลกระทบต่อ LCP ของ Largest Contentful Paint ของเว็บไซต์ในเชิงลบหากคุณอยากเรียนรู้เทคนิคดังกล่าวมากเกินไป สิ่งหนึ่งที่คุณควรหลีกเลี่ยงคือการโหลดรูปภาพแบบ Lazy Loading ที่อยู่ในวิวพอร์ตระหว่างการเริ่มต้น

เมื่อใช้ Lazy Loader ที่ทำงานด้วย JavaScript คุณจะต้องหลีกเลี่ยงการโหลดรูปภาพในวิวพอร์ตแบบ Lazy Loading เนื่องจากโซลูชันเหล่านี้มักจะใช้แอตทริบิวต์ data-src หรือ data-srcset เป็นตัวยึดตำแหน่งสำหรับแอตทริบิวต์ src และ srcset ปัญหาคือการโหลดรูปภาพเหล่านี้ล่าช้าเนื่องจากไม่พบเครื่องสแกนการโหลดล่วงหน้าของเบราว์เซอร์ระหว่างเริ่มต้นระบบ

แม้แต่การใช้การโหลดแบบ Lazy Loading ระดับเบราว์เซอร์เพื่อโหลดแบบ Lazy Loading อิมเมจในวิวพอร์ตก็อาจมีผลย้อนกลับได้ เมื่อใช้ loading="lazy" กับรูปภาพในวิวพอร์ต รูปภาพนั้นจะล่าช้าจนกว่าเบราว์เซอร์จะรู้ว่าอยู่ในวิวพอร์ต ซึ่งอาจส่งผลต่อ LCP ของหน้าเว็บ

ไม่โหลดรูปภาพแบบ Lazy Loading ที่เห็นในวิวพอร์ตในระหว่างการเริ่มต้นทำงาน เป็นรูปแบบที่จะส่งผลกระทบต่อ LCP ของเว็บไซต์ของคุณในทางลบต่อประสบการณ์ของผู้ใช้ หากต้องการรูปภาพเมื่อเริ่มต้น ให้โหลดเมื่อเริ่มต้นระบบให้เร็วที่สุดโดยไม่ต้องโหลดแบบ Lazy Loading

ไลบรารีการโหลดแบบ Lazy Loading

คุณควรใช้การโหลดแบบ Lazy Loading ระดับเบราว์เซอร์ทุกครั้งที่ทำได้ แต่หากอยู่ในสถานการณ์ที่ไม่สามารถเลือกได้ เช่น กลุ่มผู้ใช้สำคัญที่ยังคงต้องใช้เบราว์เซอร์รุ่นเก่า คุณสามารถใช้ไลบรารีต่อไปนี้เพื่อโหลดรูปภาพแบบ Lazy Loading ได้

  • lazysizes คือไลบรารีการโหลดแบบ Lazy Loading ที่มีฟีเจอร์เต็มรูปแบบ ซึ่งจะโหลดรูปภาพและ iframe รูปแบบที่ใช้ค่อนข้างคล้ายกับตัวอย่างโค้ดที่แสดงที่นี่ตรงที่จะเชื่อมโยงกับคลาส lazyload ในองค์ประกอบ <img> โดยอัตโนมัติ และคุณต้องระบุ URL รูปภาพในแอตทริบิวต์ data-src และ/หรือ data-srcset ซึ่งจะสลับเนื้อหาเป็นแอตทริบิวต์ src และ/หรือ srcset ตามลำดับ โดยจะใช้ Intersection Observer (ซึ่งสามารถใช้ Polyfill) และขยายได้ด้วยปลั๊กอินหลายรายการเพื่อทำสิ่งต่างๆ เช่น วิดีโอที่โหลดแบบ Lazy Loading ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้ขนาดแบบ Lazysize
  • vanilla-lazyload เป็นตัวเลือกขนาดเล็กสำหรับการโหลดรูปภาพแบบ Lazy Loading, ภาพพื้นหลัง, วิดีโอ, iframe และสคริปต์ ใช้ประโยชน์จาก Intersection Observer, รองรับรูปภาพที่ปรับเปลี่ยนตามอุปกรณ์ และเปิดใช้การโหลดแบบ Lazy Loading ระดับเบราว์เซอร์
  • lozad.js เป็นอีกตัวเลือกหนึ่งที่ไม่ซับซ้อน ซึ่งใช้ Intersection Observer เท่านั้น ด้วยเหตุนี้ โปรแกรมจึงมีประสิทธิภาพสูงแต่จะต้องเขียนด้วย Polyfill ก่อนแล้วจึงจะใช้ในเบราว์เซอร์รุ่นเก่าได้
  • หากต้องการใช้ไลบรารีการโหลดแบบ Lazy Loading โดยเฉพาะสำหรับ React ให้พิจารณาใช้ react-lazyload แม้จะไม่ได้ใช้ Intersection Observer แต่ได้ให้วิธีการที่คุ้นเคยในการโหลดรูปภาพแบบ Lazy Loading สำหรับผู้ที่คุ้นเคยกับการพัฒนาแอปพลิเคชันด้วย React