تنبلی بارگذاری ویدیو

منتشر شده: ۱۶ آگوست ۲۰۱۹، آخرین به‌روزرسانی: ۲ جولای ۲۰۲۶

همانند عناصر تصویر ، ممکن است بخواهید ویدیو را نیز به صورت lazy-load بارگذاری کنید. ویدیوها معمولاً با عنصر <video> بارگذاری می‌شوند، اگرچه برای ویدیوهایی که در سرویس‌های دیگر مانند یوتیوب میزبانی می‌شوند، ممکن است از <iframe> استفاده کنند (در این صورت مقاله مربوط به بارگذاری lazy-load iframes را بررسی کنید).

نحوه بارگذاری تنبل <video> به مورد استفاده بستگی دارد، زیرا چند راه حل مختلف وجود دارد.

استفاده از ویژگی loading

مرورگرها شروع به پشتیبانی از ویژگی loading ) در عناصر رسانه‌ای ( <video> و <audio> ) کرده‌اند. در صورت پشتیبانی، این بدان معناست که هم رسانه و هم هر تصویر پوستر فقط با اضافه کردن ویژگی loading="lazy" به طور خودکار بارگذاری تنبل (lazy-loaded) می‌شوند:

<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 ، تا زمانی که به محدوده دید (viewport) یا نزدیک آن نرسد، می‌شود و سپس از ویژگی preload برای تصمیم‌گیری در مورد میزان بارگذاری video استفاده می‌کند. این همچنین به این معنی است که ویدیوهای autoplay تا زمانی که به محدوده دید (viewport) یا نزدیک آن نرسند، به طور خودکار پخش نمی‌شوند. ویژگی loading="lazy" با ویژگی‌های poster ، preload و autoplay کار می‌کند و جایگزین نیاز به آنها نمی‌شود.

مرورگرهایی که از ویژگی loading در عناصر رسانه پشتیبانی نمی‌کنند، این ویژگی را نادیده می‌گیرند که منجر به بارگذاری فوری تصویر poster و بارگذاری ویدیو بر اساس ویژگی preload می‌شود که در ادامه به آن خواهیم پرداخت.

از ویژگی preload برای بارگذاری تنبل ویدیو که به صورت خودکار پخش نمی‌شود استفاده کنید

معمولاً بهترین روش، جلوگیری از پخش خودکار ویدیوها است، زیرا کنترل را به کاربر واگذار می‌کند. در این موارد، تعیین ویژگی 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> یک placeholder می‌دهد که در حین بارگذاری ویدیو، فضا را اشغال می‌کند.

در اکثر مرورگرها، پیش‌فرض‌ها روی metadata preload و بخشی از ویدیو با استفاده از هدر 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" استفاده کنند - همانطور که نباید ویدیوهای تصاویر LCP را با lazy load بارگذاری کنید .

برای استفاده از ویدیو به عنوان جایگزین انیمیشن GIF

ویدیوهای خودکار معمولاً برای انیمیشن‌های سریع به سبک GIF استفاده می‌شوند. در حالی که GIFهای متحرک کاربرد گسترده‌ای دارند، اما از بسیاری جهات، به ویژه در اندازه فایل، در مقایسه با معادل‌های ویدیویی خود، ضعیف‌تر هستند. GIFهای متحرک می‌توانند تا چندین مگابایت داده را در خود جای دهند. ویدیوهایی با کیفیت بصری مشابه، معمولاً بسیار کوچک‌تر هستند.

استفاده از عنصر <video> به عنوان جایگزینی برای GIF متحرک به سادگی عنصر <img> نیست. GIF های متحرک سه ویژگی دارند:

  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>

ویژگی loading="lazy" از بارگذاری ویدیو تا نزدیکی viewport جلوگیری می‌کند. ویژگی‌های 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>

برای پشتیبانی از بارگذاری تنبل ویدیو در مرورگرهای دیگر، باید از جاوا اسکریپت استفاده کنید و نشانه‌گذاری <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 خواهید شد که به شما امکان می‌دهد یک placeholder برای اشغال فضای عنصر <video> تا زمان بارگذاری تنبل ویدیو تعیین کنید. سپس، از یک ناظر تقاطع جاوا اسکریپت برای فعال کردن مجدد پخش خودکار استفاده می‌کنیم:

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);
    });
  }
});

با استفاده از این روش، ویدیو به طور پیش‌فرض به صورت خودکار پخش نمی‌شود و فقط زمانی که ناظر تقاطع، ویدیو را به عنوان ورودی به viewport تشخیص دهد، پخش می‌شود. علاوه بر این، ویژگی controls مواردی را که جاوا اسکریپت با شکست مواجه می‌شود، مدیریت می‌کند. این بدان معناست که شما یک راه‌حل ویدیویی دارید که رفتار GIF متحرک را شبیه‌سازی می‌کند، اما مانند GIF های متحرک، مصرف داده زیادی ندارد و می‌توانید آن محتوا را به صورت lazy-load بارگذاری کنید.

کتابخانه‌های بارگذاری تنبل

کتابخانه‌های زیر می‌توانند به شما در بارگذاری تنبل ویدیو کمک کنند:

  • vanilla-lazyload و lozad.js گزینه‌های فوق‌العاده سبکی هستند که فقط از Intersection Observer استفاده می‌کنند. به همین دلیل، عملکرد بسیار خوبی دارند، اما قبل از اینکه بتوانید از آنها در مرورگرهای قدیمی استفاده کنید، باید polyfill شوند.
  • اگر به یک کتابخانه بارگذاری تنبل مخصوص React نیاز دارید، می‌توانید react-lazyload را در نظر بگیرید. اگرچه از Intersection Observer استفاده نمی‌کند، اما روشی آشنا برای بارگذاری تنبل تصاویر برای کسانی که به توسعه برنامه‌های React عادت دارند، ارائه می‌دهد .

هر یک از این کتابخانه‌های بارگذاری تنبل به خوبی مستند شده‌اند و الگوهای نشانه‌گذاری فراوانی برای تلاش‌های مختلف شما در بارگذاری تنبل ارائه می‌دهند.

با در دسترس قرار گرفتن ویژگی loading برای <video> در مرورگرهای بیشتر، انتظار داریم راه‌حل‌های جاوااسکریپت (از جمله کتابخانه‌ها) کمتر به نفع راه‌حل‌های از پیش ساخته شده استفاده شوند، مگر برای آن‌هایی که کنترل بیشتری از آنچه اجازه می‌دهد می‌خواهند.