Use efficient cache lifetimes in Lighthouse: come risolverlo
Lighthouse 13 elenca ogni file che i browser dei visitatori possono riutilizzare per meno di 30 giorni. Cosa costa alla pagina successiva e alla visita di ritorno, e il fix per server e piattaforma.
"Use efficient cache lifetimes" abbassa il punteggio Lighthouse?
Lighthouse segnala ogni file statico con una durata della cache inferiore a 30 giorni nell'insight Use efficient cache lifetimes ("Una durata prolungata della cache può velocizzare le visite successive alla pagina"), chiamato "Serve static assets with an efficient cache policy" prima di Lighthouse 13 e "Leverage browser caching" nelle versioni precedenti di PageSpeed Insights. Non incide sul punteggio e non può cambiarlo: Lighthouse carica sempre a cache vuota. Imposta durate più lunghe sul server, sulla CDN o nel plugin di caching.
Table of Contents!
Cosa significa Use efficient cache lifetimes in Lighthouse?
La descrizione di Lighthouse dice: "Una durata prolungata della cache può velocizzare le visite successive alla pagina. Scopri di più sulla memorizzazione nella cache."
Lighthouse elenca ogni script, foglio di stile, font, immagine, video e file audio con una durata della cache inferiore a 30 giorni, o senza alcuna durata. La durata corrisponde al max-age nell'header Cache-Control del file, oppure al tempo rimanente fino alla data di Expires. I file provenienti da altri domini vengono elencati esattamente come quelli del sito.
Lighthouse ignora i file il cui Cache-Control specifica no-cache, no-store, private o must-revalidate, indipendentemente dal valore di max-age: li considera una scelta deliberata di non usare la cache. Esclude anche i file con max-age=0 e non elenca mai la pagina HTML stessa.

Una pagina che carica Google Tag Manager, GA4 e il Meta Pixel. Google invia i propri tag come private, quindi dei tre viene elencato solo il Meta Pixel. Lighthouse 13.5.0, throttling simulato come in PageSpeed Insights.
Come funziona la cache del browser?
Il browser memorizza il file insieme alla sua durata. Alla pagina successiva o alla visita successiva, controlla prima la copia salvata:
- Entro la durata: il browser usa la propria copia e non invia alcuna richiesta. È l'unico caso in cui non si attende il server.
- A durata scaduta: il browser chiede al server se il file è cambiato, usando l'ETag o la data Last-Modified ricevuti con il file. Se non è cambiato, il server risponde 304 Not Modified, senza inviare il file. Il download viene risparmiato, ma ogni file costa comunque un round trip verso il server, e la pagina non può eseguire il paint finché il server non ha risposto per ogni foglio di stile.
- A durata scaduta e senza ETag o Last-Modified: il browser scarica nuovamente il file.
| Header del file | Visualizzazione successiva in Chrome |
|---|---|
max-age=31536000 | Dalla cache per un anno |
max-age=14400 | Dalla cache per 4 ore, poi un 304 |
no-cache | Un 304 ogni volta |
no-store | Scaricato ogni volta |
Un normale ricaricamento in Chrome non ricontrolla i file che rientrano ancora nella durata di validità. Firefox e Safari invece sì, a meno che il file non abbia immutable nel Cache-Control.
Da Chrome 86 ogni sito ha la propria cache. Un font o un file jQuery già scaricato da un visitatore su un altro sito viene scaricato di nuovo sul tuo, anche dallo stesso URL. La durata impostata da una terza parte aiuta quindi solo all'interno del tuo sito, per la pagina successiva e per la visita di ritorno; "è già nella cache di tutti" non è più un motivo valido per caricare i font da Google (ospitali in locale).
La cache del browser e quella della CDN sono due cose diverse, così come la page cache di un plugin di caching per WordPress. Una CDN o una page cache conserva una copia in modo che il server non debba inviarla o generarla per ogni visitatore, riducendo il TTFB (durata della cache). La cache del browser risparmia l'intera richiesta, per un singolo visitatore. Questo insight riguarda solo la cache del browser, quindi una page cache già attiva non risolve la segnalazione.
Una durata della cache più lunga migliora LCP e FCP?
FCP e LCP alla prima visita
Nessuna variazione. Su una pagina prodotto WooCommerce, su smartphone con connessione Slow 4G, il primo paint è avvenuto a 2,13 s e l'LCP è arrivato a 2,26 s con qualunque header, da nessuno fino a un anno: alla prima visita nella cache non c'è ancora nulla. Lighthouse e PageSpeed Insights caricano le pagine sempre così. Risolvere questo insight non modifica mai il punteggio né le metriche di Lighthouse, anche quando compare in rosso con accanto stime di risparmio per FCP e LCP.

Nessuna durata

4 ore di Cloudflare

Un anno

no-store
La stessa pagina prodotto con quattro header di cache diversi sui file. Lighthouse 13.5.0, mobile, throttling simulato.
FCP e LCP alla pagina successiva e nella visita di ritorno
Il primo paint (FCP) in secondi, a fronte di 2,13 s alla prima visita:
| Header di cache | Pagina successiva | Una settimana dopo |
|---|---|---|
| un anno | 0,79 | 0,78 |
| 4 ore | 0,80 | 1,94 |
no-cache | 1,93 | 1,94 |
no-store | 2,11 | 2,12 |
- Il vantaggio arriva dai file ancora entro la durata di validità. Una settimana dopo, la pagina con durata di un anno ha eseguito il paint a 0,78 s, circa un terzo rispetto alla prima visita. Resta soltanto l'attesa dell'HTML. Nella visita di ritorno l'LCP, la foto del prodotto, è arrivato nello stesso istante del primo paint con qualsiasi header tranne no-store (2,24 s).
- Con le risposte 304 la visita di ritorno è stata lenta quasi quanto la prima. Senza alcuna durata impostata, una settimana dopo tutti i 13 file del negozio hanno restituito un 304: 1 kB trasferito sulla rete invece di 404 kB, ma comunque un primo paint a 1,94 s, appena 0,19 s prima rispetto a riscaricare tutto.
- Le durate brevi coprono la visita e scadono prima del ritorno. Le 4 ore di Cloudflare hanno servito la pagina successiva dalla cache. Una settimana dopo sono serviti i 304. Solo l'impostazione a un anno ha coperto entrambi i casi.
- no-cache e no-store rallentano ogni pagina. Hanno portato la pagina successiva da 0,79 s a 1,93 s e 2,11 s.

Nessuna durata, una settimana dopo

Durata di un anno, una settimana dopo
Entrambe le pagine a 0,8 s sullo smartphone con throttling.
Su una vera connessione Slow 4G ogni visualizzazione richiede più tempo; la gerarchia tra gli header rimane invariata. Su Fast 4G la durata di un anno ha eseguito il paint a 0,52 s nella visita di ritorno, mentre il ritorno con i 304 ha richiesto 0,85 s, esattamente quanto la prima visita su quella connessione.
Quando puoi ignorare Use efficient cache lifetimes?
Se Lighthouse elenca i file del tuo sito e gli utenti tornano a distanza di giorni o settimane, intervieni: basta una sola regola sul server e non ha alcun costo durante il caricamento della pagina. Ignoralo se:
- tutti i file elencati si trovano su un altro dominio o sono serviti dalla piattaforma (vedi sotto); su Shopify è sempre così;
- CSS e JavaScript cambiano mantenendo lo stesso nome file e non puoi aggiungere una versione: in questo caso una durata breve è la scelta corretta, e Lighthouse continuerà a elencare quei file;
- quasi tutti i visitatori visualizzano una sola pagina e non tornano più, come nel caso di una landing page per una campagna pubblicitaria: nessuno userà la cache.
Come misuri l'effetto della durata della cache nei field data?
I field data mescolano le prime visite con le pagine successive e le visite di ritorno. In CoreDash, raggruppa l'LCP su mobile per Repeat Visitor, poi fai lo stesso con il TTFB:


CoreDash su un sito demo, acme-pagespeed.com: mobile, p75.
I visitatori di ritorno hanno un LCP di 0,65 s, i nuovi visitatori di 1,74 s. Questo divario non dipende interamente dalla cache: i visitatori di ritorno ricevono anche il primo byte prima, 323 ms contro 0,87 s, spesso perché il browser ha già una connessione aperta verso il server. Sottrai quindi il TTFB dall'LCP. Dopo il primo byte, i visitatori di ritorno attendono 0,33 s e i nuovi visitatori 0,87 s. Quei 0,54 s rappresentano all'incirca il risparmio dovuto alla cache, circa metà del divario; il primo byte più rapido costituisce l'altra metà.
Per isolare la pagina successiva di una visita, raggruppa per Navigation Origin: same origin indica che il visitatore proviene da un'altra pagina del sito. CrUX aggrega tutte queste visite in un unico p75 per pagina o per sito, quindi non può mostrare questa suddivisione.
Come controlli gli header di cache di un file in DevTools?
Apri il pannello Network e assicurati che Disable cache sia disattivato (le impostazioni di rete di DevTools spiegano quando attivarlo). Carica la pagina, poi clicca per passare a una seconda pagina. Le colonne Status e Size mostrano cosa è successo a ciascun file:
- (disk cache) o (memory cache) nella colonna Size: recuperato dalla cache, nessuna richiesta.
- 304 nella colonna Status: il browser ha interrogato il server e non ha ricevuto alcun file in risposta.
- 200 con una dimensione: scaricato di nuovo.

Nessuna durata: 304 per ogni file

Un anno: dalla disk cache
La visita di ritorno una settimana dopo nel pannello Network, Slow 4G.
Clicca su un file e apri la scheda Headers. Sotto Response Headers, cache-control ed expires mostrano la durata inviata dal server; etag e last-modified indicano con cosa il browser può effettuare la verifica. Da riga di comando:
curl -sI https://www.example.com/wp-content/themes/acme/style.css | grep -iE "cache-control|expires|etag|last-modified" Anche il pannello Performance include lo stesso insight. Registra un ricaricamento e apri Use efficient cache lifetimes nella barra laterale Insights: elenca i file e li evidenzia nella traccia Network. Un file privo di durata compare lì come 0 ms, e come None in Lighthouse. La valutazione si basa sugli header, quindi un file proveniente dalla cache viene comunque elencato se la sua durata è breve.

Come risolvere Use efficient cache lifetimes?
Il dominio di ciascun file indicato da Lighthouse chiarisce chi imposta l'header: sul tuo dominio spetta al server, all'hosting o alla CDN; su qualunque altro dominio spetta al fornitore di quel file.
nginx, Apache, IIS e Caddy
Sul proprio server, basta una regola per tipo di file per impostare la durata. Queste regole impostano un anno con immutable: usale per le immagini e, per CSS, JavaScript e font, solo quando i rispettivi URL includono una versione (quale durata assegnare a ciascun file). In nginx:
location ~* \.(?:css|js|mjs|woff2|svg|png|jpe?g|gif|webp|avif|ico)$ {
add_header Cache-Control "public, max-age=31536000, immutable";
} Inseriscila nel blocco server che serve questi file dal disco. Se la configurazione include già una direttiva location per queste estensioni, aggiungi la riga add_header direttamente lì, perché nginx elabora solo la prima location regex che fa match. Rimuovi eventuali righe expires al suo interno, altrimenti i file riceveranno due header Cache-Control. Un'istruzione add_header dentro una location fa sì che nginx ignori tutti gli add_header del blocco server per quei file; copia quindi anche in questa location le righe add_header del server block (come l'header HSTS).
In Apache, inserisci questo nel file .htaccess:
<IfModule mod_headers.c>
<FilesMatch "\.(css|js|mjs|woff2|svg|png|jpe?g|gif|webp|avif|ico)$">
Header set Cache-Control "public, max-age=31536000, immutable"
</FilesMatch>
</IfModule> FilesMatch verifica il nome del file, quindi le pagine generate da PHP mantengono i propri header. Se in seguito Lighthouse continua a elencare i file, significa che il server non applica la regola: mod_headers è disattivato, oppure l'hosting serve questi file da un server separato che ignora il file .htaccess. Chiedi all'hosting.
Di default IIS non invia alcuna durata. Imposta l'header nel file web.config, limitandone l'ambito alla cartella dei file statici:
<configuration>
<location path="assets">
<system.webServer>
<httpProtocol>
<customHeaders>
<add name="Cache-Control" value="public, max-age=31536000, immutable" />
</customHeaders>
</httpProtocol>
</system.webServer>
</location>
</configuration> In Caddy:
@static path *.css *.js *.mjs *.woff2 *.svg *.png *.jpg *.jpeg *.gif *.webp *.avif *.ico
header @static Cache-Control "public, max-age=31536000, immutable" WordPress
Di per sé WordPress non invia alcuna durata per gli elementi in /wp-content/ o /wp-includes/: la decisione spetta all'hosting, al server o a un plugin. Kinsta, WP Engine, WordPress VIP e WordPress.com inviano già un anno: con questi provider, i file segnalati da Lighthouse si trovano di solito su altri domini (vedi sotto). La segnalazione compare tipicamente sugli hosting condivisi Apache che non inviano alcuna durata, su un server gestito in proprio con nginx e con la configurazione predefinita di Cloudflare. Nei plugin di caching:
- WP Rocket scrive regole mod_expires nel file .htaccess sui server Apache e LiteSpeed: un anno per CSS e JavaScript, quattro mesi per immagini e font. Su nginx non fa nulla: aggiungi la regola per nginx riportata sopra, oppure contatta l'hosting.
- LiteSpeed Cache ha Browser Cache disattivato per impostazione predefinita. Attivalo in LiteSpeed Cache, Cache, Browser; a quel punto invierà un anno.
- W3 Total Cache ha Browser Cache abilitato di default. Su nginx genera un file nginx.conf da includere manualmente nella configurazione del server.
WordPress aggiunge ?ver= a ogni foglio di stile e script che carica: per impostazione predefinita la versione di WordPress, oppure quella passata dal tema o dal plugin. Questo valore cambia solo in occasione di un aggiornamento. Se modifichi il CSS senza aggiornare la versione, l'URL rimane invariato e i visitatori di ritorno continueranno a usare il vecchio CSS per tutta la durata della cache. Carica i file personalizzati usando la data di modifica come versione, così l'URL cambierà a ogni modifica:
add_action( 'wp_enqueue_scripts', function () {
$file = '/css/custom.css';
wp_enqueue_style( 'acme-custom', get_stylesheet_directory_uri() . $file, array(), filemtime( get_stylesheet_directory() . $file ) );
} ); I file caricati non hanno versione. Se carichi di nuovo un file, WordPress gli assegna un nuovo nome (photo-1.jpg), quindi un anno è sicuro, a meno che un plugin non sostituisca i media mantenendo lo stesso nome.
Cloudflare e altre CDN
Su qualsiasi piano, il Browser Cache TTL di Cloudflare è impostato di default a 4 ore. Se il server non invia alcuna durata o ne invia una inferiore, Cloudflare restituisce 4 ore e Lighthouse segnala il file con "4h". Imposta le durate sul server e modifica Browser Cache TTL (in Caching, Configuration) su Respect Existing Headers. In alternativa, crea una Cache Rule per le estensioni dei file statici che imposti il TTL del browser. Non impostare il valore dell'intera zona su un anno: si applicherebbe a qualsiasi file servito da Cloudflare con un header più breve, compresi i CSS privi di versione. Maggiori dettagli sulle altre impostazioni nell'articolo su come configurare Cloudflare per i Core Web Vitals.
CloudFront e Fastly inoltrano direttamente al browser l'header del server; le rispettive impostazioni del TTL modificano unicamente il tempo di conservazione della copia nella CDN. Su Bunny, una Edge Rule con Override Browser Cache Time imposta la durata in base all'estensione del file.
Shopify
Shopify assegna già un anno ai file del tema, ai file caricati e alle immagini dei prodotti (public, max-age=31557600), e non è possibile modificare gli header di Shopify. I file segnalati da Lighthouse su Shopify provengono da Shopify stessa e dalle app installate: i pulsanti dinamici di checkout (portable-wallets, 5 minuti, sul dominio del negozio sotto /cdn/shopifycloud/), il loader shop-js (30 minuti) e il web pixels manager (60 secondi). Non c'è nulla da correggere. Ignora la segnalazione.
Next.js e altri build tool
Next.js assegna a qualsiasi elemento sotto /_next/static/ un anno con immutable, impostazione che non si può sovrascrivere. I file in public/ ricevono max-age=0 (su Vercel con must-revalidate) e /_next/image invia must-revalidate, quindi l'insight ignora entrambi. Su un sito Next.js, i file elencati da Lighthouse provengono da terze parti, oppure da un proxy o da una CDN a monte che riscrive gli header. Per i file in public/ il cui nome cambia in base al contenuto, imposta un anno in next.config.js:
module.exports = {
async headers() {
return [{
source: '/fonts/:path*',
headers: [{ key: 'Cache-Control', value: 'public, max-age=31536000, immutable' }],
}]
},
} Su qualsiasi altro stack, configura il bundler in modo che inserisca un hash nel nome dei file (app.3f9a1c.js), così ogni modifica genererà un nuovo URL. A quel punto imposta un anno per quei file.
File di terze parti e di piattaforma che non puoi modificare
I fornitori mantengono breve la durata dei propri script per poterli aggiornare ovunque contemporaneamente, e non puoi modificarne gli header. Lighthouse segnala spesso questi file, indicando la durata impostata dal fornitore:
- Meta Pixel (fbevents.js): 20 minuti
- Hotjar: 60 secondi
- Il vecchio analytics.js di Google Analytics: 2 ore
- Google Maps (maps/api/js): 30 minuti
- Stripe (js.stripe.com/v3): 2 minuti
- Gli script di Cloudflare sul tuo dominio (email-decode.min.js, Rocket Loader): 2 giorni
Non toccarli. Non ospitare in locale loader come fbevents.js o gtag.js solo per applicarvi i tuoi header: la copia smetterebbe di ricevere gli aggiornamenti del fornitore. Ecco cosa puoi fare:
- Carica le librerie da una CDN pubblica specificando la versione esatta nell'URL. jsDelivr assegna a swiper@11 sette giorni e a una versione esatta un anno. In alternativa, ospita direttamente quella specifica versione con i tuoi header.
- Disattiva le funzionalità di Cloudflare che non ti servono, come Email Address Obfuscation.
- Rimuovi i tag che nessuno utilizza più.
Quale durata di cache impostare per ciascun file
- CSS, JavaScript e font con versione o hash nell'URL: un anno, con immutable:
Cache-Control: public, max-age=31536000, immutable. Una nuova versione corrisponde a un nuovo URL, quindi il browser la scaricherà immediatamente. - Immagini: lo stesso header. Assegna un nuovo nome file alle immagini modificate e nessuno vedrà mai la versione precedente.
- CSS, JavaScript e font senza versione: aggiungila prima di tutto (seguendo i passaggi per WordPress e build tool illustrati sopra). Finché non puoi farlo, mantieni la durata breve e accetta che Lighthouse li elenchi: impostando una durata lunga su un foglio di stile che cambia con lo stesso nome, i visitatori di ritorno riceveranno il nuovo HTML con il vecchio CSS.
- Il documento HTML:
Cache-Control: no-cacheo un max-age breve, perché con una durata lunga gli utenti continuerebbero a vedere una pagina obsoleta. - Mai no-store, no-cache o must-revalidate sui file statici per eliminare la segnalazione, perché in quel modo a ogni visualizzazione di pagina verrebbe ricontrollato o riscaricato ogni file (vedi la sezione sulla pagina successiva).
Come verifichi che le nuove durate della cache funzionino?
Controlla prima l'header del file con curl o nella scheda Headers (come spiegato sopra): deve mostrare il nuovo max-age. Poi esegui Lighthouse su mobile. I file non compariranno più nell'elenco, mentre il punteggio e le metriche rimarranno invariati, esattamente come nei quattro report sopra. Sulla pagina prodotto il punteggio oscillava tra 96 e 80 da un test all'altro, indipendentemente dall'header; quindi una variazione del punteggio dopo l'intervento non dice nulla sulla cache.
I visitatori di ritorno in CoreDash mostrano per primi l'effetto, nel giro di pochi giorni, tornando sul sito e ricevendo i file con la nuova durata. CrUX e Search Console mostrano i dati degli ultimi 28 giorni, quindi due settimane dopo la modifica metà dei dati fa ancora riferimento al vecchio sito.
Non sai quali dei file elencati spetti a te correggere, o se i visitatori di ritorno debbano attendere per file che hanno già scaricato? In una Core Web Vitals power hour esaminiamo insieme gli header e i field data del tuo sito, e ricevi le regole pronte per il server prima di chiudere la chiamata.
Il punteggio Lighthouse non ti dice tutto.
I tuoi utenti reali sono su Android in 4G. Io guardo cosa vedono loro, non cosa vede il tuo MacBook.
Audit sui dati reali