Leniwe ładowanie filmu

Data publikacji: 16 sierpnia 2019 r., ostatnia aktualizacja: 2 lipca 2026 r.

Podobnie jak w przypadku elementów graficznych możesz też wczytywać filmy na żądanie. Filmy są zwykle wczytywane za pomocą elementu <video>, ale w przypadku filmów hostowanych w innych usługach, takich jak YouTube, mogą być używane elementy <iframe> (w takim przypadku zapoznaj się z artykułem o leniwe wczytywanie elementów iframe).

Sposób leniwego ładowania <video> zależy od przypadku użycia, ponieważ istnieje kilka różnych rozwiązań.

Używanie atrybutu loading

Przeglądarki zaczęły obsługiwać atrybut loading w przypadku elementów multimedialnych (<video><audio>). W obsługiwanych przeglądarkach oznacza to, że zarówno multimedia, jak i obraz plakatu są automatycznie ładowane z opóźnieniem po dodaniu atrybutu 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>

Użycie atrybutu loading="lazy" zapobiegnie wczytywaniu obrazu poster, dopóki nie znajdzie się on w obszarze widocznym lub w jego pobliżu. Następnie atrybut preload określi, ile obrazu video ma zostać wczytane. Oznacza to również, że filmy autoplay nie będą odtwarzane automatycznie, dopóki nie znajdą się w obszarze widoku lub w jego pobliżu. Atrybut loading="lazy" działa z atrybutami poster, preload i autoplay i nie zastępuje ich.

Przeglądarki, które nie obsługują atrybutu loading w elementach multimedialnych, zignorują ten atrybut, co spowoduje natychmiastowe wczytanie obrazu poster i wczytanie filmu na podstawie atrybutu preload, o którym opowiemy w następnej kolejności.

Użyj atrybutu preload, aby wczytywać w leniwy sposób filmy, które nie są odtwarzane automatycznie.

Unikanie autoodtwarzania filmów jest zwykle najlepszym rozwiązaniem, ponieważ pozostawia kontrolę użytkownikowi. W takich przypadkach najlepszym sposobem na uniknięcie wczytywania całego filmu, dopóki nie będzie potrzebny, jest określenie atrybutu preload w elemencie <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>

W poprzednim przykładzie użyto atrybutu preload o wartości none, aby zapobiec wstępnemu wczytywaniu przez przeglądarki jakichkolwiek danych wideo, nawet gdy znajdują się one w obszarze widocznym. Atrybut poster nadaje elementowi <video> obiekt zastępczy, który będzie zajmować miejsce podczas ładowania filmu.

W większości przeglądarek wartość domyślna preload to metadata, a część filmu jest wstępnie wczytywana za pomocą nagłówka Content-Range. Może to spowodować pobranie większej ilości danych niż oczekiwano, ponieważ przeglądarki nie wiedzą, w których bajtach są przechowywane metadane, a mogą one nie być przechowywane na początku pliku. Dlatego najlepszym sposobem na uniknięcie wczytania filmu jest użycie preload="none".

Możesz to jeszcze bardziej ulepszyć, aby wstępnie wczytywać metadane, gdy użytkownik najedzie kursorem na film, używając atrybutu onmouseenter (lub równoważnego programu obsługi zdarzeń 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>

Dzięki temu nie tylko zmniejsza się opóźnienie, gdy użytkownik chce odtworzyć film, ale też od razu wyświetla się jego długość.

Filmy mogą kwalifikować się jako kandydaci do LCP. poster obraz wczytuje się szybciej niż film, więc jeśli jest kandydatem do LCP, użyj obrazu plakatu, ale też wstępnie go wczytaj za pomocą wartości atrybutu fetchpriority "high", ponieważ w momencie pisania tego artykułu nie można określić atrybutu fetchpriority dla atrybutów plakatu:

<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, które są elementami LCP, nie powinny używać atrybutu loading="lazy" – tak samo jak nie należy leniwie wczytywać obrazów LCP .

W przypadku filmów zastępujących animowane GIF-y

Filmy odtwarzane automatycznie są często używane w przypadku krótkich animacji w stylu GIF-ów. Animowane GIF-y są powszechnie używane, ale pod wieloma względami, zwłaszcza pod względem rozmiaru pliku, ustępują odpowiednikom wideo. Animowane GIF-y mogą mieć rozmiar kilku megabajtów. Filmy o podobnej jakości obrazu są zwykle znacznie mniejsze.

Używanie elementu <video> jako zamiennika animowanego GIF-a nie jest tak proste jak w przypadku elementu <img>. Animowane GIF-y mają 3 cechy:

  1. Po załadowaniu są odtwarzane automatycznie.
  2. Są odtwarzane w pętli (chociaż nie zawsze).
  3. Nie mają ścieżki audio.

Osiągnięcie tego za pomocą elementu <video> wygląda mniej więcej tak:

<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>

Atrybut loading="lazy" zapobiega ładowaniu filmu, dopóki nie znajdzie się on w pobliżu widocznego obszaru. Atrybuty autoplay, muted i loop są oczywiste. playsinline jest niezbędne do automatycznego odtwarzania na urządzeniach z iOS.

Teraz masz działającą na różnych platformach alternatywę dla GIF-ów w postaci filmów. Jak jednak zastosować leniwe ładowanie?

W przypadku przeglądarek, które obsługują tę funkcję, najłatwiejszą opcją jest 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>

Aby obsługiwać leniwe wczytywanie filmów w innych przeglądarkach, musisz użyć JavaScriptu i odpowiednio zmodyfikować kod <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>

Zauważysz usunięcie atrybutu autoplay oraz dodanie atrybutów class="lazy", preload="none"poster, które umożliwiają określenie obiektu zastępczego, który będzie zajmować miejsce elementu <video>, dopóki film nie zostanie wczytany z opóźnieniem. Następnie używamy interfejsu JavaScript Intersection Observer, aby ponownie włączyć autoodtwarzanie:

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

W przypadku tej metody film nie jest domyślnie odtwarzany automatycznie, a tylko wtedy, gdy obserwator przecięcia wykryje, że film wchodzi w obszar widoczny. Dodatkowo atrybut controls obsługuje przypadki, w których JavaScript nie działa. Oznacza to, że masz rozwiązanie wideo, które naśladuje zachowanie animowanych GIF-ów, ale nie powoduje tak intensywnego zużycia danych jak one. Możesz też leniwie wczytywać te treści.

Leniwe ładowanie bibliotek

Te biblioteki mogą Ci pomóc w leniwym wczytywaniu filmów:

  • vanilla-lazyloadlozad.js to bardzo lekkie opcje, które korzystają tylko z Intersection Observer. Dlatego są one bardzo wydajne, ale zanim będzie można ich używać w starszych przeglądarkach, trzeba je uzupełnić.
  • Jeśli potrzebujesz biblioteki leniwego wczytywania przeznaczonej specjalnie dla Reacta, możesz rozważyć użycie react-lazyload. Chociaż nie korzysta z Intersection Observer, zapewnia znaną metodę leniwego ładowania obrazów dla osób przyzwyczajonych do tworzenia aplikacji w React.

Każda z tych bibliotek leniwego ładowania jest dobrze udokumentowana i zawiera wiele wzorców znaczników, które możesz wykorzystać w różnych projektach.

W miarę jak atrybut loading dla <video> będzie dostępny w większej liczbie przeglądarek, spodziewamy się, że rozwiązania JavaScript (w tym biblioteki) będą rzadziej używane na rzecz rozwiązań wbudowanych, z wyjątkiem tych, którzy chcą mieć większą kontrolę.