เผยแพร่: 16 สิงหาคม 2019, อัปเดตล่าสุด: 2 กรกฎาคม 2026
เช่นเดียวกับองค์ประกอบรูปภาพ คุณอาจต้องการเลื่อนโหลดวิดีโอด้วย โดยทั่วไปแล้ว วิดีโอจะโหลดด้วยองค์ประกอบ <video> แต่สำหรับวิดีโอที่โฮสต์ในบริการอื่นๆ เช่น YouTube อาจใช้ <iframe>s (ในกรณีนี้ โปรดดูบทความในการโหลด iframe แบบ Lazy Loading)
วิธีเลื่อนโหลด <video> ขึ้นอยู่กับกรณีการใช้งาน เนื่องจากมีโซลูชันที่แตกต่างกันอยู่ 2-3 แบบ
การใช้แอตทริบิวต์ loading
เบราว์เซอร์เริ่มรองรับแอตทริบิวต์ loading ในองค์ประกอบสื่อ (<video> และ <audio>) แล้ว ซึ่งหมายความว่าทั้งสื่อและรูปภาพโปสเตอร์จะโหลดแบบ Lazy Loading โดยอัตโนมัติเพียงแค่เพิ่มแอตทริบิวต์ loading="lazy" ในเบราว์เซอร์ที่รองรับ
<video controls loading="lazy" preload="none" poster="one-does-not-simply-placeholder.jpg">
<source src="one-does-not-simply.webm" type="video/webm">
<source src="one-does-not-simply.mp4" type="video/mp4">
</video>
การใช้ loading="lazy" จะป้องกันไม่ให้รูปภาพ poster โหลดเลยจนกว่าจะอยู่ในหรือใกล้กับวิวพอร์ต จากนั้นจะใช้แอตทริบิวต์ preload เพื่อตัดสินใจว่าจะโหลด video มากน้อยเพียงใด ซึ่งหมายความว่าวิดีโอ autoplay จะไม่เล่นอัตโนมัติจนกว่าจะอยู่ในหรือใกล้กับวิวพอร์ต แอตทริบิวต์ loading="lazy" ทำงานร่วมกับแอตทริบิวต์ poster, preload และ autoplay และไม่ได้มาแทนที่แอตทริบิวต์เหล่านั้น
เบราว์เซอร์ที่ไม่รองรับแอตทริบิวต์ loading ในองค์ประกอบสื่อจะละเว้นแอตทริบิวต์นี้ ซึ่งจะส่งผลให้posterโหลดรูปภาพทันที และวิดีโอจะโหลดตามแอตทริบิวต์ preload ซึ่งเราจะกล่าวถึงในส่วนถัดไป
ใช้แอตทริบิวต์ preload เพื่อโหลดวิดีโอแบบ Lazy Loading ที่ไม่เล่นอัตโนมัติ
โดยปกติแล้วแนวทางปฏิบัติแนะนำคือการหลีกเลี่ยงวิดีโอที่เล่นอัตโนมัติ เนื่องจากจะทำให้ผู้ใช้เป็นผู้ควบคุม ในกรณีเหล่านี้ การระบุแอตทริบิวต์ preload ในองค์ประกอบ <video> เป็นวิธีที่ดีที่สุดในการหลีกเลี่ยงการโหลดวิดีโอทั้งรายการจนกว่าจะจำเป็น
<video controls loading="lazy" preload="none" poster="one-does-not-simply-placeholder.jpg">
<source src="one-does-not-simply.webm" type="video/webm">
<source src="one-does-not-simply.mp4" type="video/mp4">
</video>
ตัวอย่างก่อนหน้านี้ใช้แอตทริบิวต์ preload ที่มีค่าเป็น none เพื่อป้องกันไม่ให้เบราว์เซอร์โหลดข้อมูลวิดีโอใดๆ ล่วงหน้า แม้ว่าจะอยู่ในวิวพอร์ตก็ตาม แอตทริบิวต์ poster จะให้ตัวยึดตำแหน่งแก่องค์ประกอบ <video> ซึ่งจะใช้พื้นที่ในขณะที่วิดีโอกำลังโหลด
ในเบราว์เซอร์ส่วนใหญ่ preload จะเป็นค่าเริ่มต้นของ metadata และระบบจะโหลดวิดีโอบางส่วนล่วงหน้าโดยใช้ส่วนหัว Content-Range ซึ่งอาจส่งผลให้มีการดาวน์โหลดข้อมูลมากกว่าที่ต้องการ เนื่องจากเบราว์เซอร์ไม่ทราบว่าระบบจัดเก็บข้อมูลเมตาไว้ที่ไบต์ใด และอาจไม่ได้จัดเก็บไว้ที่จุดเริ่มต้นของไฟล์ ดังนั้น วิธีที่ดีที่สุดในการหลีกเลี่ยงการโหลดวิดีโอคือการใช้ preload="none"
ซึ่งสามารถปรับปรุงเพิ่มเติมเพื่อโหลดข้อมูลเมตาล่วงหน้าเมื่อผู้ใช้วางเมาส์เหนือวิดีโอที่มีแอตทริบิวต์ onmouseenter (หรือตัวแฮนเดิลเหตุการณ์ mouseenter ที่เทียบเท่า) ได้ดังนี้
<video controls
loading="lazy"
preload="none"
poster="one-does-not-simply-placeholder.jpg"
onmouseenter="event.target.setAttribute('preload','metadata')">
<source src="one-does-not-simply.webm" type="video/webm">
<source src="one-does-not-simply.mp4" type="video/mp4">
</video>
ซึ่งไม่เพียงช่วยลดเวลาในการรอเมื่อผู้ใช้ไปเล่นวิดีโอ แต่ยังแสดงระยะเวลาของวิดีโอทันทีที่ผู้ใช้ไปเล่นวิดีโอด้วย
วิดีโอมีสิทธิ์เป็นผู้สมัครรับเลือกเป็น LCP posterรูปภาพจะโหลดได้เร็วกว่าวิดีโอ ดังนั้นหากรูปภาพเป็น LCP ที่มีสิทธิ์ คุณควรใช้รูปภาพโปสเตอร์ แต่ก็ควรโหลดล่วงหน้าด้วยfetchpriorityค่าแอตทริบิวต์ "high" เนื่องจากในขณะที่เขียน คุณไม่สามารถระบุ fetchpriority สำหรับแอตทริบิวต์โปสเตอร์ได้
<link rel="preload" href="one-does-not-simply-placeholder.jpg" as="image" fetchpriority="high">
<video controls preload="none"
poster="one-does-not-simply-placeholder.jpg"
onmouseenter="event.target.setAttribute('preload','metadata')">
<source src="one-does-not-simply.webm" type="video/webm">
<source src="one-does-not-simply.mp4" type="video/mp4">
</video>
วิดีโอที่เป็นองค์ประกอบ LCP ไม่ควรใช้ loading="lazy" ในลักษณะเดียวกับที่คุณไม่ควรใช้ Lazy Loading กับรูปภาพ LCP ในวิดีโอ
สำหรับวิดีโอที่ใช้แทน GIF แบบเคลื่อนไหว
โดยทั่วไปแล้ว วิดีโอที่เล่นอัตโนมัติจะใช้กับภาพเคลื่อนไหวสั้นๆ ในรูปแบบ GIF แม้ว่า GIF แบบเคลื่อนไหวจะมีการใช้งานอย่างแพร่หลาย แต่ก็ด้อยกว่าวิดีโอในหลายๆ ด้าน โดยเฉพาะขนาดไฟล์ GIF แบบเคลื่อนไหวอาจมีขนาดข้อมูลหลายเมกะไบต์ วิดีโอที่มีคุณภาพของภาพคล้ายกันมักจะมีขนาดเล็กกว่ามาก
การใช้องค์ประกอบ <video> แทน GIF แบบเคลื่อนไหวไม่ได้ตรงไปตรงมาเหมือนองค์ประกอบ <img> GIF แบบเคลื่อนไหวมีลักษณะ 3 อย่างดังนี้
- โดยจะเล่นโดยอัตโนมัติเมื่อโหลด
- โดยจะเล่นซ้ำอย่างต่อเนื่อง (แต่ก็ไม่เสมอไป)
- ไม่มีแทร็กเสียง
การทำเช่นนี้ด้วยองค์ประกอบ <video> จะมีลักษณะดังนี้
<video autoplay muted loop playsinline>
<source src="one-does-not-simply.webm" type="video/webm">
<source src="one-does-not-simply.mp4" type="video/mp4">
</video>
แอตทริบิวต์ loading="lazy" จะหลีกเลี่ยงการโหลดวิดีโอจนกว่าจะใกล้กับวิวพอร์ต แอตทริบิวต์ autoplay, muted และ loop อธิบายตัวเองได้ playsinline จำเป็นต่อการเล่นอัตโนมัติใน iOS
ตอนนี้คุณมีวิดีโอที่ใช้แทน GIF ได้ซึ่งใช้งานได้ในทุกแพลตฟอร์ม แต่จะใช้ Lazy Loading ได้อย่างไร
สำหรับเบราว์เซอร์ที่รองรับ loading="lazy" เป็นตัวเลือกที่ง่ายที่สุด
<video loading="lazy" autoplay muted loop playsinline>
<source src="one-does-not-simply.webm" type="video/webm">
<source src="one-does-not-simply.mp4" type="video/mp4">
</video>
หากต้องการรองรับการโหลดวิดีโอแบบ Lazy Loading ในเบราว์เซอร์อื่นๆ คุณต้องใช้ JavaScript และแก้ไขมาร์กอัป <video> ตามนั้น
<video class="lazy" preload="none" controls muted loop playsinline width="610" height="254" poster="one-does-not-simply.jpg">
<source src="one-does-not-simply.webm" type="video/webm">
<source src="one-does-not-simply.mp4" type="video/mp4">
</video>
คุณจะเห็นว่าระบบนำ autoplay ออก และเพิ่มแอตทริบิวต์ class="lazy", preload="none" และ poster ซึ่งช่วยให้คุณระบุตัวยึดตำแหน่งเพื่อใช้พื้นที่ขององค์ประกอบ <video> จนกว่าจะโหลดวิดีโอแบบ Lazy Load จากนั้นเราจะใช้ JavaScript Intersection Observer เพื่อเปิดใช้การเล่นอัตโนมัติอีกครั้ง
document.addEventListener("DOMContentLoaded", function() {
var lazyVideos = [].slice.call(document.querySelectorAll("video.lazy"));
if ("IntersectionObserver" in window) {
var lazyVideoObserver = new IntersectionObserver(function(entries, observer) {
entries.forEach(function(video) {
if (video.isIntersecting) {
video.target.removeAttribute('preload');
video.target.removeAttribute('controls');
video.target.autoplay = true;
video.target.classList.remove("lazy");
lazyVideoObserver.unobserve(video.target);
}
});
});
lazyVideos.forEach(function(lazyVideo) {
lazyVideoObserver.observe(lazyVideo);
});
}
});
เมื่อใช้วิธีนี้ วิดีโอจะไม่เล่นอัตโนมัติโดยค่าเริ่มต้น และจะเล่นเฉพาะเมื่อ Intersection Observer ตรวจพบว่าวิดีโอกำลังเข้าสู่ Viewport นอกจากนี้ แอตทริบิวต์ controls ยังจัดการกรณีที่ JavaScript ทำงานไม่สำเร็จด้วย ซึ่งหมายความว่าคุณมีโซลูชันวิดีโอที่จำลองลักษณะการทำงานของ GIF แบบเคลื่อนไหว แต่ไม่ได้ใช้ข้อมูลมากเท่ากับ GIF แบบเคลื่อนไหว และคุณสามารถโหลดเนื้อหาแบบ Lazy Load ได้
ไลบรารีการโหลดแบบ Lazy Loading
ไลบรารีต่อไปนี้จะช่วยให้คุณโหลดวิดีโอแบบ Lazy Load ได้
- vanilla-lazyload และ lozad.js เป็นตัวเลือกที่มีน้ำหนักเบามากซึ่งใช้เฉพาะ Intersection Observer ด้วยเหตุนี้ จึงมีประสิทธิภาพสูง แต่คุณจะต้องใช้ Polyfill ก่อนจึงจะใช้ในเบราว์เซอร์รุ่นเก่าได้
- หากต้องการไลบรารีการโหลดแบบ Lazy สำหรับ React โดยเฉพาะ คุณอาจลองใช้ react-lazyload แม้ว่าจะไม่ได้ใช้ Intersection Observer แต่ก็มีวิธีการโหลดรูปภาพแบบ Lazy Loading ที่คุ้นเคยสำหรับผู้ที่คุ้นเคยกับการพัฒนาแอปพลิเคชันด้วย React
ไลบรารีการโหลดแบบ Lazy Loading แต่ละรายการมีเอกสารประกอบอย่างละเอียด พร้อมรูปแบบมาร์กอัปมากมายสำหรับการโหลดแบบ Lazy Loading ต่างๆ
เมื่อแอตทริบิวต์ loading สำหรับ <video> พร้อมใช้งานในเบราว์เซอร์มากขึ้น เราคาดว่าการใช้โซลูชัน JavaScript (รวมถึงไลบรารี) จะลดลงเพื่อหันไปใช้โซลูชันในตัวแทน ยกเว้นผู้ที่ต้องการควบคุมมากกว่าที่โซลูชันในตัวอนุญาต