Introducción a Express (parte 1)

Introducción a Express (parte 1)


Como lo prometido es deuda, aquí; comienzo mi primer post orientado al desarrollo con Node.Aunque bajo mi punto de vista y por l que he leido hasta ahora, lo que mejor hace (Node)[http://nodejs.org/] no es servir paginas web; pero claro yo soy muy cabezon (y creo que no soy el único que lo piensa) y mi primer contacto con Node lo he orientado a servir contenidos Web

Leyendo un libro bastante didáctico además de cortito llamado "Node for front-end developers" y googleleando un poco, os dareís cuenta de que en Node disponemos de un millar de librerías en npm enfocadas al desarrollo web, aunque finalmente es Express la más extendida.

En esta primera parte hablaré un poco de la estructura básica de un proyecto Express y en futuros post iré entrando en más detalle de cada uno de los elementos de Express

Express es un framework (que aplica MVC) basado principalmente en Connect, además de varias librerías y utilidades que nos permiten desarrollar webs de una forma bastante sencilla.

Podeis encontrar infinidad de documentación sobre como iniciar un proyecto Express (la documentación oficial es bastante buena), aunque al final se reduce a escribir en linea de comandos:

~ $ sudo npm install -g express
~ $ mkdir mysite
~ $ cd mysite
~ $ express --sessions
~ $ npm install express jade

Esto da lugar a la siguiente estructura de directorios dentro de nuestro directorio mysite:

  • public/: contenidos estáticos CSS, JS, imagenes y otros.
  • routers/: controladores, básicamente el código que gestiona cada pagina.
  • views/: vistas, plantillas que serán usadas para mostrar los contenidos. Por defecto, si no determinamos el motor de plantillas Express usa Jade.
  • app.js: Núcleo y configuración de nuestra aplicación Express

Centrandonos en nuestro fichero app.js, observamos que esta dividido en cuatro secciones bien diferenciadas:

Configuración global

app.configure(function(){  
    app.set("port", process.env.PORT || 3000);
    app.set("views", __dirname + "/views");
    app.set("view engine", "jade");
    app.use(express.favicon());
    app.use(express.logger("dev"));
    app.use(express.bodyParser());
    app.use(express.methodOverride());
    app.use(express.cookieParser("your secret here"));
    app.use(express.session());
    app.use(app.router);
    app.use(express.static(path.join(__dirname, "public")));
});

En este bloque se configura todo el objeto Express de nuestro site haciendo uso de:

  • set, que permite configurar valores que más tarde usaremos, como puede ser el puerto o valores de configuración usados por Express. Un ejemplo es app.set('view engine', 'jade'); el cual configura el motor de plantillas por defecto.
  • use, con el que agregamos funciones denominadas "middleware" utilizadas para incorporar nuevas funcionalidades (plugins) a nuestra configuración, como es el caso de app.use(express.static(path.join(__dirname, 'public'))); que define la ruta desde donde los contenidos estáticos publicados será servidos.

Configuración de entorno

app.configure("development", function(){  
    app.use(express.errorHandler());
});

Esta configuración será cargada de manera opcional y solo cuando la variable de entorno NODE_ENV haya sido definida(más información). Por defecto Express usará "development". Para cambiar de una configuración a otra, basta con cambiar el valor de la variable NODE_ENV por el valor definido en nuestra configuración, tal y como se muestra en este ejemplo en el cual usamos la configuración de producción(si existiera):

~ $ NODE_ENV=production node app.js

Volviendo al primer ejemplo, observamos app.use(express.errorHandler()); el cual permite configurar el gestor de excepciones por defecto para nuestra aplicación y que por defecto en Express muestra una pantalla con la traza completa del error. Para cambiarlo, solo tenemos que agregar una función con cuatro parametros que son error, request, response, next y agregar el código para gestionar nuestro error; como por ejemplo (parte del que yo mismo uso):

app.use(function(error, request,response,next){  
    console.log(request.method, "500", request.url, error.stack);
    data.title = 500;
    data.error = "Something broke!";
    response.status(500).render("error", data);
}); 

Mapeos de routes

Los routes o controladores gestionan los contenidos asociados a una ruta o conjunto de las mismas. En el siguiente fragmento de código:

// file top
var routes = require("./routes"),  
user = require("./routes/user")  
...

app.get("/", routes.index);  
app.get("/users", user.list);  

en primer lugar realizamos una llamada a función require sobre el directorio routes y routes/user(escribiré un post sobre la carga de modulos en Node para aclarar esto) donde se guardan los controladores definidos en los ficheros routes/index.js y routes/user.js y los vincula a las variables routes y user respectivamente.

require enlaza a la variable cualquier función u objecto dentro del fichero siempre y cuando fuera referenciado en el objeto exports:

// exports gives us access to index function
exports.index = function(req, res){  
    res.render("index", { title: "Express" });
};

Por defecto cada route que definimos debe de tener la siguiente signatura de función recibiendo como entrada los objectos request y response. El resto dentro de nuestra función será cosa nuestra aunque eso sí, es importante terminar invocando a:

  • render, que recibe como parametros el nombre de la plantilla sin extensión (disponible en views), un JSON con los valores usados en el motor de plantillas y si se desea la función de callback. Podeis verificar su uso ejemplo anterior.
  • send, util para remitir códigos de error HTTP y emitir contenidos sin hacer uso del motor de plantillas.

Configuración del servidor

No difiere mucho del tipico createServer de Node, solo que en vez de agregar nuestra propia función, agregamos el objecto application de Express

/* 
// Normal node create server
http.createServer(function (request, response) {  
    response.writeHead(200, {"Content-Type": "text/plain"});
    response.end("Hello World\n");
}).listen(8124);
*/

// Express create server
http.createServer(app).listen(app.get("port"), function(){  
    console.log("Express server listening on port " + app.get("port"));
});

Arrancando nuestro proyecto

Para terminar solo nos queda arrancar nuestro servidor con un simple node app.js en linea de comandos y abrír la URL 0.0.0.0:3000 (si estaís de forma local) en nuestro browser favorito.

Bueno, se que ha sido breve pero pronto agregaré nuevos post para ir completado lo ya descrito. Espero que lo hayais disfrutado.