Wprowadzenie: dlaczego obrazy wciąż są najsłabszym ogniwem wydajności
Obrazy odpowiadają za 60–70% całkowitej wagi przeciętnej strony internetowej. Według danych HTTP Archive z początku 2026 roku, mediana strony mobilnej pobiera ponad 1,4 MB samych grafik — i to zanim policzymy JavaScript, CSS czy czcionki. W poprzednich artykułach z tej serii omawialiśmy optymalizację Core Web Vitals, redukcję bundli JavaScript i strategie cachowania. Teraz pora na czwarty filar wydajności: kompleksową optymalizację obrazów.
I nie, to nie jest kolejny artykuł typu „zamień JPEG na WebP i będzie szybciej".
Pokażę Ci pełny obraz (pun intended): od wyboru formatu, przez responsywne ładowanie z srcset i <picture>, po zaawansowane techniki jak fetchpriority, automatyczne pipeline'y z Sharp, aż po Image CDN. Na końcu każdej sekcji znajdziesz gotowy kod do wdrożenia — kopiuj, wklejaj, działaj.
Formaty obrazów w 2026: AVIF vs WebP vs JPEG
Zanim zajmiemy się technikami ładowania, musisz wybrać odpowiedni format. W 2026 roku mamy trzech głównych graczy i każdy z nich ma swoje mocne strony.
JPEG — weteran, który jeszcze żyje
JPEG ma ponad 30 lat i wciąż obsługuje 100% przeglądarek. Szczerze mówiąc, stosuj go wyłącznie jako ostateczny fallback. Przy jakości 80–85% daje akceptowalne wyniki, ale przegrywa z nowszymi formatami pod względem rozmiaru pliku o 25–60%. To dużo.
WebP — obecny standard rynkowy
WebP oferuje zarówno kompresję stratną, jak i bezstratną. Pliki WebP stratne są 25–34% mniejsze od porównywalnych JPEG przy zachowaniu zbliżonej jakości wizualnej. Bezstratne WebP to 26% mniej niż PNG. Wsparcie przeglądarek w 2026 roku przekracza 97%, co czyni go bezpiecznym domyślnym formatem.
Jeśli miałbym wybrać jeden format „na szybko" — byłby to właśnie WebP.
AVIF — przyszłość, która już nadeszła
AVIF bazuje na kodeku AV1 i oferuje jeszcze lepszą kompresję niż WebP — do 50% mniejsze pliki niż JPEG przy porównywalnej jakości. Format radzi sobie świetnie z dużymi fotografiami, szczególnie w scenach z subtelnymi gradientami i przejściami tonalnymi, gdzie JPEG generuje widoczne artefakty. Na początku 2026 roku wsparcie AVIF obejmuje Chrome, Firefox, Safari 17+ i Edge — łącznie ponad 93% globalnego ruchu.
Jest jednak jeden minus: kodowanie AVIF jest znacząco wolniejsze niż WebP czy JPEG. Dlatego konwersja powinna odbywać się w procesie budowania albo na CDN — nigdy w locie na serwerze origin przy każdym żądaniu. Naprawdę, nigdy.
Rekomendowana hierarchia formatów
Strategia jest prosta: serwuj AVIF jako format pierwszy, WebP jako fallback, a JPEG jako ostateczną rezerwę. W HTML realizujesz to elementem <picture>:
<picture>
<source srcset="hero.avif" type="image/avif">
<source srcset="hero.webp" type="image/webp">
<img src="hero.jpg" alt="Opis obrazu" width="1200" height="630">
</picture>
Przeglądarka automatycznie wybierze najlepszy obsługiwany format — czytając od góry. Jeśli obsługuje AVIF, pobierze hero.avif. Jeśli nie, spróbuje WebP. W ostateczności sięgnie po JPEG. Eleganckie, prawda?
Ustawienia kompresji — na co celować
Ludzkie oko zazwyczaj nie dostrzega różnic przy odpowiednich ustawieniach jakości. Oto sprawdzone zakresy, które stosuję w swoich projektach:
- AVIF: jakość 45–60 (niższe wartości niż JPEG/WebP, bo algorytm kompresji jest po prostu skuteczniejszy)
- WebP: jakość 70–82
- JPEG: jakość 80–85
Zawsze testuj na swoich konkretnych obrazach — grafiki z dużą ilością tekstu lub ostrych krawędzi mogą wymagać nieco wyższej jakości niż typowe zdjęcia fotograficzne.
Responsywne obrazy: srcset, sizes i element picture
Serwowanie identycznego obrazu 2560px szerokości zarówno na 4K monitorze, jak i na telefonie z ekranem 375px to czysty sabotaż wydajności. Responsywne obrazy rozwiązują ten problem, pozwalając przeglądarce wybrać optymalny wariant.
Atrybut srcset z deskryptorami szerokości
Atrybut srcset pozwala zdefiniować kilka wariantów tego samego obrazu w różnych rozmiarach:
<img
srcset="hero-640.webp 640w,
hero-1024.webp 1024w,
hero-1440.webp 1440w,
hero-1920.webp 1920w"
sizes="(max-width: 768px) 100vw,
(max-width: 1200px) 80vw,
1200px"
src="hero-1024.webp"
alt="Opis obrazu"
width="1920"
height="1080"
>
Jak to działa? Atrybut srcset informuje przeglądarkę o dostępnych wariantach i ich rzeczywistej szerokości w pikselach (wartości z w). Atrybut sizes mówi przeglądarce, jak szeroki będzie obraz na ekranie — na ekranach do 768px zajmie 100% viewportu, do 1200px — 80%, a powyżej będzie miał stałe 1200px.
Przeglądarka dzieli szerokość zasobu przez wynikowy rozmiar wyświetlania (uwzględniając DPR urządzenia) i wybiera optymalny wariant. Na telefonie z ekranem 375px i DPR 2 efektywnie potrzebuje obrazu 750px — więc wybierze hero-1024.webp, a nie pełny obraz 1920px. Sprytne.
Ile wariantów generować?
Rekomendacja na 2026 rok: 3–5 wariantów na obraz. Więcej wariantów oznacza lepsze dopasowanie, ale też gorsze wykorzystanie cache (więcej unikalnych URL-i do cachowania). Sprawdzone breakpointy:
- 640px — smartfony (orientacja pionowa)
- 1024px — tablety i małe laptopy
- 1440px — standardowe monitory
- 1920px — duże monitory Full HD
- 2560px — ekrany Retina/HiDPI (opcjonalnie)
Nie ma sensu generować wariantów powyżej 2560px — nawet na ekranach 4K różnica jest praktycznie niewidoczna, a rozmiar pliku rośnie znacząco.
Połączenie picture, srcset i formatów
No dobrze, a teraz najlepsza część. Prawdziwa moc ujawnia się, gdy połączysz responsywność z wieloformatowością:
<picture>
<source
srcset="hero-640.avif 640w,
hero-1024.avif 1024w,
hero-1920.avif 1920w"
sizes="(max-width: 768px) 100vw, 1200px"
type="image/avif">
<source
srcset="hero-640.webp 640w,
hero-1024.webp 1024w,
hero-1920.webp 1920w"
sizes="(max-width: 768px) 100vw, 1200px"
type="image/webp">
<img
src="hero-1024.jpg"
alt="Opis obrazu"
width="1920"
height="1080"
fetchpriority="high">
</picture>
To daje przeglądarce maksymalną elastyczność — wybiera zarówno optymalny format, jak i rozmiar. Na nowoczesnym telefonie z Chrome dostanie mały AVIF; na starszym Safari bez wsparcia AVIF — odpowiedni WebP. Użytkownik nic nie musi robić, a jego transfer danych będzie Ci wdzięczny.
fetchpriority i preload: jak przyspieszyć LCP o setki milisekund
Oto jedno z najbardziej niedocenianych narzędzi w arsenale web developera. Serio, zbyt mało osób z tego korzysta. Atrybut fetchpriority pozwala powiedzieć przeglądarce, który zasób jest naprawdę ważny — a który może poczekać.
Problem: domyślna priorytetyzacja obrazów
Domyślnie przeglądarki traktują obrazy jako zasoby o niskim priorytecie. Dopiero po zakończeniu layoutu Chrome odkrywa, które obrazy są widoczne w viewporcie i podwyższa ich priorytet. Problem polega na tym, że to odkrycie następuje za późno — obraz hero konkuruje wtedy z innymi zasobami o przepustowość.
Rozwiązanie: fetchpriority="high"
Dodanie fetchpriority="high" do elementu <img> (lub wewnątrz <picture>) mówi przeglądarce: „ten obraz jest krytyczny, zacznij go pobierać natychmiast z wysokim priorytetem".
<!-- Hero image z wysokim priorytetem -->
<img
src="hero.webp"
alt="Hero banner"
width="1200"
height="630"
fetchpriority="high">
<!-- Obrazy poniżej foldu — niski priorytet -->
<img
src="feature.webp"
alt="Funkcja produktu"
loading="lazy"
fetchpriority="low">
Efekty potrafią być naprawdę spektakularne. Zespół Google Flights dodał fetchpriority="high" do swojego obrazu hero i zanotował poprawę LCP o 700 milisekund. W testach na różnych stronach poprawa LCP wynosi typowo 20–30%. Za jedną linijkę kodu — nieźle, prawda?
Preload w sekcji head — wczesne odkrycie zasobu
Sam fetchpriority podwyższa priorytet, ale nie pomaga z odkryciem zasobu. Jeśli URL obrazu jest zakopany w CSS (background-image) albo generowany przez JavaScript, przeglądarka nie wie o nim, dopóki nie przetworzy tych zasobów. Rozwiązanie? Dodaj <link rel="preload"> w sekcji <head>:
<head>
<!-- Preload obrazu hero z wysokim priorytetem -->
<link
rel="preload"
as="image"
href="/img/hero.avif"
type="image/avif"
fetchpriority="high">
<!-- Preload responsywnego obrazu -->
<link
rel="preload"
as="image"
imagesrcset="hero-640.avif 640w, hero-1024.avif 1024w, hero-1920.avif 1920w"
imagesizes="(max-width: 768px) 100vw, 1200px"
type="image/avif"
fetchpriority="high">
</head>
Ważna różnica: preload to obowiązkowe pobranie — przeglądarka musi pobrać zasób, nawet jeśli go nie potrzebuje. fetchpriority to jedynie wskazówka dotycząca priorytetu. Najlepszy efekt daje ich połączenie.
Kiedy NIE używać preload
Nie ładuj zbyt wielu zasobów z preload — każdy preload konkuruje o przepustowość. To trochę jak kolejka priorytetowa: jeśli wszystko jest priorytetowe, to nic nie jest. Używaj go wyłącznie dla:
- Obrazu hero / LCP
- Krytycznych tłowych obrazów CSS
- Logo w nagłówku (jeśli jest duże)
Lazy loading: prawidłowe wdrożenie w 2026
Lazy loading to technika, która opóźnia ładowanie obrazów poniżej foldu do momentu, gdy użytkownik zbliży się do nich podczas scrollowania. W 2026 roku natywne lazy loading jest w pełni wspierane przez wszystkie główne przeglądarki — nie potrzebujesz już żadnych bibliotek.
Natywne lazy loading z atrybutem loading
<!-- Obraz poniżej foldu — lazy load -->
<img
src="feature.webp"
alt="Opis"
width="800"
height="450"
loading="lazy">
<!-- Obraz hero — NIGDY nie lazy load! -->
<img
src="hero.webp"
alt="Hero"
width="1200"
height="630"
loading="eager"
fetchpriority="high">
Krytyczny błąd: lazy loading obrazu LCP
To jeden z najczęstszych błędów wydajnościowych, jaki widuję na stronach. Raport Chrome UX z 2024 roku wykazał, że strony z lazy loadingiem na elemencie LCP miały o 35% wolniejszy LCP. Nie dodawaj loading="lazy" do:
- Obrazu hero
- Jakiegokolwiek elementu widocznego bez scrollowania (above the fold)
- Logo w nagłówku
- Pierwszego obrazu w artykule (jeśli jest widoczny od razu)
Brzmi oczywiste? A jednak zdarza się to zaskakująco często — zwłaszcza gdy ktoś globalnie doda loading="lazy" do wszystkich obrazów „na wszelki wypadek".
Zaawansowane lazy loading z Intersection Observer
Natywny atrybut loading="lazy" jest prosty w użyciu, ale daje ograniczoną kontrolę nad momentem ładowania. Jeśli potrzebujesz precyzyjnej konfiguracji — na przykład ładowanie obrazów 200px przed ich wejściem w viewport — użyj Intersection Observer API:
// Zaawansowane lazy loading z Intersection Observer
const lazyImages = document.querySelectorAll('img[data-src]');
const imageObserver = new IntersectionObserver((entries, observer) => {
entries.forEach(entry => {
if (entry.isIntersecting) {
const img = entry.target;
// Podmień data-src na src
img.src = img.dataset.src;
if (img.dataset.srcset) {
img.srcset = img.dataset.srcset;
}
img.removeAttribute('data-src');
img.removeAttribute('data-srcset');
observer.unobserve(img);
}
});
}, {
// Zacznij ładowanie 200px przed wejściem w viewport
rootMargin: '200px 0px',
threshold: 0
});
lazyImages.forEach(img => imageObserver.observe(img));
To podejście jest szczególnie przydatne w nieskończonych listach produktów, galeriach zdjęć i feedach społecznościowych — wszędzie tam, gdzie liczba obrazów jest dynamiczna i nie wiadomo z góry, ile ich będzie.
Atrybuty width i height: zapobieganie przesunięciom layoutu (CLS)
Obrazy bez atrybutów width i height powodują przesunięcia layoutu (Cumulative Layout Shift) — przeglądarka nie zna wymiarów obrazu, dopóki go nie pobierze, i musi przerysować układ strony po jego załadowaniu. To jeden z głównych winowajców słabego wyniku CLS.
Rozwiązanie jest trywialne. Ale wciąż ignorowane na zaskakującej liczbie stron:
<!-- ŹLE: brak wymiarów, powoduje CLS -->
<img src="photo.webp" alt="Zdjęcie">
<!-- DOBRZE: wymiary pozwalają zarezerwować miejsce -->
<img src="photo.webp" alt="Zdjęcie" width="800" height="450">
<!-- DOBRZE: CSS aspect-ratio jako alternatywa -->
<style>
.hero-img {
aspect-ratio: 16 / 9;
width: 100%;
height: auto;
}
</style>
<img src="photo.webp" alt="Zdjęcie" class="hero-img">
Nowoczesne przeglądarki automatycznie obliczają aspect-ratio na podstawie atrybutów width i height, więc nawet jeśli obraz jest responsywny (z width: 100% w CSS), przeglądarka zarezerwuje odpowiednią ilość miejsca. Dwie liczby w HTML — a tyle problemów mniej.
Automatyzacja: pipeline optymalizacji obrazów z Sharp i Vite
Dobra, ręczna konwersja obrazów do AVIF i WebP, generowanie wariantów responsywnych, kompresja — kto by to chciał robić ręcznie za każdym razem? Na szczęście to wszystko da się zautomatyzować. Najlepszym narzędziem do tego w ekosystemie Node.js jest Sharp.
Skrypt konwersji z Sharp
// scripts/optimize-images.mjs
import sharp from 'sharp';
import { readdir, mkdir } from 'fs/promises';
import path from 'path';
const INPUT_DIR = './src/images/originals';
const OUTPUT_DIR = './public/img';
const WIDTHS = [640, 1024, 1440, 1920];
const FORMATS = [
{ name: 'avif', options: { quality: 50 } },
{ name: 'webp', options: { quality: 75 } },
];
async function optimizeImages() {
await mkdir(OUTPUT_DIR, { recursive: true });
const files = await readdir(INPUT_DIR);
for (const file of files) {
const inputPath = path.join(INPUT_DIR, file);
const baseName = path.parse(file).name;
for (const width of WIDTHS) {
for (const format of FORMATS) {
const outputPath = path.join(
OUTPUT_DIR,
`${baseName}-${width}.${format.name}`
);
await sharp(inputPath)
.resize(width)
.toFormat(format.name, format.options)
.toFile(outputPath);
console.log(`Wygenerowano: ${outputPath}`);
}
}
// Fallback JPEG
for (const width of WIDTHS) {
await sharp(inputPath)
.resize(width)
.jpeg({ quality: 82 })
.toFile(path.join(OUTPUT_DIR, `${baseName}-${width}.jpg`));
}
}
}
optimizeImages();
Ten skrypt bierze oryginalne obrazy z jednego katalogu i generuje wszystkie warianty (AVIF, WebP, JPEG w czterech rozmiarach) do katalogu wyjściowego. Podłącz go do npm run build i zapomnij o ręcznej konwersji.
Integracja z Vite przez vite-imagetools
Jeśli używasz Vite (a w 2026 roku kto nie używa?), wtyczka vite-imagetools automatyzuje generowanie wariantów responsywnych bezpośrednio w procesie budowania:
// vite.config.js
import { defineConfig } from 'vite';
import { imagetools } from 'vite-imagetools';
export default defineConfig({
plugins: [
imagetools({
defaultDirectives: (url) => {
if (url.searchParams.has('responsive')) {
return new URLSearchParams({
w: '640;1024;1440;1920',
format: 'avif;webp;jpg',
as: 'picture',
});
}
return new URLSearchParams();
},
}),
],
});
Dzięki temu w kodzie importujesz obraz z parametrem ?responsive, a Vite automatycznie generuje wszystkie warianty:
// W komponencie (np. React, Svelte)
import heroImage from './hero.jpg?responsive';
// heroImage zawiera dane do stworzenia <picture> z srcset
Muszę przyznać, że od kiedy zacząłem używać tego podejścia, nie wyobrażam sobie powrotu do ręcznego zarządzania wariantami obrazów.
Image CDN: optymalizacja bez zmian w kodzie
Jeśli nie chcesz zarządzać pipeline'em obrazów samodzielnie, Image CDN to rozwiązanie typu „podłącz i zapomnij". Zobaczmy, jakie są najważniejsze opcje w 2026 roku.
Cloudflare Images
Cloudflare oferuje transformacje obrazów na poziomie edge — resize, konwersja formatu i kompresja odbywają się na serwerach brzegowych, blisko użytkownika. Kluczowa funkcja to format=auto, która automatycznie serwuje AVIF lub WebP w zależności od przeglądarki:
<!-- Cloudflare Image Resizing — automatyczny format i rozmiar -->
<img
src="/cdn-cgi/image/width=800,quality=75,format=auto/images/hero.jpg"
alt="Hero banner"
width="800"
height="450">
<!-- Responsywny wariant z srcset -->
<img
srcset="/cdn-cgi/image/width=640,format=auto/images/hero.jpg 640w,
/cdn-cgi/image/width=1024,format=auto/images/hero.jpg 1024w,
/cdn-cgi/image/width=1920,format=auto/images/hero.jpg 1920w"
sizes="(max-width: 768px) 100vw, 1200px"
src="/cdn-cgi/image/width=1024,format=auto/images/hero.jpg"
alt="Hero banner">
Cloudflare Images jest dostępny nawet w darmowym planie z ograniczoną liczbą transformacji — to chyba najlepsza opcja budżetowa na start.
Inne rozwiązania Image CDN
Oprócz Cloudflare, popularne opcje to:
- Cloudinary — najbardziej rozbudowane funkcje (inteligentne kadrowanie, AI-based quality), ale też najdroższa opcja
- ImageKit — moim zdaniem najlepszy stosunek funkcji do ceny, łatwa integracja
- Imgix — potężne API z transformacjami przez parametry URL
- Uploadcare — przyjazne API dla deweloperów, dobre wsparcie AVIF
Wspólna cecha wszystkich tych usług: automatyczna konwersja formatu (auto format) i automatyczna optymalizacja jakości (auto quality). Przesyłasz oryginalne obrazy w wysokiej jakości, a CDN dostarcza optymalny wariant dla każdej przeglądarki i urządzenia. Proste.
Optymalizacja tłowych obrazów CSS
Obrazy ładowane przez background-image w CSS mają dodatkowy problem wydajnościowy: są niewidoczne dla skanera preload przeglądarki. Przeglądarka po prostu nie wie o ich istnieniu, dopóki nie pobierze HTML, nie sparsuje CSS i nie zbuduje drzewa renderowania. To może dodać setki milisekund opóźnienia — a często to właśnie obraz tła jest elementem LCP.
Rozwiązanie: preload z atrybutem fetchpriority
<head>
<!-- Preload krytycznego tła CSS -->
<link
rel="preload"
as="image"
href="/img/hero-bg.avif"
type="image/avif"
fetchpriority="high">
</head>
<style>
.hero {
background-image: url('/img/hero-bg.avif');
background-size: cover;
background-position: center;
}
</style>
Dzięki preload przeglądarka zaczyna pobieranie obrazu tła natychmiast po sparsowaniu sekcji <head>, bez czekania na przetworzenie CSS. Jedna linijka w <head> — a różnica potrafi być ogromna.
content-visibility: optymalizacja renderowania obrazów poza ekranem
CSS content-visibility: auto to stosunkowo nowa właściwość (Baseline od września 2024), która mówi przeglądarce: „nie renderuj tego elementu, dopóki nie jest widoczny w viewporcie". Dla sekcji z dużą liczbą obrazów — np. galerii produktów czy list artykułów — może przyspieszyć początkowe renderowanie nawet o 40%.
<style>
.product-card {
content-visibility: auto;
contain-intrinsic-size: auto 300px;
}
</style>
<div class="product-card">
<img src="product.webp" alt="Produkt" width="300" height="300" loading="lazy">
<h3>Nazwa produktu</h3>
<p>Opis produktu...</p>
</div>
Właściwość contain-intrinsic-size jest tu niezbędna — informuje przeglądarkę o przybliżonym rozmiarze elementu, zanim ten zostanie wyrenderowany. Bez niej pasek przewijania będzie się chaotycznie zmieniał, co pogorszy CLS. A tego chcemy unikać.
Uwaga: nie stosuj content-visibility: auto do elementów widocznych w początkowym viewporcie — efekt będzie podobny do lazy loadingu LCP, czyli zdecydowanie negatywny.
Pełna checklista optymalizacji obrazów na 2026
Na zakończenie — kompletna lista kontrolna, którą możesz przejść punkt po punkcie na swojej stronie. Zaznacz każdy punkt i sprawdź, ile z tego już wdrożyłeś:
- Format: Serwuj AVIF z fallbackiem na WebP i JPEG przez element
<picture> - Responsywność: Generuj 3–5 wariantów rozmiarowych z
srcsetisizes - Kompresja: AVIF 45–60, WebP 70–82, JPEG 80–85
- Obraz LCP:
fetchpriority="high"+<link rel="preload">w<head> - Lazy loading:
loading="lazy"dla wszystkich obrazów poniżej foldu - Wymiary: Zawsze podawaj
widthiheight(lubaspect-ratiow CSS) - Tła CSS: Preload krytycznych obrazów tła
- Automatyzacja: Sharp + Vite lub Image CDN z auto format/quality
- Renderowanie:
content-visibility: autodla sekcji z wieloma obrazami poza ekranem - Maksymalny rozmiar: Cel poniżej 200 KB dla obrazu hero, poniżej 100 KB dla pozostałych
FAQ — najczęściej zadawane pytania
Czy AVIF jest już bezpieczny do użycia w produkcji?
Tak, zdecydowanie. W 2026 roku AVIF jest wspierany przez Chrome, Firefox, Safari 17+ i Edge, co obejmuje ponad 93% globalnego ruchu przeglądarkowego. Używając elementu <picture> z fallbackiem na WebP i JPEG, zapewniasz kompatybilność ze 100% przeglądarek. Jedyna rzecz, na którą warto uważać, to wolniejsze kodowanie — konwertuj obrazy w procesie budowania, nie w locie.
Czy fetchpriority="high" zastępuje link rel="preload" dla obrazów?
Nie, to dwa różne mechanizmy, które najlepiej działają razem. preload mówi przeglądarce, że zasób istnieje i powinien być pobrany jak najwcześniej — pomaga z odkryciem zasobu. fetchpriority mówi, z jakim priorytetem go pobrać — pomaga z kolejnością pobierania. Połączenie obu na obrazie LCP daje najlepsze rezultaty.
Ile wariantów responsywnych obrazów powinienem generować?
Rekomendacja to 3–5 wariantów na obraz (np. 640px, 1024px, 1440px, 1920px). Zbyt wiele wariantów pogarsza wykorzystanie cache, bo każdy wariant to osobny URL do cachowania. Zbyt mało — i użytkownicy mobilni pobierają niepotrzebnie duże pliki. Klucz to znalezienie odpowiedniego balansu między dopasowaniem a cachowalnością.
Czy lazy loading wpływa negatywnie na SEO?
Nie. Natywne lazy loading z atrybutem loading="lazy" jest w pełni rozpoznawane przez Googlebot i nie wpływa negatywnie na indeksowanie obrazów. Google oficjalnie wspiera i rekomenduje lazy loading dla obrazów poniżej foldu. Problem pojawia się tylko wtedy, gdy lazy loading jest zastosowany do obrazu LCP — wtedy pogarsza metrykę Largest Contentful Paint, co pośrednio szkodzi rankingom.
Image CDN vs własny pipeline z Sharp — co wybrać?
Jeśli masz mało obrazów i pełną kontrolę nad procesem budowania — własny pipeline z Sharp i Vite jest darmowy i daje pełną kontrolę. Jeśli zarządzasz dużą liczbą obrazów, masz treści dodawane przez użytkowników (UGC) albo po prostu chcesz uniknąć konfiguracji — Image CDN będzie lepszym wyborem. Cloudflare Images w darmowym planie to dobry kompromis na start, choć z czasem pewnie i tak warto rozważyć coś bardziej rozbudowanego.