Blog
/
Jak optymalnie ładować obrazy w Next.js z rozmyciem albo kolorem
Nagłówek posta na Blogu
22.09.2024
~ 6 min

Jak optymalnie ładować obrazy w Next.js z rozmyciem albo kolorem

ui/ux
poradnik
Optymalizuj ładowanie obrazów w Next.js z placeholderami blur i kolorami. Zmniejsz efekt 'podskakujących' zdjęć i popraw UX aplikacji internetowej.

Serwus, dzisiaj coś z kategorii UI/UX 🤓

Ładowanie obrazów w aplikacjach webowych może mieć duży wpływ na wydajność i UX (dzisiaj bardziej o tym drugim). W Next.js mamy kilka możliwości, aby poprawić ten proces, np. wykorzystując placeholdery z efektem rozmycia (blur) lub kolorowe tło, zanim obraz zostanie w pełni załadowany, bo mało rzeczy tak denerwuje jak "podskakujące" zdjęcia w momencie ładowania. 😉

Dziś pokażę jak to osiągnąć, będę opierać się w głównej mierze na jednej paczce (wymienionej też w dokumentacji Next'a): Plaiceholder

(Chociaż, gdy ktoś się uprze można robić to też bez tej paczki, przykład na samym końcu)

Początkowa konfiguracja Next'a

config.webp

WAŻNE - aby to działało nasz plik next.config musi być w formacie .mjs

Tag <Image/> z statycznym zdjęciem i bazowym rozmyciem

classic.webp

Dla statycznych zdjęć w Nextjs (np. z folderu /public), aby rozmycie działało należy je zaimportować statycznie tak jak poniżej, podając ścieżkę do folderu ze zdjęciem np: import StaticImage from "../../public/cowboy.jpg"; Bez importu Next nie jest w stanie poprawnie zapewnić rozmycia, dlatego dodając bezpośrednią ścieżkę do pliku placeholder="blur" wyrzuci błąd o tym, aby zapewnić mu też blurDataURL co nas w ogóle nie urządza. 👀

Ładowanie statycznego zdjęcia z Plaiceholder

static_blur_plaiceholder.webp

Jak widać na snippecie kodu czytamy plik z wybranej lokalizacji w naszym projekcie, dostajemy buffer, który pozwala nam zaciągać pliki kawałek po kawałku, następnie przekazujemy go do funkcji z naszej paczki, tzn getPlaiceholder, która zwróci nam baaardzo mały, rozmyty plik w formacie base64, który jako-tako przypomina docelowe zdjęcie. 🙂 Plik base64 jest naszą wartością "blurDataURL", gdzie src to nasz docelowy plik (który pojawi się w miejsce poprzedniego, gdy tylko zostanie załadowany).

funkcja getPlaiceholder przyjmuje w drugim argumencie również opcje konfiguracyjne, ale najważniejsza jest jedna, tzn size, która pozwala możliwie zredukować rozmiar pliku z rozmyiem i jego "szczegółowość": const { base64 } = await getPlaiceholder(buffer, { size: 5 });

WAŻNE - z racji na używanie modułu z Node, która czyta plik z naszego systemu, ten sposób zadziała tylko w serwerowym środowisku.

static_color_plaiceholder.webp

Bardzo podobna sytuacja, co w poprzednim przykładzie, tutaj natomiast dodajemy backgroundColor do bezpośredniego rodzica naszego zdjęcia. Plaiceholder zapewnia, że ten kolor będzie głównym kolorem naszego docelowego zdjęcia. Na przykład gdy damy zdjęcie morza, to nasz loader będzie niebieski (chyba, że to Bałtyk, to pewnie zielony od sinic 👀)

Dynamiczne zdjęcie z rozmyciem

dynamic_blur.webp Podobna sprawa jak z statycznym rozmyciem, tutaj natomiast nasz buffer zdjęcia odbieramy za pomocą fetcha oraz "arrayBuffer".

Dynamiczne zdjęcie z kolorem przewodnim jako placeholder

dynamic_color.webp Jak wyżej, z funkcji getPlaiceholder możemy zdestrukturyzować propetkę color i jej użyć jako tło naszego diva.

Można to też zrobić bez dodatkowej paczki

Dynamiczne rozmycie bez dodatkowych paczek Nie mamy tak łatwej możliwości wyciągnięcia koloru przewodniego, ani zmiany rozmiaru, ale jest to napewno łatwy i szybki sposób na rozmycie naszego loadera 😉

(Bonus) Ładowanie zdjęcia z animacją, gdy wejdzie do Viewportu

observer_view_loader.webp Tutaj wykorzystałem paczkę react-intersection-observer ze względu na lenistwo (hyhy), ale równie dobrze można pobawić się po prostu z natywnym Interection Observerem. Gdy zdjęcie pojawia się w naszym Viewporcie, to płynnie przechodzi z koloru tła rodzica (czyi diva) do zdjęcia. Na gifie poniżej trwa to najdłużej z racji na to, że jest to w pełni kliencka operacja + zaczynamy z Viewportem na tym zdjęciu (a nie scrollujemy), co też sprawia problem. W normalnym toku strony, wszystko działa idealnie. 👌

Efekty

Pociete (1).gif

Podsumowanie

Korzystając z tych sposobów na ładowanie zdjęć napewno Wasza aplikacja zyska nieco "blasku", to tyle na dziś! 👋

Kod źródłowy: Link

Bądź na bieżąco!

Zapisz się do mojego newslettera, aby otrzymywać najświeższe wiadomości i aktualizacje prosto na swoją skrzynkę mailową! Tak jak Ty, też nie przepadam za spamem - zapewniam, że moje wiadomości będą zawierać tylko najważniejsze informacje.
Emoji wykonujące gest dzwonienia.