Evita vernici inutili

Paul Lewis

Introduzione

La pittura degli elementi di un sito o di un'applicazione può essere molto costosa e può avere un effetto domino negativo sulle prestazioni di runtime. In questo articolo daremo un'occhiata veloce a cosa può attivare la pittura nel browser e a come puoi impedire la realizzazione di pitture non necessarie.

Pittura: un tour super veloce

Una delle principali attività che un browser deve svolgere è convertire il DOM e il CSS in pixel sullo schermo e lo fa attraverso un processo abbastanza complesso. Inizia leggendo il markup e da questo crea una struttura DOM. Esegue un'operazione simile con il CSS e da lì crea il CSSOM. Il DOM e il CSSOM vengono quindi combinati e, alla fine, arriviamo a una struttura da cui possiamo iniziare a dipingere alcuni pixel.

Il processo di pittura stesso è interessante. In Chrome, l'albero combinato di DOM e CSS viene rasterizzato da un software chiamato Skia. Se hai mai utilizzato l'elemento canvas, l'API Skia ti sembrerà molto familiare; sono disponibili molte funzioni in stile moveTo e lineTo, oltre a una serie di funzioni più avanzate. In sostanza, tutti gli elementi che devono essere dipinti vengono distillati in una raccolta di chiamate Skia che possono essere eseguite e l'output è un insieme di bitmap. Queste bitmap vengono caricate sulla GPU, che le compone per darci l'immagine finale sullo schermo.

Dom a pixel

La cosa da ricordare è che il carico di lavoro di Skia è direttamente influenzato dagli stili applicati agli elementi. Se utilizzi stili algoritmici complessi, Skia avrà più lavoro da fare. Colt McAnlis ha scritto un articolo su come il CSS influisce sul peso del rendering della pagina, quindi ti consigliamo di leggerlo per saperne di più.

Detto questo, l'applicazione della vernice richiede tempo e, se non la riduciamo, supereremo il budget frame di circa 16 ms. Gli utenti noteranno che abbiamo perso dei frame e lo percepiranno come un problema, il che alla fine peggiora l'esperienza utente della nostra app. Non vogliamo che ciò accada, quindi vediamo quali tipi di problemi richiedono l'utilizzo di Paint e cosa possiamo fare al riguardo.

Scorrimento

Ogni volta che scorri verso l'alto o verso il basso nel browser, i contenuti devono essere ridisegnati prima di essere visualizzati sullo schermo. Se tutto va bene, si tratterà di una piccola area, ma anche in questo caso agli elementi da disegnare potrebbero essere applicati stili complessi. Quindi, anche se hai una piccola area da dipingere, non significa che il lavoro verrà svolto rapidamente.

Per vedere quali aree vengono ridipinte, puoi utilizzare la funzionalità "Mostra rettangoli di pittura" in DevTools di Chrome (basta fare clic sul piccolo ingranaggio nell'angolo in basso a destra). Dopodiché, con DevTools aperto, interagisci con la pagina e vedrai dei rettangoli lampeggianti che indicano dove e quando Chrome ha dipinto una parte della pagina.

Mostrare i rettangoli colorati in Chrome DevTools
Mostrare i rettangoli di pittura in Chrome DevTools

Le prestazioni di scorrimento sono fondamentali per il successo del tuo sito. Gli utenti notano molto quando il tuo sito o la tua applicazione non scorre bene e non gli piace. Pertanto, abbiamo un interesse diretto a mantenere leggero il lavoro di pittura durante lo scorrimento in modo che gli utenti non vedano scatti.

In passato ho scritto un articolo sul rendimento durante lo scorrimento, quindi dai un'occhiata se vuoi saperne di più sulle specifiche del rendimento durante lo scorrimento.

Interazioni

Le interazioni sono un'altra causa di interventi di pittura: passaggi del mouse, clic, tocchi, trascinamenti. Ogni volta che l'utente esegue una di queste interazioni, ad esempio un passaggio del mouse, Chrome dovrà ridipingere l'elemento interessato. Come per lo scorrimento, se è richiesta una pittura grande e complessa, la frequenza frame diminuirà.

Tutti vogliono animazioni di interazione piacevoli e fluide, quindi dovremo capire se gli stili che cambiano nella nostra animazione ci stanno costando troppo tempo.

Una combinazione sfortunata

Una demo con vernici costose
Una demo con vernici costose

Che cosa succede se scorro e contemporaneamente muovo il mouse? È perfettamente possibile che io inadvertentemente "interagisca " con un elemento mentre scorro, attivando un'operazione di pittura costosa. Ciò, a sua volta, potrebbe superare il mio budget di frame di circa 16,7 ms (il tempo che dobbiamo mantenere al di sotto per raggiungere i 60 frame al secondo). Ho creato una demo per mostrarti esattamente cosa intendo. Speriamo che, mentre scorri e muovi il mouse, vedrai gli effetti di passaggio del mouse, ma vediamo cosa ne pensano gli Strumenti per sviluppatori di Chrome:

Chrome DevTools mostra frame costosi
Chrome DevTools mostra frame costosi

Nell'immagine qui sopra puoi vedere che DevTools registra l'operazione di pittura quando passo il mouse sopra uno dei blocchi. Ho scelto alcuni stili molto pesanti nella mia demo per farti capire il punto, quindi sto raggiungendo e a volte superando il mio budget per i frame. L'ultima cosa che voglio è dover fare questo lavoro di pittura inutilmente, soprattutto durante lo scorrimento quando c'è altro da fare.

Come possiamo evitare che ciò accada? La correzione è piuttosto semplice da implementare. Il trucco è associare un gestore scroll che disattivi gli effetti di passaggio del mouse e imposti un timer per riattivarli. Ciò significa che ti garantiamo che, quando scorri, non dovremo eseguire costose operazioni di pittura interattiva. Se hai smesso di guidare per un periodo di tempo sufficientemente lungo, riteniamo che sia sicuro riattivarli.

Ecco il codice:

// Used to track the enabling of hover effects
var enableTimer = 0;

/*
 * Listen for a scroll and use that to remove
 * the possibility of hover effects
 */
window.addEventListener('scroll', function() {
  clearTimeout(enableTimer);
  removeHoverClass();

  // enable after 1 second, choose your own value here!
  enableTimer = setTimeout(addHoverClass, 1000);
}, false);

/**
 * Removes the hover class from the body. Hover styles
 * are reliant on this class being present
 */
function removeHoverClass() {
  document.body.classList.remove('hover');
}

/**
 * Adds the hover class to the body. Hover styles
 * are reliant on this class being present
 */
function addHoverClass() {
  document.body.classList.add('hover');
}

Come puoi vedere, utilizziamo una classe nel corpo per monitorare se gli effetti di passaggio del mouse sono "consentiti" o meno e gli stili sottostanti si basano sulla presenza di questa classe:

/* Expect the hover class to be on the body
 before doing any hover effects */
.hover .block:hover {
 
}

Ed è fatta.

Conclusione

Le prestazioni di rendering sono fondamentali per consentire agli utenti di utilizzare la tua applicazione e dovresti sempre cercare di mantenere il carico di lavoro di pittura inferiore a 16 ms. Per aiutarti a farlo, devi integrare l'utilizzo di DevTools durante tutto il processo di sviluppo per identificare e correggere i colli di bottiglia man mano che si presentano.

Le interazioni involontarie, in particolare con elementi con molto colore, possono essere molto costose e influire negativamente sulle prestazioni di rendering. Come hai visto, possiamo utilizzare un piccolo pezzo di codice per risolvere il problema.

Dai un'occhiata ai tuoi siti e alle tue applicazioni. Potrebbero avere bisogno di un po' di protezione?