Optimizare viteză magazin online — Core Web Vitals explicați
Un magazin online lent pierde 40% din vizitatori la 3 secunde și 7% conversie pentru fiecare secundă în plus. Core Web Vitals sunt metricile cu care Google măsoară experiența reală a utilizatorului. Le explicăm pe fiecare, cu cauze concrete și fixuri aplicabile azi.
Ce sunt Core Web Vitals
Core Web Vitals sunt trei metrici standardizate de Google care măsoară experiența reală a utilizatorului (NU estimări de laborator). Datele provin din browserul real al vizitatorilor — Chrome Raportează (CrUX). Din iunie 2021 sunt factor de ranking confirmat: site-urile verzi primesc un avantaj în SERP, cele roșii sunt penalizate.
Cele trei metrici acoperă trei dimensiuni distincte: încărcare (LCP), interactivitate (INP) și stabilitate vizuală (CLS). Toate trebuie verzi pentru a trece pragul Google.
LCP — Largest Contentful Paint (încărcare)
Definiție: timpul până când cel mai mare element vizual din viewport se randează complet. Într-un magazin online, elementul dominant este de obicei imaginea hero, slider-ul principal sau titlul paginii.
Tinte Google: sub 2,5 secunde (verde). 2,5s-4s (portocaliu). peste 4s (roșu).
Cauze comune de LCP slab
- Imagine hero neoptimizată: 3-5 MB JPEG/PNG, fără format modern (WebP/AVIF), fără dimensiuni responsive.
- Resurse render-blocking: CSS extern ne-critic, fonturi Google sincrone, JS în head fără
defer. - TTFB ridicat: serverul răspunde în peste 600ms. Vezi și optimizarea bazei de date.
- Layout-uri client-rendered: conținutul principal apare doar după execuție JS (SPA fără SSR/SSG).
Fixuri LCP
- Preload imaginea LCP:
<link rel="preload" as="image" href="/hero.webp" fetchpriority="high"> - Formate moderne: WebP (cu fallback JPEG) sau AVIF. Reducere 30-70% față de JPEG.
- Responsive:
srcset+sizespentru a servi imaginea potrivită pe fiecare device. - Critical CSS inline: CSS-ul necesar above-the-fold direct în
<style>, restul încărcat asincron. - CDN pentru imagini: Cloudflare Images, Cloudinary, imgix — redimensionare + conversie la cerere.
INP — Interaction to Next Paint (interactivitate)
Definiție: latența medie a tuturor interacțiunilor utilizatorului (click, tap, tastatură) cu pagina, pe parcursul vizitei. A înlocuit FID în martie 2024 și este mult mai strict.
Tinte Google: sub 200ms (verde). 200ms-500ms (portocaliu). peste 500ms (roșu).
Cauze comune de INP slab
- Task-uri JS lungi: bucle care blochează thread-ul principal peste 50ms (parsare JSON mare, render listă de sute de produse).
- Third-party scripts: chat-uri, popups, pixels marketing care ascultă click-uri pe document.
- Re-render-uri grele: React/Vue care re-randează tot arborele la fiecare modificare de stare.
- Event handleri pe body/window: ascultă fiecare mișcare de mouse și execută logică scumpă.
Fixuri INP
- Yield la main thread: sparge task-uri lungi cu
setTimeout,requestIdleCallback, sauscheduler.yield(). - Partytown: mută third-party scripts (GA, Meta Pixel) într-un Web Worker — nu mai blochează main thread-ul.
- Debounce/throttle: pe handleri de scroll, resize, input.
- Virtualizare liste: randează doar elementele vizibile (react-window, vue-virtual-scroller) pentru liste peste 100 itemi.
- Memoizare:
useMemo,React.memo, computed properties pentru a evita re-render-uri inutile.
CLS — Cumulative Layout Shift (stabilitate vizuală)
Definiție: suma tuturor deplasărilor vizuale neașteptate pe parcursul vizitei. CLS mare = conținutul „sare” sub deget, vizitatorul lovește butonul greșit, frustrare.
Tinte Google: sub 0,1 (verde). 0,1-0,25 (portocaliu). peste 0,25 (roșu).
Cauze comune de CLS slab
- Imagini/fără dimensiuni: fără
width+height, browser-ul nu rezervă spațiu, conținutul sare după încărcare. - Fonturi care apar târziu: fără
font-display: swap, textul se redenmensează când fontul se încarcă. - Bannere/cookies care apar după 2s: popup-uri, bannere, newsletter modals care împing conținutul.
- Anunțuri și embed-uri fără rezervare spațiu: iframe-uri YouTube, widget-uri recenzii.
Fixuri CLS
- Dimensiuni mereu pe img:
<img width="800" height="600">— browser-ul rezervă aspect ratio. - Min-height pe containere: pentru bannere, sliders, player-uri video:
aspect-ratio: 16/9. - Preconnect la fonturi:
<link rel="preconnect" href="https://fonts.gstatic.com">+font-display: swap. - Reservă spațiu pentru ads: container cu dimensiune fixă, ad-ul încarcă în interior.
- Popup-uri fixed/overlay: nu împing conținutul, plutesc deasupra.
Imagini — cea mai mare oportunitate
În 80% din magazinele pe care le audităm, imaginile reprezintă 60-80% din greutatea paginii. Optimizarea lor singură poate scoate LCP-ul de la 4s la 2s.
- Format: AVIF > WebP > JPEG/PNG.
<picture>cu fallback:<source srcset="img.avif" type="image/avif">+<source srcset="img.webp" type="image/webp">+<img src="img.jpg">. - Compresie: 80-85% calitate pentru fotografii, 90% pentru produse. Sub 80% artefacte vizibile.
- Lazy load:
loading="lazy"pe toate imaginile sub fold. NICIODATĂ pe imaginea LCP — foloseștefetchpriority="high". - Responsive: generează 3-5 dimensiuni per imagine (400w, 800w, 1200w, 1920w), servește prin
srcset. - Host pe CDN: Cloudflare Images, Cloudinary. Redimensionare la cerere prin URL.
JavaScript blocking — taie din bundle
Bundle-uri JS peste 200KB gzipped sunt o problemă. Fiecare KB executat pe main thread întârzie INP și LCP.
- Tree-shaking: importă doar ce folosești.
import { debounce } from 'lodash'nuimport _ from 'lodash'. - Code-splitting: route-level chunks cu React.lazy / Vue async components. Dashboard-ul nu se încarcă pe homepage.
- Defer toate scripturile:
<script defer>pe tot ce nu e critic. Nu pune JS în head fărădefer. - Audit apps Shopify: multe teme au 10-20 apps care încarcă JS propriu. Dezinstalează-le pe cele nefolosite.
- Partytown pentru analytics: GA4, Meta Pixel, Hotjar — toate în Web Worker, nu pe main thread.
Fonturi — unii sutimi de secundă
- Max 2 familii: una pentru titluri, una pentru text. Fiecare familie = încă 1 request + delay.
- font-display: swap: arată textul imediat cu font fallback, apoi swap la fontul real. Elimină FOIT (flash of invisible text).
- Preload:
<link rel="preload" as="font" type="font/woff2" crossorigin>pentru fontul principal. - Subset: încarcă doar caracterele folosite pe site (latin-ext pentru RO/EN). Reduce woff2 de la 100KB la 20KB.
Tool-uri de măsură
- PageSpeed Insights (pagespeed.web.dev): raport combinat Lab (Lighthouse) + Field (CrUX). Free, esențial.
- Lighthouse (Chrome DevTools): audit local pe orice pagină. Modul mobile/desktop separat.
- WebPageTest (webpagetest.org): waterfall detaliat din multiple locații. Pentru audit aprofundat.
- Google Search Console — Core Web Vitals: raport agregat pe toți vizitatorii reali. Arată câte URL-uri sunt verzi/portocalii/roșii.
- Chrome UX Report (CrUX): date publice pe origin (dacă site-ul are trafic suficient).
Caz concret — before/after
Magazin WooCommerce, 15.000 vizitatori/lună, conversie 1,2%. Plângere: „se încarcă greu pe mobil”.
Diagnostic inițial (PageSpeed mobile):
- LCP: 6,8s (roșu) — imagine hero 4,2MB JPEG, fără preload
- INP: 480ms (portocaliu) — 14 apps Shopify-style, 1,2MB JS
- CLS: 0,32 (roșu) — imagini fără dimensiuni, fonturi fără swap
Intervenții (3 săptămâni):
- Conversie imagini la WebP + responsive (hero de la 4,2MB la 180KB)
- Redis object cache + indexi pe tabelele WooCommerce
- Lazy load + dimensiuni pe toate imaginile,
fetchpriority="high"pe hero - Defer JS, Partytown pentru GA, eliminat 6 apps redundante
- Cloudflare CDN + image resize la cerere
Rezultat (după 30 zile):
- LCP: 2,1s (verde) — îmbunătățire 69%
- INP: 160ms (verde) — îmbunătățire 67%
- CLS: 0,04 (verde) — îmbunătățire 87%
- Conversie: 1,9% (+58%). Trafic organic: +14% în 60 zile.