Web Design Blog / Programowanie:

Lazy load (opóźnione ładowanie zdjęć) w jQuery

Data publikacji: 18 maja 2019

W tym poradniku napiszemy od zera mechanizm opóźnionego (czy odłożonego) ładowania zdjęć. Inne nazwy to „leniwe” ładowanie zdjęć lub po prostu lazy load.

Skrypt jest dosyć prosty, jednak niepoprawne wdrożenie potrafi zrujnować wydajność przegladarki dlatego w tym wpisie napiszemy skrypt a potem wdrożymy tzw. throttling, który będzie czuwał nad tym aby scroll listener nie próbował w każdej milisekundzie sprawdzać wysokości widoku i wczytywać zdjęć. Zapewni to odpowiednią wydajność i wygodę użytkownika.

Czego nie potrafię stworzyć, tego nie rozumiem.

Richard Feynman

Po co wdrażać i jak działa Lazy-load?

Na początku wytłumaczymy sobie o co chodzi z tym lazy-loadem. Wyobraźmy sobie stronę internetową np. wpis na blogu, który zawiera wiele zdjęć. Załóżmy, że zdjęcia są zoptymalizowane i trafnie dobrano formaty zapisu i mają poprawną wielkość do strony internetowej.

Problem w tym, że nawet jak zdjęcia będą idealnie zoptymalizowane ich spora ilość spowoduje, że strona mimo to będzie się wczytywać wolno i zanim wszystkie zdjęcia się nie ściągną, strona nie będzie interaktywna. Nie będzie można zjechać w dół, tekst będzie niewidoczny i nie będą działały linki. Rozwiązanie tego problemu jest konieczne do zdobycia 100 punktów w Page Speed Insights:

Rozwiązaniem na ten problem (jak można się domyślić) jest lazy-load. Wykorzystuje on prosty fakt, mianowicie, na ekranie widzimy co najwyżej wstęp do artykułu i pierwsze zdjęcie. Cała reszta może się ściągnąć w tle dopiero jak zjedziemy do tych zdjęć. To powoduje, że zdjęcia , które będą oglądane dopiero za jakiś czas nie będą blokować już na starcie wczytywania się kluczowych elementów tej strony czyli tekstu, fontów i zdjęć, które znajdują się na samej górze.

HTML

Standardowe zdjęcie jest zamieszczane w taki sposób:

<img src=”obrazek.jpg” alt=”opis obrazka”>

Najwydajniejszym sposobem na zablokowanie wczytywania zdjęcia jest po prostu usunięcie wartości atrybutu src. Informacja o tym jakie ma się wczytać zdjęcie możey być przechowywana w atrybucie data. Zdefiniujmy go jako data-src. Aby móc łatwo wybrać te zdjęcia z DOM dodajmy klasę. Np. lazy-load. Pozostaje nam jeszcze dodanie placeholdera, czyli obrazka który będzie przechowywał miejsce na wczytane zdjęcie. Niektórzy decydują się na załadowanie animowanego loadera.

Dla mnie jest to marnotrawstwo zasobów dlatego polecam użyć np. białego jednego piksela. Poprawnie zaimplementowany lazy-load ma działać transparentnie, czyli tak, że użytkownik nie zobaczy ani luki ani tego loadera. Ponieważ odwołanie się do zewnętrznego zasobu też marnuje komunikację HTTP w obie strony, wykorzystamy możliwość umieszczenia zdjęcia za pomocą danych w URL, które przechowują zaszyfrowany obrazek w formacie base64. Np. przezroczysty piksel w formacie GIF wygląda tak:

data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7

Cały znacznik, który będzie współpracował z naszym lazy-load będzie wyglądał tak:

<img class="lazy lazy-img" src="data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7" data-src="obrazek.jpg" alt="opis obrazka">

JavaScript

Cała magia jak zwykle dzieje się w JavaScript. będziemy korzystać ze standardowych metod jQuery dlatego wystarczy nam kompilacja jQuery Slim.

Aby sprawnie korzystać z listenerów stwórzmy sobie funkcję lazyLoad(). W niej będziemy mieli pętlę each, która będzie sprawdzała wszystkie zdjęcia z klasą lazy-image czy tak czasem nie znajdują się na tyle wysoko aby podmienić wartość atrybutu src na wartość przechowywaną w data-src.

Sprawdzenie tego czy zdjęcie ma się już załadować jest banalnie proste. Jeżeli offset.top (czyli taki jakby margines od górnej krawędzi strony) będzie mniejszy niż wysokość widoku przeglądarki, plus „przewinięty” obszar widoku przeglądarki, plus margines jaki dajemy przeglądarce na załadowanie zdjęcia za wczasu aby właśnie użytkownik nie widział przerwy. U nas ten margines będzie wynosił 300 pikseli.

Po wszystkim warto posprzątać, po podmianie zdjęcia usuńmy klasę lazy-image aby nie dokonywać niepotrzebnych obliczeń.:

function lazyLoad(){
$('.lazy-img').each(function(){
if ($(this).offset().top < window.innerHeight + window.pageYOffset + 300) {
$(this).attr('src', $(this).data('src'));
$(this).removeClass('lazy-img');
}
})
};

Teraz czas na stworzenie czujnika, który przy przewijaniu będzie odpalał naszą funkcję. Większość „programistów” zrobiłaby

$(document).on('scroll', function() {
lazyLoad();
});

To jest bardzo niewydajne, bo jak wiadomo scroll trwa w czasie. W ciągu jednego przewinięcia myszką funkcja wykona się kilkadziesiąt razy. To niepotrzebnie marnuje moc obliczeniową urządzenia. Zróbmy prosty throttling:

var eventTimeout;
var eventThrottler = function () {
if ( !eventTimeout ) {
eventTimeout = setTimeout(function() {
eventTimeout = null;
lazyLoad();
}, 1000);
}
};

Dzięki temu zabiegowi, funkcja lazyLoad() będzie się włączać najczęściej raz na sekundę. Teraz wystarczy dodać listenera w jQuerowym stylu:

$(document).on('scroll', function() {       
eventThrottler();
});

Testowanie

Sprawdźmy czy działa.

Jak widać skrypt mówiąc kolokwialnie daje radę. Przy „normalnym” czytaniu artykułu użytkownik nie ma szans zauważyć pobierania się zdjęć w tle. Przy szybkim przewijaniu widać jak puste pola są wypełniane zdjęciem.

Podsumowanie

Lazy-load to technika zwiększania wydajności stron internetowych poprzez odłożenie w czasie pobierania wszystkich zasobów. To konieczny krok, jeżeli na naszej stronie jest wiele zdjęć a chcemy idealnie zoptymalizować stronę i uzyskać 100 punktów w PageSpeed Insights.

Źródła

https://developers.google.com/web/tools/lighthouse/audits/offscreen-images?utm_source=lighthouse&utm_medium=unknown

Lazy load (opóźnione ładowanie zdjęć) w jQuery
4.6 (91.11%) głosów: 9


Komentarze

Brak komentarzy.

Dodaj swój komentarz