Express, AngularJs y Nginx (en español)

Introducción

En varias oportunidades los requerimientos de algunos clientes obligan a retomar tecnologías, sea por facilidad para nosotros o algún pedido especial de parte de ellos. Yendo al grano, el objetivo de este post es explicar como utilizar en armonía las tecnologías de express.js , angular.js y nginx, no sin antes dar una pequeña descripción de cada tecnología, si conoces el alcance de cada uno de los instrumentos previamente mencionados, puedes pasar de este preámbulo.

Para descargar el proyecto completo, utiliza este repositorio: https://github.com/fabian818/express-conf/

Nota: No soy un experto en estas tecnologías, normalmente me desempeño en entornos RoR, pero dejo esta guía para uso y corrección libre del lector.
Nota2: Esta guía esta hecha sobre el entorno Elementary Os Freya, basado en Ubuntu 14.04.

Nginx

Es un servidor web/proxy inverso que se ha vuelto bastante popular en los últimos años, siendo su principal característica la velocidad para servir archivos estáticos. En esta ocasión lo utilizaremos como servidor web que manejará nuestras peticiones. Link: https://nginx.org/.

AngularJs

Framework Web Frontend aclamado por la gran comunidad dev frontend, siendo autodenominado por su soporte (Google) como el “framework superheróico”, en mi opinión es el framework más completo en lo que a frontend web compete.
PD: Es de mi conocimiento que Angular 2 es la opción de estos últimos tiempos, fue una decisión personal hacer la guía con Angular 1, sin embargo, la arquitectura permite que sea desarrollado con cualquier framework frontend.

ExpressJs

Framework Backend que brinda infraestructura para aplicaciones en node js, además de brindar herramientas (como todo framework) para agilizar el desarrollo y hacerlo más flexible.

Pero Fabian, si el fin de la guía es mostrar como funciona Angular en esta arquitectura, ¿Nó se podía hacer con node js y ya?

Sí, pero el fin de esta arquitectura es que en un futuro se aplique un servicio de api desde la misma aplicación para ser consumida por el frontend web o tal vez algún otro tipo de aplicación.

Fabian, la api también podía ser desarrollada usando sólo node js, no es necesario emplear un framework para eso.

También, sí, pero el desarrollo de una api en express es sumamente sencillo, sin perder tiempo en varias configuraciones con un código más limpio y flexible, además no será la única función que nos facilitará desarrollar a futuro.

Habiendo terminado la presentación, podemos pasar a la ejecución del proyecto.

Instalación de node js

Lo primero que debemos tener en cuenta es asegurarnos que estamos apostando por una manera de instalación segura, que a futuro no nos traiga problemas en cuanto a escalabilidad o siendo más exactos, versiones. Para eso utilizaremos una herramienta llamada nvm (node version manager) o manejador de versiones de node, así podemos utilizar node con versiones un poco más antiguas o modernas en diferentes proyectos, personalmente me brinda tranquilidad, y estoy seguro que a muchos más desarrolladores también.

Ejecutamos el comando, preferiblemente en la raiz de nuestro usuario:

curl https://raw.githubusercontent.com/creationix/nvm/v0.30.2/install.sh | bash

Como se puede apreciar es un comando para descargar un archivo directamente del proyecto de github de nvm, luego se ejecuta con el comando bash, en caso deje de funcionar el link por X razones, basta con buscar en el proyecto de github nvm y aplicar la misma lógica, confío en que el lector sabrá como resolver problemas de este tipo.

source ~/.profile

Este comando asegura que nvm se pueda ejecutar en cada sesión que se abra a partir de este momento en el equipo que estemos desarrollando (obviamente con el usuario con el que se instaló nvm).

nvm install 5.0.0

Para esta guía vamos a trabajar con la version 5, a mi parecer es una versión estable con la que no tendremos problemas.

nvm alias default node

Por último vamos a “setear” como “default”, o sea, definir por defecto a la versión actual, es decir, la versión 5.

Configuración y arquitectura del proyecto

Backend

Para configuración inicial del proyecto utilizaremos una estructura sencilla, y crearemos las siguientes carpetas:
-public
-routes
-views

Y los siguientes archivos:
-app.js
-package.json
-.gitignore

La carpeta public se utilizará para almacenar nuestros archivos estáticos, es decir, js, css, imágenes, fonts, y al decir js también hago referencia a la arquitecura de Angular.

La carpeta routes será empleada para contener a los archivos que definan a nuestras rutas, aquí posteriormente se escribirán las rutas de la api, pero por ahora, sólo redirecciona al ruteo que brinda Angular. Inicialmente tiene un sólo archivo “index.js”, cuya función es la de conectar con las rutas de Angular, y cuyo contenido se encuentra en: https://github.com/fabian818/express-conf/blob/master/routes/index.js.

La carpeta views sirve para contener a los archivos html del proyecto, no están dentro de public puesto que mientras mas escale el proyecto más será la cantidad de archivos html(partials, templates, layouts, etc) y me pareció necesario anticiparlo así. 
Nota: Para testear el proyecto podemos crear dentro de esta carpeta el archivo index.html, con algún “Hola mundo” de contenido.

<h1>Hola Fabian! </h1>

El archivo app.js es el archivo principal de node js, es en dónde se colocará la configuración raiz del proyecto y de donde el archivo que se ejecuta para que este inicie. El contenido documentado del archivo se encuentra aquí : https://github.com/fabian818/express-conf/blob/master/app.js

El archivo package.json es dónde están todas las dependencias del proyecto, es el que define que librerías de npm vamos a utilizar, y posteriormente se instalarán dentro del directorio node_modules. De igual manera el contenido del archivo está en el repositorio: https://github.com/fabian818/express-conf/blob/master/package.json

Por último, .gitignore es un archivo oculto que estamos creando para poder definir que NO vamos a incluir dentro del repositorio de git, en este caso será a la carpeta generada por package.json: node_modules, pues al ser un conjunto de librerías sólo hacen mas pesado el deploy, es mejor que cada entorno las obtenga por su cuenta (ejecutando package.json). El contenido en esta dirección: https://github.com/fabian818/express-conf/blob/master/.gitignore

Ahora que tenemos la infraestructura correctamente definida, encapsulamos todo en un repositorio de git y si queremos hacer deploy (como se indica al final) tal vez sea necesario incluirlo en un repositorio remoto como github. De igual manera, aquí la guía oficial de cómo realizar la tarea: https://help.github.com/articles/adding-an-existing-project-to-github-using-the-command-line/

Y… probamos que nuestro proyecto no tenga errores. Ejecutamos en la raiz del proyecto.

npm install
node app.js

Se debería visualizar un gigante “Hola Fabian!” en la dirección de http://localhost:3000/

Frontend

Obviamente cuando nos referimos al frontend, nos estamos refiriendo a la arquitectura y configuración de Angular Js, la parte de cliente, cuya distribución afortunadamente es bastante sencilla, apoyándonos en el patrón MVC. Nos centraremos en public/js/ donde estarán los archivos javascript que configuren Angular.

Nota: Como expliqué al inicio del post, se puede utilizar cualquier framework o arquitectura de frontend, aplicando el js en public/ y las vistas en views/ ya que este proyecto ha sido escrito de la manera más flexible posible.

App.js

La parte principal es el archivo de configuración del módulo de Angular: public/js/app.js cuya descripción y documentación está en el siguiente archivo del respositorio: https://github.com/fabian818/express-conf/blob/master/public/js/app.js

Este archivo tiene dos partes, las referencias del módulo y la definición de rutas, en esta ocasión se utiliza ngRoute, dentro del link de github está el archivo con la explicación de cada línea de código.

Controllers, Directives, Services and Filters

Son las partes secundarias de la arquitectura frontend, contienen a los controladores, filtros, servicios y directivas. Representan la MV de MVC.

Los controladores son los encargados de manejar la lógica de las vistas y las redirecciones, además de consumir los servicios. Nuestros controladores estan aquí: https://github.com/fabian818/express-conf/blob/master/public/js/controllers.js

Los filtros son los homólogos de los helpers, métodos que sirven de apoyo para las vistas, por ejemplo convierten texto en las vistas de: 4345, a un formato de dinero $4,345 , sin necesidad de llenar el controlador o la vista de lógica innecesaria. Los filtros del proyecto: https://github.com/fabian818/express-conf/blob/master/public/js/filters.js

Los servicios son la M de MVC, nos brindan la capacidad de consumir servicios http, por ejemplo. De igual manera desarrollar métodos que puedan se consumidos de apoyo por el controlador. Los servicios del proyecto: https://github.com/fabian818/express-conf/blob/master/public/js/services.js

Por último las directivas, son etiquetas, clases o atributos html que podemos personalizar para poder dar más reusabilidad a la vista, por ejemplo puedo definir una etiqueta <card></card> y puedo llamarla desde cualquier vista, siendo un card una vista elaborada, con la facilidad de solo referenciar a dicha etiqueta. Las directivas del proyecto :https://github.com/fabian818/express-conf/blob/master/public/js/directives.js

Vistas, parciales y layout

Nuestras vistas de todo tipo, como se dijo anteriormente, se encuentran en la carpeta views, nuestro layout es el archivo index.html, y nuestros archivos parciales están dentro de la carpeta partials/, el contenido sw index.html se encuentra aquí: https://github.com/fabian818/express-conf/blob/master/views/index.html

En resumen el archivo index.html se resume en tres partes, en el head nuestras referencias, en el body el ng-view que se encarga de traer a todos los archivos parciales dependiendo de las ruta (en nuestro ejemplo page1 y page2), debajo tenemos las referencias a nuestros demás archivos, aquí hay una aclaración.

Estas son todas las referencias.

En la configuración del backend, en el archivo app.js de node, se convirtió a dos carpetas en servidores de archivos estáticos: node_modules/ y public/

Conversión de public y node_modules a servidores de archivos estáticos.

Quiere decir que ahora node_modules y public están fusionados en un sólo servidor de archivos estáticos es por eso que en las referencias de index.html sólo se nombra a las carpetas pero no ‘public’ o ‘node_modules’.

Si colocamos los archivos parciales tal como está en el respositorio: https://github.com/fabian818/express-conf/tree/master/views

Y ejecutamos el comando:

node app.js

Se debería visualizar en la ruta definida en frontend http://localhost:3000/page1 algo similar a esto:

Página 1 correctamente ruteada por Angular.

Y si hemos configurado todo correctamente hasta ahora, podríamos linkear libremente entre page1 y page2.

Hasta aquí tenemos todo lo referente a arquitectura de desarrollo, pero de nada nos sirve tener una aplicación en nuestro ordenador, donde nadie más lo puede ver, así que el siguiente paso es la publicación, el despliegue de nuestro trabajo, el deploy.

Deploy

Configuración del entorno

Para demostrar el despliegue de la aplicación nos valdremos de un VPS comprado en Digital Ocean, por dentro las herramientas de pm2 para “daemonization” (no estoy seguro de si tiene una traducción exacta al español), este proceso consiste en que los procesos se ejecuten en background, sin necesidad de tener abierta una terminal; y nginx, como servidor web que gestione las peticiones, así que manos a la obra.

Instalar repositorio

En alguna parte de nuestro servidor instalamos nuestro repositorio, en éste caso:

git clone https://github.com/fabian818/express-conf

PM2

Esta herramienta requiere ser instalada por medio de npm, así que debemos instalar npm también en nuestro servidor, de la misma manera que lo hicimos en el entorno local. Luego ejecutamos para instalar de manera global:

npm install -g pm2

Nos ubicamos en la raiz de nuestro proyecto y ejecutamos para levantar el servidor:

pm2 start app.js

Ahora nuestro servidor está corriendo en http://ip.del.servidor/:3000 donde podemos ver nuestra aplicación. Pero necesitamos que nuestra aplicación se levante cada vez que el VPS se reinicie, para ello hacemos un job con una herramienta de pm2.

pm2 startup ubuntu

Lo cuál generará los archivos necesarios para automatizar el levantamiento de la aplicación y finalmente:

pm2 save

Para guardar la configuración del job, con esto la aplicación estará corriendo indefinidamente, hasta que, claro, paremos el proceso manualmente (pm2 stop id), pero para eso leer la guía del pm2.

Nginx

El paso final es la instalación y configuración de nginx, para lo cual empezamos con:

sudo apt-get install nginx

Con esto tenemos el nginx listo para usar, hasta podemos visualizar en la dirección de nuestro servidor la página de bienvenida de nginx. Pero lo que nosotros necesitamos es visualizar nuestra página directamente de la ip de nuestro servidor(o un dominio), para ello ubicamos el archivo de configuración de nginx en /etc/nginx/sites-available/default y lo editamos:

sudo nano /etc/nginx/sites-available/default

Donde sólo debe quedar esto:

server { 
 listen 80;

location / {
 proxy_set_header X-Real-IP $remote_addr;
 proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 proxy_set_header Host $http_host;
 proxy_set_header X-NginX-Proxy true;
 proxy_pass http://127.0.0.1:3000; #Aquí la magia
 proxy_redirect off;
 }
}

La configuración de nginx nos indica que el servidor debe escuchar en el puerto 80, el predeterminado para peticiones http, y que redireccionará estas al puerto 3000 donde está corriendo nuestra aplicación node js.

Hacemos un enlace del archivo default:

sudo ln -s /etc/nginx/sites-available/default /etc/nginx/sites-enabled

Y recargamos nginx para que se muestren los cambios:

sudo service nginx reload

Con esto, habremos terminado de hacer el deploy de nuestro aplicación, cada vez que hagamos un nuevo despliegue debemos reiniciar el pm2 y el nginx. Recuerda que para descargar el proyecto completo, debes acceder aquí: https://github.com/fabian818/express-conf/

Conclusión

El desarrollo de aplicaciones debe de hacerse pensando en que una tecnología puede ser reemplazada por otra en cualquier momento del ciclo de vida de una aplicación, ninguna debe depender de otra, es por ello que la arquitectura flexible de una solución es importante. Con este mensaje me despido y recuerdo al lector que no soy un experto en estas tecnologías, si hay una corrección será bienvenida y valorada. Happy code. NoFear Code.

One clap, two clap, three clap, forty?

By clapping more or less, you can signal to us which stories really stand out.