IntersectionObserver API und verzögertes Laden von Bildern

Die Verwendung des verzögerten Ladens von Bildern zur Verbesserung der Leistung von Webprojekten ist eine beliebte Optimierungstechnik. Die Sache ist, dass Bilder „schwere“ Ressourcen sind, die mit modernen Websites überfüllt sind. Wir haben bereits etwas darüber veröffentlicht. Hier können Sie lesen, was das verzögerte Laden der Walmart-Website bewirkt hat, und erfahren, wie Sie IntersectionObserver in React-Projekten verwenden. Hier ist ein Artikel zur Optimierung statischer Sites. Hier finden Sie aktuelles Material zum verzögerten Laden mit Browser-Tools.



Heute machen wir Sie auf eine Übersetzung eines Artikels aufmerksam, in dem die Verwendung der IntersectionObserver-API am Beispiel einer einfachen Webseite beschrieben wird. Dieses Material ist für Anfänger gedacht.

Was ist das verzögerte Laden von Bildern?


Bei der Analyse der Anwendungsleistung stehen zwei Indikatoren im Vordergrund: Zeit bis zur ersten Interaktivität (Time To Interactive) und Ressourcenverbrauch (Ressourcenverbrauch). Sie werden sich unweigerlich denen stellen müssen, die sich mit Webentwicklung beschäftigen. Darüber hinaus können Probleme mit Anwendungen auftreten, nicht nur, weil es lange dauert, bis sie für die Arbeit bereit sind oder zu viele Ressourcen verbrauchen. In jedem Fall ist es jedoch sehr wichtig, die Ursachen dieser Probleme so früh wie möglich zu finden und sicherzustellen, dass die Probleme nicht einmal auftreten.

Die Verwendung von Technologien zum Laden verzögerter Bilder in Webanwendungen minimiert das Risiko von Leistungsproblemen. Wenn wir nämlich das verzögerte Laden unter dem Gesichtspunkt seines Einflusses auf den Zeitpunkt des Betriebs der Seite und den Ressourcenverbrauch analysieren, erhalten wir Folgendes:

  1. Zeit für die erste Interaktivität. Dies ist die Zeit, die die Webanwendung benötigt, um die Benutzeroberfläche zu laden und in einen Zustand zu bringen, der für den Benutzer geeignet ist, damit zu arbeiten. Das verzögerte Laden (außerdem geht es nicht nur um Bilder) optimiert die Reaktionszeit von Anwendungen dank der Technologie, Code zu trennen und nur das zu laden, was eine bestimmte Seite benötigt oder was zu einem bestimmten Zeitpunkt benötigt wird.
  2. Ressourcenverbrauch. Menschen sind ungeduldige Wesen. Wenn das Laden einer Website länger als 3 Sekunden dauert, verlassen 70% der Benutzer diese Website. Webanwendungen sollten nicht so lange geladen werden. Durch das verzögerte Laden können Sie die Ressourcen reduzieren, die für die Arbeit der Seiten erforderlich sind. Dies kann beispielsweise bedeuten, dass der Code eines bestimmten Projekts in Fragmente aufgeteilt wird, die nur auf den Seiten geladen werden, die sie benötigen. Infolgedessen steigt die Standortleistung und der Systemressourcenverbrauch sinkt.

Lazy-Loading-Technologien beschleunigen also Anwendungen und verkürzen die Zeit, die sie herunterladen und aufrufen. Dies wird dadurch erreicht, dass Ressourcen nur dann geladen werden, wenn sie benötigt werden.

Hier sind einige Vorteile, die das verzögerte Laden Webprojekten bietet:

  • Seiten werden schneller geladen und sind betriebsbereit.
  • Beim ersten Laden von Seiten müssen Sie weniger Daten übertragen und verarbeiten.

Lazy Laden von Bildern mit der IntersectionObserver API


Wenn Sie darüber nachdenken, wie Webseiten geladen werden, wird deutlich, dass es keinen Sinn macht, Bilder oder andere Ressourcen herunterzuladen, die für den Benutzer nicht sichtbar sind. Beim verzögerten Laden werden zuerst Bilder geladen, die sich im sichtbaren Bereich der Seite befinden. Wenn der Benutzer die Seite scrollt, werden dann andere Bilder geladen, die in den sichtbaren Bereich der Seite fallen.

Betrachten Sie ein Beispiel.


Seite und ihr sichtbarer Bereich

Schauen Sie sich die vorherige Abbildung an. Hier sehen Sie den Browser und die darin geladene Webseite. Die Bilder #IMG_1 und #IMG_2 befinden sich im Bereich der Seite. Dies bedeutet, dass sie für den Benutzer sichtbar sind und sich innerhalb der Grenzen des Bereichs des Browserfensters befinden, der auf dem Bildschirm angezeigt wird.

Diese Reihenfolge der Arbeit mit der Seite kann nicht als ideal angesehen werden, wenn beim Laden die Bilder #IMG_1 , #IMG_2 , #IMG_3 und #IMG_4 . Nur #IMG_1 und #IMG_2 sind für den #IMG_2 sichtbar, und #IMG_3 und #IMG_4 sind vor ihm verborgen. Wenn Sie das erste und das zweite Bild beim Laden der Seite laden, aber das dritte und vierte Bild nicht herunterladen, kann sich dies positiv auf die Leistung der Website auswirken. Wir sprechen nämlich über Folgendes. Wenn der Benutzer die Seite so scrollt, dass das dritte Bild sichtbar wird, wird es geladen. Wenn der Bildlauf fortgesetzt wird und das vierte Bild sichtbar wird, wird es ebenfalls geladen.


Scrollen einer Seite und Laden von Bildern

Nachdem wir genau herausgefunden haben, wie wir mit Bildern arbeiten möchten, fragen wir uns, wie wir herausfinden können, dass ein bestimmtes Element einer Seite in den sichtbaren Bereich fällt. Moderne Browser verfügen über eine API, mit der der Programmierer herausfinden kann, wann ein bestimmter Bereich der Seite sichtbar wird. Es geht um die IntersectionObserver-API. Mithilfe asynchroner Mechanismen können Sie die Überwachung von Elementen organisieren und Benachrichtigungen erhalten, wenn ein Element den Gültigkeitsbereich des Dokuments überschreitet oder die Grenze eines anderen Elements überschreitet.

Um das verzögerte Laden von Bildern zu konfigurieren, müssen wir zunächst einen Vorlagencode für das Element vorbereiten, das zur Beschreibung der Bilder verwendet wird. Da ist er:

 <img class="lzy_img" src="lazy_img.jpg" data-src="real_img.jpg" /> 

Mit der Klasse können Sie ein Element als Bild identifizieren, auf das das verzögerte Laden angewendet wird. Mit dem Attribut src können Sie ein Platzhalterbild anzeigen, bevor Sie das tatsächliche Bild anzeigen. data-src speichert die Adresse des realen Bildes, die geladen wird, wenn das Element den sichtbaren Bereich der Seite betritt.

Schreiben wir nun den Code, der das verzögerte Laden implementiert. Wie bereits erwähnt, verwenden wir die IntersectionObserver-API, um den Moment zu erkennen, in dem das Bild in den Seitenanzeigebereich gelangt.

Erstellen Sie zunächst eine Instanz von IntersectionObserver :

 const imageObserver = new IntersectionObserver(...); 

Der IntersectionObserver Konstruktor akzeptiert eine Funktion mit zwei Parametern. Einer von ihnen speichert ein Array, das aus Elementen besteht, die überwacht werden müssen, der andere eine IntersectionObserver Instanz. Es sieht so aus:

 const imageObserver = new IntersectionObserver((entries, imgObserver) => {   entries.forEach((entry) => {       //...   }) }); 

Der Funktionscode prüft, ob die durch die entries Eintragsarray dargestellten Bilder das Ansichtsfenster schneiden. Wenn dies der Fall ist, zeichnet das src Attribut des entsprechenden Bildes auf, was in seinem data-src Attribut enthalten war.

 const imageObserver = new IntersectionObserver((entries, imgObserver) => {   entries.forEach((entry) => {       if(entry.isIntersecting) {           const lazyImage = entry.target           lazyImage.src = lazyImage.dataset.src       }   }) }); 

Hier prüfen wir anhand der Bedingung if(entry.isIntersecting) {...} , ob das Element den if(entry.isIntersecting) {...} des Browsers überschreitet. In diesem lazyImage speichern wir das img Element in der lazyImage Konstante. Dann schreiben wir in sein src Attribut, was in sein data-src Attribut war. Dadurch wird das Bild geladen und angezeigt, dessen Adresse in data-src gespeichert ist. Im Browser sieht es so aus, als würde das Platzhalterbild lazy_img.jpg durch ein echtes Bild ersetzt.

Jetzt müssen wir die .observe() -Methode unserer IntersectionObserver Instanz verwenden, um mit der Überwachung der für uns interessanten Elemente zu beginnen:

 imageObserver.observe(document.querySelectorAll('img.lzy_img')); 

Hier wählen wir alle img Elemente mit der Klasse lzy_img dem document.querySelectorAll('img.lzy_img') mit dem Befehl document.querySelectorAll('img.lzy_img') und übergeben sie an die Methode .observe() . Nachdem er eine Liste von Elementen erhalten hat, beginnt er mit deren Beobachtung.

Um dieses Beispiel zu testen, initialisieren wir zunächst das Node.js-Projekt:

 mkdir lzy_img cd lzy_img npm init -y 

Erstellen Sie nun die Datei lzy_img im Ordner lzy_img :

 touch index.html 

Fügen Sie den folgenden Code hinzu:

 <html> <title>Lazy Load Images</title> <body>   <div>       <div style="">           <img class="lzy_img" src="lazy_img.jpg" data-src="img_1.jpg" />           <hr />       </div>       <div style="">           <img class="lzy_img" src="lazy_img.jpg" data-src="img_2.jpg" />           <hr />       </div>       <div style="">           <img class="lzy_img" src="lazy_img.jpg" data-src="img_3.jpg" />           <hr />       </div>       <div style="">           <img class="lzy_img" src="lazy_img.jpg" data-src="img_4.jpg" />           <hr />       </div>       <div style="">           <img class="lzy_img" src="lazy_img.jpg" data-src="img_5.jpg" />           <hr />       </div>   </div>   <script>       document.addEventListener("DOMContentLoaded", function() {           const imageObserver = new IntersectionObserver((entries, imgObserver) => {               entries.forEach((entry) => {                   if (entry.isIntersecting) {                       const lazyImage = entry.target                       console.log("lazy loading ", lazyImage)                       lazyImage.src = lazyImage.dataset.src                   }               })           });           const arr = document.querySelectorAll('img.lzy_img')           arr.forEach((v) => {               imageObserver.observe(v);           })       })   </script> </body> </html> 

Möglicherweise stellen Sie fest, dass hier 5 Bilder beschrieben sind, in denen der Platzhalter lazy_img.jpg beim Laden angezeigt wird. Das data-src Attribut von jedem von ihnen enthält Informationen über reale Bilder. Hier ist eine Liste der im Projekt verwendeten Bildnamen:

 lazy_img.jpg img_1.jpg img_2.jpg img_3.jpg img_4.jpg img_5.jpg 

Sie müssen alle diese Bilder selbst erstellen, indem Sie den Projektordner in die in der folgenden Abbildung gezeigte Ansicht bringen.


Projektordner

In meinem Fall wurde die Datei lazy_img.jpg mit Windows Paint erstellt und die realen Bilder ( img_*.jpg Jpg ) wurden von pixabay.com übernommen .

Beachten Sie, dass der zum Erstellen der IntersectionObserver Instanz verwendete Rückruf einen Aufruf von console.log() . Auf diese Weise können wir lernen, wie Operationen zum Laden verschiedener Bilder ausgeführt werden.

index.html , verwenden wir jetzt das http-server Paket:

 npm i http-server 

Fügen Sie die Eigenschaft start zum package.json Datei package.json :

 "scripts": {   "start": "http-server ./" } 

npm run start Befehl npm run start im Terminal aus.

Öffnen Sie nun den Browser und gehen Sie zur Adresse 127.0.0.1:8080 . Unsere index.html Seite ganz am Anfang sieht ungefähr so ​​aus wie in der folgenden Abbildung.


Seite ohne echte Bilder

Möglicherweise stellen Sie fest, dass dort, wo echte Bilder sein sollten, nur Platzhalter angezeigt werden. Hier gehen wir davon aus, dass sich das erste Bild im Anzeigebereich befindet, sodass der Browser mit dem Herunterladen beginnt. Infolgedessen sieht die Seite jetzt so aus.


Browser hat erstes Bild hochgeladen

Andere Bilder noch nicht hochgeladen. Sie haben den Sichtbereich noch nicht erreicht.

Wenn Sie beim Betrachten der Konsole durch die Seite scrollen, werden Sie ein Problem feststellen. Es besteht darin, dass der Browser beim Scrollen durch dasselbe Bild im Anzeigefenster mehrmals versucht, es herunterzuladen.


Mehrere Uploads desselben Bildes

Das brauchen wir überhaupt nicht. Dies führt zu unnötiger Verschwendung von Systemressourcen und beeinträchtigt die Projektleistung.

Um dieses Problem zu lösen, müssen wir das img Element, für das das reale Image bereits geladen ist, aus der Liste der Elemente entfernen, die unsere IntersectionObserver Instanz überwacht. Wir müssen auch die Klasse lzy_img aus diesem Element entfernen. So sieht es im bearbeiteten Rückruffunktionscode aus:

 <script>   document.addEventListener("DOMContentLoaded", function() {       const imageObserver = new IntersectionObserver((entries, imgObserver) => {           entries.forEach((entry) => {               if (entry.isIntersecting) {                   const lazyImage = entry.target                   console.log("lazy loading ", lazyImage)                   lazyImage.src = lazyImage.dataset.src                   lazyImage.classList.remove("lzy_img");                   imgObserver.unobserve(lazyImage);               }           })       });       const arr = document.querySelectorAll('img.lzy_img')       arr.forEach((v) => {           imageObserver.observe(v);       })   }) </script> 

Nach dem Laden des realen Bildes des entsprechenden img Elements wird dessen lzy_img Klasse lzy_img und das Element aus der Liste der Elemente ausgeschlossen, die IntersectionObserver beobachtet.

Hier ist der Beispielcode:

 <html> <title>Lazy Load Images</title> <body>   <div>       <div style="">           <img class="lzy_img" src="lazy_img.jpg" data-src="img_1.jpg" />           <hr />       </div>       <div style="">           <img class="lzy_img" src="lazy_img.jpg" data-src="img_2.jpg" />           <hr />       </div>       <div style="">           <img class="lzy_img" src="lazy_img.jpg" data-src="img_3.jpg" />           <hr />       </div>       <div style="">           <img class="lzy_img" src="lazy_img.jpg" data-src="img_4.jpg" />           <hr />       </div>       <div style="">           <img class="lzy_img" src="lazy_img.jpg" data-src="img_5.jpg" />           <hr />       </div>   </div>   <script>       document.addEventListener("DOMContentLoaded", function() {           const imageObserver = new IntersectionObserver((entries, imgObserver) => {               entries.forEach((entry) => {                   if (entry.isIntersecting) {                       const lazyImage = entry.target                       console.log("lazy loading ", lazyImage)                       lazyImage.src = lazyImage.dataset.src                       lazyImage.classList.remove("lzy_img");                       imgObserver.unobserve(lazyImage);                   }               })           });           const arr = document.querySelectorAll('img.lzy_img')           arr.forEach((v) => {               imageObserver.observe(v);           })       })   </script> </body> </html> 

Zusammenfassung


Wir haben das einfachste Beispiel für die Implementierung des Systems des verzögerten Ladens von Bildern untersucht. Mit IntersectionObserver können Sie jedoch recht komplexe und verzögerte Ladeschemata erstellen. Wenn Sie sich für dieses Thema interessieren, empfehlen wir Ihnen, die am Anfang des Materials genannten Veröffentlichungen zu lesen und die Dokumentation zu lesen.

Liebe Leser! Haben Sie Beispiele für die Verbesserung der Website-Leistung nach der Implementierung eines verzögerten Bildladesystems?

Source: https://habr.com/ru/post/de453586/


All Articles