טעינה מדורגת של סרטון

פורסם: 16 באוגוסט 2019, עדכון אחרון: 2 ביולי 2026

בדומה לרכיבי תמונה, יכול להיות שתרצו להשתמש בטעינה עצלה גם לסרטונים. בדרך כלל סרטונים נטענים באמצעות רכיב <video>, אבל אם הסרטונים מתארחים בשירותים אחרים כמו YouTube, יכול להיות שהם משתמשים ב-<iframe> (במקרה כזה, כדאי לעיין במאמר בנושא טעינה עצלה של iframe).

האופן שבו מבצעים טעינה עצלה של <video> תלוי בתרחיש לדוגמה, כי יש כמה פתרונות שונים.

שימוש במאפיין loading

הדפדפנים התחילו לתמוך במאפיין loading ברכיבי מדיה (<video> ו-<audio>). במקומות שבהם יש תמיכה, המשמעות היא שגם המדיה וגם תמונת הפוסטר נטענות אוטומטית בטעינה עצלה רק על ידי הוספת המאפיין 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 לטעינה מדורגת של סרטון שלא מופעל אוטומטית

בדרך כלל מומלץ להימנע מהפעלה אוטומטית של סרטונים, כי כך השליטה נשארת בידי המשתמש. במקרים כאלה, הדרך הכי טובה להימנע מטעינת הסרטון כולו עד שצריך אותו היא לציין את 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 (או עם handler מקביל של אירוע 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 או סרטונים.

לסרטון שמשמש כתחליף ל-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" מונע את טעינת הסרטון עד שהוא כמעט מוצג באזור התצוגה. המאפיינים autoplay, muted ו-loop מובנים מאליהם. האפליקציה playsinline נדרשת להפעלה אוטומטית ב-iOS.

עכשיו יש לכם סרטון שניתן להשתמש בו במקום קובץ GIF בכל הפלטפורמות. אבל איך עושים את זה?

בדפדפנים שתומכים באפשרות הזו, הדרך הכי קלה היא ללחוץ על 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>

כדי לתמוך בטעינה עצלה של סרטונים בדפדפנים אחרים, צריך להשתמש ב-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, שמאפשרים לכם לציין placeholder שימלא את המקום של רכיב <video> עד שהסרטון ייטען. לאחר מכן, אנחנו משתמשים ב-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 מזהה שהסרטון נכנס לאזור התצוגה. בנוסף, המאפיין controls מטפל במקרים שבהם JavaScript נכשל. כלומר, יש לכם פתרון וידאו שמדמה את ההתנהגות של אנימציות GIF, אבל לא צורך את אותה כמות גדולה של נתונים כמו אנימציות GIF, ואפשר להשתמש בטעינה עצלה של התוכן הזה.

ספריות של טעינה מדורגת

הספריות הבאות יכולות לעזור לכם בטעינה עצלה של סרטונים:

  • vanilla-lazyload ו-lozad.js הן אפשרויות קלות מאוד שמשתמשות רק ב-Intersection Observer. לכן, הן מניבות ביצועים טובים מאוד, אבל צריך להשתמש ב-polyfill כדי להשתמש בהן בדפדפנים ישנים יותר.
  • אם אתם צריכים ספריית טעינה עצלה ספציפית ל-React, כדאי לכם לשקול את react-lazyload. הספרייה לא משתמשת ב-Intersection Observer, אבל היא כן מספקת שיטה מוכרת לטעינה עצלה של תמונות למי שמורגל בפיתוח אפליקציות באמצעות React.

כל אחת מהספריות האלה של טעינה עצלה מתועדת היטב, ויש בה הרבה דפוסי תגי עיצוב לשימושים השונים של טעינה עצלה.

ככל שהמאפיין loading של <video> יהיה זמין בדפדפנים נוספים, אנחנו צופים שהשימוש בפתרונות JavaScript (כולל ספריות) יפחת לטובת הפתרונות המובנים, למעט אצל מי שרוצה שליטה רבה יותר.