Optymalizacja obrazków – Page Speed

Optymalizacja obrazków ma znaczenie


Na szybkość wczytywania strony negatywnie wpływają przede wszystkim te trzy czynniki:

  1. Rozmiar strony (w kilobajtach) – obciąża łącze
  2. Ilość i złożoność kodu (skrypty, renderowanie) – obciążają procesor
  3. Szybkość serwera (czas oczekiwania) – wydłuża proces

W poniższym artykule skupię się na redukcji rozmiaru strony poprzez optymalizację obrazków. Jest to tzw. low hanging fruit, ponieważ nakład pracy potrzebny aby przeprowadzić taką optymalizację jest relatywnie niski w porównaniu do innych obszarów. Rozmiar strony bardzo mocno wpływa na czas wczytywania, z kolei rozmiar obrazków znacząco wpływa na rozmiar strony. W ostatnich latach, szacuje się, że obrazki zajmują ok. 40-50% całkowitego rozmiaru strony. Dane te można w różnych ujęciach czasowych przejrzeć w raporcie httparchive.org.

W raportach Page Speed Insights oraz Lighthouse, bardzo często pojawiają się niezaliczone audyty wymienione niżej:

  • Properly size images (zmień rozmiar obrazów)
  • Serve images in next-gen formats (wyświetlaj obrazy w formatach nowej generacji)
  • Defer offscreen images (odłóż ładowanie obrazów poza ekranem)

Mają one bardzo duży potencjał dotyczący poprawy szybkości wczytywania.

Page Speed - optymalizacja obrazków
Elementy do poprawki wedle Lighthouse

Omówię zatem trzy oddzielne kroki, które pozwolą przejść powyższe audyty i spowodują, że strona będzie się wczytywać znacznie szybciej.

  1. Serwowanie obrazków w odpowiedniej skali za pomocą atrybutów <srcset> oraz <sizes>
  2. Wprowadzenie formatu WebP
  3. Wykorzystanie “lazy-loading”

Responsywne obrazki serwowane w odpowiednim rozmiarze

Trudnością z jaką trzeba się zmierzyć jest to, że jedna strona internetowa może zostać wyświetlona na wielu różnych urządzeniach, które różnią się wieloma parametrami:

  • Device Viewport Size – Czyli przede wszystkim szerokość wyświetlacza. Nowy telefon Samsunga to 360px, monitor na którym piszę ten artykuł to full HD (1920px).
  • Device Pixel Density – Czyli większa gęstość pikseli na wyświetlaczach typu Retina lub nowoczesnych smartfonach. Poza standardowym ratio = 1, najczęściej spotyka się 2, 3 i 4.

Dodatkowo layout strony może się całkowicie zmieniać dla telefonów lub tabletów.

Świetnym przykładem może być obrazek wybrany jako tzw. “hero image”, czyli tytułowy dla danego wpisu.

  • Na stronie wpisu wyświetla się na całą szerokość ekranu. Zmienia się zależnie od urządzenia – od ok. 350px na telefonie, po 1920px (lub więcej) na desktopie.
  • Na stronie głównej w karuzeli z ostatnimi wpisami zajmuje mniej niż 33% ekranu i ok. 50% ekranu na urządzeniach mobilnych.
  • Na stronach kategorii blogowych zajmuje 50% ekranu (jako jeden z wielu na liście) oraz 100% ekranu na urządzeniach mobilnych.

Jeśli ograniczymy się do serwowania wszędzie jednego źródła, to będziemy niepotrzebnie wysyłać do użytkownika ciężki obrazek 1920px, kiedy potrzebny jest np. 640px. Lub w drugą stronę, możemy wysłać mały obrazek, który przeglądarka będzie automatycznie rozciągać przez co jego jakość będzie bardzo słaba.

O tym, jaką ostatecznie rozdzielczość przyjmie obrazek w wyrenderowanym layoucie informuje nas wartość “computed size”.

computed size
computed size w Chrome Dev Tools

Jest to rozdzielczość, do której obraz zostanie przeskalowany przez przeglądarkę po obliczeniu CSS, JS, rozdzielczości ekranu i wszystkich innych czynników, które mogą wpływać na layout.

Jak sprawdzić w jaki sposób serwowane są obrazki

Polecam wbudowane w Chrome narzędzie Inspect (F12). Wystarczy najechać na obrazek na stronie, kliknąć prawym przyciskiem myszy i wybrać opcję “Zbadaj”.

Chrome - optymalizacja obrazków, funkcja zbadaj
Podgląd obrazka w narzędziu Web Developer Tools w Chrome

Pierwsza wartość po lewej to aktualna rozdzielczość wykorzystana przez przeglądarkę dla danego viewportu. Intrinsic size to oryginalna rozdzielczość obrazka. Jak widać na tym przykładzie, mógłby być znacznie mniejszy. Alternatywną opcją jest sprawdzenie w zakładce “Network” jaki obrazek w rzeczywistości został pobrany.

Chrome - optymalizacja obrazków
W praktyce pobrane obrazki w narzędziu “Zbadaj”

Każdy obrazek można indywidualnie otworzyć w nowej karcie, aby sprawdzić w jakiej rozdzielczości został wysłany do przeglądarki. Lista uwzględnia także wagę wszystkich pobranych elementów, więc pozwala to bez problemu zweryfikować co w praktyce najbardziej spowalnia wczytywanie.

Warto zweryfikować kilka różnych komponentów (hero image, obrazki w karuzelach, gridach, zwykłe obrazki w treści) zmieniając szerokość przeglądarki i testując mobile layout. Kiedy otwarty jest Chrome Inspect Tool (F12), tryb responsywny można wywołać skrótem CTRL + SHIFT + M. Na górze strony wyświetli się poniższy panel:

Optymalizacja obrazków - testy responsywne
W Chrome można przetestować każdą rozdzielczość urządzenia

Z jego użyciem można łatwo sprawdzić jak zachowują się obrazki przy różnych rozdzielczościach i różnych layoutach.

Cel: Obrazek wysyłany do przeglądarki jest jak najbliższy rozmiarowi w którym jest aktualnie wyświetlany

Aby osiągnąć powyższy cel, znane muszą być następujące zmienne:

  1. Rozdzielczość ekranu urządzenia klienta
  2. Pixel density urządzenia klienta
  3. Określenie jaką część viewporta zajmuje obrazek
  4. Określenie jakie warianty obrazka są dostępne do pobrania

Odpowiedź na punkty 1, 2 i 4 zna przeglądarka. Odpowiedź na punkt 3 zna twórca strony. Aby połączyć te dane w jedno i osiągnąć jak najlepszy rezultat wykorzystamy <srcset> oraz <sizes>:

<img src="SEO.jpg"
  srcset="SEO-767.jpg 768w, SEO-1080.jpg 1080w, SEO-1366.jpg 1366w, SEO-1440.jpg 1440w, SEO-1680.jpg 1680w, SEO-1920.jpg 1920w"
  sizes="(max-width: 768px) 100vw, (max-width: 1039px) 63vw, 700px">

<srcset> podajemy przeglądarce informacje, że do wyboru jest np. 6 różnych wersji obrazka. Wartość “w” określa dokładnie, jaką szerokość ma dany obrazek (jego szerokość wcale nie musi wynikać z nazwy, tak jak na podanym przykładzie). O tym jakie rozdzielczości powinny znaleźć się w secie powinny decydować następujące informacje:

  • dane analityczne dotyczące urządzeń użytkowników odwiedzających naszą witrynę,
  • dane dotyczące najpopularniejszych urządzeń w danym kraju/roku,
  • pixel density powyższych urządzeń.

Więcej o odpowiednim doborze obrazków do source set opisuję w kolejnej sekcji.

<sizes> za pomocą przedziałów, wiedząc jak wygląda i zachowuje się dany obrazek (lub grupa/klasa obrazków) w naszym layoucie, dajemy przeglądarce kolejną podpowiedź – jaką część viewportu zajmuje on przy danej rozdzielczości urządzenia.

Przykładowy kod powyżej, przez przeglądarkę interpretowany jest następująco:

  • Do wyboru jest 6 wersji obrazka o szerokościach 768px, 1080px, 1366px, 1440px, 1680px, 1920px.
  • Na urządzeniach do 768px szerokości (w tym wypadku jest to breakpoint layoutu mobile), obrazek zajmuje 100% viewportu.
  • Na urządzeniach do 1039px szerokości, obrazek zajmuje 63% viewportu (w tym wypadku jest to przedział od przeskoczenia layoutu na desktop do maksymalnej szerokości projektu strony).
  • Dla wszystkich innych rozdzielczości obrazek ma dokładnie 700px (w tym wypadku jest to szerokość ekranu powyżej której layout już się nie zmienia).

Zamiast wartości “px” lub “vw” można wykorzystać też kalkulację np. calc(50vw-10px).

Jak dobrać zestaw rozdzielczości do <srcset>

Dobrze skrojony source set musi uwzględniać następujące czynniki:

  1. Dane analityczne dotyczące urządzeń naszych klientów
  2. Dane dotyczące najpopularniejszych urządzeń w danym rejonie
  3. Pixel density wymienionych wyżej urządzeń
  4. Punkt zmiany layoutu na mobilny
  5. Maksymalna szerokość projektu

Dane analityczne – popularne urządzenia klientów

Dane dotyczące naszych klientów możemy sprawdzić w Google Analytics w widoku – Odbiorcy > Technologia > Przeglądarka i system, po wybraniu wymiaru podstawowego “rozdzielczość ekranu”.

rozdzielczość ekranu użytkowników w Google Analytics
Widok danych dot. rozdzielczości ekranu w Google Analytics

Drugim źródłem, a w przypadku nowej witryny – jedynym, są ogólne dane statystyczne dotyczące najpopularniejszych wyświetlaczy – https://gs.statcounter.com/screen-resolution-stats/

Obecnie (końcówka 2020) najpopularniejsze wyświetlacze to:

  1. 1920×1080 – 9,01%
  2. 1366×768 – 8,8%
  3. 360×640 – 7,6%

Na potrzeby optymalizacji page speed, powyższa informacja musi zostać uzupełniona o jeszcze jedną zmienną – pixel density.

Pixel denisty – odpowiednie rozmiary w source set

Niezbędne jest rozróżnienie dwóch wartości:

  • Viewport Size – Dokładnie te wartości widać w raportach Google Analytics oraz danych statycznych dotyczących najpopularniejszych urządzeń. Zależnie od tej wartości wyświetlany jest layout mobile lub desktop. Nie jest to jednakże wartość kluczowa na potrzeby obliczeń atrybutu “sizes”.
  • Device Resolution – Prawdziwa rozdzielczość urządzenia, uwzględniająca pixel density (pixel ratio). Nowoczesne smartfony wykorzystują najczęściej pixel ratio x3 (Apple IPhone 6 i nowsze) i x4 (np. Samsung S6 i nowsze). Oznacza to, że rozdzielczość 360×640 wedle danych z GA to tak naprawdę, zależnie od pixel density, 1080px lub 1440px w kontekście obliczenia wyświetlanej rozdzielczości obrazka.

Dane dotyczące pixel ratio popularnych urządzeń można znaleźć tutaj – https://yesviz.com/viewport/

Pixel density jest bardzo ważne jeśli na wersji mobilnej chcemy zachować wysoką jakość prezentowanej zawartości. Obrazek w rozdzielczości 360px oglądany z bliska na wyświetlaczu telefonu nie wygląda dostatecznie dobrze.

Layout strony – wpływ na source set

Ostatnim czynnikiem, który warto wziąć pod uwagę określając source set, jest zachowanie layoutu strony. Pod uwagę należy wziąć dwie zmienne:

  • Maksymalną szerokość projektu (jeśli istnieje) – gdy maksymalna szerokość strony jest określona i wynosi np. 1680px, nie ma potrzeby planowania obrazków dla layoutu szerszego, gdyż powyżej tej szerokości będzie się zwiększać jedynie pusty odstęp między zawartością a krawędzią wyświetlacza.
  • Mobile layout breakpoint – określa przy jakiej szerokości okna layout przeskakuje na mobilny. Jest to istotne w wypadkach gdzie obrazek zajmuje inną przestrzeń w wersji mobilnej. Najczęściej jest to sytuacja gdzie obrazki które w wersji desktop zajmują więcej niż 30% ale mniej niż 100% ekranu, na wersji mobilnej zajmują 100%.

Przykładowy zoptymalizowany source set

Na potrzebę omówienia przykładu podstawię następujące dane:

  • Maksymalna szerokość layoutu – 1680px
  • Mobile breakpoint – 768px
  • Najpopularniejsze urządzenia klientów:
    • 1920px
    • 1366px
    • (mobile) 360px 3.0 ratio = 1080px
    • (mobile) 360px 4.0 ratio = 1440px
    • 1440px

Zalecany source set powinien wyglądać następująco:

  • 1680px – maksymalna szerokość projektu, czyli dopasowanie 1:1 do wyświetlaczy 1680+
  • 1440px – dopasowanie 1:1 do ekranów 1440 i smartfonów z pixel density x4
  • 1366px – dopasowanie 1:1 do ekranów 1366
  • 1080px – dopasowanie 1:1 dla smartfonów z pixel density x3
  • 768px – dopasowanie 1:1 dla maksymalnej szerokości w layoucie mobile

Dzięki takiemu zestawowi mamy pewność, że obrazki które zajmują całą szerokość strony nie będą wysyłane do klienta zbyt duże i przeskalowywane przez przeglądarkę. Kolejnym krokiem będzie zadbanie o obrazki, które nie zajmują 100% szerokości ekranu, posłuży do tego atrybut “sizes”, zgodnie z opisem w następnej sekcji.

Tworząc odpowiedni source set, nie należy dodawać zbyt dużej liczby elementów, to obciążenie dla kodu i serwera, który musiałby trzymać każdy obrazek w dużej liczbie wariantów. Polecam maksymalnie 5-6 wersji. Może okazać się, że wśród naszych użytkowników jest bardzo szeroki wachlarz różnych urządzeń i nie da się tego dobrze dopasować w 5 elementach. Istnieje jednak jeszcze jeden czynnik, który może być pomocny przy podjęciu decyzji.

Zmniejszając duży obrazek (np. 1920px) o 10%, oszczędzamy więcej danych niż zmniejszając mały (np. 400px) o 30%.

Innymi słowy, warto skupić się na zagęszczeniu opcji dla dużych rozdzielczości kosztem małych. Oto przykład:

  • Obraz 1680px zmniejszony o 10% do 1512px = 20% redukcji / 42 kB mniej
  • Ten sam obraz 768px zmniejszony o 50% do 384px = 69% redukcji / 41,8 kB mniej

Mały obrazek musielibyśmy zmniejszyć o 50%, żeby uzyskać taką samą oszczędność jak przy zmniejszeniu o 10% obrazka dużego.

Atrybut “sizes” – optymalizacja rozmiaru obrazków

Posiadając zweryfikowany już wcześniej element <srcset>, do pełnej optymalizacji brakuje już tylko jednego kroku. Sam source set, wykorzystywany często w połączeniu z atrybutami “media”, pozwala przeglądarce dopasować pobierany obrazek idealnie do urządzenia użytkownika, ale tylko pod warunkiem, że zajmuje on 100% szerokości ekranu. Przeglądarka nie jest sama w stanie określić jaki będzie “computed size” obrazka. W rezultacie, żeby wyświetlić mały obrazek, który tak naprawdę po wyrenderowaniu ma np. 400px, pobierana jest wersja odpowiednia do maksymalnej szerokości ekranu, czyli np. 1680px. Z perspektywy rozmiaru pliku jest to kolosalna różnica.

Za pomocą atrybutu “sizes” możemy dokładnie określić jaki jest “computed size”, przeglądarka jest w stanie wykorzystać tę informację, aby wybrać z source seta rozdzielczość najbliższą rzeczywistości i tym samym zaoszczędzić cenne bajty danych. Omówię to na poniższym przykładzie:

Obrazek zajmuje 50% szerokości layotu w wersji desktop i 100% szerokości w wersji mobile, dla projektu którego maksymalna szerokość to 1680px (wykorzystamy source set z poprzedniej sekcji).

<img src="page-speed.jpg"
srcset="page-speed-768.jpg 768w, page-speed-1080.jpg 1080w, page-speed-1366.jpg 1366w, page-speed-1440.jpg 1440w, page-speed-1680.jpg 1680w"
sizes="(max-width: 768px) 100vw, (max-width: 1679px) 60vw, 840px">

Za pomocą “sizes”, informujemy przeglądarkę że:

  • dla rozdzielczości do 768px, obrazek zajmuje 100% szerokości,
  • dla rozdzielczości od 769px (przeskok na desktop layout) do 1679px, obrazek dynamicznie zajmuje 60% szerokości,
  • dla każdej innej rozdzielczości nie uwzględnionej w przedziałach, w tym wypadku 1680px i więcej – obrazek ma zawsze dokładnie 840px.

W rezultacie, jeśli otworzę stronę na ekranie 1920px, moja przeglądarka nie pobierze obrazka 1680px (czyli największego z source set), tylko 1080px (czyli najbliższy większy od obliczonego 840px). Dla przykładowego obrazka w formacie JPEG i jakości ustawionej na 85 jest to redukcja o ok. 50% czyli np. z 300kB do 150kB.

Więcej o wykorzystaniu atrybutu “sizes” można przeczytać tutaj – https://web.dev/serve-responsive-images/

WebP – lepsza kompresja obrazków

Oszczędności wynikające z odpowiedniego responsywnego skalowania możemy podwoić za pomocą lepszej kompresji. W większości serwisów internetowych i CMS-ów, standardem nadal jest stare, dobre JPG. Co nie oznacza, że jest to format najlepszy dla nowoczesnych stron internetowych.

W odpowiedzi na pytanie – czym jest WebP i dlaczego jest takie dobre – odsyłam do świetnego wprowadzenia na YT – Image Compression Deep Dive .

Do samodzielnych testów może posłużyć genialna, darmowa aplikacja webowa do kompresowania i porównywania obrazków – Squoosh .

WebP – kompatybilność z przeglądarkami

Stan na dzisiaj (grudzień 2020) jest następujący:

  • Przeglądarki 90% użytkowników są kompatybilne z WebP
  • Dla pozostałych 10% (np. IE), można zastosować “fallback” który będzie serwował JPEG

Dane można zweryfikować na bieżąco tutaj – https://caniuse.com/?search=webp .

Przykładowe zastosowanie dwóch formatów, do wyboru przez przeglądarkę:

<picture>
  <source type="image/webp" srcset="seo.webp">
  <source type="image/jpeg" srcset="seo.jpg">
  <img src="flower.jpg" alt="">
</picture>

WebP – implementacja w WordPress

Szczegółowe opisanie implementacji WebP na różnych CMS-ach lub różnymi metodami, wymagałoby kilku oddzielnych artykułów, dlatego skupię się na dwóch przykładach – w CMS WordPress i za pomocą przykładowej Content Delivery Network.

Wtyczka ShortPixel

Jestem zwolennikiem instalowania jak najmniejszej ilości wtyczek do WP i w miarę możliwości próbowania łączenia wielu funkcjonalności w jednej. Ogólnie w kwestii optymalizacji obrazków zdecydowanie mogę polecić wtyczkę ShortPixel. Oferuje kompresję, przycinanie, skalowanie, integrację z CDN i wiele innych. Pozwala także automatycznie podstawić wersje WebP dla całej witryny, jest to zabieg dokładnie opisany na ich blogu . W pełni automatycznie procesy nie działają w każdym wypadku, dokładnie tak samo jest z WebP i ShortPixel. Na szczęście wtyczka oferuje dwa zupełnie inne rozwiązania, dlatego ryzyko, że zawiodą oba jest bardzo małe.

Pierwsza opcja podmienia elementy w kodzie strony. Zamienia elementy <img> na <picture>, w rezultacie przeglądarka klienta jest w stanie wybrać czy woli pobrać WebP czy JPEG. Ograniczeniem jest sam motyw używany w WP, w określonych przypadkach aktywacja tej funkcji może doprowadzić do niepożądanych zmian w layoucie. W takich wypadkach ShortPixel oferuje alternatywne rozwiązanie.

Serwowanie wersji WebP obrazków jedynie za pomocą .htaccess. W tym wypadku, potencjalnym ograniczeniem jest nie WordPress, lecz serwer, który może po prostu takiego rozwiązania nie obsługiwać. Wtyczka automatycznie sprawdza, czy konfiguracja serwera jest odpowiednia. O rozwiązaniu za pomocą .htaccess można przeczytać w oddzielnym wpisie w sekcji pomocy ShortPixel.

WebP – implementacja za pomocą CDN

Jeśli witryna wykorzystuje Content Delivery Network do serwowania obrazków, jest szansa że bezpośrednio w panelu CDN jesteśmy w stanie skonfigurować serwowanie WebP. Duża część popularnych dostawców takich usług ma już WebP w swoim repertuarze, m.in.:

  • CloudFlare
  • Akamai
  • KeyCDN
  • Frontify

Jeśli zarządzamy dużą witryną, która ma ogrom zasobów, a WebP nie jest jeszcze w ogóle wykorzystywane, rozwiązanie wykorzystujące CDN często będzie najlepszym wyjściem, gdyż nie wymaga żadnych działań na już istniejących obrazkach, serwerze, tudzież kodzie strony.

Panele odpowiadające za zarządzanie obrazkami i filmami potrafią być bardzo rozbudowane. Dla przykładu, Akamai Image Manager oferuje opcje, które bardzo ciężko byłoby wprowadzić bezpośrednio na witrynie:

  • różne polityki zależnie od wymiaru/ścieżki/umiejscowienia obrazka,
  • wartość kompresji fixed oraz perceptual – automatyczne dopasowanie kompresji do skomplikowania obrazka,
  • dashboard z danymi zbiorczymi na temat oszczędności transferu dzięki kompresji,
  • wtyczkę dla Chrome/Firefox, żeby “na żywo” przeglądając stronę móc obserwować efekty kompresji,
  • JPEG 2000 oraz JPEG XR dla urządzeń nie obsługujących WebP,
  • poza kompresją także skalowanie i inne transformacje (przycinanie, edycja kolorów itd.)
Ustawienia WebP w CDN
Ustawienia WebP dla wybranej polityki w Akamai Image Manager

Możliwości są niemal nieograniczone. Dla dużych serwisów, bez wątpienia, optymalizacja obrazków oraz ich kompresja za pomocą CDN to idealne wyjście. Największym, jeśli nie jedynym, minusem takiego rozwiązania są oczywiście koszty. Serwowanie obrazków przez CDN to już jest dodatkowy koszt, a w wielu wypadkach pakiety dotyczące automatycznego zarządzania kompresją znacznie go powiększają.

Ile megabajtów można zaoszczędzić za pomocą skalowania i WebP?

W sytuacji gdzie punktem startu jest witryna, która posiada tylko jakieś podstawowe skalowanie obrazków i standardową kompresję JPEG, można od razu założyć, że średnia redukcja wagi obrazków na stronę osiągnie nawet 70-80%. Poniżej omówię kilka przykładów znalezionych w Internecie oraz jeden projekt nad którym pracowałem bezpośrednio.

Własny projekt

Domena, której nazwą niestety nie mogę się podzielić, serwuje na stronie głównej ok. 7-9 obrazków. Szeroki na cały ekran obrazek główny + 6-8 obrazków, które ilustrują produkty lub artykuły (zajmują 50-60% szerokości ekranu). Przed pracami nad optymalizacją obrazków przeglądarka pobierała ok. 6.0 MB danych. Obecnie pobiera ok. 1.0 MB. Poza pojedynczymi wypadkami, że jakiś obrazek potrafił być całkowicie nieskompresowany, najczęściej oszczędność wyglądała następująco:

  • Obrazek którego “computed size” jest w okolicach 800px – 900px, do klienta wysyłany był w wersji 1700px+.
  • Kompresja ustawiona była na JPEG jakość = 85
  • Rozmiar – 200 kB

Optymalizacja – format WebP jakość “perceptual medium/high” + skalowanie “sizes” do 1080px = 55 kB. W tym wypadku redukcja 71% (z 200 kB do 55 kB.)

Im więcej obrazków na stronie oraz im gorsza ich początkowa optymalizacja, tym lepsze efekty. Natomiast nawet dla teoretycznie nie najgorzej zoptymalizowanych (JPEG i skalowanie do media query), można spokojnie osiągnąć ponad 50% redukcji.

Strona banku Pekao SA – przykład z internetu

Omawiany case – https://www.pekao.com.pl/

optymalizacja obrazków - przykład
zrzut ekranu ze strony głównej PEKAO SA

Na stronie widać 3 małe obrazki-kafelki, ich computed size to 280px – 360px. Tymczasem przeglądarka pobiera ważące nawet 1.0 MB, wysokiej jakości pliki PNG o szerokości 800px.

optymalizacja obrazków - przykład
obrazki ciężkiej wagi pobrane aby wyświetlić miniaturki 280px

Ile zatem powinien ważyć obrazek 360px przedstawiający ludzi? Odpowiedź brzmi – ok. 10kB. Obrazki które w layoucie są małe, nawet jeśli mają kompresję WebP rzędu 75 lub mniejszą, to w wielu wypadkach ubytki jakości nie są widoczne gołym okiem.

Na stronie głównej PEKAO SA, jest ok. 20 obrazków, łącznie ważą ok 8.0 MB. Przy dobrej optymalizacji mogłoby ważyć razem ok. 600 kB. Jest to ponad 90% redukcji.

Strona EY Polska – przykład z internetu

Omawiany case – https://www.ey.com/pl_pl

Strona zaczyna się od dużego obrazka na całą szerokość przeglądarki, a następnie dwóch kafelków promujących konkretne oferty. Na moim ekranie (1920px), obrazki te pobierają się w rozdzielczości 3840px (waga nawet 2.0 MB) aby wyświetlić się jako 875px.

optymalizacja obrazków - przykład
2.0 MB aby wyświetlić obrazek 875px

Powinny ważyć mniej niż 100 kB – 875px, WebP quality 85. Optymalizacja tylko tych 3 obrazków spowodowałaby, że strona jest lżejsza o 3.7 MB

Test jednego obrazka

Ponownie chciałem Was zachęcić do korzystania z – https://squoosh.app/ i eksperymentowania z obrazkami, które macie na swoich stronach internetowych, żeby zobaczyć o ile strona mogłaby być lżejsza gdyby się je zoptymalizowało. Poniżej dwa przykłady:

  • Obrazek 640px, oryginalna waga: 79,2 kB
  • Po mocnej kompresji WebP (quality 60), waga: 31,2 kB (61% redukcji, sama kompresja, bez skalowania)
kompresja WebP 60
JPEG vs WebP quality 60

Lewa połówka to oryginalny obrazek, prawa to WebP. Przy quality ustawionym na 60, na aucie widać różnice, natomiast w szumie tła – zdecydowanie nie. Niestety nie ma jednego uniwersalnego ustawienia, które idealnie skompresuje wszystkie obrazki. Poziom kompresji, tak aby nie zmniejszał widocznie jakości, jest uzależniony od rozmiaru obrazka, jego miejsca na stronie oraz tego co przedstawia. W związku z powyższym, nad twardym ustawieniem wszędzie jednej jakości, zawsze przewagę będzie miała ręczna praca lub algorytm “perceptual quality”.

Drugi przykład to typowy przypadek, który powtarza się na stronach internetowych, gdzie brakuje zarówno kompresji jak i skalowania. Poniżej ten sam obrazek, zoptymalizowany do tego bloga (720px) i w jakości WebP 75.

kompresja WebP 75
WebP 75, 720px

Żeby go wyświetlić, Wasza przeglądarka musiała pobrać 47,6 kB danych. Gdyby CMS wrzucił po prostu oryginalny obrazek 1920px bez dodatkowej kompresji, Wasza przeglądarka musiałaby pobrać 425 kB danych, a rezultat wizualny byłby dokładnie taki sam.

Lazy loading

Mając już za sobą skalowanie i kompresje, pozostaje finalny krok – niewysyłanie do klienta obrazków które nie są w danej chwili potrzebne. Obecnie jednym z najważniejszych parametrów jest należący do Core Web Vitals – Largest Contentful Paint (LCP) . Nie tylko całkowity rozmiar strony jest ważny, kluczowa jest ilość danych potrzebna żeby w ogóle ją wyświetlić. Jeśli zależy nam na jak najlepszych wynikach w Core Web Vitals, LCP nie ma szans bez lazy loadingu.

W dużym skrócie – lazy loading powoduje, że przeglądarka pobiera tylko te obrazki, które są widoczne na ekranie oraz te, które są tuż “pod”. W praktyce oznacza to, że otwierając typowy artykuł pobrany zostanie tylko obrazek nagłówka, a wszystkie obrazki w treści będą czekać na swój moment. W rezultacie, w kluczowym dla użytkownika momencie, czyli pierwszych kilku sekundach obcowania ze stroną internetową, będzie musiał czekać na pobranie tylko pierwszego obrazka, w związku z czym widok będzie stabilny i responsywny w 2 sekundy, zamiast np. w 4 sekundy lub więcej.

Poprzednie kroki pomagają w zmniejszeniu całkowitego rozmiaru strony. Lazy loading spowoduje, że podczas pierwszego ładowania potrzebne będzie tylko kilkanaście procent tej wartości. Wcześniej pisałem, że implementacja “sizes” i WebP zmniejszyła rozmiar obrazków na stronie z 6.0 MB do 1.0 MB. Z lazy loading, wartość ta spadła do 166 kB, zanim zacznie się przewijać.

Lazy loading w przeglądarkach

Dawniej wprowadzenie skutecznego lazy loadingu wymagało skomplikowanych zabiegów w kodzie strony. Licząc od wersji Chrome 76 – atrybut loading=”lazy” stał się integralną częścią przeglądarek. Nadal nie wszystkie go wspierają – https://caniuse.com/loading-lazy-attr , obecnie szacuje się, że 72% użytkowników będzie w stanie z niego skorzystać.

Więcej o lazy loadingu wspieranym przez przeglądarki można przeczytać tutaj – https://web.dev/browser-level-image-lazy-loading/ .

W kontekście poprawy szybkości wczytywania za pomocą optymalizacji obrazków znaczy to jedynie:

Warto dodać atrybut loading=”lazy” do obrazków na swojej stronie internetowej

<img loading="lazy" width="439" height="308" src="https://mad-lab.pl/wp-content/uploads/2020/10/Zrzut-ekranu-2020-10-14-212055.png" alt="Chrome - optymalizacja obrazków" class="wp-image-774" srcset="https://mad-lab.pl/wp-content/uploads/2020/10/Zrzut-ekranu-2020-10-14-212055.png 439w, https://mad-lab.pl/wp-content/uploads/2020/10/Zrzut-ekranu-2020-10-14-212055-300x210.png 300w" sizes="(max-width: 439px) 100vw, 439px">

Podsumowanie – 75% redukcji rozmiaru obrazów w 5 krokach

  1. Chrome Web Dev Tools – Sprawdź czy przeglądarka nie pobiera obrazków znacznie większych niż ich computed size.
  2. Chrome Web Dev Tools – Sprawdź czy przeglądarka pobiera obrazki w wersji WebP czy JPEG.
  3. Za pomocą wtyczek do CMS-a lub konfiguracji CDN włącz kompresję WebP
  4. Zmień kod strony tak aby obrazki wykorzystywały atrybut “sizes”
  5. Zmień kod strony tak aby obrazki wykorzystywały atrybut “loading”

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *