Estructura de archivos para proyectos con backbonejs

Estructurando un proyecto de backbonejs

Estructurando un proyecto de backbonejs

No me jactaré de ser el más habilidoso con backbonejs, ya que hace algunas semanas empecé a utilizarlo, lo conozco desde hace mucho y alguna vez lo comparé contra batmanjs y emberjs, pero ahora que he estado desarrollando API’s, es que me he visto en la necesidad de llegar a utilizar una librería como backbonejs que me ayude a gestionar toda la lógica de una aplicación clientside.

En mi aprendizaje que fue bastante rápido por cierto, casi desde el primer día intenté organizar los diferentes archivos generados en mi proyecto, de modo que me fuera familiar al uso del MVC al que estoy muy acostumbrado por los diferentes frameworks en varios lenguajes. Este es una estructura básica de un proyecto en backbone, que considero bastante ordenada:

backbonejs structure

backbonejs structure

Se que hay algunas librerías como marionettejs y chaplinjs, las cuales se hicieron precisamente para mantener organizado todo el código, pero también al utilizarlas se agrega un nivel más de complejidad, ya que en esas librerías introducen nuevas clases y lógicas de programación que hacen que la curva de aprendizaje sea un poco mayor (lo digo con experiencia porque también he utilizado marionettejs).

Entonces intentaré explicar y detalles cada uno de los archivos, para empezar tengo una carpeta llamada app que es donde están todos los archivos de mi proyecto.

Luego el primero archivo es mi index.html, ese es básico y desde ahí es donde incluyo el archivo principal llamado app.js .. y claro, utilizo también bower para administrar los paquetes que estaré utilizando y requirejs para cargar los diferentes módulos o paquetes que haya descargado con bower.

index.html

<!DOCTYPE html>
<html>
<head>
    <title>CMS Demo</title>
    <link href="styles/main.css" rel="stylesheet" />
</head>
<body>
    <div class="page-content" id="page-content"></div>
    <script data-main="scripts/app.js" src="scripts/vendor/requirejs/require.js"></script>
</body>
</html>

bower.json

{
  "name": "test cms",
  "version": "0.0.1",
  "authors": [
    "jackfiallos <erling.fiallos@qbit.com.mx>"
  ],
  "description": "CMS Demo",
  "keywords": [
    "cms",
    "module"
  ],
  "license": "MIT",
  "homepage": "http://qbit.com.mx",
  "dependencies": {
    "jquery": "~1.9.1",
    "backbone-amd": null,
    "underscore-amd": null,
    "requirejs": null,
    "requirejs-text": "~2.0.12",
  },
  "ignore": [
    "**/.*",
    "node_modules",
    "bower_components",
    "test",
    "tests"
  ]
}

.bowerrc

{
    "directory": "scripts/vendor"
}

Como verán bower.json tiene la definición de todos los paquetes que estoy utilizando en mi proyecto y .bowerrc tiene la definición de donde se descargarán dichos paquetes.

El archivo app.js contiene la definición de todos los paquetes que deseo incluir en el proyecto e incluye el manejo de rutas, que en este caso solamente manejo la ruta de la página principal.

app.js

require.config({  
	paths: {
		'jquery': 'vendor/jquery/jquery',
		'underscore': 'vendor/underscore-amd/underscore',
		'backbone': 'vendor/backbone-amd/backbone',
		'text': 'vendor/requirejs-text/text',
		'templates': 'layouts',
		'collections': 'collections'
	},
	shim: {
		underscore: {
			exports: '_'
		},
		backbone: {
			exports: 'Backbone',
			deps: ['jquery', 'underscore']
		}
	},
	deps: ['jquery', 'underscore']
});
 
require(['backbone', 'views/home'], function(Backbone, HomeView) {
	var home = new HomeView();
 
	var Router = Backbone.Router.extend({
		routes: {
			'': 'home'
		}
	});
 
	var route = new Router();
	route.on('route:home', function() {
		home.render();
	});
 
	Backbone.history.start();
});

Ahora, presenten atención al la inclusión del archivo ‘views/home’, puesto que ahí se encuentra la lógica para manejar la vista home (que dicho sea de paso es nuestra vista principal).

views/home.js

define([
    'backbone', 
    'underscore', 
    'collections/postsCollection',
    'text!templates/home.tmpl'], function(Backbone, _, PostsCollection, homeTemplate) {
 
    var HomeView = Backbone.View.extend({
        el: '.page-content',
        render: function() {
            var that = this;
            var posts = new PostsCollection();
 
            posts.fetch({
                success: function(posts) {
                    var template = _.template(homeTemplate, {
                        posts: posts.models
                    });
                    that.$el.html(template);
                }
            });
        }
    });
 
    return HomeView;
});

En el orden de ejecución, primero se ejecutó app.js, luego views/home.js y ahora se ejecutará postCollection.js, que haciendo fetch irá a la dirección definida en la propiedad url y traerá los datos que necesito para la página principal (en este caso lo configuré para que busque todos los repos de Qbit Mexhico en github).

postsCollection.js

define(['backbone'], function(Backbone) {
    var PostsCollection = Backbone.Collection.extend({
        url: 'https://api.github.com/users/qbitmexhico/repos',
        initialize: function() {
            console.log('postsCollection loaded');
        },
    });
 
    return PostsCollection;
});

Y por último, desde views/home.js indicamos que al responder el fetch pinte el resultado en una plantilla y es ahí donde entra el uso de layouts/home.tmpl, donde básicamente enviamos el resultado de los repos encontrados y se dibujarán en una tablita.

layouts/home.tmpl

<h3>Lista de publicaciones</h3>
 
<table>
    <thead>
        <tr>
            <th>Fecha de Creaci&oacute;n</th>
            <th>T&iacute;tulo</th>
            <th>Es privado</th>
        </tr>
    </thead>
    <tbody>
        <% _.each(posts, function(post){ %>
            <tr>
                <td><%= post.get('created_at') %></td>
                <td><a href="#"><%= post.get('name') %></a></td>
                <td><%= post.get('private') %></td>
            </tr>
        <% }) %>
    </tbody>
</table>

Y listo, ahí termina lo básico, la idea es que vean que no es necesario tener en un solo archivo toda la lógica de un módulo o aplicación, quizás para este pequeño ejemplo tener tantos archivos y carpetas parezca una tontería, pero para proyectos más grandes agradecerán tener todo organizado.

Por ahí dejé pendiente el uso de ‘model/post.js’, pero no lo utilicé porque para hacerlo debería utilizar altas, bajas y edición y vista (CRUD) y eso extendería mucho más mi artículo, considero que no es necesario porque habrán entendido el punto, que precisamente era la organización del código en proyectos con backbone.

Espero que esto les ayude de algo y si tienen alguna recomendación para mi, adelante que todo es bienvenido y como les digo, uso mucho javascript, pero en backbonejs son relativamente nuevo.

Happy coding!

Co-fundador de Qbit Mexhico, usuario de linux, Developer en tecnologías web.. Nicaragüense, centro en basketball, primer centro en rugby y pintor los fines de semana. Ortögrafo y ambientalista psicológico (de escritorio).. ese soy yo!

Si te ha servido compártelo y difunde nuestro blog..

Facebook Twitter LinkedIn Google+ Flickr YouTube Skype 

Compartir en...Tweet about this on TwitterPin on Pinterest0Share on LinkedIn1Share on Google+0Share on Facebook0