Informazioni sulla tua app web
Le applicazioni web ad alte prestazioni sono fondamentali per un'esperienza utente ottimale. Man mano che le applicazioni web diventano sempre più complesse, è fondamentale comprendere l'impatto sulle prestazioni per creare un'esperienza coinvolgente. Negli ultimi anni, nel browser sono state visualizzate diverse API per contribuire ad analizzare il rendimento della rete, i tempi di caricamento e così via, ma queste non forniscono necessariamente dettagli granulari con flessibilità sufficiente per trovare ciò che rallenta l'applicazione. Inserisci l'API User Timing, che fornisce un meccanismo che puoi utilizzare per analizzare la tua applicazione web e identificare dove la tua applicazione impiega il tempo. In questo articolo illustreremo l'API e alcuni esempi di utilizzo.
Non puoi ottimizzare ciò che non misuri
Il primo passaggio per velocizzare un'applicazione web lenta consiste nell'individuare dove viene speso il tempo. Misurare l'impatto in termini di tempo delle aree di codice JavaScript è il modo ideale per identificare gli hot spot, il primo passo per scoprire come migliorare il rendimento. Fortunatamente, l'API User Timing ti consente di inserire chiamate API in parti diverse del codice JavaScript ed estrarre dati di temporizzazione dettagliati che possono essere utilizzati per aiutarti a ottimizzare.
Tempo ad alta risoluzione e now()
Una parte fondamentale di una misurazione accurata del tempo è la precisione. In passato, i tempi erano basati sulla misurazione in millisecondi, il che va bene, ma per creare un sito a 60 FPS senza scatti, ogni frame deve essere disegnato in 16 ms. Pertanto, se hai una precisione solo a livello di millisecondi, manca la precisione necessaria per un'analisi efficace. Inserisci High Resolution Time, un nuovo tipo di tempo integrato nei browser moderni. La funzionalità Tempo ad alta risoluzione ci fornisce indicatori di data e ora con virgola mobile che possono essere precisi fino a una risoluzione di microsecondi, mille volte meglio di prima.
Per ottenere l'ora corrente nella tua applicazione web, chiama il metodo now()
che forma un'estensione dell'interfaccia Performance. Il seguente codice mostra come procedere:
var myTime = window.performance.now();
Esiste un'altra interfaccia chiamata PerformanceTiming che fornisce una serie di tempi diversi relativi al caricamento dell'applicazione web. Il metodo now()
restituisce il tempo trascorso da quando si è verificato il tempo navigationStart
in PerformanceTiming.
Il tipo DOMHighResTimeStamp
In passato, per misurare il tempo delle applicazioni web si utilizzava qualcosa come Date.now()
, che restituisce un DOMTimeStamp. DOMTimeStamp restituisce un numero intero di millisecondi come valore. Per fornire la maggiore precisione necessaria per il tempo ad alta risoluzione, è stato introdotto un nuovo tipo denominato DOMHighResTimeStamp. Questo tipo è un valore con virgola mobile che restituisce anche il tempo in millisecondi. Tuttavia, poiché è con virgola mobile, il valore può rappresentare millisecondi frazionari e quindi può fornire una precisione di un millesimo di millisecondo.
Interfaccia di misurazione dei tempi utente
Ora che abbiamo timestamp ad alta risoluzione, utilizziamo l'interfaccia Tempi dell'utente per estrarre le informazioni sui tempi.
L'interfaccia Tempi utente fornisce funzioni che ci permettono di chiamare metodi in diversi punti dell'applicazione in grado di fornire un breadcrumb in stile Hansel e Gretel per consentirci di monitorare dove viene trascorso il tempo.
In uso: mark()
Il metodo mark()
è lo strumento principale del nostro kit di strumenti per l'analisi dei tempi. mark()
memorizza un timestamp per noi. L'aspetto di mark()
è molto utile perché possiamo assegnare un nome al timestamp e l'API ricorderà il nome e il timestamp come una singola unità.
Chiamare mark()
in vari punti della tua applicazione ti consente di capire quanto tempo è stato necessario per premere quel "segno" nella tua applicazione web.
La specifica indica una serie di nomi suggeriti per i marchi che potrebbero essere interessanti e sono abbastanza autoesplicativi, come mark_fully_loaded
, mark_fully_visible
,mark_above_the_fold
e così via.
Ad esempio, potremmo impostare un indicatore per quando l'applicazione è completamente caricata utilizzando il seguente codice:
window.performance.mark('mark_fully_loaded');
Impostando dei contrassegni con nome nella nostra applicazione web, possiamo raccogliere una serie di dati sulle tempistiche e analizzarli quando necessario per capire cosa sta facendo l'applicazione e quando.
Calcolo delle misurazioni con measure()
Dopo aver impostato una serie di indicatori di tempo, devi scoprire il tempo trascorso tra un indicatore e l'altro. A questo scopo, utilizza il metodo measure()
.
Il metodo measure()
calcola il tempo trascorso tra i vari indicatori e può anche misurare il tempo tra un indicatore e uno dei nomi di eventi noti nell'interfaccia PerformanceTiming.
Ad esempio, puoi calcolare il tempo che intercorre tra il completamento del DOM e il caricamento completo dello stato dell'applicazione utilizzando il seguente codice:
window.performance.measure('measure_load_from_dom', 'domComplete', 'mark_fully_loaded');
Quando chiami measure()
, il risultato viene memorizzato indipendentemente dai segni impostati, in modo da poterli recuperare in un secondo momento. Se memorizzi i tempi di attesa durante l'esecuzione dell'applicazione, questa rimane reattiva e puoi scaricare tutti i dati dopo che l'applicazione ha completato un lavoro in modo che possano essere analizzati in un secondo momento.
Eliminare i segni con clearMarks()
A volte è utile riuscire a eliminare i segni che hai impostato. Ad esempio, potresti eseguire esecuzioni collettive sulla tua applicazione web e quindi vuoi iniziare da capo ogni esecuzione.
È abbastanza facile eliminare i segni che hai configurato chiamando clearMarks()
.
Pertanto, il codice di esempio riportato di seguito eliminerà tutti i segni esistenti, in modo da poter configurare di nuovo un'esecuzione del tempo, se vuoi.
window.performance.clearMarks();
Naturalmente, in alcuni casi potresti non voler cancellare tutti i segni. Quindi, se vuoi eliminare dei segni specifici, puoi passare semplicemente il nome del marchio che vuoi rimuovere. Ad esempio, il codice riportato di seguito:
window.performance.clearMarks('mark_fully_loaded');
elimina l'indicatore impostato nel primo esempio, lasciando invariati gli altri indicatori impostati.
Potresti anche voler eliminare le misure che hai effettuato. A questo scopo, esiste un metodo corrispondente chiamato clearMeasures()
. Funziona esattamente come clearMarks()
, ma agisce sulle misurazioni che hai effettuato. Ad esempio, il codice:
window.performance.clearMeasures('measure_load_from_dom');
rimuoverà la misura che abbiamo creato nell'esempio measure()
riportato sopra. Se vuoi rimuovere tutte le misure, funziona come clearMarks()
, in quanto devi solo chiamare clearMeasures()
senza argomenti.
Estrazione dei dati relativi ai tempi
È bene impostare indicatori e misurare gli intervalli, ma a un certo punto è necessario accedere ai dati relativi ai tempi per eseguire alcune analisi. Anche questo è molto semplice, devi solo utilizzare l'interfaccia di PerformanceTimeline
.
Ad esempio, il metodo getEntriesByType()
ci consente di ottenere tutti i tempi di marcatura o tutti i tempi di misurazione sotto forma di elenco, in modo da poterli analizzare e interpretare. La cosa bella è che l'elenco viene restituito in ordine cronologico, quindi puoi vedere i segni nell'ordine in cui sono stati raggiunti nella tua applicazione web.
Il codice riportato di seguito:
var items = window.performance.getEntriesByType('mark');
restituisce un elenco di tutti i markup raggiunti nella nostra applicazione web, mentre il codice:
var items = window.performance.getEntriesByType('measure');
ci restituisce un elenco di tutte le misure che abbiamo adottato.
Puoi anche recuperare un elenco di voci utilizzando il nome specifico che hai assegnato. Ad esempio, il codice:
var items = window.performance.getEntriesByName('mark_fully_loaded');
ci restituirà un elenco contenente un elemento con il timestamp "mark_fully_loaded" nella proprietà startTime
.
Temporizzazione di una richiesta XHR (esempio)
Ora che abbiamo un quadro abbastanza chiaro dell'API User Timing, possiamo utilizzarla per analizzare il tempo necessario per l'esecuzione di tutti i nostri XMLHttpRequest nella nostra applicazione web.
Innanzitutto, modificheremo tutte le richieste send()
in modo da emettere una chiamata di funzione che configuri gli indicatori e, contemporaneamente, cambieremo i nostri callback di successo con una chiamata di funzione che imposta un altro indicatore e genera una misura del tempo impiegato dalla richiesta.
Quindi normalmente la nostra XMLHttpRequest avrebbe questo aspetto:
var myReq = new XMLHttpRequest();
myReq.open('GET', url, true);
myReq.onload = function(e) {
do_something(e.responseText);
}
myReq.send();
Per il nostro esempio, aggiungeremo un contatore globale per monitorare il numero di richieste e utilizzarlo anche per memorizzare una misura per ogni richiesta effettuata. Il codice per eseguire questa operazione è il seguente:
var reqCnt = 0;
var myReq = new XMLHttpRequest();
myReq.open('GET', url, true);
myReq.onload = function(e) {
window.performance.mark('mark_end_xhr');
reqCnt++;
window.performance.measure('measure_xhr_' + reqCnt, 'mark_start_xhr', 'mark_end_xhr');
do_something(e.responseText);
}
window.performance.mark('mark_start_xhr');
myReq.send();
Il codice riportato sopra genera una misura con un valore del nome univoco per ogni XMLHttpRequest inviato. Supponiamo che le richieste vengano eseguite in sequenza. Il codice per le richieste parallele dovrebbe essere un po' più complesso per gestire le richieste che vengono restituite fuori ordine. Lasciamo questo esercizio al lettore.
Una volta che l'applicazione web ha effettuato una serie di richieste, potremmo scaricarle tutte nella console utilizzando il codice seguente:
var items = window.performance.getEntriesByType('measure');
for (var i = 0; i < items.length; ++i) {
var req = items[i];
console.log('XHR ' + req.name + ' took ' + req.duration + 'ms');
}
Conclusione
L'API User Timing ti offre molti strumenti utili da applicare a qualsiasi aspetto della tua applicazione web. Restringere gli hotspot nella tua applicazione può essere facilmente ottenuto disperdendo le chiamate API in tutta l'applicazione web e post-elaborando i dati di tempo generati per creare un quadro chiaro del tempo trascorso. Ma cosa succede se il tuo browser non supporta questa API? Nessun problema, puoi trovare un ottimo polyfill qui che emula molto bene l'API e che funziona perfettamente anche con webpagetest.org. Cosa stai aspettando? Prova subito l'API User Timing nelle tue applicazioni. Scoprirai come velocizzarle e i tuoi utenti ti ringrazieranno per aver migliorato così tanto la loro esperienza.