รูปภาพปรากฏในหน้าเว็บได้เนื่องจากแทรกอยู่ใน 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 คุณจะต้องรวม URL นี้เข้ากับวิธีการใดวิธีการหนึ่งที่อธิบายต่อไป
ดูข้อมูลเพิ่มเติมได้ที่การโหลดแบบ 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 ส่วนที่เกี่ยวข้องซึ่งคุณควรมุ่งเน้น ดังนี้
- แอตทริบิวต์
class
ซึ่งเป็นสิ่งที่คุณจะเลือกองค์ประกอบใน JavaScript - แอตทริบิวต์
src
ซึ่งอ้างอิงรูปภาพตัวยึดตำแหน่งที่จะปรากฏขึ้นเมื่อ โหลดหน้าเว็บเป็นครั้งแรก - แอตทริบิวต์
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
สร้างผู้สังเกตการณ์ใหม่ที่เรียกใช้ Callback เมื่อองค์ประกอบ img.lazy
ป้อน
วิวพอร์ต
Intersection Observer ใช้ได้ในเบราว์เซอร์รุ่นใหม่ทั้งหมด
ดังนั้นการใช้โปรโตคอลดังกล่าวเป็น Polyfill สำหรับ loading="lazy"
จะทำให้ผู้เข้าชมส่วนใหญ่ใช้งานการโหลดแบบ Lazy Loading ได้
รูปภาพใน CSS
แม้ว่าแท็ก <img>
จะเป็นการใช้รูปภาพในหน้าเว็บ รูปภาพ ที่ใช้กันมากที่สุด
สามารถเรียกใช้ผ่าน CSS ได้ด้วย
background-image
พร็อพเพอร์ตี้ (และพร็อพเพอร์ตี้อื่นๆ) การโหลดแบบ Lazy Loading ระดับเบราว์เซอร์จะไม่มีผลกับภาพพื้นหลัง CSS
คุณจึงต้องพิจารณาวิธีอื่นหากมีภาพพื้นหลังให้โหลดแบบ Lazy Loading
ไม่เหมือนองค์ประกอบ <img>
ซึ่งโหลดได้ไม่ว่า
การแสดงผล ลักษณะการโหลดรูปภาพใน CSS นั้น
การคาดเดาต่างๆ เมื่อเอกสารและออบเจ็กต์ 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);
});
}
});
ผลต่อ Largest Contentful Paint (LCP)
การโหลดแบบ Lazy Loading นั้นเป็นการเพิ่มประสิทธิภาพที่ยอดเยี่ยมซึ่งลดทั้งการใช้ข้อมูลโดยรวมและการแย่งชิงเครือข่ายในช่วงที่เริ่มต้นใช้งานด้วยการเลื่อนการโหลดรูปภาพไปยังเวลาที่จำเป็นจริงๆ การดำเนินการนี้จะช่วยปรับปรุงเวลาเริ่มต้น และลดการประมวลผลในเทรดหลักด้วยการลดเวลาที่ต้องใช้ในการถอดรหัสรูปภาพ
อย่างไรก็ตาม การโหลดแบบ Lazy Loading เป็นเทคนิคที่อาจส่งผลต่อ LCP การแสดงผลเนื้อหาขนาดใหญ่ที่สุดของเว็บไซต์ในทางลบหากคุณสนใจเทคนิคนี้มากเกินไป สิ่งหนึ่งที่คุณควรหลีกเลี่ยงคือรูปภาพที่โหลดแบบ Lazy Loading ที่อยู่ในวิวพอร์ตในระหว่างการเริ่มต้นใช้งาน
เมื่อใช้ตัวโหลดแบบ Lazy Loading ที่ใช้ 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 ที่มีฟีเจอร์ครบถ้วน
ไลบรารีที่โหลดแบบ Lazy Loading สำหรับโหลดรูปภาพและ iframe รูปแบบที่ใช้นั้นค่อนข้าง
คล้ายกับตัวอย่างโค้ดที่แสดงที่นี่ ซึ่งจะเชื่อมโยงกับ
lazyload
ในเอลิเมนต์<img>
และกำหนดให้คุณระบุ URL รูปภาพใน แอตทริบิวต์data-src
และ/หรือdata-srcset
ซึ่งเนื้อหามีการสลับ ลงในแอตทริบิวต์src
และ/หรือsrcset
ตามลำดับ มีการใช้ทางแยก สังเกตการณ์ (ซึ่งคุณสามารถ polyfill ได้) และสามารถขยายได้ด้วย แท็ก ปลั๊กอินไปยัง ทำสิ่งต่างๆ อย่างเช่น วิดีโอที่โหลดแบบ Lazy Loading ดูข้อมูลเพิ่มเติมเกี่ยวกับการใช้ Lazysizes - vanilla-lazyload คือ ตัวเลือกที่ใช้งานง่ายสำหรับรูปภาพการโหลดแบบ Lazy Loading, ภาพพื้นหลัง, วิดีโอ, iframe และสคริปต์ต่างๆ ใช้ประโยชน์จาก Intersection Observer, รองรับรูปภาพที่ปรับเปลี่ยนตามอุปกรณ์ และ จะเปิดใช้การโหลดแบบ Lazy Loading ระดับเบราว์เซอร์
- lozad.js เป็นอีกหนึ่งฟีเจอร์ที่ใช้งานง่าย ตัวเลือกที่ใช้ Intersection Observer เท่านั้น ด้วยเหตุนี้ โซลูชันนี้จึงมีประสิทธิภาพสูง แต่จะต้องมี Polyfill ก่อน จึงจะใช้ได้ในเบราว์เซอร์รุ่นเก่าได้
- หากต้องการใช้ไลบรารีการโหลดแบบ Lazy Loading ที่เจาะจงของ React โปรดพิจารณา react-lazyload ขณะที่ ไม่ได้ใช้ Intersection Observer แต่มีวิธีการใช้งานแบบ Lazy ที่คุ้นเคย การโหลดภาพสำหรับผู้ที่คุ้นเคยกับการพัฒนาแอปพลิเคชันด้วย React