Crear una app NodeJS con Express Generator

Aquí en mi página, malnuer, ya hemos visto cómo instalar NodeJS y cómo hacer un par de cosillas básicas con ExpressJS, pero ahora vamos a ir un poco más allá y vamos a montar un proyecto web usando la utilidad Express Generator, que creará para nosotros toda la estructura de carpetas, archivos y dependencias. ¿Empezamos?

Bien, voy a dar por hecho que tienes instalado NodeJS incluyendo el NPM (si no es así, o no estás seguro, puedes seguir los pasos que vienen aquí), también voy a suponer que sabes qué es ExpressJS y que incluso has visto un poco de qué va (si no es el caso, te vendría bien leer esto antes).

Instalar Express Generator

ExpressJS es un framework para NodeJS que nos sirve de base para hacer páginas web, pero necesita algunos complementos adicionales si queremos trabajar con más comodidad ciertos aspectos típicos, como son: servir el favicon, el manejo de las cookies, los datos de las peticiones POST, hacer debug o usar un motor de plantillas. El hecho de que estos complementos no vengan incluidos por defecto dentro Express tiene la ventaja de que podremos controlar si preferimos los recomendados, queremos usar otros o simplemente no queremos usar cierta característica.

Si queremos usar los complementos recomendados para ExpressJS y además queremos seguir las buenas prácticas sugeridas, entonces lo mejor será usar Express Application Generator, que es una utilidad que nos construirá la estructura básica de carpetas, además del archivo package.json para la inclusión de las dependencias y los archivos mínimos para poner en marcha tu aplicación.

Vamos a instalar express-generator con NPM:

npm install express-generator -g

Lo instalamos en global (-g) ya que así podemos usarlo en cualquier sitio desde la línea de comando y no sólo desde la carpeta donde lo hayamos instalado. Además, lo vamos a usar una sola vez, así que no nos interesa tenerlo dentro del proyecto todo el tiempo.

Usar Express Generator para crear una App

Cuando acabe de instalarse vamos al sitio donde queramos crear nuestro proyecto, al que llamaremos «miweb» por ejemplo, y ejecutamos esta línea:
(Esto creará una carpeta llamada «miweb» con toda la estructura dentro)

express --ejs miweb

Nota: la opción –ejs sirve para indicar que queremos usar el motor de renderizado EJS en vez de Jade que es el que viene por defecto. Lo he elegido así porque si estás empezando con ExpressJS, seguramente usar EJS te resulte más sencillo que Jade, ya que es más parecido a usar el HTML de toda la vida. Para más información sobre Express Generator y sus opciones de uso, consulta su web oficial.

Ahora tendrás una carpeta llamada «miweb» con todo preparado según las buenas prácticas. Además habrá un archivo package.json en el que habrá una lista de todos los módulos necesarios para que la aplicación funcione. Estos módulos son los que se sugiere incluir para trabajar cómodamente con ExpressJS, aunque como he comentado antes, hay cierta libertad (nosotros por ejemplo hemos cambiado el motor de plantillas). Estos módulos están ahí indicados, pero todavía no están instalados, vamos a hacerlo:

cd miweb
npm install

Cuando ejecutamos la orden «install«, NPM leerá el archivo package.json y comprobará si ya se han descargado los paquetes necesarios. Si alguno no está, se descargará, y si hay versiones nuevas también se actualizarán. Otra cosa para la que sirve este archivo es para informar del nombre de la App, la versión y qué archivo es el punto de entrada de ejecución:

{
  "name": "miweb",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node ./bin/www"
  },
  "dependencies": {
    "body-parser": "~1.13.2",
    "cookie-parser": "~1.3.5",
    "debug": "~2.2.0",
    "ejs": "~2.3.3",
    "express": "~4.13.1",
    "morgan": "~1.6.1",
    "serve-favicon": "~2.3.0"
  }
}

En azul he marcado las dependencias que necesita nuestro proyecto para funcionar y la versión mínima que queremos de cada uno. Ahí puedes ver que evidentemente hace falta Express y que también aparece EJS entre otras cosas. También en naranja he marcado el punto de entrada, que resulta ser un archivo llamado www que se encuentra en la carpeta bin.

Poner en marcha la App de Express Generator

Pues si ya que tenemos todo instalado, vamos a ponerlo en marcha, y para eso, ya que el package.json sabe cómo hacerlo, mejor será que lo haga él y así no tenemos que acordarnos nosotros de cuál era el archivo de entrada. Ejecuta esto:

npm start

Aparecerá algo parecido a «miweb@0.0.0 start C:\miweb node ./bin/www«, y eso quiere decir que ya tenemos nuestra aplicación funcionando en el puerto 3000. Vamos a echarle un vistazo desde el navegador. Ve a la dirección: localhost:3000. Si aparece algo como «Express Welcome to Express«, es que todo va bien. Además en la consola verás que se van escribiendo todas las peticiones y respuestas que se han atendido. Seguramente con la respuesta HTTP 200. Las siguientes veces que lo ejecutes es posible que aparezca 304 (not modified) que significa que se está usando la caché.

Funciona, pero ¿cómo funciona? Vamos a verlo.

Entendiendo Express Generator

Empecemos por la estructura de carpetas y archivos. Tenemos 5 carpetas: bin, node_modules, public, routes y views.

Carpetas de Express Generator

Vista de las carpetas de proyecto Express

  • bin: Es una carpeta de asuntos generales. Aquí puedes guardar los archivos que contengan funciones y cosas de uso general.
  • node_modules: Aquí es donde el NPM guarda todos los módulos de los que depende el proyecto de Express Generator. Mejor que no toques nada, eso es territorio del NPM.
  • public: Esta carpeta estará accesible públicamente, por lo que es el sitio ideal para los CSS, las imágenes, los JS (los que se usen en el navegador) o archivos descargables.
  • routes: Aquí se describen todas las posibles rutas accesibles de la web. Es una carpeta porque pueden organizarse en distintos archivos para mejor organización.
  • views: Este es el sitio para las plantillas de las páginas y serán usadas por el motor de plantillas elegido, que en nuestro caso ha sido EJS.

Entonces, ¿qué pasa cuando se activa la aplicación? Pues todo empieza con el ya citado archivo www que está en la carpeta bin. Si miramos ahí dentro, la primera línea que vemos es:

var app = require('../app');

Que nos lleva directamente al archivo app.js de la carpeta superior. Así que vamos para allá. Voy a poner aquí solamente las cosas que me parecen interesantes para explicar y dejaré a un lado las cosillas menos importantes por ahora.

var express = require('express');

...

var routes = require('./routes/index');
var users = require('./routes/users');

var app = express();

...

app.use('/', routes);
app.use('/users', users);

...

module.exports = app;

Las líneas en azul, son las básicas para poner en marcha ExpressJS como vimos en el artículo anterior «Introducción a Express«, y lo que nos faltaría por hacer es asociarle las rutas y ponerlo a escuchar en un puerto determinado. La línea que hace que se ponga a escuchar no está en este archivo, se hará después en el www, es por esto que se hace el module.exports para que lo pueda recibir. Así que vamos a ver qué pasa con las rutas.

Las líneas en naranja, son las que se encargan de asociar las rutas, pero como ya te habrás imaginado, las rutas no están definidas en este archivo, se encuentran en otros archivos dentro de la carpeta «routes«. Nos vamos a centrar en las rutas del archivo index.js y luego mencionaré algo del otro archivo, aunque básicamente funcionan igual.

Veamos qué hay dentro del archivo index.js:

var express = require('express');
var router = express.Router();

/* GET home page. */
router.get('/', function(req, res, next) {
 res.render('index', { title: 'Express' });
});

module.exports = router;

Si revisas lo que hicimos en el artículo de introducción a Express, verás que las rutas las asociabamos directamente al objeto «app» usando por ejemplo la función «app.get()«. Ahora con el proyecto de Express Generator lo vamos a hacer de una forma más organizada. Declaramos un objeto «router» y lo usamos para asignarle las rutas con «router.get()«. Después asociamos este objeto «router» al objeto «app» con la función «app.use()«. Realmente viene a ser lo mismo pero con un objeto intermedio:
(A la izquierda usando app directamente y a la derecha con un router intermedio)

Comparación usar App o Router en Express

Comparación de declaración de rutas con App y Router

En este archivo index.js, solamente creamos el «router«, le asignamos las posibles URLs y sus funciones asociadas (en naranja), y lo devolvemos con module.exports para que lo reciba el archivo app.js. Así que en el app.js recogemos el router y lo usamos con el app:

var routes = require('./routes/index');
...
app.use('/', routes);

Bien, esto es lo que hemos hecho con con el archivo index.js donde podremos definir todas las rutas públicas de nuestra web. Entonces ¿para qué sirve el archivo users.js? Pues para lo mismo, pero para una sección privada (necesario login), o cualquier otra parte de la web que tenga características distintas. Al estar en otro archivo podemos asignar rutas y middlewares concretos y tenerlo todo más ordenado. Al crear el proyecto con Express Generator se crean estos dos archivos index.js y users.js para que veas la diferencia, pero podrías tener muchos más o tener sólo uno.

Ten en cuenta que si en el app.use() ponemos una URL distinta de «/«, esta se usará como base para todas las rutas definidas con el router.get(). De manera que si lo que tenemos es esto:

var users = require('./routes/users');
...
app.use('/users', users);

Todas las rutas definidas dentro del archivo users.js se encontrarán dentro de la URL «/users«.

Usar EJS para renderizar una plantilla

Sólo nos queda una cosa por mencionar, que es cómo funcionan las plantillas de EJS. Por suerte es muy sencillo. Veamos el ejemplo: (recuerda que Express Generator nos permite usar EJS o Jade, y nosotros hemos elegido EJS)

res.render('index', { title: 'Express' });

Aquí res es el objeto response que se recibe en las funciones de manejo de las rutas. Usamos la función res.render() y le pasamos el nombre de la plantilla (que será un archivo con extensión ejs), y un objeto con las variables que se usarán dentro de dicha plantilla. Esto funciona porque lo hemos configurado previamente en el archivo app.js con estas líneas:

var path = require('path');
...
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'ejs');

Nota: el objeto path sirve para hacer operaciones con strings que contienen URLs y rutas de archivos (más información sobre path), y __dirname es una variable global de Node (más información sobre variables globales).

La primera línea de app.set() informa de cuál es la carpeta de plantillas y la segunda de cuál es la extensión que tienen estos archivos de plantilla. Más información sobre la función app.set().

Las plantillas de EJS son fáciles de usar. Haces la página normal con HTML y usas los tags <%= nombre_variable %> para renderizar variables. Como puedes ver en el ejemplo:

<!DOCTYPE html>
<html>
  <head>
    <title><%= title %></title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>
    <h1><%= title %></h1>
    <p>Welcome to <%= title %></p>
  </body>
</html>

Nota: EJS permite hacer muchas otras cosas más, también fáciles, que puedes consultar en su página web: http://ejs.co/http://www.embeddedjs.com/.

Fíjate en la ruta que se ha usado para el archivo style.css. Aquí se ve que estamos accediendo a la carpeta public que es donde está la carpeta stylesheets, pero no nos hace falta poner public. Esto funciona gracias a la línea de configuración del archivo app.js:

app.use(express.static(path.join(__dirname, 'public')));

Nota: Esta línea ya se comentó en el artículo anterior sobre ExpressJS

¿Qué nos ha quedado sin comentar?

Este artículo se está haciendo muy largo y lo principal ya está comentado. Se podría profundizar mucho más en ExpressJS y en cómo funciona el proyecto creado por Express Generator, por supuesto, pero lo haré en otros artículos. ¿Qué se ha quedado en el tintero? Pues revisando por encima el archivo app.js, veo que hay configuraciones para:

  • Servir el favicon: (hay que descomentar la línea cuando tengamos el archivo favicon.ico en la carpeta public)
  • var favicon = require('serve-favicon');
    ...
    // uncomment after placing your favicon in /public
    //app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
    
    
  • El logger Morgan, que se encarga de que aparezca información en la consola en tiempo real:
  • var logger = require('morgan');
    ...
    app.use(logger('dev'));
  • El Cookie Parser, para manejar las cookies con comodidad:
  • var cookieParser = require('cookie-parser');
    ...
    app.use(cookieParser());
  • El Body Parser, para manejar los datos Post:
  • var bodyParser = require('body-parser');
    ...
    app.use(bodyParser.json());
    app.use(bodyParser.urlencoded({ extended: false }));
  • Lo demás son detecciones de errores 404 o 500

Esto es todo por ahora, gracias por leer este artículo y si te ha quedado alguna duda, comenta.

Share on FacebookShare on Google+Tweet about this on TwitterShare on LinkedIn