Come e perché abbiamo creato gli approfondimenti sulle prestazioni

In Chrome 102 noterai un nuovo riquadro sperimentale, Informazioni sulle prestazioni, in DevTools. In questo post parleremo non solo del motivo per cui abbiamo lavorato a un nuovo panel, ma anche delle sfide tecniche che abbiamo dovuto affrontare e delle decisioni che abbiamo preso lungo il percorso.

ALT_TEXT_HERE

Perché creare un altro riquadro?

Se non l'hai ancora visto, abbiamo pubblicato un video sul perché creare il riquadro Approfondimenti sul rendimento e su come ottenere informazioni strategiche sul rendimento del tuo sito web.

Il pannello sul rendimento esistente è un'ottima risorsa se vuoi visualizzare tutti i dati del tuo sito web in un unico posto, ma abbiamo ritenuto che potesse essere un po' troppo complesso. Se non sei un esperto di prestazioni, è difficile sapere esattamente cosa cercare e quali parti della registrazione sono pertinenti.

Vai al riquadro Approfondimenti, dove puoi comunque visualizzare una sequenza temporale della traccia e ispezionare i dati, ma anche ottenere un pratico elenco di ciò che DevTools considera gli "Approfondimenti" principali da esaminare. Gli Approfondimenti identificheranno problemi come richieste di blocco del rendering, cambiamenti di layout e attività lunghe, per citarne alcuni, che possono influire negativamente sul rendimento del caricamento delle pagine del tuo sito web e, in particolare, sui punteggi Core Web Vital (CWV) del tuo sito. Oltre alla segnalazione dei problemi, le Statistiche sul rendimento ti forniranno suggerimenti utili per migliorare i tuoi punteggi CWV e ti forniranno link a ulteriori risorse e documentazione.

Link Feedback nel riquadro

Questo panel è sperimentale e ci interessa il tuo feedback. Non esitare a contattarci se riscontri bug o hai richieste di funzionalità che ritieni possano esserti utili per migliorare il rendimento del tuo sito.

Come abbiamo creato Informazioni sul rendimento

Come per il resto di DevTools, abbiamo creato Performance Insights in TypeScript e abbiamo utilizzato i componenti web, supportati da lit-html, per creare l'interfaccia utente. La differenza tra Performance Insights e gli altri report è che l'interfaccia utente principale è un elemento HTML canvas e la cronologia viene disegnata su questa tela. Gran parte della complessità deriva dalla gestione di questa tela: non solo disegnare i dettagli giusti nel posto giusto, ma anche gestire gli eventi del mouse (ad esempio, dove ha fatto clic l'utente sulla tela? Ha fatto clic su un evento che abbiamo disegnato?) e assicurarci di eseguire il rendering della tela in modo efficace.

Più tracce su un unico canvas

Per un determinato sito web, vogliamo eseguire il rendering di più "canali", ciascuno dei quali rappresenta una categoria di dati diversa. Ad esempio, per impostazione predefinita il riquadro Approfondimenti mostra tre canali:

Man mano che continuiamo a implementare funzionalità nel riquadro, prevediamo di aggiungere altri canali.

La nostra idea iniziale era che ogni traccia avesse il proprio <canvas>, in modo che la visualizzazione principale diventasse più elementi canvas impilati verticalmente. Ciò semplifica il rendering a livello di traccia, perché ogni traccia può essere visualizzata in modo isolato e non c'è il rischio che venga visualizzata al di fuori dei suoi limiti, ma purtroppo questo approccio presenta due problemi principali:

Il rendering (e il relativo rifacimento) degli elementi canvas è costoso; avere più canvas è più costoso di un solo canvas, anche se più grande. Il rendering di eventuali overlay che attraversano più tracce (ad esempio linee verticali per contrassegnare eventi come il tempo FCP) diventa complesso: dobbiamo eseguire il rendering su più canvas e assicurarci che vengano tutti visualizzati insieme e allineati correttamente.

L'utilizzo di un canvas per l'intera interfaccia utente ha richiesto di capire come garantire che ogni traccia venga visualizzata alle coordinate corrette e non travalichi in un'altra traccia. Ad esempio, se una determinata traccia ha un'altezza di 100 px, non possiamo permettergli di eseguire il rendering di un elemento di questo livello e di fare in modo che si concentri nella traccia sottostante. Per risolvere il problema, possiamo utilizzare clip. Prima di eseguire il rendering di ogni traccia, disegniamo un rettangolo che rappresenta la finestra della traccia visibile. In questo modo, tutti i percorsi tracciati al di fuori di questi limiti verranno ritagliati dal canvas.

canvasContext.beginPath();
canvasContext.rect(
    trackVisibleWindow.x, trackVisibleWindow.y, trackVisibleWindow.width, trackVisibleWindow.height);
canvasContext.clip();

Inoltre, non volevamo che ogni traccia dovesse conoscere la propria posizione verticale: ogni traccia deve essere visualizzata come se fosse visualizzata in (0, 0) e abbiamo un componente di livello superiore (che chiamiamo TrackManager) per gestire la posizione complessiva della traccia. Questa operazione può essere eseguita con translate, che trasla la tela in base a una determinata posizione (x, y). Ad esempio:

canvasContext.translate(0, 10); // Translate by 10px in the y direction
canvasContext.rect(0, 0, 10, 10); // draw a rectangle at (0, 0) that’s 10px high and wide

Nonostante il codice rect imposti 0, 0 come posizione, la traduzione complessiva applicata comporterà il rendering del rettangolo in 0, 10. In questo modo, possiamo lavorare su ogni traccia come se fosse in (0, 0) e il nostro gestore delle tracce esegue la traduzione durante il rendering di ogni traccia per assicurarsi che venga visualizzata correttamente sotto la precedente.

Canvas off-screen per tracce e Video Ricordo

Il rendering di Canvas è relativamente costoso e vogliamo assicurarci che il riquadro Approfondimenti rimanga fluido e reattivo durante l'utilizzo. A volte non puoi evitare di dover eseguire nuovamente il rendering dell'intero canvas: ad esempio, se modifichi il livello di zoom, dobbiamo ricominciare da capo e eseguire nuovamente il rendering di tutto. Il rendering di nuovo della tela è particolarmente costoso perché non puoi semplicemente eseguire il rendering di una piccola parte; devi cancellare l'intera tela e ridisegnare. A differenza del rendering DOM, in cui gli strumenti possono calcolare il lavoro minimo richiesto e non rimuovere tutto e ricominciare da capo.

Un'area in cui abbiamo riscontrato problemi visivi è stata l'evidenziazione. Quando passi il mouse sopra le metriche nel riquadro, queste vengono evidenziate nella sequenza temporale. Analogamente, se passi il mouse sopra un insight per un determinato evento, viene visualizzato un bordo blu attorno all'evento.

Questa funzionalità è stata inizialmente implementata rilevando il movimento del mouse sopra un elemento che attiva un'evidenziazione e poi disegnando l'evidenziazione direttamente sulla tela principale. Il problema si verifica quando dobbiamo rimuovere l'evidenziazione: l'unica opzione è ridisegnare tutto. È impossibile ridisegnare solo l'area in cui si trovava l'evidenziazione (non senza enormi modifiche all'architettura), ma ridisegnare l'intero canvas solo perché vogliamo rimuovere un bordo blu attorno a un elemento ci è sembrato eccessivo. Inoltre, si verificava un ritardo visivo se si spostava rapidamente il mouse sopra diversi elementi per attivare più elementi in rapida successione.

Per risolvere il problema, abbiamo suddiviso l'interfaccia utente in due canvas off-screen: il canvas "principale", in cui vengono visualizzati i canali, e il canvas "momenti salienti", in cui vengono disegnati i momenti salienti. Poi eseguiamo il rendering copiando questi canvas nel singolo canvas visibile sullo schermo per l'utente. Possiamo utilizzare il metodo drawImage in un contesto canvas, che può avere un'altra canvas come origine.

In questo modo, la rimozione di un'evidenziazione non comporta il ricalcolo della tela principale: possiamo invece cancellare la tela sullo schermo e copiare la tela principale su quella visibile. La copia di una tela è economica, è il disegno che è costoso; quindi, spostando gli elementi in evidenza in una tela separata, evitiamo questo costo quando li attiviamo e disattiviamo.

Analisi delle tracce testata in modo completo

Uno dei vantaggi di creare una nuova funzionalità da zero è che puoi riflettere sulle scelte tecniche fatte in precedenza e apportare miglioramenti. Una delle cose che volevamo migliorare era suddividere esplicitamente il codice in due parti quasi completamente distinte:

Analizza il file di traccia e recupera i dati richiesti. Esegui il rendering di un insieme di tracce.

Mantenere la convalida (parte 1) separata dal lavoro sull'interfaccia utente (parte 2) ci ha permesso di creare un sistema di convalida solido; ogni traccia viene eseguita attraverso una serie di handler responsabili di problemi diversi: un LayoutShiftHandler calcola tutte le informazioni di cui abbiamo bisogno per i cambiamenti di layout e un NetworkRequestsHandler si occupa esclusivamente dell'estrazione delle richieste di rete. Anche la presenza di questo passaggio di analisi esplicita in cui abbiamo diversi gestori responsabili di parti diverse della traccia è stata utile: l'analisi della traccia può diventare molto complicata e consente di concentrarsi su un problema alla volta.

Inoltre, siamo stati in grado di testare in modo completo l'analisi delle tracce acquisendo registrazioni in DevTools, salvandole e caricandole come parte della nostra suite di test. Questo è fantastico perché possiamo eseguire test con tracce reali e non accumulare enormi quantità di dati di tracce false che potrebbero diventare obsoleti.

Test degli screenshot per l'interfaccia utente di Canvas

Rimanendo in tema di test, di solito testiamo i nostri componenti frontend eseguendone il rendering nel browser e assicurandoci che si comportino come previsto. Possiamo inviare eventi di clic per attivare gli aggiornamenti e affermare che il DOM generato dai componenti è corretto. Questo approccio funziona bene per noi, ma tende a non funzionare correttamente quando si considera il rendering su una tela: non c'è modo di ispezionare una tela per determinare cosa è stato disegnato lì. Pertanto, il nostro approccio abituale di rendering e query non è appropriato.

Per poter fare un po' di copertura di test, abbiamo optato per il test degli screenshot. Ogni test attiva una tela, esegue il rendering della traccia che vogliamo testare e poi acquisisce uno screenshot dell'elemento canvas. Questo screenshot viene poi archiviato nella nostra base di codice e le future esecuzioni dei test lo confronteranno con quello generato. Se gli screenshot sono diversi, il test non andrà a buon fine. Forniamo anche un flag per eseguire il test e forzare un aggiornamento dello screenshot quando abbiamo modificato intenzionalmente il rendering e abbiamo bisogno che il test venga aggiornato.

I test degli screenshot non sono perfetti e sono leggermente smussati; puoi solo verificare che il rendering dell'intero componente sia quello previsto, anziché delle asserzioni più specifiche, e inizialmente siamo colpevoli di un loro uso eccessivo per garantire che ogni singolo componente (HTML o canvas) venga visualizzato correttamente. Ciò ha rallentato drasticamente la suite di test e ha causato problemi in cui piccole modifiche all'interfaccia utente, quasi irrilevanti (ad esempio lievi variazioni di colore o l'aggiunta di un margine tra gli elementi), hanno causato l'errore di più screenshot e il loro aggiornamento. Ora abbiamo ridotto l'utilizzo degli screenshot e li utilizziamo solo per i componenti basati su canvas. Finora questo equilibrio ha funzionato bene per noi.

Conclusione

La creazione del nuovo riquadro Informazioni sulle prestazioni è stata un'esperienza molto piacevole e formativa per il team. Abbiamo imparato molto sui file di traccia, sull'utilizzo di canvas e altro ancora. Ci auguriamo che il nuovo riquadro ti piaccia e non vediamo l'ora di ricevere il tuo feedback.

Per scoprire di più sul riquadro Approfondimenti sul rendimento, consulta Approfondimenti sul rendimento: informazioni strategiche sul rendimento del tuo sito web.

Scaricare i canali in anteprima

Prendi in considerazione l'utilizzo di Chrome Canary, Dev o Beta come browser di sviluppo predefinito. Questi canali di anteprima ti consentono di accedere alle funzionalità più recenti di DevTools, di testare API di piattaforme web all'avanguardia e di trovare i problemi sul tuo sito prima che lo facciano gli utenti.

Contatta il team di Chrome DevTools

Utilizza le seguenti opzioni per discutere di nuove funzionalità, aggiornamenti o qualsiasi altro argomento relativo a DevTools.