Velocizzare le Webapp con Template HTML che funzionano sia lato server che client. Twitter -like

Il Web del futuro sarà sempre meno fatto da pagine e sempre più da dati e interazioni. Cioè, se ora la gran parte richieste HTTP consiste in un continuo invio di pagine HTML totali o parziali (via AJAX/XHR), la tendenza è quella di separare nettamente i dati dalla loro rappresentazione.

Questa nuova organizzazione "ad eventi" si può riassumere in 3 passi:

  1. Alla prima richiesta si ottiene una pagina web HTML con dei dati e dei template statici che potranno essere utilizzati dalle interazioni successive. Volendo li si può anche salvare ed utilizzare in modalità offline se viene utilizzato tecniche HTML5 come il cache Manifest o il Webstorage.
  2. Le richieste dell'utente successive saranno solo più di invio e ricezione dati (JSON è il formato più compatto e usato rispetto ad XML).
  3. Questi dati JSON possono essere "reimpastati" con un template javascript per produrre nuovo HTML direttamente dal browser.

A questo punto c'é la ridondanza che i punti 1 e 3 entrambi hanno il compito di far visualizzare/renderizzare in HTML dei dati solo che nel primo caso la renderizzazione avviene sul server attraverso file .php, .erb, .jsp e nel terzo avviene nel client, che ovviamente supporta l'HTML ma non conosce nulla di php, ruby o java.

Che fare? Bisogna trovare un linguaggio di template HTML franco, logicless, che funzioni sia sul client che sul server che permetta di iniettare nell'HTML i dati che verranno presi da elaborazioni di server esterni.
Le alternative in campo sono liquid, haml js, tempo, mustache (usato da Twitter), ma io ho scelto handlebars perché secondo benchmark indipendenti è quello con le performance migliori ed è anche compilabile con il compilatore di Google V8.

Pro

  • Stessi dati JSON per client Web o nativi: Applicazioni Android, iOS,..
  • Interazione più veloce (viene inviato solo i dati che effettivamente cambiano)
  • Si usa un sistema unico per i template HTML lato server e lato client (e si è indipendenti dal linguaggio di programmazione adottato)

Contro

  • Non si possono usare gli helper del linguaggio form_for, ecc..
  • Google potrebbe avere dei problemi ad indicizzare i dati delle pagine (SEO), quindi sono da usare con moderazione nelle pagine pubbliche

Esempio pratico: Ruby on Rails 3 + Handlebars + JQuery

In questo demo handlebars-rails-demo è possibile farsi un'idea di come funzioni questo sistema di gestione dell'interazione e dei dati che effettivamente transiteranno in rete.

Qualche punto saliente:

# application.html.erb
<script id="note-template" type="text/x-handlebars-template">
  <%=raw File.read(RAILS_ROOT+"/app/views/notes/show.html.hbs") -%>
</script>

In application.html.erb si carica il layout della pagina e la struttura principale, il codice sopra verrà renderizzato con lo stesso template che si usa lato server per mostrare il contenuto:

<script id="note-template" type="text/x-handlebars-template"> 
  <article>
  <header>
    <h1>{{{ note/title }}}</h1>
  </header>
  {{{ note/content }}}
  <footer>
</article>
 
<button id="load-json">Load JSON and render</button>
</script> 

Il contenuto delle graffe {{{ note/title }}} verrà rimpiazzato da @note.title lato server e dal rispettivo json {} lato client, ma il template HTML è esattamente lo stesso!

# http://localhost:3000/notes/<id>.json
{
  note: {
    title: "Nota di prova"
content: "..." 
  }
}

Una volta che si ha il template HTML e i dati JSON si può procedere con la renderizzazione lato client in questo modo

# application.html.erb
<div id="container"> ... </div>
<script id="main"> 
  var source = $('#note-template').html(); <== carica il template
  var template = Handlebars.compile(source);
  $('#load-json').click(function() {
    $.getJSON("http://localhost:3000/notes/2.json", function(json) {
      $('#container').append(template(json) ); <== lo riempe con i dati json ottenuti con la richiesta successiva
    });
  });
</script> 

Per quanto riguarda la renderizzazione lato server lo stesso template "show.html.hbs" viene convertito in HTML (per la prima richiesta) dall'inteprete javascript embedded therubyracer per ruby che si interfaccia con il Google V8. Il risultato finale sarà sempre lo stesso cioé: un template HTML riempito con i dati.

Conclusione

Questa tecnica sarà presto una Best Practice per tutte le Web Application, in quando davvero permette di ridurre drasticamente il traffico dati nei siti in particolare quelli con forte interazione, inoltre separa nettamente il lavoro del Web Designer dal Web Developer.