Leniwe ładowanie obrazów i elementów <iframe>

Obrazy i elementy <iframe> często zużywają większą przepustowość niż inne typy zasobów. W przypadku elementów <iframe> wczytanie i renderowanie zawartych w nich stron może potrwać dość długo.

W przypadku leniwego ładowania obrazów opóźnione wczytywanie obrazów, które znajdują się poza początkowym widocznym obszarem, może pomóc w zmniejszeniu rywalizacji o bardziej krytyczne zasoby w początkowym obszarze widocznym. Może to poprawić wskaźnik największego wyrenderowania treści (LCP) strony w przypadkach, gdy połączenia sieciowe są słabe, a przekierowana przepustowość może pomóc w szybszym ładowaniu i wyrenderowaniu kandydatów LCP.

Jeśli dotyczy to elementów <iframe>, interakcje z kolejnym wyrenderowaniem (INP) można poprawić podczas uruchamiania, korzystając z leniwego ładowania. Dzieje się tak, ponieważ <iframe> jest całkowicie oddzielnym dokumentem HTML z własnymi zasobami podrzędnymi. Elementy <iframe> można uruchamiać w osobnym procesie, ale często współużytkują je z innymi wątkami, co może powodować słabsze reagowanie stron na działania użytkowników.

Dlatego opóźnienie wczytywania obrazów spoza ekranu i elementów <iframe> warto zastosować i wymagać stosunkowo niewielkiego wysiłku, który zapewni względnie dobry zwrot z inwestycji. W tym module omówiono leniwe ładowanie tych 2 typów elementów, które przyspiesza i zwiększa wygodę użytkowników w okresie krytycznego uruchamiania strony.

Leniwe ładowanie obrazów z atrybutem loading

Do elementów <img> można dodać atrybut loading, aby poinformować przeglądarki, jak mają być ładowane:

  • "eager" informuje przeglądarkę, że obraz powinien zostać wczytany natychmiast, nawet jeśli znajduje się on poza początkowym widocznym obszarem. Jest to również domyślna wartość atrybutu loading.
  • "lazy" opóźnia wczytanie obrazu, aż znajdzie się on w określonej odległości od widocznego obszaru. Odległość różni się w zależności od przeglądarki, ale często jest na tyle duża, aby obraz był wczytywany, gdy użytkownik go przewinie.

Pamiętaj też, że jeśli używasz elementu <picture>, atrybut loading nadal powinien być stosowany do jego podrzędnego elementu <img>, a nie do samego elementu <picture>. Dzieje się tak, ponieważ element <picture> jest kontenerem zawierającym dodatkowe elementy <source> wskazujące różne kandydujące obrazy, a wybrany przez przeglądarkę kandydat jest stosowany bezpośrednio do jego podrzędnego elementu <img>.

Nie leniwie ładuj obrazów, które znajdują się w początkowym widocznym obszarze

Atrybut loading="lazy" należy dodawać tylko do elementów <img>, które znajdują się poza początkowym widocznym obszarem. Znajomość dokładnego położenia elementu względem widocznego obszaru przed wyrenderowaniem strony może być jednak dość skomplikowana. Musisz wziąć pod uwagę różne rozmiary widocznego obszaru, formaty obrazu i urządzenia.

Na przykład widoczny obszar dla komputerów może znacznie różnić się od widocznego na telefonie komórkowym, ponieważ renderuje się w większej przestrzeni w pionie i może zmieścić w początkowym widocznym obszarze obrazy, które nie byłyby widoczne w początkowym widocznym obszarze na fizycznie mniejszych urządzeniach. Tablety używane w orientacji pionowej również mają znaczną ilość miejsca w pionie – nawet więcej niż niektóre komputery.

W niektórych przypadkach jednak jasne jest, aby unikać stosowania właściwości loading="lazy". Na przykład zdecydowanie należy pominąć atrybut loading="lazy" w elementach <img> w przypadku banerów powitalnych lub innych obrazów, w których elementy <img> prawdopodobnie pojawią się w części strony widocznej na ekranie lub w pobliżu górnej części układu na dowolnym urządzeniu. Jest to jeszcze ważniejsze w przypadku obrazów, które prawdopodobnie kwalifikują się do LCP.

Obrazy z leniwym ładowaniem muszą poczekać, aż przeglądarka zakończy układ, by ustalić, czy jego końcowa pozycja znajduje się w widocznym obszarze. Oznacza to, że jeśli element <img> w widocznym obszarze ma atrybut loading="lazy", żądanie jest wysyłane tylko po pobraniu, przeanalizowaniu i zastosowaniu na stronie całego kodu CSS – a nie dopiero po tym, jak skaner wstępnego wczytywania znajdzie go w nieprzetworzonych znacznikach.

Ponieważ atrybut loading elementu <img> jest obsługiwany we wszystkich najpopularniejszych przeglądarkach, nie trzeba używać JavaScriptu do leniwego ładowania obrazów. Dodanie do strony dodatkowego kodu JavaScriptu, którego już teraz udostępnia przeglądarka, wpływa na inne aspekty wydajności strony takie jak INP.

Wersja demonstracyjna leniwego ładowania obrazu

Leniwe ładowanie elementów <iframe>

Leniwe ładowanie elementów <iframe>, dopóki nie pojawią się w widocznym obszarze, pozwala zaoszczędzić sporo danych i przyspieszyć wczytywanie najważniejszych zasobów wymaganych do wczytania strony najwyższego poziomu. Poza tym elementy <iframe> to właściwie całe dokumenty HTML wczytywane w dokumencie najwyższego poziomu. Mogą zawierać znaczną liczbę zasobów podrzędnych – w szczególności kodu JavaScript – co może mieć znaczący wpływ na wartość INP strony, jeśli zadania w tych ramkach wymagają znacznego czasu przetwarzania.

Częstym przypadkiem użycia elementów <iframe> jest umieszczanie elementów innych firm. Na przykład umieszczone odtwarzacze wideo lub posty w mediach społecznościowych często wykorzystują elementy <iframe> i często wymagają znacznej liczby zasobów podrzędnych, co może też powodować rywalizację z przepustowością o zasoby strony najwyższego poziomu. Na przykład dzięki leniwemu ładowaniu umieszczonego filmu z YouTube można zaoszczędzić ponad 500 KiB podczas początkowego wczytywania strony, a leniwe ładowanie wtyczki przycisku „Lubię to” Facebooka pozwala zaoszczędzić ponad 200 kiB, w większości z kodu JavaScript.

W obu przypadkach, gdy strona <iframe> znajduje się w części strony widocznej po przewinięciu, warto rozważyć leniwe ładowanie, jeśli nie jest konieczne ładowanie jej z góry, ponieważ może to znacznie poprawić wygodę użytkowników.

Atrybut loading elementów <iframe>

Atrybut loading elementów <iframe> jest też obsługiwany we wszystkich głównych przeglądarkach. Wartości atrybutu loading i ich zachowania są takie same jak w przypadku elementów <img>, które korzystają z atrybutu loading:

  • "eager" to wartość domyślna. Informuje on przeglądarkę o natychmiastowym wczytaniu kodu HTML elementu <iframe> i jego zasobów podrzędnych.
  • Funkcja "lazy" opóźnia wczytywanie kodu HTML elementu <iframe> i jego zasobów podrzędnych do momentu, gdy znajdzie się on w określonej odległości od widocznego obszaru.

Wersja demonstracyjna leniwego ładowania elementów iframe

Fasady

Zamiast wczytywać umieszczony element natychmiast podczas wczytywania strony, możesz go wczytać na żądanie w odpowiedzi na interakcję użytkownika. Można to zrobić, wyświetlając obraz lub inny odpowiedni element HTML, dopóki użytkownik nie wejdzie z nim w interakcję. Gdy użytkownik wejdzie w interakcję z elementem, możesz go zastąpić elementem zewnętrznym. Ta technika nazywa się fasadą.

Typowym przypadkiem użycia fasad jest umieszczanie filmów z usług innych firm, gdzie może to wymagać wczytania nie tylko treści wideo, ale też dodatkowych i potencjalnie kosztownych zasobów podrzędnych, takich jak JavaScript. W takim przypadku, o ile nie ma uzasadnionej potrzeby autoodtwarzania filmu, umieszczanie filmów na stronie wymaga od użytkownika interakcji z nimi przed rozpoczęciem odtwarzania, klikając przycisk odtwarzania.

To doskonała okazja do pokazania statycznego obrazu, który jest wizualnie podobny do obrazu umieszczonego na stronie, i pozwala oszczędzać przepustowość. Gdy użytkownik kliknie obraz, zostaje on zastąpiony przez umieszczoną treść z elementu <iframe>, co powoduje rozpoczęcie pobierania kodu HTML zewnętrznego elementu <iframe> i jego zasobów podrzędnych.

Poza poprawą wstępnego wczytywania strony kolejną zaletą jest to, że jeśli użytkownik nie odtwarza filmu, zasoby wymagane do jego wyświetlenia nigdy nie są pobierane. Jest to prawidłowy wzorzec, ponieważ daje pewność, że użytkownik pobiera tylko to, czego faktycznie chce, bez przyjmowania błędnych założeń dotyczących jego potrzeb.

Widżety czatu to kolejny doskonały przypadek użycia techniki fasadowej. Większość widżetów czatu pobiera znaczne ilości kodu JavaScript, który może negatywnie wpłynąć na wczytywanie strony i responsywność w odniesieniu do danych wejściowych użytkownika. Podobnie jak w przypadku wczytywania z góry opłaty są naliczane w momencie wczytywania, ale w przypadku widżetu czatu nie każdy użytkownik ma zamiar korzystać z niego w ogóle.

Jeśli natomiast ma fasadę, przycisk „Rozpocznij czat” u innych firm można zastąpić fałszywym przyciskiem. Gdy użytkownik wejdzie w interakcję z instrukcją, np. przytrzyma nad nim wskaźnik przez określony czas lub kliknie, rzeczywisty, funkcjonalny widżet czatu zostanie umieszczony w miejscu, gdy użytkownik będzie tego potrzebować.

Choć oczywiście można samodzielnie stworzyć fasadę, dostępne są też opcje open source dla najpopularniejszych firm zewnętrznych, jak np. lite-youtube-embed dla filmów w YouTube, lite-vimeo-embed dla filmów z Vimeo i React Live Chat Loader w przypadku widżetów czatu.

Biblioteki leniwego ładowania JavaScriptu

Jeśli potrzebujesz leniwego ładowania elementów <video>, elementów <video> poster, obrazów ładowanych przez właściwość CSS background-image lub innych nieobsługiwanych elementów, możesz skorzystać z rozwiązania leniwego ładowania opartego na języku JavaScript, np. lenisizes lub yall.js. Leniwe ładowanie zasobów tego typu nie jest funkcją na poziomie przeglądarki.

W szczególności autoodtwarzanie i zapętlanie elementów <video> bez ścieżki dźwiękowej są znacznie skuteczniejszą alternatywą od animowanych GIF-ów, które często mogą być kilka razy większe niż materiały wideo o takiej samej jakości wizualnej. Mimo to filmy te nadal mogą mieć duże znaczenie przepustowości, więc leniwe ładowanie ich jest dodatkową optymalizacją, która może znacznie zmniejszyć straty przepustowości.

Większość z tych bibliotek korzysta z interfejsu Intersection Observer API, a także Mutation Observer API, jeśli kod HTML strony zmieni się po wstępnym wczytaniu, aby rozpoznać, kiedy element wchodzi w obszar widoczny użytkownika. Jeśli obraz jest widoczny lub zbliża się do widocznego obszaru, biblioteka JavaScript zastępuje niestandardowy atrybut (często data-src lub podobny) prawidłowym atrybutem, np. src.

Załóżmy, że masz film, który zastępuje animowany GIF, ale chcesz go leniwie wczytywać przy użyciu rozwiązania JavaScript. Jest to możliwe w kodzie yall.js o tym wzorcu znaczników:

<!-- The autoplay, loop, muted, and playsinline attributes are to
     ensure the video can autoplay without user intervention. -->
<video class="lazy" autoplay loop muted playsinline width="320" height="480">
  <source data-src="video.webm" type="video/webm">
  <source data-src="video.mp4" type="video/mp4">
</video>

Domyślnie yall.js obserwuje wszystkie kwalifikujące się elementy HTML z klasą "lazy". Po wczytaniu i wykonaniu kodu yall.js na stronie film zostanie wczytany dopiero wtedy, gdy użytkownik przewinie go do widocznego obszaru. W tym momencie atrybuty data-src w podrzędnych elementach <source> elementu <video> są zamieniane na atrybuty src, co powoduje wysłanie żądania pobrania filmu i automatycznego rozpoczęcia jego odtwarzania.

Sprawdź swoją wiedzę

Która jest domyślna wartość atrybutu loading elementów <img> i <iframe>?

"eager"
Dobrze!
"lazy"
Spróbuj ponownie.

Kiedy warto korzystać z rozwiązań do leniwego ładowania opartych na języku JavaScript?

Dla każdego zasobu, który można leniwie ładować.
Spróbuj ponownie.
Dotyczy zasobów, w których atrybut loading nie jest obsługiwany, na przykład w przypadku autoodtwarzania filmów, które mają zastąpić animowane obrazy, lub leniwego ładowania obrazu plakatu elementu <video>.
Dobrze!

Kiedy fasada jest przydatną techniką?

Dotyczy też jakichkolwiek innych elementów umieszczanych na stronach, które zużywają znaczną ilość danych, niezależnie od potrzeb użytkownika.
Spróbuj ponownie.
W przypadku zewnętrznych odtwarzaczy umieszczonych na stronie, których zasoby wymagane do wczytania są nie tylko znaczne, ale i istnieje wysokie prawdopodobieństwo, że nie wszyscy użytkownicy będą mogli wchodzić z nimi w interakcje.
Dobrze!

Następny krok: pobieranie z wyprzedzeniem i wstępne renderowanie

Wiesz już, jak szybko ładować się obrazy i elementy <iframe>, więc możesz zadbać o szybsze wczytywanie stron z uwzględnieniem potrzeb użytkowników. Jednak w niektórych przypadkach ładowanie spekulacyjne zasobów może być wskazane. Z następnego modułu dowiesz się więcej o wstępnym pobieraniu i renderowaniu oraz o tym, jak te techniki, gdy są stosowane ostrożnie, mogą znacznie przyspieszyć nawigację do kolejnych stron, ponieważ ładują się z wyprzedzeniem.