I Core Web Vitals non sono una formalità SEO: Google li usa come segnale di ranking dal 2021 e, soprattutto, un sito lento perde conversioni reali. In questo articolo mostro come porto i siti WordPress che gestisco a TTFB sotto 40ms, LCP sotto 2 secondi e CLS a zero — senza dipendere da plugin pesanti.
Cosa sono davvero i Core Web Vitals
Google misura tre metriche principali:
- LCP (Largest Contentful Paint) — quanto tempo passa prima che l'elemento più grande della pagina sia visibile. Soglia: <2.5s.
- INP (Interaction to Next Paint) — reattività agli input dell'utente. Soglia: <200ms.
- CLS (Cumulative Layout Shift) — quanto si sposta il contenuto durante il caricamento. Soglia: <0.1.
A questi si aggiunge il TTFB (Time to First Byte), che non è un CWV ufficiale ma è il fondamento di tutto: se il server impiega 800ms a rispondere, LCP non può mai essere sotto 2.5s.
Step 1: il server — Nginx + PHP-FPM + OPcache
La maggior parte dei WordPress lenti gira su hosting condiviso con Apache e configurazioni di default. Il primo intervento è il più impattante: passare a Nginx con PHP-FPM.
PHP-FPM pool dedicato
PHP-FPM gestisce i worker PHP separatamente da Nginx. Configurarlo correttamente (pm = dynamic, pm.max_children calibrato sulla RAM disponibile) evita i colli di bottiglia che Apache+mod_php crea con traffico concorrente.
OPcache
OPcache mantiene il bytecode PHP compilato in memoria. Senza di esso, ogni richiesta ricompila tutti i file PHP di WordPress. Con questa configurazione base il TTFB scende già del 40-60%:
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.revalidate_freq=60
opcache.save_comments=1
FastCGI cache Nginx
Il vero game changer è la cache full-page di Nginx: le pagine vengono servite direttamente da disco, senza toccare PHP o MySQL. Per un sito con contenuti che cambiano raramente (blog, vetrina, portfolio), il TTFB medio scende a 15-30ms.
fastcgi_cache_path /tmp/nginx_cache levels=1:2
keys_zone=wordpress:100m inactive=60m;
fastcgi_cache_key "$scheme$request_method$host$request_uri";
Attenzione: la cache va invalidata sui post aggiornati. Un plugin leggero come Nginx Helper gestisce questo automaticamente tramite purge.
Step 2: Cloudflare
Cloudflare non è solo un CDN: è una cache globale che serve i tuoi asset dall'edge node più vicino all'utente. Con un piano gratuito ottieni:
- Cache statica su 300+ datacenter
- Minify automatico di JS, CSS, HTML
- HTTP/3 (QUIC) abilitato con un click
- Protezione DDoS base
La configurazione più importante è impostare Cache Rules personalizzate
per evitare che Cloudflare faccia bypass del cache sulle pagine WordPress
(di default bypassa se trova cookie wordpress_*).
Regola pratica: bypassa il cache solo per utenti loggati e pagine carrello/checkout. Tutto il resto va in cache Cloudflare con TTL 1 giorno.
Step 3: immagini — WebP e dimensioni esplicite
Le immagini sono la causa principale di LCP alto e CLS non zero. Due fix obbligatori:
Conversione WebP
WebP pesa mediamente il 30-50% in meno di JPEG a parità di qualità visiva.
Su Nginx si può servire WebP automaticamente con un blocco map
che controlla l'header Accept del browser, senza plugin.
Attributi width e height espliciti
Il CLS alto è quasi sempre causato da immagini senza dimensioni esplicite.
Il browser non sa quanto spazio riservare prima che l'immagine carichi,
quindi il layout salta. Soluzione: ogni <img> deve avere
width e height nel markup.
<img src="hero.webp" width="1200" height="630"
alt="..." loading="lazy">
Per l'immagine LCP (la prima grande dell'above the fold), usa
loading="eager" e aggiungi un <link rel="preload">
nell'head — questo da solo può abbassare l'LCP di 0.5-1 secondo.
Step 4: Google Fonts senza render-blocking
Google Fonts con il metodo standard blocca il rendering della pagina. La soluzione è caricare il foglio di stile in modo asincrono:
<link rel="preconnect" href="https://fonts.googleapis.com">
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
<link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;600;700
&display=swap" rel="stylesheet">
Il parametro display=swap fa sì che il testo venga mostrato
subito con il font di sistema, e sostituito con Inter appena disponibile.
Zero blocco del rendering.
Risultati misurabili
Applicando questi interventi su un WordPress medio (blog aziendale, ~20 plugin):
- TTFB: da 800ms → 35ms con FastCGI cache attiva
- LCP: da 4.2s → 1.8s
- CLS: da 0.18 → 0
- PageSpeed mobile: da 42 → 94
Questi non sono numeri di laboratorio: sono i dati CrUX (reali, da utenti Chrome) sui siti che gestisco. La differenza si vede nelle conversioni, non solo nel punteggio.
Vuoi questi risultati sul tuo sito?
Analisi gratuita del tuo WordPress: ti dico esattamente dove perdete velocità e cosa fare. Rispondo entro 24 ore.
Scrivi a info@edstudio.dev