Questa è la traduzione dell'articolo Speed Up Your Site with Delayed Content di Paul Hammond pubblicato originariamente su 24 Ways il 18 dicembre 2010.
La velocità rimane uno dei fattori che più influenzano il successo di un sito web, e la prima regola rispetto alle performance (secondo Yahoo!) è che bisogna ridurre il numero di richieste HTTP. Negli ultimi anni abbiamo visto emergere per questo fine tecniche come gli sprites CSS e la concatenazione di file CSS/Javascript. Ma ci sono situazioni in cui un gran numero di richieste HTTP continua ad essere un fatto inevitabile. Per esempio il caricamento dei piccoli avatar collegati alle liste di commenti, come avviene anche nel nostro articolo.
Avatar
Molti siti come 24Ways usano un fantastico servizio chiamato Gravatar per presentare le immagini associate agli utenti che commentano. È infatti possibile, come utente, iscriversi a Gravatar, fornire un indirizzo e-mail e caricare un'immagine che ci rappresenti. I siti possono includere le immagini generando un hash dell'indirizzo e-mail e usando quest'ultimo per costruire l'URL di un'immagine. Per esempio, il markup per i commenti del nostro articolo è così:
<div>
<h4><a href="http://allinthehead.com/">
<img src="http://www.gravatar.com/avatar.php?
gravatar_id=13734b0cb20708f79e730809c29c3c48&size=100"
class="gravatar" alt="" height="100"width="100" />
Drew McLellan
</a></h4>
<p>This is a great article!</p>
</div>
L'URL relativo a Gravatar contiene due parti. 100
è la dimensione in pixel dell'immagine che vogliamo. 13734b0cb20708f79e730809c29c3c48
è un digest MD5 dell'indirizzo e.mail di Drew McLellan. Usare MD5 significa che possiamo richiedere l'immagine di un utente senza condividere il suo indirizzo con chi visualizza il sorgente della pagina.
Cosa non va con gli avatar?
Il problema è che un articolo molto popolare può facilmente avere centinaia di commenti, e ciascuno di essi significa che un'altra immagine deve essere individualmente richiesta ai server di Gravatar. Ogni richiesta è piccola in quanto a dimensioni e i server di Gravatar sono veloci, ma quando le immagini si sommano i tempi di caricamento della pagina possono crescere di parecchi secondi. Peggio ancora, le immagini possono bloccare il caricamento di risorse molto importanti come i fogli di stile CSS necessari per rendere il contenuto principale della pagina.
Queste immagini non sono critiche rispetto alla pagina e non è necessario che siano caricate e presentate immediatamente. Vediamo allora se possiamo ritardare il loro caricamento fino a quando tutto il resto non sia tutto disponibile. In questo modo possiamo dare l'impressione che il nostro sito si è caricato rapidamente anche se alcune richieste sono in via di completamento.
Ritardare il caricamento delle immagini
Il problema problema che incontriamo è che non abbiamo modo di impedire che Internet Explorer, Chrome e Safari carichino un'immagine senza rimuoverla dall'HTML stesso. Trucchi come la rimozione al volo delle immagini via Javascript non funzionano, perché il browser ha già iniziato a richiedere le immagini prima che sia possibile bloccarlo.
Rimuovere le immagini dall'HTML significa che gli utenti che non possono contare su Javascript sul browser non vedranno gli avatar. Come Drew McLellan ha spiegato in un articolo apparso sempre su 24Ways, ciò può avere accadere con molte persone e non possiamo certo ignorarle. Ma la maggior parte dei siti hanno già un nome in forma testuale collegato a ciascun commento e gli avatar sono solo abbellimenti visuali. Nella maggior parte dei casi va bene se alcuni dei nostri utenti non li vedranno, specie se tutto ciò velocizza l'esperienza del rimanente 98% di visitatori.
Rimuovere le immagini dal sorgente della nostra pagina significa anche che avremo bisogno di rimetterle a posto ad un certo punto. Così dobbiamo tenere traccia di quali immagini devono essere richieste. Tutte le immagini di Gravatar hanno lo stesso formato di URL; l'unica cosa che cambia è l'hash relativo all'indirizzo e-mail. Possiamo salvarlo grazie agli attributi per i dati di HTML5.
Cosa sono gli attributi per i dati di HTML5
Gli attributi data
sono una nuova funzionalità di HTML5. L'ultima versione della specifica dice:
"Un attributo per i dati personalizzato è un attributo senza namespace il cui nome inizia con la stringa
data-
, ha almeno un carattere dopo il trattino, è compatibile con XML, non contiene caratteri nel range daU+0041
aU+005A
(dalla lettera maiuscola A alla lettera maiuscola Z).[...]
Gli attributi per dati personalizzati sono indicati per salvare dati privati su una pagina o un'applicazione per cui non vi siano attributi o elementi più appropriati. Questi attributi non si intendono destinati all'uso di software che sia indipendente dal sito che li usa.
In altre parole: sono attributi di un elemento HTML che inizia con data-
che potete usare per condividere dati con gli script che vengono eseguiti sul vostro sito. Sono un ottimo strumento per aggiungere piccole proporzioni di metadati che non si adattano del tutto nel markup esistente come fanno ad esempio i microformati.
Attributi per i dati in azione
Diamo nuovamente un'occhiata al markup dei commenti:
<div>
<h4><a href="http://allinthehead.com/">
<img src="http://www.gravatar.com/avatar.php?
gravatar_id=13734b0cb20708f79e730809c29c3c48&size=100"
class="gravatar" alt="" height="100"width="100" />
Drew McLellan
</a></h4>
<p>This is a great article!</p>
</div>
Sostituiamo l'elemento <img>
con un attributo data-gravatar-hash
sull'elemento <a>
:
<div>
<h4><a href="http://allinthehead.com/" data-gravatar-hash="13734b0cb20708f79e730809c29c3c48">
Drew McLellan
</a></h4>
<p>This is a great article!</p>
</div>
Una volta fatto così, abbiamo bisogno di un pizzico di Javascript per rintracciare tutti questi attributi e sostituirli con le immagini dopo che la pagina è stata caricata. Ecco un esempio basato su jQuery:
$(window).load(function() {
$('a[data-gravatar-hash]').prepend(function(index){
var hash = $(this).attr('data-gravatar-hash')
return '<img width="100" height="100" alt=""
src="http://www.gravatar.com/avatar.php?size=100&gravatar_id=' + hash + '">'
})
})
Questo codice aspetta fino a che tutto sulla pagina non sia stato caricato, poi usa jQuery.prepend per inserire un'immagine in ogni link che contiene l'attributo data-gravatar-hash
. È tutto semplice, ma nei test ha ridotto il tempo di rendering di una pagina usata come esempio da 3 secondi a 1 secondo.
Ultimi ritocchi
Dobbiamo ancora considerare l'aspetto della pagina prima che gli avatar vengano caricati. Quando il nostro script aggiunge contenuto extra alla pagina, viene effettuato da parte del browser un riposizionamento degli elementi della pagina, cosa che è davvero fastidiosa. Possiamo evitare tutto ciò usando i CSS per riservare dello spazio a ciascuna immagine prima che sia inserita nel codice HTML:
#comments div {
padding-left: 110px;
min-height: 100px;
position: relative;
}
#comments div h4 img {
display: block;
position: absolute;
top: 0;
left: 0;
}
In un esempio reale, verificheremo anche l'HTML per un commento è più vario, dal momento che molti utenti non lasciano non forniscono il link ad una pagina web. Possiamo fare a quel punto delle piccole modifiche al nostro codice CSS e Javascript per aggiustare il tutto.
Ecco l'esempio finale.
Espandere l'idea
Non c'è ragione per limitare questa tecnica ai siti che usano Gravatar; possiamo usare un codice simile per ritardare il caricamento di qualunque immagine non sia necessario caricare immediatamente. Per esempio, la pagina delle foto di Flickr ridisegnata quest'anno usa un attributo data-defer-src
per descrivere le immagini che non hanno bisogno di essere caricate all'inizio, compresi gli avatar e i certi elementi della mappa.
Non dovete nemmeno limitarvi a caricare le risorse extra una volta che la pagina sia stata caricata. Potete risparmiare ulteriormente banda aspettando fino a quando l'utente non compia una certa azione prima di scaricare queste risorse extra. Amazon usa questo metodo sulla sua pagina dei prodotti, il contenuto extra viene infatti caricato man mano che si scorre giù la pagina.
Così, la prossima volta che realizzate una pagina, prendetevi un po' di minuti per capire se ci sono elementi meno importanti e che possono essere ritardati nel caricamento per permettere ai contenuti principali di apparire sulla pagina il più presto possibile.