תאריך פרסום: 16 באוגוסט 2019
בדומה לרכיבי תמונה, כדאי גם להשתמש בטעינה איטית של סרטונים. סרטונים נטענים בדרך כלל באמצעות הרכיב <video>
, אבל בסרטונים שמתארחים בשירותים אחרים כמו YouTube, יכול להיות שייעשה שימוש ברכיבים מסוג <iframe>
(במקרה כזה, כדאי לעיין במאמר בנושא טעינה איטית של iframe).
האופן שבו מבצעים טעינה איטית של <video>
תלוי בתרחיש לדוגמה, כי יש כמה פתרונות שונים.
בסרטונים שלא מופעלים באופן אוטומטי
מומלץ להימנע מהפעלה אוטומטית של סרטונים, כי כך השליטה נשארת בידי המשתמש. במקרים כאלה, הדרך הטובה ביותר למנוע את טעינת הסרטון כולו היא לציין את המאפיין 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>
placeholder שיתפוס את המקום בזמן טעינת הסרטון.
ברוב הדפדפנים, הערך שמוגדר כברירת מחדל ל-preload
הוא metadata
, וחלק מהסרטון נטען מראש באמצעות הכותרת Content-Range
. כתוצאה מכך, יכול להיות שיורדו יותר נתונים ממה שרצוי – במיוחד אם הדפדפן לא תומך בכותרת Content-Range
. גם אם התכונה הזו נתמכת, הדפדפנים לא יכולים לדעת באילו ביטים המטא-נתונים מאוחסנים, ויכול להיות שהם לא מאוחסנים בתחילת הקובץ. לכן, כדי למנוע את טעינת הסרטון, הכי טוב לציין את none
ולהשתמש ב-preload="none"
.
אפשר לשפר את הקוד הזה עוד יותר כדי לטעון מראש את המטא-נתונים כשהמשתמש מעביר את העכבר מעל הסרטון עם מאפיין onmouseenter
(או עם פונקציית הטיפול באירועים mouseenter
המקבילה):
<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. טעינת תמונה מסוג poster
תהיה מהירה יותר מטעינת הסרטון, לכן אם מדובר ברכיב LCP פוטנציאלי, כדאי להשתמש בתמונה סטטית, אבל גם לטעון אותה מראש עם ערך המאפיין fetchpriority
של "high"
:
<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>
לסרטון שמשמש כתחליף לקובץ GIF מונפש
סרטונים שמתחילים לפעול באופן אוטומטי משמשים בדרך כלל ליצירת אנימציות מהירות בסגנון GIF. קובצי GIF מונפשים נפוצים מאוד, אבל הם נחותים מקובצי וידאו מקבילים בכמה דרכים, במיוחד בגודל הקובץ. קובצי GIF מונפשים יכולים להכיל כמה מגה-בייט של נתונים. סרטונים באיכות חזותית דומה נוטים להיות קטנים בהרבה.
השימוש ברכיב <video>
כתחליף ל-GIF מונפש לא פשוט כמו השימוש ברכיב <img>
. קובצי GIF באנימציה מתאפיינים בשלושה מאפיינים:
- הם מופעלים באופן אוטומטי כשהם נטענים.
- הם חוזרים על עצמם בלי הפסקה (אבל זה לא תמיד המצב).
- אין להם טראק אודיו.
כדי לעשות זאת באמצעות הרכיב <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 שעובד בכל הפלטפורמות. אבל איך מבצעים טעינה מדורגת של הקוד? כדי להתחיל, משנים את ה-Markup של <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
, שמאפשר לציין placeholder שיתפוס את המרחב של רכיב <video>
עד שהסרטון ייטען באיטרציה. בדומה לדוגמאות לטעינה איטית של <img>
, שומרים את כתובת ה-URL של הסרטון במאפיין data-src
בכל רכיב <source>
. לאחר מכן, משתמשים בקוד 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) {
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>
, אתם צריכים לעבור על כל רכיבי הצאצאים <source>
ולהפוך את המאפיינים data-src
שלהם למאפיינים src
. לאחר מכן, צריך להפעיל את הטעינה של הסרטון על ידי קריאה ל-method load
של האלמנט. לאחר מכן, המדיה תתחיל לפעול באופן אוטומטי בהתאם למאפיין autoplay
.
השיטה הזו מאפשרת לכם להשתמש בפתרון וידאו שמחקה את ההתנהגות של קובצי GIF מונפשים, אבל לא גורם לשימוש אינטנסיבי בנתונים כמו קובצי GIF מונפשים, ואפשר לטעון את התוכן הזה באיטרציה.
טעינה מדורגת של ספריות
הספריות הבאות יכולות לעזור לכם לטעון וידאו באיטרציה:
- vanilla-lazyload ו-lozad.js הן אפשרויות קלילות במיוחד שמשתמשות ב-Intersection Observer בלבד. לכן, הביצועים שלהם טובים מאוד, אבל צריך לבצע להם פוליפיל כדי שאפשר יהיה להשתמש בהם בדפדפנים ישנים יותר.
- yall.js היא ספרייה שמשתמשת ב-Intersection Observer ומשתמשת בטיפולי אירועים כחלופה. אפשר גם לטעון בטעינה איטית תמונות
poster
של סרטונים באמצעות מאפייןdata-poster
. - אם אתם צריכים ספרייה ספציפית לטעינה איטית ב-React, כדאי לכם לנסות את react-lazyload. הספרייה לא משתמשת ב-Intersection Observer, אבל כן מספקת שיטה מוכרת של טעינת תמונות בזמן אמת (lazy loading) למפתחים רגילים לפתח אפליקציות עם React.
לכל אחת מהספריות האלה של טעינת פריטים בזמן אמת יש תיעוד מקיף, עם שפע של דפוסי סימון לניסויים השונים שלכם בטעינת פריטים בזמן אמת.