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

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

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

สำหรับวิดีโอที่ผู้ใช้เป็นผู้เริ่มต้นการเล่น (กล่าวคือ วิดีโอที่ไม่ได้เล่นอัตโนมัติ) การระบุแอตทริบิวต์ 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 จะทำงานในลักษณะเดียวกัน
  • Safari เวอร์ชัน 11.0 บนเดสก์ท็อปจะโหลดวิดีโอล่วงหน้าเช่นเดียวกับ Chrome บนเดสก์ท็อป จากเวอร์ชัน 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 แบบต่างๆ