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

Obrazy i elementy <iframe> często zużywają więcej przepustowości niż inne typy zasobów. W przypadku elementów <iframe> załadowanie i wyrenderowanie stron w ich obrębie może wymagać sporo dodatkowego czasu przetwarzania.

W przypadku obrazów wczytywanych z opóźnieniem odroczenie wczytywania obrazów znajdujących się poza początkowym obszarem widoku może pomóc w zmniejszeniu konkurencji o przepustowość w przypadku ważniejszych zasobów w tym obszarze. W niektórych przypadkach, gdy połączenia sieciowe są słabe, może to poprawić największe wyrenderowanie treści (LCP) strony. Przekierowana przepustowość może pomóc elementom LCP szybciej się wczytywać i wyświetlać.

W przypadku elementów <iframe> można poprawić interakcję do kolejnego wyrenderowania (INP) strony podczas uruchamiania, stosując leniwe wczytywanie. Dzieje się tak, ponieważ <iframe> to zupełnie oddzielny dokument HTML z własnymi zasobami podrzędnymi. Elementy <iframe> mogą być uruchamiane w osobnym procesie, ale często współdzielą proces z innymi wątkami, co może powodować, że strony stają się mniej responsywne na działania użytkownika.

Dlatego odroczenie ładowania obrazów i elementów <iframe> znajdujących się poza ekranem jest techniką, którą warto zastosować. Wymaga ona stosunkowo niewielkiego wysiłku, a przynosi dość dobre efekty w zakresie wydajności. Z tego modułu dowiesz się, jak opóźniać wczytywanie tych 2 rodzajów elementów, aby przyspieszyć działanie strony i zwiększyć wygodę użytkowników w krytycznym okresie początkowym.

Leniwe ładowanie obrazów za pomocą atrybutu loading

loading Atrybut można dodać do elementów <img>, aby poinformować przeglądarki, jak powinny być ładowane:

  • "eager" informuje przeglądarkę, że obraz powinien zostać załadowany natychmiast, nawet jeśli znajduje się poza początkowym widocznym obszarem. Jest to również wartość domyślna atrybutu loading.
  • "lazy" odracza ładowanie obrazu, dopóki nie znajdzie się w określonej odległości od widocznego obszaru. Ta odległość różni się w zależności od przeglądarki, ale często jest ustawiana tak, aby obraz zdążył się załadować, zanim użytkownik do niego dotrze.

Warto też pamiętać, że jeśli używasz elementu <picture>, atrybut loading powinien być nadal stosowany do jego elementu podrzędnego <img>, a nie do samego elementu <picture>. Dzieje się tak, ponieważ element <picture> jest kontenerem zawierającym dodatkowe elementy <source> wskazujące różne kandydatki do obrazu, a kandydatka wybrana przez przeglądarkę jest stosowana bezpośrednio do elementu podrzędnego <img>.

Nie używaj leniwego ładowania w przypadku obrazów w początkowo widocznym obszarze

Atrybutu loading="lazy" należy używać tylko w przypadku elementów <img>, które są umieszczone poza początkowym widocznym obszarem. Jednak przed wyrenderowaniem strony trudno jest określić dokładne położenie elementu w widocznym obszarze. Należy wziąć pod uwagę różne rozmiary widocznego obszaru, formaty obrazu i urządzenia.

Na przykład obszar widoczny na komputerze może znacznie różnić się od obszaru widocznego na telefonie komórkowym, ponieważ renderuje więcej miejsca w pionie, co może umożliwiać dopasowanie obrazów do początkowego obszaru widocznego, który nie pojawiłby się w początkowym obszarze widocznym na mniejszym urządzeniu. Tablety używane w orientacji pionowej również wyświetlają znaczną ilość miejsca w pionie, być może nawet więcej niż niektóre urządzenia stacjonarne.

Są jednak przypadki, w których wyraźnie widać, że należy unikać stosowania loading="lazy". Na przykład zdecydowanie należy pominąć atrybut loading="lazy" w elementach <img> w przypadku obrazów głównych lub innych zastosowań obrazów, w których elementy <img> prawdopodobnie będą się wyświetlać nad linią podziału 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 mogą być kandydatami do LCP.

Obrazy wczytywane z opóźnieniem muszą poczekać, aż przeglądarka zakończy układ, aby sprawdzić, czy ich ostateczna pozycja znajduje się w obszarze widocznym. Oznacza to, że jeśli element <img> w widocznym obszarze ma atrybut loading="lazy", żądanie dotyczące tego elementu jest wysyłane dopiero po pobraniu, przeanalizowaniu i zastosowaniu do strony wszystkich plików CSS, a nie od razu po wykryciu go przez skaner wstępnego wczytywania w nieprzetworzonym znaczniku.

Atrybut loading elementu <img> jest obsługiwany przez wszystkie główne przeglądarki, więc nie musisz używać JavaScriptu do leniwego ładowania obrazów. Dodawanie do strony dodatkowego kodu JavaScript, aby zapewnić funkcje, które przeglądarka już udostępnia, wpływa na inne aspekty wydajności strony, takie jak INP.

Wersja demonstracyjna leniwego ładowania obrazów

Leniwe ładowanie <iframe> elementów

Odłożone ładowanie elementów <iframe> do momentu, aż staną się widoczne w obszarze widoku, może znacznie zmniejszyć ilość danych i przyspieszyć ładowanie krytycznych zasobów wymaganych do wczytania strony najwyższego poziomu. Dodatkowo, ponieważ elementy <iframe> to w zasadzie całe dokumenty HTML wczytywane w dokumencie najwyższego poziomu, mogą one zawierać znaczną liczbę zasobów podrzędnych – zwłaszcza JavaScript – co może znacznie wpłynąć na INP strony, jeśli zadania w tych ramkach wymagają znacznego czasu przetwarzania.

Umieszczanie treści innych firm to typowy przypadek użycia elementów <iframe>. Na przykład osadzone odtwarzacze wideo lub posty w mediach społecznościowych często używają elementów <iframe> i wymagają znacznej liczby zasobów podrzędnych, co może również powodować rywalizację o przepustowość z zasobami strony najwyższego poziomu. Na przykład leniwe wczytywanie umieszczonego filmu z YouTube pozwala zaoszczędzić ponad 500 KiB podczas początkowego wczytywania strony, a leniwe wczytywanie wtyczki przycisku „Lubię to” na Facebooku pozwala zaoszczędzić ponad 200 KiB, z czego większość to JavaScript.

W każdym przypadku, gdy na stronie masz element <iframe> w części widocznej po przewinięciu, warto rozważyć jego leniwe ładowanie, jeśli nie jest on niezbędny do natychmiastowego wczytania. Może to znacznie poprawić wygodę użytkowników.

Atrybut loading dla elementów <iframe>

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

  • Wartością domyślną jest "eager". Informuje przeglądarkę, że ma natychmiast wczytać kod HTML elementu <iframe> i jego zasoby podrzędne.
  • "lazy" odracza ładowanie kodu HTML elementu <iframe> i jego zasobów podrzędnych, dopóki nie znajdą się one w określonej odległości od widocznego obszaru.

Wersja demonstracyjna leniwego ładowania elementów iframe

Fasady

Zamiast wczytywać element do umieszczenia od razu podczas wczytywania strony, możesz wczytywać go na żądanie w odpowiedzi na interakcję użytkownika. Możesz 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 zastąpić go osadzonym elementem zewnętrznym. Ta technika jest znana jako fasada.

Typowym zastosowaniem fasad jest osadzanie filmów z usług innych firm, w przypadku których osadzanie może wiązać się z wczytywaniem wielu dodatkowych i potencjalnie kosztownych zasobów podrzędnych, takich jak JavaScript, oprócz samego filmu. W takim przypadku – o ile nie ma uzasadnionej potrzeby automatycznego odtwarzania filmu – osadzone filmy wymagają interakcji użytkownika przed odtworzeniem, czyli kliknięcia przycisku odtwarzania.

To doskonała okazja, aby wyświetlić statyczny obraz, który jest wizualnie podobny do osadzonego filmu, i zaoszczędzić w ten sposób sporo przepustowości. Gdy użytkownik kliknie obraz, zostanie on zastąpiony rzeczywistym kodem <iframe>, który spowoduje rozpoczęcie pobierania kodu HTML elementu <iframe> innej firmy i jego zasobów podrzędnych.

Oprócz poprawy początkowego ładowania strony kolejną ważną zaletą jest to, że jeśli użytkownik nigdy nie odtworzy filmu, zasoby potrzebne do jego wyświetlenia nie zostaną pobrane. To dobry wzorzec, ponieważ zapewnia, że użytkownik pobiera tylko to, czego naprawdę potrzebuje, bez dokonywania potencjalnie błędnych założeń dotyczących jego potrzeb.

Widżety czatu to kolejny doskonały przykład zastosowania techniki fasady. Większość widżetów czatu pobiera duże ilości kodu JavaScript, co może negatywnie wpływać na czas wczytywania strony i jej responsywność w odniesieniu do danych wprowadzanych przez użytkownika. Podobnie jak w przypadku ładowania z wyprzedzeniem, koszt jest ponoszony w momencie ładowania, ale w przypadku widżetu czatu nie każdy użytkownik zamierza z niego korzystać.

W przypadku komponentu fasadowego można zastąpić przycisk „Rozpocznij czat” innej firmy fałszywym przyciskiem. Gdy użytkownik wejdzie z nim w interakcję (np. przytrzyma nad nim wskaźnik przez odpowiedni czas lub kliknie go), w odpowiednim momencie pojawi się rzeczywisty, działający widżet czatu.

Oczywiście możesz tworzyć własne fasady, ale w przypadku popularniejszych usług zewnętrznych dostępne są opcje open source, takie jak lite-youtube-embed w przypadku filmów w YouTube, lite-vimeo-embed w przypadku filmów w Vimeo i React Live Chat Loader w przypadku widżetów czatu.

Biblioteki JavaScript do leniwego wczytywania

Jeśli chcesz wczytywać z opóźnieniem elementy <video>, obrazy w elemencie poster, obrazy wczytywane przez właściwość CSS background-image lub inne nieobsługiwane elementy, możesz to zrobić za pomocą rozwiązania do wczytywania z opóźnieniem opartego na JavaScript, takiego jak lazysizes lub yall.js, ponieważ wczytywanie z opóźnieniem tych typów zasobów nie jest funkcją przeglądarki.<video>

W szczególności autoodtwarzanie i zapętlanie <video>elementów bez ścieżki audio jest znacznie wydajniejszą alternatywą niż używanie animowanych GIF-ów, które często mogą być kilka razy większe niż zasób wideo o równoważnej jakości wizualnej. Nawet wtedy mogą one jednak zajmować dużo miejsca, więc leniwe wczytywanie to dodatkowa optymalizacja, która może znacznie ograniczyć marnowanie przepustowości.

Większość tych bibliotek działa przy użyciu interfejsu Intersection Observer API, a dodatkowo interfejsu Mutation Observer API, jeśli kod HTML strony zmienia się po początkowym wczytaniu, aby rozpoznawać, kiedy element wchodzi w obszar widoczny dla użytkownika. Jeśli obraz jest widoczny lub zbliża się do obszaru widocznego, biblioteka JavaScript zastępuje niestandardowy atrybut (często data-src lub podobny atrybut) prawidłowym atrybutem, np. src.

Załóżmy, że masz film, który zastępuje animowany GIF, ale chcesz go wczytywać z opóźnieniem za pomocą rozwiązania JavaScript. Jest to możliwe w przypadku yall.js przy użyciu tego wzorca 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". Gdy plik yall.js zostanie wczytany i wykonany na stronie, film nie zostanie wczytany, dopóki użytkownik nie przewinie go do widocznego obszaru. W tym momencie atrybuty data-src elementów podrzędnych <source> elementu <video> są zamieniane na atrybuty src, co powoduje wysłanie żądania pobrania filmu i automatyczne rozpoczęcie jego odtwarzania.

Sprawdź swoją wiedzę

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

"lazy"
"eager"

Kiedy warto używać rozwiązań do leniwego wczytywania opartych na JavaScript?

W przypadku zasobów, w których atrybut loading nie jest obsługiwany, np. w przypadku filmów odtwarzanych automatycznie, które mają zastępować obrazy animowane, lub w przypadku obrazu plakatu elementu <video> wczytywanego z opóźnieniem.
W przypadku każdego zasobu, który można ładować leniwie.

Kiedy fasada jest przydatną techniką?

W przypadku osadzonych elementów pochodzących od osób trzecich, w których przypadku zasoby wymagane do wczytania są nie tylko znaczne, ale istnieje też duże prawdopodobieństwo, że nie wszyscy użytkownicy będą z nimi wchodzić w interakcje.
W przypadku każdego elementu osadzonego innej firmy, który zużywa znaczną ilość danych, niezależnie od potrzeb użytkownika.

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

Teraz, gdy znasz już leniwe wczytywanie obrazów i elementów <iframe>, możesz zadbać o to, aby strony wczytywały się szybciej, a jednocześnie spełniały potrzeby użytkowników. W niektórych przypadkach jednak spekulacyjne wczytywanie zasobów może być pożądane. W następnym module dowiesz się więcej o pobieraniu z wyprzedzeniem i wstępnym renderowaniu oraz o tym, jak te techniki – jeśli są stosowane ostrożnie – mogą znacznie przyspieszyć przechodzenie do kolejnych stron, ponieważ są one wczytywane z wyprzedzeniem.