Core Web Vitals: Come Ottimizzare le Performance del Tuo Sito

THEJORD Team8 min di lettura
performanceseoweb-development

Guida completa ai Core Web Vitals: LCP, INP, CLS spiegati con tecniche pratiche. Migliora performance, ranking SEO e user experience del tuo sito web.

Core Web Vitals: Come Ottimizzare le Performance del Tuo Sito

Cosa Sono i Core Web Vitals

I Core Web Vitals sono metriche di Google che misurano l'esperienza utente di un sito web. Dal 2021 influenzano direttamente il ranking SEO, rendendo l'ottimizzazione delle performance non solo una best practice ma una necessità competitiva. Nel 2024, Google ha aggiornato le metriche sostituendo FID con INP, rendendo la valutazione ancora più accurata.

Le Tre Metriche Principali

LCP (Largest Contentful Paint)

LCP misura quanto tempo ci vuole per caricare l'elemento più grande visibile nella viewport iniziale. Questo potrebbe essere un'immagine hero, un blocco di testo o un video. È la metrica più importante per la percezione di velocità da parte dell'utente.

ValutazioneTempoImpatto SEO
Buono≤ 2.5 secondiPositivo
Da migliorare2.5 - 4 secondiNeutro/Negativo
Scarso> 4 secondiNegativo

Ottimizzare LCP

<!-- 1. Preload risorse critiche -->
<link rel="preload" as="image" href="hero.webp" fetchpriority="high">
<link rel="preload" as="font" href="font.woff2" crossorigin>

<!-- 2. Immagini ottimizzate -->
<img
  src="hero.webp"
  srcset="hero-400.webp 400w, hero-800.webp 800w, hero-1200.webp 1200w"
  sizes="100vw"
  width="1200"
  height="600"
  alt="Hero image"
  fetchpriority="high"
  decoding="async"
>

<!-- 3. Lazy loading solo sotto la fold -->
<img src="below-fold.webp" loading="lazy" alt="...">

<!-- 4. Font optimization -->
<link rel="preconnect" href="https://fonts.googleapis.com">
<style>
@font-face {
  font-family: 'CustomFont';
  font-display: swap;
  src: url('font.woff2') format('woff2');
}
</style>

INP (Interaction to Next Paint)

INP ha sostituito FID (First Input Delay) nel 2024. Mentre FID misurava solo la prima interazione, INP valuta la latenza di TUTTE le interazioni durante l'intera sessione utente, fornendo un quadro più completo della reattività.

ValutazioneTempoSignificato
Buono≤ 200 msInterazioni fluide
Da migliorare200 - 500 msRitardi percepibili
Scarso> 500 msEsperienza frustrante

Ottimizzare INP

// 1. Spezza task lunghi con yield
function processLargeArray(items) {
  const chunk = items.splice(0, 100);
  processChunk(chunk);

  if (items.length > 0) {
    // Cede il controllo al browser tra i chunk
    setTimeout(() => processLargeArray(items), 0);
  }
}

// 2. Usa scheduler.yield() (modern browsers)
async function processWithYield(items) {
  for (const item of items) {
    process(item);
    if (scheduler.yield) {
      await scheduler.yield();
    }
  }
}

// 3. requestIdleCallback per task non urgenti
requestIdleCallback(() => {
  analytics.track('page_view');
  prefetchResources();
});

// 4. Web Workers per calcoli pesanti
const worker = new Worker('heavy-calculation.js');
worker.postMessage(data);
worker.onmessage = (e) => updateUI(e.data);

// 5. Debounce input handlers
const debouncedSearch = debounce((query) => {
  searchAPI(query);
}, 300);

CLS (Cumulative Layout Shift)

CLS misura la stabilità visiva della pagina. Quantifica quanto gli elementi si spostano inaspettatamente durante il caricamento. Layout shift sono frustranti: l'utente clicca su un pulsante e un banner appare, spostando il pulsante e causando un click sbagliato.

ValutazionePunteggioImpatto
Buono≤ 0.1Layout stabile
Da migliorare0.1 - 0.25Shift occasionali
Scarso> 0.25Esperienza instabile

Ottimizzare CLS

<!-- 1. Dimensioni esplicite per immagini -->
<img src="photo.jpg" width="800" height="600" alt="...">

<!-- 2. aspect-ratio CSS -->
<style>
.video-container {
  aspect-ratio: 16/9;
  width: 100%;
}

.image-placeholder {
  aspect-ratio: 4/3;
  background: #f0f0f0;
}

/* Spazio riservato per ads */
.ad-slot {
  min-height: 250px;
  background: #eee;
}

/* Skeleton loading */
.skeleton {
  background: linear-gradient(90deg, #f0f0f0 25%, #e0e0e0 50%, #f0f0f0 75%);
  background-size: 200% 100%;
  animation: loading 1.5s infinite;
}
</style>

<!-- 3. Font display swap per evitare FOIT -->
<style>
@font-face {
  font-family: 'CustomFont';
  font-display: swap;
  src: url('font.woff2') format('woff2');
}

/* Fallback font con metriche simili */
body {
  font-family: 'CustomFont', Arial, sans-serif;
}
</style>

<!-- 4. Riserva spazio per contenuti dinamici -->
<div class="dynamic-content" style="min-height: 200px;">
  <!-- Caricato dinamicamente -->
</div>

Strumenti di Misurazione

Dati di Campo vs Dati di Lab

  • Field Data (RUM): Dati reali da utenti reali, riflettono l'esperienza effettiva
  • Lab Data: Test simulati in condizioni controllate, utili per debugging

PageSpeed Insights

# Analizza qualsiasi URL
https://pagespeed.web.dev/

# Fornisce:
- Punteggio performance (0-100)
- Core Web Vitals reali (dati campo - CrUX)
- Dati lab simulati
- Suggerimenti specifici con priorità
- Comparazione mobile vs desktop

Chrome DevTools

# Lighthouse integrato
1. Apri DevTools (F12)
2. Tab "Lighthouse"
3. Seleziona "Performance"
4. Genera report
5. Analizza suggerimenti

# Performance tab per analisi dettagliata
1. Tab "Performance"
2. Click su Record
3. Interagisci con la pagina
4. Stop e analizza il timeline

# Web Vitals overlay
1. DevTools → More tools → Rendering
2. Abilita "Core Web Vitals"
3. Visualizza metriche in tempo reale

Web Vitals Extension

# Estensione Chrome ufficiale
- Mostra LCP, INP, CLS in tempo reale
- Identifica elementi problematici
- Segnala quando i valori superano le soglie
- Debug mode per dettagli avanzati

Ottimizzazioni Pratiche

Ottimizzazione Immagini

# Formati moderni
WebP: 25-35% più piccolo di JPEG
AVIF: 50% più piccolo di JPEG (supporto 90%+)

# Picture element per formati multipli
<picture>
  <source type="image/avif" srcset="image.avif">
  <source type="image/webp" srcset="image.webp">
  <img src="image.jpg" alt="Fallback">
</picture>

# Next.js Image (ottimizzazione automatica)
import Image from 'next/image';

<Image
  src="/hero.jpg"
  width={1200}
  height={600}
  priority        // Per immagini above-the-fold
  quality={80}    // Qualità compressione
  placeholder="blur"
  blurDataURL={blurUrl}
/>

Critical CSS

<!-- Inline CSS critico nell'head -->
<style>
  /* Solo stili above the fold */
  .hero { display: flex; }
  .nav { position: fixed; }
  .header { background: #fff; }
</style>

<!-- CSS non critico caricato in modo asincrono -->
<link rel="preload" href="styles.css" as="style"
      onload="this.onload=null;this.rel='stylesheet'">
<noscript>
  <link rel="stylesheet" href="styles.css">
</noscript>

JavaScript Optimization

// Code splitting con import dinamico
const HeavyComponent = lazy(() => import('./HeavyComponent'));

// Suspense per loading state
<Suspense fallback={<Skeleton />}>
  <HeavyComponent />
</Suspense>

// Script loading
<script src="analytics.js" defer></script> // Dopo HTML parsing
<script src="widget.js" async></script>    // Appena disponibile

// Preconnect per third-party
<link rel="preconnect" href="https://cdn.example.com">
<link rel="dns-prefetch" href="https://api.example.com">

Framework Integration

Next.js

// next.config.js
module.exports = {
  images: {
    formats: ['image/avif', 'image/webp'],
    minimumCacheTTL: 60,
    deviceSizes: [640, 750, 1080, 1200, 1920, 2048],
  },
  experimental: {
    optimizeCss: true,
    optimizePackageImports: ['lodash', 'date-fns'],
  }
};

React Performance

// Lazy loading componenti
const Chart = lazy(() => import('./Chart'));

// Memoization
const MemoizedComponent = memo(ExpensiveComponent);

// useMemo per calcoli pesanti
const result = useMemo(() => heavyCalculation(data), [data]);

// useCallback per handler stabili
const handleClick = useCallback(() => {
  doSomething();
}, [dependency]);

Monitoraggio Continuo

Real User Monitoring (RUM)

// web-vitals library
import { onLCP, onINP, onCLS } from 'web-vitals';

function sendToAnalytics(metric) {
  // Invia a analytics backend
  fetch('/api/vitals', {
    method: 'POST',
    body: JSON.stringify({
      name: metric.name,
      value: metric.value,
      id: metric.id,
      page: window.location.pathname
    })
  });
}

onLCP(sendToAnalytics);
onINP(sendToAnalytics);
onCLS(sendToAnalytics);

Google Search Console

Il report "Esperienza con le pagine" mostra Core Web Vitals aggregati per tutte le pagine del sito, con trend temporali e URL problematici.

Strumenti Correlati

Per ottimizzare le performance:

Conclusione

I Core Web Vitals sono critici per SEO e UX. Priorità d'azione:

  • LCP: Ottimizza immagini, preload risorse critiche, usa CDN
  • INP: Minimizza JavaScript, spezza task lunghi, usa Web Workers
  • CLS: Riserva spazio per elementi dinamici, usa aspect-ratio

Misura regolarmente con dati reali e monitora i trend nel tempo.

Per altri strumenti utili, esplora i nostri tool online gratuiti. Per approfondimenti, consulta web.dev Core Web Vitals.