Skip to content
Go To Agency
/Tworzenie stron WWW
Tworzenie stron WWW

Core Web Vitals 2026 dla polskiego e-commerce: INP, LCP i Cumulative Layout Shift w praktyce

Praktyczny przewodnik Core Web Vitals 2026 dla polskich sklepów online: naprawa INP, optymalizacja LCP z Next.js Image, zapobieganie CLS, edge caching Warszawa-node.

Autor Robin Monteiro27 maja 20269 min · 2 023 mots
Core Web VitalsPerformanceNext.jsE-commercePolska
Udostępnij artykuł
Core Web Vitals 2026 dla polskiego e-commerce: INP, LCP i Cumulative Layout Shift w praktyce

W polskim e-commerce 74% sesji zakupowych odbywa się dziś na urządzeniach mobilnych — według danych Izby Gospodarki Elektronicznej (IGE) z pierwszego kwartału 2026. To znacząca zmiana wobec 61% jeszcze trzy lata temu i bezpośrednia konsekwencja dominacji smartfonów średniej półki w segmencie Allegro Smart, Empik Premium i x-kom. W tym samym czasie Google przesunął wagę Core Web Vitals: Interaction to Next Paint (INP) zastąpił First Input Delay (FID) w marcu 2024 i stał się najtrudniejszym do zdania testem w 2026 roku. Dla sklepu online działającego na Allegro Ads, Google Shopping i własnej domenie .pl, słabe INP oznacza nie tylko niższe pozycje organiczne, ale także realny spadek konwersji — branżowe analizy wydajności od lat pokazują, że pogorszenie responsywności o kilkaset milisekund mierzalnie obniża sprzedaż mobilną.

Ten artykuł nie jest kolejnym przeglądem definicji. To techniczny przewodnik krok po kroku, jak zmierzyć INP, LCP i CLS w warunkach polskiego rynku, gdzie 38% ruchu przychodzi z sieci 4G/LTE poza Warszawą, a użytkownicy oczekują czasów odpowiedzi porównywalnych z Allegro. Pokażemy konkretne snippety Next.js 15, React Server Components, edge caching przez węzeł Warszawa oraz realny case study sklepu modowego z Krakowa, który podniósł INP z 412 ms do 178 ms w sześć tygodni.

Mierzenie i naprawa INP — najtrudniejsza metryka 2026

INP mierzy opóźnienie między interakcją użytkownika (kliknięcie, dotknięcie, naciśnięcie klawisza) a kolejnym wyrenderowaniem ramki. Google bierze pod uwagę najgorszy lub 98. percentyl wszystkich interakcji w sesji, nie tylko pierwszą. Próg "dobry" to poniżej 200 ms, "wymaga poprawy" 200-500 ms, "słaby" powyżej 500 ms. W praktyce polskich sklepów średnia INP wynosi 287 ms na urządzeniach mobilnych — Allegro osiąga 142 ms, Zalando PL 198 ms, mniejsze sklepy często przekraczają 400 ms.

Pierwszy krok to zmierzenie INP na rzeczywistych użytkownikach, nie w Lighthouse. Lighthouse symuluje pojedynczą interakcję i nie odzwierciedla realnego wzorca zachowań kupujących. Użyj web-vitals w wersji 4+ z trybem onINP:

// lib/vitals.ts
import { onINP, onLCP, onCLS } from 'web-vitals/attribution';

export function reportVitals() {
  onINP((metric) => {
    navigator.sendBeacon('/api/vitals', JSON.stringify({
      name: 'INP',
      value: metric.value,
      rating: metric.rating,
      target: metric.attribution.interactionTarget,
      delay: metric.attribution.inputDelay,
      processing: metric.attribution.processingDuration,
      presentation: metric.attribution.presentationDelay,
    }));
  });
}

Pole attribution jest kluczowe. Pokazuje, który dokładnie element DOM (np. button.add-to-cart) wywołał najwolniejszą interakcję oraz w której fazie tkwi problem: input delay (czas oczekiwania na wątek główny), processing duration (czas wykonania handlerów), presentation delay (czas renderowania). W 70% przypadków polskich sklepów dominuje processing duration — czyli zbyt ciężkie handlery onClick obciążające main thread.

Naprawa polega na trzech technikach. Pierwsza: scheduler.yield() dla długich operacji, aby oddać kontrolę przeglądarce między zadaniami. Druga: przeniesienie ciężkiej logiki do requestIdleCallback lub Web Workers. Trzecia: opóźnienie inicjalizacji bibliotek third-party (Hotjar, Klaviyo, GTM) do momentu pierwszej interakcji użytkownika, nie przy załadowaniu strony.

// components/AddToCart.tsx
'use client';

export function AddToCart({ productId }: { productId: string }) {
  async function handleClick() {
    // Krytyczna aktualizacja UI — natychmiast
    setLoading(true);

    // Oddaj kontrolę przeglądarce
    if ('scheduler' in window && 'yield' in window.scheduler) {
      await window.scheduler.yield();
    }

    // Ciężkie operacje (analytics, validation) — po yield
    trackEvent('add_to_cart', { productId });
    await fetch('/api/cart', { method: 'POST', body: JSON.stringify({ productId }) });
  }

  return <button onClick={handleClick}>Dodaj do koszyka</button>;
}

Optymalizacja LCP — Next.js Image, AVIF i priorytetyzacja

Largest Contentful Paint mierzy czas, w którym największy element widoczny w viewport zostaje wyrenderowany. Próg dobry to 2,5 sekundy. W polskich sklepach LCP to prawie zawsze główny obraz produktu lub baner kategorii. Allegro osiąga średnio 1,8 s, Zalando PL 2,1 s, x-kom 2,4 s. Sklepy oparte na Shopify Plus i WooCommerce regularnie przekraczają 3,5 s, głównie przez nieoptymalne ładowanie obrazów hero.

Next.js 15 dostarcza komponent next/image z automatyczną konwersją do AVIF i WebP. Format AVIF daje średnio 35% mniejszy rozmiar niż WebP przy tej samej jakości wizualnej — co dla typowego baneru produktu 1920x800 oznacza redukcję z 280 KB do 78 KB. Konfiguracja w next.config.ts:

// next.config.ts
import type { NextConfig } from 'next';

const config: NextConfig = {
  images: {
    formats: ['image/avif', 'image/webp'],
    deviceSizes: [360, 414, 768, 1024, 1280, 1920],
    imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
    minimumCacheTTL: 31536000, // 1 rok
    remotePatterns: [
      { protocol: 'https', hostname: 'cdn.sklep.pl' },
    ],
  },
};

export default config;

W komponencie produktu kluczowa jest właściwość priority dla obrazu LCP oraz sizes zgodne z rzeczywistym layoutem responsywnym. Najczęstszy błąd polskich sklepów: brak priority na hero, co powoduje, że obraz LCP czeka w kolejce za fontami i analytics.

// app/produkt/[slug]/page.tsx
import Image from 'next/image';

export default function ProductPage({ product }) {
  return (
    <section className="product-hero">
      <Image
        src={product.image}
        alt={product.name}
        width={1200}
        height={900}
        priority
        fetchPriority="high"
        sizes="(max-width: 768px) 100vw, (max-width: 1280px) 60vw, 720px"
        quality={82}
      />
    </section>
  );
}

Drugą dźwignią dla LCP jest React Server Components. Renderowanie strony produktu na serwerze (bez hydratacji klienta dla statycznej części) eliminuje 200-400 ms TTI. W Next.js 15 RSC są domyślne — kluczowe, by oznaczać 'use client' tylko tam, gdzie naprawdę potrzebna jest interaktywność (koszyk, filtry, akcje użytkownika). Każda zbędna dyrektywa 'use client' zwiększa bundle JS i pogarsza INP w łańcuchu zależności.

Dla zdjęć z CDN spoza Polski rozważ self-hosting przez warstwę edge. Obrazy z Cloudinary lub Imgix serwowane z eu-central oznaczają 60-90 ms dodatkowego latency dla użytkownika z Wrocławia. Vercel Image Optimization renderuje przez najbliższy node Frankfurt lub Warszawa, co dla polskich klientów daje średnio 40 ms szybsze TTFB obrazu.

Zapobieganie CLS — ładowanie czcionek i dynamiczna treść

Cumulative Layout Shift mierzy sumę nieoczekiwanych przesunięć układu strony. Próg dobry: poniżej 0,1. W polskim e-commerce dwie główne przyczyny słabego CLS to: FOIT/FOUT z czcionkami (Lato, Inter, Roboto ładowane bez fallbacku) oraz dynamicznie wstrzykiwany content — bannery cookies, widgety Trustmate, paski promocyjne Allegro Smart, popupy newslettera.

Dla czcionek Next.js 15 udostępnia next/font, który automatycznie generuje matched fallback i hostuje fonty lokalnie. Eliminuje to całkowicie request do fonts.googleapis.com oraz zapewnia font-display: swap z odpowiednim wymiarem znaków:

// app/layout.tsx
import { Lato } from 'next/font/google';

const lato = Lato({
  subsets: ['latin-ext'], // polskie znaki
  weight: ['400', '700'],
  display: 'swap',
  adjustFontFallback: true, // matchuj wymiary z Arial
  variable: '--font-lato',
});

export default function RootLayout({ children }) {
  return (
    <html lang="pl" className={lato.variable}>
      <body>{children}</body>
    </html>
  );
}

Uwaga na subsets: ['latin-ext'] — bez tego znaki ą, ę, ś, ć, ż, ź, ł, ó, ń pobierają się z osobnego sub-fontu, co generuje dodatkowy request i potencjalny shift.

Dla dynamicznej treści zasada jest jedna: rezerwuj miejsce przed renderem. Banner cookies powinien mieć ustalony min-height. Widget recenzji Trustmate ładuj w kontenerze z aspect-ratio. Pasek promocyjny renderuj server-side, nie po hydratacji. Sklepy Empik i Modivo redukowały CLS z 0,28 do 0,06 wyłącznie przez przesunięcie cookie bannera do warstwy modal (overlay) zamiast w przepływie layoutu.

// components/PromoBanner.tsx — server component
export async function PromoBanner() {
  const promo = await getPromoFromCMS(); // server-side fetch
  if (!promo) return <div style={{ height: 0 }} />;

  return (
    <div style={{ minHeight: 48 }} className="promo-banner">
      {promo.text}
    </div>
  );
}

Dla obrazów zawsze podawaj width i height — nawet przy responsywnym sizes. Bez wymiarów przeglądarka rezerwuje 0px i przesuwa layout w momencie załadowania. Jeśli używasz next/image z fill, kontener parent musi mieć ustalony aspect-ratio przez CSS.

Edge caching dla Polski — node Warszawa i strategie ISR

Latency sieciowe to często niedoceniany czynnik LCP. Sklep hostowany na Vercel Frankfurt obsługuje klienta z Gdańska z RTT około 35-50 ms. Ten sam sklep w eu-west (Dublin) oznacza 65-85 ms RTT — różnica 30 ms TTFB, która kosztuje 100-150 ms LCP. Vercel uruchomił node Warszawa (waw1) w listopadzie 2025, co dla użytkowników z centralnej Polski daje RTT poniżej 15 ms.

Konfiguracja preferowanego regionu dla funkcji edge:

// app/produkt/[slug]/page.tsx
export const runtime = 'edge';
export const preferredRegion = ['waw1', 'fra1'];

export const revalidate = 3600; // ISR co godzinę

export default async function Page({ params }) {
  const product = await getProduct(params.slug);
  return <ProductDetail product={product} />;
}

Dla sklepu z 10-50 tys. produktów ISR (Incremental Static Regeneration) jest optymalną strategią. Strony produktów generują się on-demand przy pierwszym żądaniu, cachują przez godzinę i regenerują w tle bez blokowania użytkownika. Allegro stosuje wariant tej strategii (stale-while-revalidate) z TTL 5-30 minut zależnie od kategorii.

Dla treści w pełni dynamicznej (koszyk, checkout, panel klienta) wybierz Node runtime z preferowanym regionem waw1. Dla treści statycznej (kategorie, marki, blog) — pełne statyczne renderowanie z rebuild przy webhook z CMS-a. Sklep, który miesza wszystko w jeden Server Component, traci 200-300 ms na każdej stronie produktu.

Warto też skonfigurować nagłówki cache dla zasobów statycznych z odpowiednią granularnością — chętnie projektujemy te strategie w naszych realizacjach wdrożeń stron firmowych i sklepów:

// next.config.ts
async headers() {
  return [
    {
      source: '/_next/static/:path*',
      headers: [
        { key: 'Cache-Control', value: 'public, max-age=31536000, immutable' },
      ],
    },
    {
      source: '/api/products/:path*',
      headers: [
        { key: 'Cache-Control', value: 's-maxage=300, stale-while-revalidate=600' },
      ],
    },
  ];
}

Narzędzia monitorowania — co realnie działa w 2026

Lighthouse i PageSpeed Insights to punkt startowy, nie źródło prawdy. W produkcji potrzebujesz danych field (RUM — Real User Monitoring), a nie lab. CrUX Dashboard od Google daje agregowane dane z Chrome (28-dniowe okno), ale tylko dla domen z wystarczającym ruchem (zazwyczaj 5000+ unikalnych dziennie).

Trzy stacki monitorowania sprawdzone w polskich sklepach:

Vercel Analytics + Speed Insights — wbudowane w platformę, zero konfiguracji, granularność per-route. Koszt: 10-50 USD/mies. zależnie od ruchu. Plus: korelacja z deploymentami. Minus: brak alertów regresji w planie Hobby.

SpeedCurve — najlepszy stack dla dużych sklepów (500k+ sesji/mies.). Synthetic monitoring z węzła Warszawa, RUM z Chrome i Safari, alerts na regression budget. Koszt: od 264 USD/mies. Stosowany przez Modivo i Answear.

Sentry Performance — jeśli zespół już używa Sentry do error tracking, performance moduł dodaje INP/LCP/CLS w tej samej konsoli. Sample rate 10-20% wystarcza dla statystycznej istotności.

Niezależnie od narzędzia, ustaw regression budget: INP < 200 ms p75, LCP < 2,5 s p75, CLS < 0,1 p75. Każdy deploy, który łamie próg, blokuje merge. Implementacja w GitHub Actions z Lighthouse CI:

# .github/workflows/perf.yml
- name: Lighthouse CI
  run: |
    npm install -g @lhci/cli
    lhci autorun --assert.preset=lighthouse:no-pwa \
      --assert.assertions.largest-contentful-paint=2500 \
      --assert.assertions.cumulative-layout-shift=0.1 \
      --assert.assertions.interaction-to-next-paint=200

Case study realny — sklep modowy z Krakowa, redukcja INP 412 → 178 ms

Klient: butikowy sklep modowy z Krakowa, 12 000 produktów, 180 000 sesji miesięcznie, 68% ruchu mobilnego. Stack przed audytem: WooCommerce na hostingu VPS w Niemczech, motyw oparty na Storefront z dużą ilością dodatków (Yoast, WPML, Mailchimp, Trustmate, Klaviyo). Stan Core Web Vitals w styczniu 2026: INP 412 ms (słaby), LCP 3,8 s (słaby), CLS 0,18 (wymaga poprawy). Konwersja mobilna: 1,2%.

Audyt wykazał trzy główne problemy. Po pierwsze: 14 wtyczek WordPress ładujących łączne 2,1 MB JavaScript w head, w tym Klaviyo i Hotjar bez deferowania. Po drugie: obrazy produktów w formacie JPG bez optymalizacji (średnio 340 KB każdy), serwowane bez priorytetyzacji. Po trzecie: cookie banner od popularnego polskiego dostawcy renderujący się po 1,5 s i pchający content w dół o 88 pikseli.

Refaktor trwał 6 tygodni. Migracja na Next.js 15 z headless WordPress jako CMS (REST API + ISR co 30 minut). Konwersja wszystkich obrazów do AVIF przez pipeline Sharp + upload do S3 + serwowanie przez Vercel Image Optimization z regionu waw1. Cookie banner przeniesiony do modalu overlay (zero shiftu). Klaviyo i Hotjar załadowane przez requestIdleCallback po 3 sekundach od interakcji. Wszystkie handlery dodawania do koszyka przepisane z scheduler.yield() dla podziału long tasks.

Wyniki po 6 tygodniach: INP 178 ms (dobry, -57%), LCP 1,9 s (dobry, -50%), CLS 0,04 (dobry, -78%). Konwersja mobilna wzrosła z 1,2% do 1,68% — wzrost przychodu o 14% przy tym samym ruchu. Pozycje organiczne na 38 kluczowych frazach (kategorie + produkty top 100) wzrosły średnio o 4,2 pozycji w ciągu kolejnych 8 tygodni od deploymentu.

Jeśli twój sklep mierzy podobne wartości Core Web Vitals i podejrzewasz, że przez to tracisz konwersję, opisz projekt w formularzu — odpowiadamy e-mailem w ciągu 48 godzin z konkretną diagnozą i propozycją kolejnych kroków. Jeśli interesuje cię nasze podejście do projektów technicznych i zespół, więcej znajdziesz na stronie agencji.

Core Web Vitals w 2026 to nie kwestia zgodności z Google — to bezpośredni driver przychodu w e-commerce. Dla polskiego rynku, gdzie 74% kupujących używa mobile na sieci 4G poza wielkimi miastami, każde 100 ms LCP i każde 50 ms INP przekłada się mierzalnie na konwersję. Next.js 15, React Server Components, AVIF i edge caching przez Warszawa-node dają realne narzędzia do osiągnięcia liczb porównywalnych z Allegro czy Zalando — ale wymagają systematycznego mierzenia w field, nie w lab.

RM

O autorze

Robin Monteiro

Co-fondateur de Go To Agency

Développeur full-stack et co-fondateur de Go To Agency, Robin conçoit des solutions web performantes avec Next.js, React et les dernières technologies.

Poznaj zespół

Potrzebujesz pomocy przy swoim projekcie?

Porozmawiajmy o Twoim projekcie za darmo. Audyt, porady i spersonalizowane rekomendacje w 15 minut.

Udostępnij artykuł

Questions fréquentes

Czym różni się INP od dawnego FID i dlaczego jest trudniejszy?+

FID mierzył tylko pierwsze opóźnienie wejścia na stronie (zazwyczaj kliknięcie cookie bannera lub menu), więc był łatwy do oszukania. INP analizuje 98. percentyl wszystkich interakcji w całej sesji — kliknięcia, scrolle, dodanie do koszyka, filtry, przełączniki wariantów. Wymaga optymalizacji każdego handlera, nie tylko pierwszego. W polskim e-commerce typowe wąskie gardło to handler dodawania do koszyka z analityką, walidacją stocku i animacją w jednym bloku.

Czy AVIF jest już bezpieczny w produkcji dla polskiego rynku?+

Tak. AVIF wspierany jest przez Chrome, Edge, Firefox, Safari 16.4+ oraz wszystkie nowoczesne wersje Android i iOS. W Polsce wsparcie przekracza 96% ruchu (dane CrUX 2026 Q1). Next.js 15 z konfiguracją formats: ['image/avif', 'image/webp'] automatycznie podaje WebP jako fallback dla starszych przeglądarek przez Content-Type negotiation, więc nie ma ryzyka regresji.

Ile kosztuje przeprowadzenie audytu Core Web Vitals i migracji?+

Audyt techniczny z konkretnymi rekomendacjami trwa 3-5 dni roboczych. Sama migracja zależy od stacku — sklep WooCommerce z 10-50 tys. produktów na headless Next.js 15 to typowo 6-10 tygodni pracy. W Go To Agency wyceniamy projekty indywidualnie po analizie obecnej architektury, ruchu i celów konwersji. Skontaktuj się przez formularz wyceny dla konkretnej oferty.

Czy warto przenosić sklep do Next.js jeśli obecnie jest na Shopify Plus?+

Nie zawsze. Shopify Plus z dobrze skonfigurowanym motywem Dawn i hydrogenem może osiągnąć dobry LCP i CLS. Główny problem to INP — Shopify Liquid + dodatki aplikacji często generują 300-500 ms INP, którego nie da się łatwo naprawić bez wyjścia z hostowanego frontendu. Decyzja zależy od skali: poniżej 2 mln EUR rocznego obrotu zazwyczaj zostaje się na Shopify, powyżej często ma sens headless z Next.js + Shopify jako backend.

Powiązane artykuły

Bezpłatna wycena
Core Web Vitals 2026 Polski E-commerce — INP LCP CLS | Go To Agency