Webapps JavaScript con Backbone

danii . jueves 7 de marzo de 2013. a las 10:13

Backbone.js logo

Vamos a replicar la demo de Webapp en AngularJS que publicamos esta misma semana, pero esta vez utilizando otro de los frameworks JavaScript para Webapps más populares, Backbone.js como alternativa. Al igual que en el caso de AngularJS, vamos a intentar ofrecer una introducción al framework así como una posible estructuración de proyecto.

El objetivo principal del framework JavaScript Backbone es evitar que el código de nuesta webapp se convierta en spagetthi code, un problema muy común en un lenguage como JavaScript que deja al programador con toda la responsabildad en lo que respecta a claridad y estructuración del código. Esto es aún más grave si tenemos en cuenta que nuestro código JavaScript va a convivir con HTML e interactuar constantemente con los elementos del DOM.

En palabras del propio creador de Backbone, Jeremy Ashkenas:

Get your truth out of the DOM!

Se podría decir que AngularJS y Backbone son dos frameworks JavaScript con la misma misión, el posibilitar la creación de single page Webapps, pero bastante diferentes en filosofía y ejecución por lo que creemos que puede ser un ejercicio muy interesante el comparar los códigos de ambos frameworks a través de un mini ejemplo práctico.

Backbone, a diferencia de Angular, no está basado en una extensión de HTML como son las directivas ng. Esto significa que a la hora de programar una Webapp en Backbone hay menos magia y no existe tanta diferencia con programar en JavaScript y jQuery “a pelo”, por lo que tenemos la comodidad de encontrarnos en un entorno más conocido.

El proyecto

Exactamente igual que la demo AngularJS, esta aplicación constará de un listado de libros obtenido de una petición ajax a un fichero .JSON, con un filtro vía JavaScript y cambio de página a la ficha de cada libro. Sin embargo, para ilustrar la versatilidad de Backbone, hemos implementado «for fun» dos pequeñas mejoras con respecto a la app en AngularJS:

  • Existe una persistencia de datos entre las páginas de la webapp al ser la lista principal de libros un objeto global. Esto significa que la app “recuerda” nuestra ordenación y filtrado al volver a al página principal tras ver una ficha de libro.

  • El filtrado se realiza a la vez en foma “multicampo” en el nombre de autor y el título de libro.

Además, para esta demo hemos decidido modificar ligeramente los datos de los libros para que exista mayor diferencia entre una vista y otra, por lo que en el listado hemos quitado la editorial del libro y recibimos una descripción resumida. Así tiene más sentido que refresquemos los datos haciendo al servidor una petición de la ficha completa del libro.

Proyecto: listado de libros y acceso a su ficha


http://lostiemposcambian.com/blog/posts/backbone-js/

ver demo

Organización del código de la App

Al igual que en el caso de la demo de Angular, hemos seguido una estructura de carpetas muy clásica y basada en las proporcionadas por otros frameworks, ya que Backbone no nos obliga a ningún tipo de organización. En este caso hemos decidido simplificar eliminando las carpetas no utilizadas:

Estructura del código de la webapp Backbone

A pesar de no existir formas canónicas de organizar un proyecto en Backbone, existen muchos recursos que ofrecen posibles estructuraciones de código de una app, personalmente nos ha gustado bastante este proyecto open source de una Backbone Boilerplate no intrusiva y que no modifica el core de Backbone.

El Modelo

El Modelo en Backbone es el corazón de la aplicación, y no sólo contendrá los datos y su lógica de datos sino que también será el encargado de notificar a las vistas de los cambios en estos datos mediante eventos.

En Backbone los modelos se agrupan en Collections de Backbone, objetos que tiene acceso a todos los métodos de las Collection de Underscore.js, genial librería de utilidades que es el único requerimiento de Backbone, aparte del ubicuo jQuery.

Los modelos pueden pedir datos al server mediante la función fetch de Backbone.Model, que atacará al server a la url predefinida en el propio modelo o en la collection a la que pertenece, y concatenando automáticamente el id del modelo que estamos fetcheando. Éste es el motivo de que en esta demo los nombres de los ficheros JSON sean simplemente los ids de los objetos a los que representan, para acomodarse así al comportamiento por defecto de los modelos Backbone.

También por supuesto pueden mandar datos al server mediante la función save, que realizará una HTTP PUT REQUEST y que en esta mini app de ejemplo no llegamos a utilizar.


//inicialización del modelo Libro
var LibroItem = Backbone.Model.extend({
  defaults: { id:0, img: '', titulo: '', autor:'', editorial:'', descripcion:''},
  urlRoot: "data/libros",
/* ... */
});

//inicialización de la collection de libros
var LibroList = Backbone.Collection.extend({
  model: LibroItem,
  url: "data/libros.json",
/* ... */
});

Una buena práctica en Backbone muy recomendada y que hemos implementado en esta app de ejemplo es hacer un bootstraping de los datos iniciales dentro de la Webapp para no tener que fetchear estos datos inicialmente y hacer esperar al usuario dos veces (carga de la app + carga de los datos iniciales desde el servidor). Simplemente hacemos que se genere los datos iniciales en un JSON u objeto incluído en el HTML del documento principal, y pasamos estos datos a nuestro objeto Model o Collection inicial como parámetro. Great! 🙂

La Vista

Las Vistas de Backbone son totalmente minimal, ni siquiera vienen con motor de templating incluido. Esto significa que podemos generar si queremos etiquetas HTML “a pelo” en las vistas y luego añadirlas al DOM mediante jQuery sin ningún problema, o si queremos podemos utilizar alguno de los muchos motores de templating de JavaScript que existen.

En esta demo hemos decidido utilizar el sistema de templates de Underscore.js debido a su simpleza de utilización y flexibilidad. Además, no es necesario incluir ninguna librería adicional ya que, como hemos comentado antes, Backbone tiene de por sí como requerimiento Underscore.js. Para renderizar las vistas, se utiliza la función render del objeto Backbone.View, en la cual debemos añadir al atributo el el HTML de la vista generada. Un shortcut muy cómodo es acceder directamente a this.$el, que sería el equivalente a $(this.el), es decir el selector jQuery para dicho elemento. Este elemento será por defecto un div, pero podemos definir cualquier otra etiqueta, por ejemplo un lien el caso de items de listado. En esta demo hemos creado las plantillas dentro de nuestro HTML, y accedemos a ellas también mediante selectores jQuery.


/**
 * LibroFichaView 
 * Vista item libro en ficha
 * encapuslado en <div></div>
 */
LibroFichaView = Backbone.View.extend({
	/* ... */
	render: function()
	{
		this.$el.html(_.template($('#fichaTemplate').html(),this.model.attributes));
	}
});

Otro motor de templating que se usa muy frecuentemente con Backbone es Mustache.js, con la ventaja añadida de que este motor es multilenguaje y su sintaxis es igual en PHP, Python, Ruby, etc (¡incluso C++!) y añade muchas abstracciones útiles (a la par que mágicas) para ahorrarnos programar una y otra vez los típicos bucles de iteración para mostrar elementos.

Routing

El routing en Backbone es muy similar al de Angular y a muchos otros framewoks web. Se pueden definir rutas con parámetros, que estos parámetros sean opcionales, incluso parte de la ruta puede ser opcional también (eliminando el problema del trailing slash de un plumazo) y también por supuesto wildcards.

/**
 * App 
 */
var App = new (Backbone.Router.extend({
  routes: {
    "libro/:id": "show", //matches "libro/1" y "libro/1/"
    "libros(/)": "index", //matches "libros" y "libros/"
    "*any" : "redirect" //matches anything else *wildcard
     },
/* ... */

Para una Webapp tan simple como este ejemplo, hemos decidido implementarlo de tal manera que el que el objeto principal de la aplicación en sí extienda directamente a la Route de Backbone, pero en un caso más complejo probablemente sería una buena práctica separar estos objetos y sus funcionalidades.

También es de destacar que Backbone soporta por defecto el pushState de HTML5 simplemente añadiendo una directiva, para que nuestras rutas no empiecen siempre por un # gracias a la HTML5 history API, aunque por desgracia, al igual que ocurre con tantas otras maravillas de HTML5, el soporte en los diferentes browsers es cuanto menos sospechoso.

Para aprender más sobre Backbone

Es posible que este recurso vaya a estar disponible tan sólo de forma temporal en lo que sale a la venta la edición final del libro, pero a fecha de publicación de este post podemos leer y consultar el early release del libro Developing Backbone.js Applications de Addy Osmani, que será includo dentro de la serie de O’Reilly “Building Better JavaScript Applications”. Una oportunidad inmejorable de acceder de forma gratuita y legal un manual sobre Backbone con el sello de calidad de la que es, en nuestra opinión, la mejor editorial de libros de programación, O’Reilly.

En un aspecto más práctico, nos ha encantado este ejemplo de mini Webapp completamemte funcional, tanto el código fuente (y muy interesante fijarse no sólo en el código en sí, sino también en la estructuración de los archivos y “clases”) como el ejemplo funcional, algo más elaborado que el nuestro :P. Si os gusta como a nosotros aprender trasteando con código mejor que leyéndolo, este es un recurso sin duda impagable.

App de ejemplo en Backbone
App de ejemplo creada por David Morrow para enseñarnos Backbone

Genial también esta página llamada Backbone patterns donde podemos encontrar un manual de patrones de diseño, buenas prácticas en general, convenciones y otros aspectos de la programación de una webapp en Backbone.

Etiquetas: , ,

5 Comentarios
» Feed RSS de los Comentarios

  1. cristian cena dice:

    este artículo es una bendición, muchas gracias!!

  2. Wilson dice:

    Gracias por el articulo. me gusto.

  3. Jose Carlos dice:

    Gracias!!!!!!

  4. CM dice:

    Excelente, muy buen material

  5. Cookie dice:

    que grandes sois !!!!

Enviar comentario