Soft Navigations: misurare le prestazioni delle SPA come fa il browser
Le euristiche di soft navigation di Chrome permettono finalmente ai Core Web Vitals di agganciarsi ai cambi di rotta lato client. Ecco come funziona l'API e come misurarla senza sorveglianza.
Per un decennio i Core Web Vitals hanno descritto solo la prima pagina caricata da un visitatore. Ogni cambio di rotta successivo in una single-page application restava invisibile alle metriche. L'esperimento delle soft navigations di Chrome colma questa lacuna e cambia il modo in cui un'analytics attenta alla privacy dovrebbe misurare le prestazioni reali degli utenti.
Il punto cieco che le soft navigations risolvono
Una hard navigation tradizionale scarica il documento e ne carica uno nuovo. Il browser reimposta la propria timeline delle prestazioni, emette un nuovo LCP e inizia a contare CLS e INP da zero. Gli strumenti sul campo come CrUX attribuiscono tutto a quell'unica URL.
Le SPA non funzionano così. Dopo il caricamento iniziale, React Router, l'App Router di Next.js o SvelteKit scambiano il contenuto sul posto usando la History API. Nessun documento viene scaricato, quindi non inizia alcuna nuova timeline delle prestazioni. Un utente può attraversare dieci "pagine" mentre ogni Core Web Vital resta inchiodato all'URL di ingresso.
Il risultato è noto a chiunque abbia fatto l'audit di una SPA: la rotta di atterraggio sembra veloce, e le interazioni lente più in profondità nell'app non compaiono mai nei dati.
Come Chrome rileva una soft navigation
L'euristica di Chrome richiede che tre cose accadano nell'ordine prima di registrare una soft navigation:
- La navigazione è avviata da un'interazione dell'utente — un clic o la pressione di un tasto.
- L'URL viene modificato dalla History API o dalla Navigation API.
- Una modifica del DOM segue l'interazione, cambiando un elemento del DOM già esistente.
Questa sequenza è volutamente rigida. Un pushState in background per l'analytics, un carosello che avanza da solo o un cambio di URL senza interazione non si qualificano. Questa precisione conta: significa che una soft navigation corrisponde a qualcosa che un umano ha realmente fatto, e non a un'attività incidentale di script.
La superficie dell'API
Le soft navigations emergono tramite il PerformanceObserver standard usando un tipo di entry dedicato. Le abiliti per observer:
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log(entry.name, entry.startTime);
}
}).observe({ type: "soft-navigation", buffered: true });
Ancora più importante: altre entry di performance ottengono un navigationId. Le entry di LCP, layout-shift ed event-timing emesse dopo una soft navigation portano il nuovo ID, così puoi riattribuire ogni Core Web Vital alla rotta su cui l'utente si trovava davvero:
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// entry.navigationId lega questo LCP a una soft navigation specifica
send({ metric: "LCP", value: entry.startTime, navId: entry.navigationId });
}
}).observe({ type: "largest-contentful-paint", buffered: true });
Oggi tutto questo vive dietro chrome://flags/#soft-navigation-heuristics e un origin trial, con esposizione limitata in CrUX. Non è ancora il comportamento predefinito in Chrome stabile, quindi tratta i numeri sul campo come indicativi, non come definitivi. La libreria web-vitals espone gli stessi dati tramite l'opzione reportSoftNavs, che è il modo pratico per collegare tutto senza scrivere observer a mano.
Perché tutto questo appartiene a un'analytics attenta alla privacy
I dati di soft navigation sono puro timing. Non contengono identificatori, né cookie, né nulla che sopravviva alla sessione della pagina — una durata, un tipo di elemento approssimativo, un percorso di rotta. È esattamente il tipo di segnale che uno strumento senza cookie può raccogliere senza toccare il meccanismo del consenso.
Il tracker si aggancia già a history.pushState per contare i cambi di rotta delle SPA. Le soft navigations affinano lo stesso hook: invece di chiedere solo la rotta è cambiata?, puoi chiedere è stata una navigazione guidata da un'interazione, e come ha reso?. Le entry di performance viaggiano insieme al beacon di pageview esistente verso /collect, aggiungendo misurazione sul campo senza appesantire lo script sotto i 2 KB né rompere il modello di identità a hash giornaliero.
La trappola da evitare è trattare le soft navigations come un motivo per raccogliere di più. Alcuni fornitori di RUM useranno la nuova attribuzione per ricucire percorsi di navigazione per utente lungo una sessione — esattamente il pattern di sorveglianza che l'analytics senza cookie esiste per rifiutare. La metrica è preziosa proprio perché può restare aggregata: INP mediano per rotta, distribuzione di LCP per rotta, nessun percorso a ritroso verso una persona.
Le soft navigations rendono misurabili per la prima volta le parti più profonde e lente della tua app. Raccogli il timing, scarta tutto il resto, e ottieni il quadro delle prestazioni senza il profilo.