Lazy Loading

Veröffentlicht: 16. August 2019

Wie bei Bildelementen können Sie auch Videos per Lazy Loading laden. Videos werden in der Regel mit dem <video>-Element geladen. Bei Videos, die auf anderen Diensten wie YouTube gehostet werden, können jedoch <iframe>s verwendet werden. In diesem Fall lesen Sie den Artikel zu Lazy-Loading-Iframes.

Wie <video> per Lazy Load geladen wird, hängt vom Anwendungsfall ab, da es mehrere Lösungen gibt.

In der Regel ist es empfehlenswert, keine automatisch abgespielten Videos zu verwenden, da die Kontrolle beim Nutzer bleibt. In diesen Fällen ist es am besten, das preload-Attribut für das <video>-Element anzugeben, um zu vermeiden, dass das gesamte Video geladen wird:

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

Im vorherigen Beispiel wird ein preload-Attribut mit dem Wert none verwendet, um zu verhindern, dass Browser alle Videodaten vorab laden. Das poster-Attribut gibt dem <video>-Element einen Platzhalter, der den Bereich belegt, während das Video geladen wird.

In den meisten Browsern ist preload standardmäßig metadata und ein Teil des Videos wird mithilfe der Content-Range-Überschrift vorab geladen. Das kann dazu führen, dass mehr Daten heruntergeladen werden, als gewünscht – insbesondere, wenn der Content-Range-Header vom Browser nicht unterstützt wird. Selbst wenn dies unterstützt wird, können Browser nicht wissen, an welchen Bytes die Metadaten gespeichert sind. Sie werden möglicherweise nicht am Anfang der Datei gespeichert. Die beste Möglichkeit, das Laden des Videos zu vermeiden, besteht daher darin, none anzugeben und preload="none" zu verwenden.

Das kann noch weiter optimiert werden, indem die Metadaten vorab geladen werden, wenn der Nutzer den Mauszeiger auf das Video bewegt, das ein onmouseenter-Attribut (oder den entsprechenden mouseenter-Ereignishandler) enthält:

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

Dadurch wird nicht nur die Verzögerung beim Abspielen des Videos reduziert, sondern auch die Dauer des Videos wird sofort angezeigt.

Videos können als LCP-Kandidaten gelten. Ein poster-Bild lässt sich schneller laden als das Video. Wenn es sich also um einen LCP-Kandidaten handelt, sollten Sie ein Posterbild verwenden und es vorabladen, indem Sie als fetchpriority-Attributwert "high" angeben:

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

Für Videos, die animierte GIFs ersetzen

Automatisch abgespielte Videos werden am häufigsten für kurze Animationen im GIF-Stil verwendet. Animierte GIFs sind zwar weit verbreitet, aber in vielerlei Hinsicht nicht so gut wie Videoformate, insbesondere in Bezug auf die Dateigröße. Animierte GIFs können mehrere Megabyte an Daten umfassen. Videos mit ähnlicher visueller Qualität sind in der Regel viel kleiner.

Die Verwendung des Elements <video> als Ersatz für animierte GIFs ist nicht so einfach wie das Element <img>. Animierte GIFs haben drei Eigenschaften:

  1. Sie werden beim Laden automatisch abgespielt.
  2. Sie werden in einer Endlosschleife abgespielt (das ist aber nicht immer der Fall).
  3. Sie haben keinen Audiotrack.

Mit dem <video>-Element sieht das ungefähr so aus:

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

Die Attribute autoplay, muted und loop sind selbsterklärend. playsinline ist erforderlich, damit die automatische Wiedergabe unter iOS funktioniert. Jetzt haben Sie einen plattformübergreifenden Ersatz für Videos als GIF. Aber wie funktioniert das Lazy Loading? Ändern Sie zuerst das <video>-Markup entsprechend:

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

Das poster-Attribut wurde hinzugefügt. Damit können Sie einen Platzhalter angeben, der den Platz des <video>-Elements belegt, bis das Video per Lazy-Loading geladen wird. Wie bei den <img>-Beispielen für Lazy Loading speichern Sie die Video-URL im data-src-Attribut jedes <source>-Elements. Verwenden Sie dann JavaScript-Code, der den Beispielen für das Lazy-Laden von Bildern mit Intersection Observer ähnelt:

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

Wenn Sie ein <video>-Element per Lazy-Load laden, müssen Sie alle untergeordneten <source>-Elemente durchgehen und ihre data-src-Attribute in src-Attribute umwandeln. Anschließend musst du das Laden des Videos durch Aufrufen der load-Methode des Elements auslösen. Danach wird das Medium gemäß dem autoplay-Attribut automatisch wiedergegeben.

Mit dieser Methode haben Sie eine Videolösung, die das Verhalten von animierten GIFs emuliert, aber nicht die gleiche intensive Datennutzung wie animierte GIFs erfordert. Außerdem können Sie diese Inhalte per Lazy-Load laden.

Lazy Loading-Bibliotheken

Die folgenden Bibliotheken können Ihnen beim Lazy-Load von Videos helfen:

  • vanilla-lazyload und lozad.js sind superleichte Optionen, die nur Intersection Observer verwenden. Sie sind daher sehr leistungsfähig, müssen aber polyfilled werden, bevor Sie sie in älteren Browsern verwenden können.
  • yall.js ist eine Bibliothek, die Intersection Observer verwendet und bei Bedarf auf Event-Handler zurückgreift. Außerdem können Videoposter-Bilder mithilfe eines data-poster-Attributs verzögert geladen werden.
  • Wenn Sie eine React-spezifische Lazy-Loading-Bibliothek benötigen, können Sie react-lazyload verwenden. Es wird zwar kein Intersection Observer verwendet, aber es bietet eine vertraute Methode zum Lazy-Laden von Bildern für diejenigen, die mit der Entwicklung von Anwendungen mit React vertraut sind.

Jede dieser Lazy-Loading-Bibliotheken ist gut dokumentiert und bietet zahlreiche Markup-Muster für Ihre verschiedenen Lazy-Loading-Aktivitäten.