Performance
INP e long task: perché la pagina non risponde
Un long task oltre 50 ms blocca ogni interazione. Tre carichi su mobile emulato hanno dato un task da 513 ms: come si trova e come si spezza.
In sintesi
- Un long task supera i 50 ms di main thread occupato e ritarda ogni input che arriva durante il blocco.
- Sui nostri tre carichi mobili il task più lungo è durato 513 ms, con un TBT tra 400 e 508 ms.
- L'INP somma ritardo di input, elaborazione e ritardo di presentazione: ottimizzarne una sola parte non basta.
- Il TBT di laboratorio spiega il problema, l'INP di campo decide se la pagina passa.
Un long task è un blocco del main thread che supera i 50 ms: se ne trovi uno da 513 ms, ogni tocco durante quel blocco aspetta. L'INP misura quanto aspetta, con la soglia buona a 200 ms.
Le tre fasi di un'interazione
| Fase | Cosa succede | Come si vede | Rimedio |
|---|---|---|---|
| Ritardo di input | Il main thread è occupato quando arriva il tocco | event con processingStart alto | task più corti |
| Elaborazione | L'handler esegue troppo codice | durata dell'evento | meno lavoro per handler |
| Ritardo di presentazione | Il browser calcola stile e layout | fine evento fino al frame successivo | meno nodi e meno CSS |
Conta la somma delle tre fasi. Durante il caricamento il ritardo di input è spesso la parte più grande, e nessuna ottimizzazione dell'handler lo tocca.
Trovare i long task
new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
console.log(Math.round(entry.duration), "ms at", Math.round(entry.startTime));
}
}).observe({ type: "longtask", buffered: true });
Lo snippet si incolla nella console del browser e la pagina va ricaricata: con buffered tornano anche i task emessi prima dell'osservatore. Il tipo longtask è esposto da Chrome ed Edge; Safari e Firefox non lo restituiscono, quindi lì conviene la traccia del pannello Performance.
Come si spezza
- Dividi il lavoro in blocchi sotto i 50 ms e cedi il controllo con scheduler.yield() o setTimeout(0). Fonte: web.dev, CC BY 4.0.
- Rimanda il JavaScript non critico con import() dinamico e type=module.
- Avvia le animazioni solo quando sono visibili: un marquee fuori schermo consuma frame senza mostrare nulla.
- Non leggere il layout dentro un handler dopo una scrittura: getBoundingClientRect forza un reflow sincrono.
Il limite da dichiarare
Il TBT di laboratorio non è l'INP: somma il tempo bloccato durante il caricamento e non dice nulla sulla latenza di un tocco reale. Un sito con TBT alto può avere INP buono se nessuno interagisce mentre carica; per l'INP reale contano i dati di campo, come quelli che il beacon in client/src/rum.ts raccoglie.
Dove continuare
Il catalogo EneUI indicizza 111.985 componenti, 1.556 blocchi e il record testimonials with marquee: un marquee che anima sempre tiene occupato il main thread anche quando è fuori schermo. Per la metrica leggi INP: cosa misura, per il quadro completo cosa sono i Core Web Vitals, per il confronto misurato librerie React 2026.
Domande frequenti
Quanto deve durare un task per essere un long task?
Oltre 50 ms di main thread occupato. La soglia è una convenzione degli strumenti di misura, non un limite del browser.
TBT e INP sono la stessa cosa?
No. Il TBT somma il tempo bloccato durante il caricamento in laboratorio, l'INP misura la latenza della risposta a un input reale. Il primo spiega, il secondo decide.
Un long task da 513 ms quanto alza l'INP?
Alza a circa 513 ms l'attesa di ogni input che arriva durante il blocco. L'INP finale è il 75° percentile delle interazioni, non il valore peggiore.
Come si spezza un task lungo?
Dividi il lavoro in blocchi sotto i 50 ms e cedi il controllo tra un blocco e l'altro con scheduler.yield(). Rimanda con import() dinamico ciò che non serve al primo paint.
Perché il mio INP è buono in Lighthouse?
Lighthouse non misura INP, riporta il TBT. La reattività reale si legge con dati di campo o con una traccia delle interazioni.