Data publikacji: 16 sierpnia 2019 r.
Podobnie jak w przypadku elementów graficznych, możesz też stosować wolne wczytywanie filmów. Filmy są zwykle ładowane za pomocą elementu <video>
, ale w przypadku filmów hostowanych w innych usługach, takich jak YouTube, mogą używać elementów <iframe>
(w takim przypadku zapoznaj się z artykułem o elementach iframe z opóźnionym wczytywaniem).
Sposób wczytywania opóźnionego zależy od przypadku użycia, ponieważ istnieje kilka różnych rozwiązań.<video>
W przypadku filmów, które nie są odtwarzane automatycznie
Unikanie automatycznego odtwarzania filmów jest zwykle sprawdzoną metodą, ponieważ daje użytkownikowi kontrolę. W takich przypadkach określenie atrybutu preload
w elemencie <video>
to najlepszy sposób na uniknięcie wczytywania całego filmu:
<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>
Poprzedni przykład używa atrybutu preload
z wartością none
, aby uniemożliwić przeglądarkom wstępne wczytywanie żadnych danych wideo. Atrybut poster
nadaje elementowi <video>
obiekt zastępczy, który zajmie miejsce podczas wczytywania filmu.
W większości przeglądarek preload
domyślnie ustawia się na metadata
, a część filmu jest wstępnie wczytana za pomocą nagłówka Content-Range
. Może to spowodować pobranie większej ilości danych niż jest to potrzebne, zwłaszcza jeśli przeglądarka nie obsługuje nagłówka Content-Range
. Nawet jeśli jest to obsługiwane, przeglądarki nie mogą wiedzieć, w których bajtach są przechowywane metadane, i mogą one nie być przechowywane na początku pliku. Dlatego najlepszym sposobem na uniknięcie wczytywania filmu jest określenie none
i użycie preload="none"
.
Funkcję tę można dodatkowo rozszerzyć, aby wstępnie wczytywać metadane, gdy użytkownik najedzie kursorem na film za pomocą atrybutu onmouseenter
(lub za pomocą odpowiednich metod obsługi zdarzenia 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>
Dzięki temu nie tylko zmniejsza się opóźnienie podczas odtwarzania filmu, ale użytkownik od razu widzi jego czas trwania.
Filmy mogą kwalifikować się jako kandydaci do uwzględnienia w LCP. Obraz poster
wczytuje się szybciej niż film, dlatego w przypadku kandydata na element LCP należy użyć obrazu plakatu, ale też wstępnie go załadować, podając wartość atrybutu 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>
Filmy zastępujące animowane GIF-y
Automatycznie odtwarzane filmy są najczęściej używane do krótkich animacji w formacie GIF. Animowane GIF-y są powszechnie używane, ale w pewnych aspektach, zwłaszcza pod względem rozmiaru pliku, są gorsze od swoich odpowiedników w formacie wideo. Animowane GIF-y mogą zajmować kilka megabajtów danych. Filmy o podobnej jakości wizualnej są zwykle znacznie mniejsze.
Używanie elementu <video>
zamiast animowanego GIF-a nie jest tak proste jak w przypadku elementu <img>
. Animowane GIF-y mają 3 cechy:
- są odtwarzane automatycznie po załadowaniu.
- Są one odtwarzane w pętli (chociaż nie zawsze).
- Nie mają ścieżki audio.
Aby to osiągnąć za pomocą elementu <video>
, wykonaj te czynności:
<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>
Atrybuty autoplay
, muted
i loop
są samoobjaśniające. playsinline
jest wymagany, aby autoodtwarzanie działało na iOS. Teraz masz alternatywę dla GIF-ów, która działa na różnych platformach. Jak jednak zastosować leniwy sposób ładowania? Aby rozpocząć, zmodyfikuj znaczniki <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>
Dodaliśmy atrybut poster
, który umożliwia określenie obiektu zastępczego, który zajmie miejsce elementu <video>
, dopóki film nie zostanie załadowany z opóźnieniem. Podobnie jak w przypadku przykładów <img>
z opóźnionym wczytywaniem, ukryj adres URL filmu w atrybucie data-src
w każdym elemencie <source>
. Następnie użyj kodu JavaScript podobnego do przykładów opóźnionego wczytywania obrazów za pomocą 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);
});
}
});
Podczas wczytywania opóźnionego elementu <video>
musisz przejrzeć wszystkie elementy podrzędne <source>
i zmienić ich atrybuty data-src
na atrybuty src
. Następnie musisz wywołać metodę load
elementu, aby rozpocząć wczytywanie filmu. Po wywołaniu tej metody media zaczną automatycznie się odtwarzać zgodnie z atrybutem autoplay
.
Dzięki tej metodzie masz rozwiązanie wideo, które emuluje zachowanie animowanego GIF-a, ale nie powoduje tak intensywnego wykorzystania danych jak animowane GIF-y. Możesz też ładować te treści z opóźnieniem.
Leniwe ładowanie bibliotek
W przypadku ładowania opóźnionego filmów możesz skorzystać z tych bibliotek:
- vanilla-lazyload i lozad.js to bardzo lekkie opcje, które korzystają tylko z Intersection Observer. Są one bardzo wydajne, ale przed użyciem w starszych przeglądarkach trzeba je wypełnić.
- yall.js to biblioteka, która korzysta z Intersection Observer i przechodzi na uchwyty zdarzeń. Może też wczytywać obrazy
poster
z filmem za pomocą atrybutudata-poster
. - Jeśli potrzebujesz biblioteki ładowania opóźnionego dla Reacta, możesz użyć react-lazyload. Nie używa ona Intersection Observer, ale za to oferuje znajomą metodę opóźnionego wczytywania obrazów dla osób przyzwyczajonych do tworzenia aplikacji za pomocą React.
Każda z tych bibliotek ładowania opóźnionego jest dobrze udokumentowana i zawiera wiele wzorów znaczników do różnych zastosowań ładowania opóźnionego.