Performance
PerformanceObserver in pratica: cosa osservare e cosa no
PerformanceObserver legge le voci di performance senza polling. Chrome 155 espone 15 tipi di entry, 7 con buffer: quali servono e quali no.
In sintesi
- PerformanceObserver riceve le voci quando il browser le produce, senza timer.
- Chrome 155 espone 15 tipi di entry e 7 restituiscono voci con buffered: true.
- Senza buffered perdi LCP e i long task emessi prima che lo script partisse.
- Il supporto dei tipi cambia per browser: va letto, non supposto.
PerformanceObserver riceve le voci di performance man mano che il browser le produce, senza timer: con buffered recuperi anche quelle emesse prima che lo script partisse.
Cosa conviene osservare
| Tipo di entry | Cosa contiene | Buffered | Uso |
|---|---|---|---|
| largest-contentful-paint | Tempo e elemento del paint più grande | sì | LCP di campo |
| event | Durata e processingStart di un evento | no | diagnosi INP |
| longtask | Blocchi oltre 50 ms | sì | attribuzione dei blocchi |
| layout-shift | Spostamenti e nodi che li causano | no | diagnosi CLS |
| resource | Tempi e byte per richiesta | sì | peso e cache |
| navigation | Tempi del documento | sì | TTFB e FCP |
Sei tipi coprono LCP, INP e CLS. Gli altri servono alla diagnosi: element e mark misurano ciò che il tuo codice segna, visibility-state dice quando la scheda è nascosta e permette di scartare le voci misurate in background.
Il pattern che regge
new PerformanceObserver((list) => {
const body = JSON.stringify(
list.getEntries().map((e) => ({
name: e.name,
start: Math.round(e.startTime),
dur: Math.round(e.duration),
})),
);
navigator.sendBeacon("/api/rum", new Blob([body], { type: "application/json" }));
}).observe({ type: "longtask", buffered: true });
Il codice richiede un browser con sendBeacon e un endpoint che accetti POST; senza endpoint sostituisci la chiamata con console.log. Un observer per tipo, non un observer per evento: la callback riceve già una lista.
Tre errori comuni
- Osservare senza buffered: le voci emesse prima dello script non arrivano.
- Osservare layout-shift senza filtrare hadRecentInput: gli spostamenti causati da un clic non contano per il CLS.
- Dimenticare disconnect() in una SPA: ogni navigazione aggiunge un observer e le voci si duplicano.
Il limite da dichiarare
Il set di tipi dipende dal browser. Chrome 155 ne espone 15, Firefox e Safari ne espongono meno e alcuni nomi non esistono; un observer che assume longtask su Safari non riceve nulla e non lancia errori. La copertura va controllata con PerformanceObserver.supportedEntryTypes, non supposta.
Dove continuare
Il catalogo EneUI indicizza 111.985 componenti, 12.808 icone e il record image auto slider: uno slider che ruota da solo produce voci anche quando nessuno lo guarda. Per il quadro delle metriche leggi cosa sono i Core Web Vitals, per la reattività INP in pratica, per il confronto tra analytics ospitato e self-hosted Vercel Analytics vs self-hosted.
Domande frequenti
PerformanceObserver sostituisce Lighthouse?
No. Lighthouse misura una pagina in laboratorio, PerformanceObserver legge ciò che il browser produce durante una visita reale.
Cosa fa buffered: true?
Chiede al browser le voci già emesse prima che l'observer partisse. Senza, perdi l'LCP e i long task del caricamento.
Quali tipi servono per le Core Web Vitals?
largest-contentful-paint per LCP, event per INP e layout-shift per CLS. Gli altri tipi aiutano a capire la causa.
Perché il mio observer non riceve nulla su Safari?
Perché quel tipo non è supportato. Controlla supportedEntryTypes e scrivi un ramo di riserva prima di osservare.
Come si evitano le voci duplicate?
Con un flag o un Set nella callback e con disconnect() quando smonti il componente. Con reportAllChanges le voci arrivano più volte.