การโหลดวิดีโอแบบ Lazy Loading

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

สำหรับวิดีโอที่ไม่เล่นอัตโนมัติ

สำหรับวิดีโอที่ผู้ใช้เริ่มเล่น (หรือวิดีโอที่ไม่ได้เล่นอัตโนมัติ) โปรดระบุแอตทริบิวต์ preload ในองค์ประกอบ <video>

<video controls 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> จะใช้พื้นที่ขณะวิดีโอโหลด สาเหตุก็คือลักษณะการทำงานเริ่มต้นในการโหลดวิดีโออาจแตกต่างกันตามแต่ละเบราว์เซอร์

  • ใน Chrome ค่าเริ่มต้นของ preload คือ auto แต่ปัจจุบันใน Chrome 64 ค่าเริ่มต้นจะเป็น metadata แต่กระนั้น ใน Chrome เวอร์ชันเดสก์ท็อป ระบบอาจโหลดวิดีโอบางส่วนไว้ล่วงหน้าโดยใช้ส่วนหัว Content-Range เบราว์เซอร์อื่นๆ ที่ใช้ Chromium และ Firefox ทำงานคล้ายๆ กัน
  • เช่นเดียวกับ Chrome บนเดสก์ท็อป Safari เวอร์ชันเดสก์ท็อป 11.0 จะโหลดวิดีโอในช่วงหนึ่งไว้ล่วงหน้า ตั้งแต่เวอร์ชัน 11.2 เป็นต้นไป ระบบจะโหลดเฉพาะข้อมูลเมตาของวิดีโอล่วงหน้าเท่านั้น ใน Safari บน iOS ระบบจะไม่โหลดวิดีโอไว้ล่วงหน้า
  • เมื่อเปิดใช้โหมดประหยัดอินเทอร์เน็ต preload จะมีค่าเริ่มต้นเป็น none

เนื่องจากลักษณะการทำงานเริ่มต้นของเบราว์เซอร์เกี่ยวกับ preload ไม่ได้กำหนดไว้เป็นกฎเฉพาะ การแสดงอย่างชัดแจ้งจึงอาจเหมาะสมที่สุด ในกรณีที่ผู้ใช้เริ่มเล่นการเล่น การใช้ preload="none" เป็นวิธีที่ง่ายที่สุดในการเลื่อนการโหลดวิดีโอในทุกแพลตฟอร์ม แอตทริบิวต์ preload ไม่ใช่วิธีเดียวในการเลื่อนการโหลดเนื้อหาวิดีโอ การเล่นอย่างรวดเร็วด้วยการโหลดวิดีโอล่วงหน้าอาจให้แนวคิดและข้อมูลเชิงลึกเกี่ยวกับการเล่นวิดีโอใน JavaScript

แต่จริงๆ แล้ว บทความนี้ไม่ได้มีประโยชน์อะไรเมื่อคุณต้องการใช้วิดีโอแทน GIF แบบเคลื่อนไหว ซึ่งจะกล่าวถึงต่อไป

สำหรับวิดีโอที่ทำหน้าที่เป็นการแทนที่ GIF แบบเคลื่อนไหว

แม้ว่า GIF แบบเคลื่อนไหวจะใช้งานได้อย่างกว้างขวาง แต่ก็ต่ำกว่าความเทียบเท่าวิดีโอในหลายๆ ด้าน โดยเฉพาะขนาดไฟล์ GIF แบบเคลื่อนไหวอาจขยาย ช่วงข้อมูลหลายเมกะไบต์ วิดีโอที่มีคุณภาพภาพใกล้เคียงกัน มีแนวโน้มที่จะมีขนาดเล็กกว่ามาก

การใช้องค์ประกอบ <video> เพื่อแทนที่ GIF แบบเคลื่อนไหวนั้นไม่เหมือนกับองค์ประกอบ <img> GIF แบบเคลื่อนไหวมีลักษณะ 3 ประการดังนี้

  1. วิดีโอจะเล่นโดยอัตโนมัติเมื่อโหลด
  2. วนซ้ำอย่างต่อเนื่อง (แต่อาจไม่ใช่กรณีเสมอไป)
  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>

แอตทริบิวต์ autoplay, muted และ loop มีความชัดเจนในตัว ต้องมี playsinline เพื่อให้การเล่นอัตโนมัติมีผลใน iOS ตอนนี้คุณมาแทนที่ วิดีโอเป็น GIF ที่ให้บริการได้ในหลายแพลตฟอร์มแล้ว แต่จะต้องทำอย่างไร กับการโหลดแบบ Lazy Loading ล่ะ ในการเริ่มต้น ให้แก้ไขมาร์กอัป <video> ของคุณดังต่อไปนี้

<video class="lazy" autoplay muted loop playsinline width="610" height="254" poster="one-does-not-simply.jpg">
  <source data-src="one-does-not-simply.webm" type="video/webm">
  <source data-src="one-does-not-simply.mp4" type="video/mp4">
</video>

คุณจะเห็นการเพิ่มแอตทริบิวต์ poster ซึ่งช่วยให้คุณระบุตัวยึดตำแหน่งเพื่อใช้พื้นที่ขององค์ประกอบ <video> จนกว่าวิดีโอจะโหลดแบบ Lazy Loading เช่นเดียวกับตัวอย่างการโหลดแบบ Lazy Loading <img> ให้ซ่อน URL ของวิดีโอไว้ในแอตทริบิวต์ data-src ในองค์ประกอบ <source> แต่ละรายการ จากนั้น ให้ใช้โค้ด JavaScript ที่คล้ายกับตัวอย่างการโหลดแบบ Lazy Loading ของรูปภาพที่อิงตาม 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) {
          for (var source in video.target.children) {
            var videoSource = video.target.children[source];
            if (typeof videoSource.tagName === "string" && videoSource.tagName === "SOURCE") {
              videoSource.src = videoSource.dataset.src;
            }
          }

          video.target.load();
          video.target.classList.remove("lazy");
          lazyVideoObserver.unobserve(video.target);
        }
      });
    });

    lazyVideos.forEach(function(lazyVideo) {
      lazyVideoObserver.observe(lazyVideo);
    });
  }
});

เมื่อโหลดองค์ประกอบ <video> แบบ Lazy Loading คุณจะต้องทำซ้ำองค์ประกอบย่อย <source> ทั้งหมด แล้วเปลี่ยนแอตทริบิวต์ data-src ขององค์ประกอบเป็น src เมื่อทำเสร็จแล้ว คุณต้องทริกเกอร์การโหลดวิดีโอด้วยการเรียกใช้เมธอด load ขององค์ประกอบ จากนั้นสื่อจะเริ่มเล่นโดยอัตโนมัติตามแอตทริบิวต์ autoplay

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

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

ไลบรารีต่อไปนี้สามารถช่วยคุณโหลดวิดีโอแบบ Lazy Loading ได้

  • vanilla-lazyload และ lozad.js เป็นตัวเลือกน้ำหนักเบาสุด ซึ่งใช้ Intersection Observer เท่านั้น ด้วยเหตุนี้ ส่วนขยายจึงมีประสิทธิภาพสูงแต่จะต้องปรับเป็น Polyfill ก่อนจึงจะใช้บนเบราว์เซอร์รุ่นเก่าได้
  • yall.js เป็นไลบรารีที่ใช้ Intersection Observer และย้อนกลับไปใช้เครื่องจัดการเหตุการณ์ นอกจากนี้ยังโหลดรูปภาพวิดีโอ poster แบบ Lazy Loading โดยใช้แอตทริบิวต์ data-poster ได้ด้วย
  • หากต้องใช้ไลบรารีการโหลดแบบ Lazy Loading โดยเฉพาะสำหรับ React คุณอาจใช้ react-lazyload ได้ แม้จะไม่ได้ใช้ Intersection Observer แต่ได้ให้วิธีการที่คุ้นเคยในการโหลดรูปภาพแบบ Lazy Loading สำหรับผู้ที่คุ้นเคยกับการพัฒนาแอปพลิเคชันด้วย React

ไลบรารีการโหลดแบบ Lazy Loading แต่ละไลบรารีเหล่านี้จะได้รับการจัดทำเป็นเอกสารไว้เป็นอย่างดี โดยมีรูปแบบมาร์กอัปมากมายสำหรับความพยายามในการโหลดแบบ Lazy Loading ที่หลากหลาย