Best practice per un'app web più veloce con HTML5

Introduzione

Gran parte di HTML5 mira a fornire il supporto del browser nativo per i componenti e le tecniche che abbiamo ottenuto finora tramite le librerie JavaScript. L'utilizzo di queste funzionalità, se presenti, può comportare un'esperienza molto più rapida per gli utenti. In questo tutorial non riassunrò l'eccellente ricerca sul rendimento che hai osservato sul sito dedicato alle prestazioni eccezionali di Yahoo o nella documentazione su Page Speed di Google. Inoltre, non tratterò in alcun modo il sito Rendiamo il web più veloce. Mi concentrerò invece su come l'utilizzo immediato di HTML5 e CSS3 può rendere le tue applicazioni web più reattive.

Suggerimento 1: usa lo spazio di archiviazione web anziché i cookie

Nonostante i cookie siano stati utilizzati per anni per tenere traccia dei dati di utenti unici, presentano gravi svantaggi. Il problema più grande è che tutti i dati dei cookie vengono aggiunti a ogni intestazione della richiesta HTTP. Questo può avere un impatto misurabile sui tempi di risposta, soprattutto durante le sessioni XHR. Pertanto, una best practice consiste nel ridurre le dimensioni dei cookie. In HTML5 possiamo fare di meglio: usare sessionStorage e localStorage al posto dei cookie.

Questi due oggetti di archiviazione web possono essere utilizzati per rendere persistenti i dati utente sul lato client per la durata della sessione o per un tempo indeterminato. Neanche i dati vengono trasferiti al server tramite ogni richiesta HTTP. Hanno un'API che ti aiuterà a sbarazzarti dei cookie. Di seguito sono riportate entrambe le API, che utilizzano i cookie come riserva.

// if localStorage is present, use that
if (('localStorage' in window) && window.localStorage !== null) {

  // easy object property API
  localStorage.wishlist = '["Unicorn","Narwhal","Deathbear"]';

} else {

  // without sessionStorage we'll have to use a far-future cookie
  //   with document.cookie's awkward API :(
  var date = new Date();
  date.setTime(date.getTime()+(365*24*60*60*1000));
  var expires = date.toGMTString();
  var cookiestr = 'wishlist=["Unicorn","Narwhal","Deathbear"];'+
                  ' expires='+expires+'; path=/';
  document.cookie = cookiestr;
}

Suggerimento 2: usa le transizioni CSS anziché l'animazione JavaScript

Le transizioni CSS offrono una transizione visiva accattivante tra due stati. È possibile eseguire la transizione della maggior parte delle proprietà di stile, ad esempio manipolando l'ombra del testo, la posizione, lo sfondo o il colore. Puoi utilizzare le transizioni negli stati di pseudo-selettore come :hover o nei moduli HTML5, :invalid e :valid (esempio con stati di convalida del modulo). Ma sono molto più potenti e possono essere attivati quando aggiungi una classe a un elemento.

div.box {
  left: 40px;
  -webkit-transition: all 0.3s ease-out;
     -moz-transition: all 0.3s ease-out;
       -o-transition: all 0.3s ease-out;
          transition: all 0.3s ease-out;
}
div.box.totheleft { left: 0px; }
div.box.totheright { left: 80px; }

Se aggiungi le classi di totheleft e totheright, puoi spostare la casella. Confronta questa quantità di codice con quella di una libreria di animazioni JavaScript. È evidente che il numero di byte inviati al browser è molto inferiore quando si utilizzano animazioni basate su CSS. Inoltre, con l'accelerazione a livello di GPU, queste transizioni visive saranno il più fluide possibile.

Suggerimento 3: utilizza i database lato client invece di round trip del server

Database SQL web e IndexedDB introducono i database sul lato client. Anziché utilizzare il modello comune di pubblicazione dei dati sul server tramite XMLHttpRequest o l'invio di moduli, puoi utilizzare questi database lato client. La riduzione delle richieste HTTP è un obiettivo principale di tutti i tecnici delle prestazioni, pertanto il loro utilizzo come datastore può salvare molte corse tramite XHR o post di modulo nel server. In alcuni casi, è possibile utilizzare localStorage e sessionStorage, ad esempio per acquisire l'avanzamento dell'invio dei moduli, e hanno visto essere notevolmente più veloci delle API del database lato client. Ad esempio, se hai un componente della griglia di dati o una casella di posta in arrivo con centinaia di messaggi, l'archiviazione locale dei dati in un database ti consente di salvare le round trip HTTP quando l'utente vuole eseguire ricerche, filtri o ordini. A ogni sequenza di tasti potrebbe essere filtrato un elenco di amici o il completamento automatico dell'input di testo, in modo da offrire un'esperienza utente molto più reattiva.

Suggerimento 4: i miglioramenti di JavaScript offrono notevoli vantaggi in termini di prestazioni

Molti metodi aggiuntivi sono stati aggiunti a Array protoype in JavaScript 1.6. Attualmente queste sono disponibili nella maggior parte dei browser, ad eccezione di IE. Ad esempio:

// Give me a new array of all values multiplied by 10.
[5, 6, 7, 8, 900].map(function(value) { return value * 10; });
// [50, 60, 70, 80, 9000]

// Create links to specs and drop them into #links.
['html5', 'css3', 'webgl'].forEach(function(value) {
  var linksList = document.querySelector('#links');
  var newLink = value.link('http://google.com/search?btnI=1&q=' + value + ' spec');
  linksList.innerHTML +=  newLink;
});


// Return a new array of all mathematical constants under 2.
[3.14, 2.718, 1.618].filter(function(number) {
  return number < 2;
});
// [1.618]


// You can also use these extras on other collections like nodeLists.
[].forEach.call(document.querySelectorAll('section[data-bucket]'), function(elem, i) {
  localStorage['bucket' + i] = elem.getAttribute('data-bucket');
});

Nella maggior parte dei casi, l'utilizzo di questi metodi nativi offre velocità notevolmente più elevate rispetto al tuo ciclo for standard, ad esempio for (var i = 0, len = arr.length; i &lt; len; i++). L'analisi JSON nativa (tramite JSON.parse()) sostituisce il file json2.js che siamo abituati a includere da un po' di tempo. JSON nativo è molto più veloce e sicuro rispetto all'uso di uno script esterno ed è già disponibile in IE8, Opera 10.50, Firefox 3.5, Safari 4.0.3 e Chrome. Il formato String.trim nativo è un altro buon esempio di come non solo è più veloce degli equivalenti JS a lungo termine, ma anche potenzialmente più corretto. Nessuna di queste aggiunte JavaScript è tecnicamente HTML5, ma rientrano nell'insieme di tecnologie disponibili di recente.

Suggerimento 5: utilizza il manifest della cache per i siti attivi, non solo per le app offline

Due anni fa, Wordpress ha utilizzato Google Gear per aggiungere una funzionalità chiamata Wordpress Turbo. Essenzialmente ha memorizzato nella cache molte delle risorse utilizzate nel pannello di amministrazione localmente, velocizzando l'accesso ai file. Possiamo replicare questo comportamento con applicationCache di HTML5 e la cache.manifest. La cache dell'app ha un leggero vantaggio rispetto all'impostazione delle intestazioni Expires; dato che crei un file dichiarativo che indica le risorse statiche che possono essere memorizzate nella cache, i browser possono ottimizzarle in modo significativo, forse anche prescrivendole nella cache prima dell'uso. Considera la struttura di base del tuo sito come un modello. I tuoi dati potrebbero cambiare, ma il codice HTML circostante solitamente rimane abbastanza coerente. Con la cache dell'app puoi considerare il codice HTML come una serie di modelli puri, memorizzare nella cache il markup tramite cache.manifest e quindi inviare JSON over-the-wire per aggiornare i contenuti. Questo modello è molto simile a quello di un'app di notizie nativa per iPhone o Android.

Suggerimento 6: attiva l'accelerazione hardware per migliorare l'esperienza visiva

Nei browser principali, molte operazioni visive possono sfruttare l'accelerazione a livello di GPU, che può rendere molto più fluide le operazioni visive altamente dinamiche. L'accelerazione hardware è stata annunciata per Firefox Minefield e IE9, mentre Safari ha aggiunto l'accelerazione a livello di hardware nella versione 5. (È arrivato in Mobile Safari molto prima). Chromium ha appena aggiunto l'accelerazione hardware e le trasformazioni 3D per Windows e a breve le altre due piattaforme saranno disponibili.

L'accelerazione della GPU si attiva solo in un insieme di condizioni piuttosto limitato, ma le trasformazioni 3D e l'opacità animata sono i modi più comuni per disattivare lo switch. Un modo un po' complicato ma discreto per attivarlo è:

.hwaccel {  -webkit-transform: translateZ(0); }

Nessuna garanzia, però. :) Con l'accelerazione hardware supportata e abilitata, le traduzioni animate, la rotazione, la scalabilità e l'opacità saranno sicuramente più fluide con la composizione tramite GPU. Avranno il vantaggio di essere gestiti direttamente sulla GPU e non richiederanno di nuovo il disegno dei contenuti del livello. Tuttavia, qualsiasi proprietà che influisce sul layout della pagina sarà relativamente lenta.

Suggerimento 7: per le operazioni che consumano molta CPU, i web worker offrono

I web worker hanno due vantaggi significativi: 1) sono veloci. 2) Mentre si impegnano a svolgere le tue attività, il browser rimane reattivo. Dai un'occhiata alla presentazione HTML5 per i lavoratori in azione. Ecco alcune possibili situazioni in cui potresti utilizzare i web worker:

  • Formattazione del testo di un documento lungo
  • Evidenziazione della sintassi
  • Elaborazione immagini
  • Sintesi di immagini
  • Elaborazione di array di grandi dimensioni

Suggerimento 8: attributi del modulo HTML5 e tipi di input

HTML5 introduce un nuovo insieme di tipi di input ed esegue l'upgrade del set text, password e file in modo da includere search, tel, url, email, datetime, date, month, week, time, datetime-local, number, range e color. Il supporto dei browser varia a seconda della versione di Opera, che al momento è in fase di implementazione. Con il rilevamento delle funzionalità puoi determinare se il browser supporta il supporto nativo (e offrire una UI come un selettore di date o un selettore colori) e, in caso contrario, puoi continuare a utilizzare i widget JS per svolgere queste attività comuni. Oltre ai tipi, abbiamo aggiunto alcune utili funzionalità ai nostri normali campi di immissione. L'input placeholder offre un testo predefinito che viene cancellato quando fai clic al suo interno e autofocus mette il cursore di testo sul caricamento pagina per consentirti di interagire immediatamente con il campo. La convalida dell'input è un altro aspetto che viene introdotto con HTML5. Se aggiungi l'attributo required, il browser non consentirà l'invio del modulo finché il campo non sarà stato compilato. Inoltre, l'attributo pattern consente di specificare un'espressione regolare personalizzata su cui eseguire il test dell'input, con valori non validi che bloccano l'invio del modulo. Questa sintassi dichiarativa rappresenta un grande upgrade non solo per la leggibilità del codice sorgente, ma anche per una significativa riduzione del codice JavaScript necessario. Anche in questo caso, puoi utilizzare il rilevamento delle caratteristiche per offrire una soluzione di riserva se non è presente il supporto nativo per queste soluzioni. Utilizzando qui i widget nativi, non dovrai inviare gli ingombranti JavaScript e CSS necessari per sfoggiarli, velocizzando il caricamento della pagina e probabilmente migliorando la reattività del widget. Per provare alcuni di questi miglioramenti dell'input, consulta la presentazione HTML5.

Suggerimento 9: usa gli effetti CSS3 invece di richiedere sprite di immagini pesanti

CSS3 offre molte nuove possibilità di stile che sostituiscono l'uso delle immagini per rappresentare in modo accurato il design visivo. La sostituzione di un'immagine 2K con 100 byte di CSS è un'ottima soluzione, per non parlare del fatto che hai rimosso l'ennesima richiesta HTTP. Ecco alcune delle proprietà con cui acquisire familiarità:

  • Gradienti lineari e radiali
  • Raggio bordo per gli angoli arrotondati
  • Ombra riquadro per ombre e incandescenza
  • RGBA per opacità alfa
  • Trasforma per la rotazione
  • Maschere CSS

Ad esempio, puoi creare pulsanti molto curati tramite gradienti e replicare molti altri effetti senza immagini. Il supporto dei browser per la maggior parte di queste è molto solido e puoi utilizzare una libreria come Modernizr per individuare i browser che non supportano le funzionalità in modo da utilizzare le immagini in un caso di riserva.

Suggerimento 10: WebSocket per una distribuzione più rapida con meno larghezza di banda rispetto a XHR

WebSockets è stato progettato in risposta alla crescente popolarità di Comet. L'uso di WebSocket ora invece del modello Comet rispetto al modello XHR, comporta dei vantaggi.

WebSocket ha un'inquadratura molto leggera, quindi la larghezza di banda che consuma è spesso più leggera di quella di XHR. Alcuni report indicano una riduzione del 35% dei byte inviati attraverso il cavo. Inoltre, in caso di volume più elevato, la differenza di prestazioni in termini di consegna dei messaggi è più evidente; l'XHR è stato registrato in questo test, con un tempo aggregato del 3500% più lungo rispetto ai WebSocket. Infine, Ericcson Labs ha esaminato le prestazioni di WebSocket e ha rilevato che i tempi di ping su HTTP erano 3-5 volte maggiori rispetto a quelli su WebSocket a causa di requisiti di elaborazione più sostanziali. La conclusione è che il protocollo WebSocket era chiaramente più adatto per le applicazioni in tempo reale.

Altre risorse

Per consigli su misurazioni e prestazioni, ti consigliamo di utilizzare le estensioni di Firefox Page Speed e YSlow. Inoltre, Speed Tracer per Chrome e DynaTrace Ajax per IE forniscono un livello più dettagliato di logging dell'analisi.