Ejemplos de Node.js Express: sitios web renderizados, REST y estáticos

El desarrollo web ha recorrido un largo camino desde el auge de WWW a finales de los 90. Nosotros, como desarrolladores, ahora tenemos infinitos recursos y herramientas a nuestra disposición. La pura inversa...

El desarrollo web ha recorrido un largo camino desde el auge de WWW a finales de los 90. Nosotros, como desarrolladores, ahora tenemos infinitos recursos y herramientas a nuestra disposición. La gran versatilidad que tenemos es alucinante.

Con el auge de Node.js y npm, JavaScript se ha convertido de facto en el lenguaje de programación más utilizado en el mundo. Es como todos los días aparece un nuevo marco. Molesto como el infierno, lo sé. Pero, subámonos al tren de la exageración y veamos cómo crear cosas geniales con Node.js. Si aún no lo has probado, te encantará, ¡estoy seguro!

Hoy crearemos cuatro tipos diferentes de aplicaciones utilizando Express.js, el marco de Node.js más popular.

Antes de comenzar, hay un par de cosas que debemos repasar con respecto a Node.js y Express, solo para orientarnos correctamente.

Mójate los pies

Node es un tiempo de ejecución de JavaScript asincrónico basado en eventos creado en el motor de JavaScript V8 de Chrome. Está diseñado para crear aplicaciones de red escalables. JavaScript es de un solo subproceso, por lo que la fuerza de Node radica en su naturaleza asíncrona. Maneja eventos sin bloquear el hilo principal de ejecución. Esta es la razón por la que Node es increíblemente rápido, porque puede manejar conexiones al mismo tiempo.

La verdadera razón por la que Node.js explotó y se volvió tan popular como lo es hoy es el administrador de paquetes que viene con el viaje. NPM es el principal lugar de encuentro de todos los paquetes de Node, de ahí su nombre. Administrador de paquetes de nodos, ¿duh? Aquí puede encontrar varios módulos de código para usar en sus aplicaciones, o publicar los suyos propios si así lo desea.

Uno de estos módulos es Express.js, un marco web minimalista súper popular para crear rápidamente aplicaciones Node.js. Express es hoy el marco principal de facto para usar con Node.js. Con mucha razón de hecho. Solo proporciona una capa delgada de abstracción fundamental sin cambiar las características principales por las que Node es famoso. Facilita la creación de aplicaciones web y API REST con poca o ninguna molestia. ¡Tan fácil de hecho que muchos otros marcos se basan en Express!

Ahora se pregunta qué tipo de aplicaciones puede incluso crear con Express. Tomemos un segundo para hablarlo. ¿Cuáles son los tipos principales que admite la web? Hay aplicaciones con páginas HTML procesadas por el servidor, que serán familiares para algunos de ustedes, programadores de la vieja escuela. Esta era la forma predeterminada de crear aplicaciones en la era del bombo anterior a JavaScript.

Luego tenemos las API REST. Por lo general, se usan para enviar y recibir cargas útiles de JSON, generalmente hacia y desde una base de datos u otro servicio.

Por último, tenemos sitios web estáticos simples. En este escenario, Express se usa para activar un servidor y servir estos archivos. Es una forma rápida de crear páginas de destino o páginas de marketing para empresas y empresas emergentes.

Saltar de cabeza

Aprender haciendo es, con mucho, el mejor principio para aprender algo nuevo, especialmente en programación. Vamos a sumergirnos y explicar las cosas en el camino.

Aplicaciones procesadas por el servidor

Puedes adivinar cómo funcionan estas aplicaciones por el título, ¿verdad? Las páginas HTML representadas en el navegador de un usuario se generan y representan en el servidor. Este proceso se denomina representación del servidor. Las aplicaciones como estas consisten en motores de plantillas y plantillas. Los motores generan la página HTML final que se representará. Algunos motores populares incluyen Jade, Pug y EJS.

¿Qué tienen de especial estos motores? Tienen una cosa elegante llamada interpolación. Permite insertar variables en una plantilla o cadena. Como este ejemplo con Jade: Hola #{mundo} donde mundo es una variable.

Vamos a comprobarlo en acción.

Cree un nuevo directorio y abra una ventana de terminal. Inicie npm en el directorio e instale los siguientes módulos.

1
2
$ npm init
$ npm install --save express jade

La estructura de este proyecto es muy simple. Un archivo app.js para todas las configuraciones de la aplicación, un archivo server.js para activar un servidor http y una carpeta de vistas donde se almacenarán todas nuestras plantillas. Primero, cree el archivo app.js y pegue este fragmento de código en él.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
// copy this into your app.js
const express = require('express');
const path = require('path');
const app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

app.get('/', function(req, res, next) {
    res.render('index', { title: 'Hello World!' });
});

module.exports = app;

Vale, ¿qué está pasando aquí? Requerimos express e instanciamos el objeto app. El módulo ruta es un módulo de Nodo incorporado que proporciona una forma de trabajar con archivos y directorios. Lo usamos en este ejemplo para asegurarnos de que nuestras rutas de archivo funcionen en todas las plataformas.

Luego configuramos el motor de vista y la carpeta donde se encuentran nuestras plantillas. El motor de vista que usaremos en esta muestra será Jade, pero cualquier motor de vista está bien aquí.

Ahora viene la parte divertida, ¿ves el método .get() en el objeto de la aplicación? Toma 2 parámetros. Primero una ruta, luego una función de devolución de llamada. Cuando se golpea la ruta '/', se invocará la devolución de llamada. Esto activará la representación de la plantilla de índice, con una variable interpolada llamada título con el valor de '¡Hola mundo!'. Finalmente exportamos la app para tener acceso a ella en otros archivos.

¡Impresionante! Con eso fuera del camino, creemos el archivo server.js y agreguemos este fragmento.

1
2
3
4
5
6
const app = require('./app');
const port = 3030;

app.listen(port, function() {
    console.log('Express server listening on port ' + port);
});

Aquí requerimos el archivo app.js y le indicamos que escuche en el puerto 3030.

Solo queda una cosa más por hacer, crear la carpeta 'views' con algunas plantillas. Continúe y agregue la carpeta 'views' ahora, y suelte estas dos plantillas.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
<!-- layout.jade -->
doctype html
html
  head
    title= title
  body
    block content

<!-- index.jade -->
extends layout

block content
  h1= title
  p Welcome to #{title}

Como puede ver, la sintaxis del motor de plantillas de jade es bastante extraña en comparación con el HTML normal. Pero no dejes que te engañe. Al final, se representará como HTML normal en el navegador. ¿Ves el gracioso #{title}? Esta es la interpolación que mencioné anteriormente. La variable título de la función de devolución de llamada se pasó a la vista y se representó como el valor proporcionado.

La estructura de carpetas final de la aplicación de muestra debería verse así.

1
2
3
4
5
6
7
8
> node_modules
> views
 - index.jade
 - layout.jade
- app.js
- package.json
- package-lock.json // this file will be present only if you have NPM version 5 or above.
- server.js 

Eche un vistazo al repositorio para ponerse al día si se saltó algunos de los pasos.

Uf, finalmente podemos ejecutar la aplicación para ver cómo se ve. Vuelve a tu terminal y ejecuta:

1
$ node server.js

Debería ver que "Express server listening on port 3030" vuelve a iniciar sesión en su terminal. En su navegador, vaya a http://localhost:3030 y debería ver el texto "¡Hola mundo!" y "¡Bienvenido a Hola mundo!" en la pantalla.

API REST

¿Estás listo para poner tu mundo patas arriba? Bienvenido a DESCANSAR APIs. El acrónimo significa Representativo **Estado Ttransferencia. Pero nunca necesitarás recordar eso. Sin embargo, lo importante es comprender la lógica detrás de cómo funciona REST y por qué es el tipo preferido de entrega de datos.

El núcleo radica en crear una API, una Aaplicación Prgrama **Interfaz, para enviar y recibir datos en formato JSON. Las API REST se utilizan para interactuar con bases de datos para almacenar datos de manera persistente. Por suerte para nosotros, usar REST con Express es fácil.

Vamos a comprobarlo en acción.

Para este ejemplo solo necesitamos dos módulos. Express y analizador de cuerpo. Cree un nuevo directorio de proyecto y ejecute:

1
$ npm init && npm install --save express body-parser

Solo necesitamos dos archivos para que la aplicación de muestra funcione, así que continúe y cree un app.js y un server.js.

Copie estos fragmentos en los archivos.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
'use strict';

//
// app.js
//

const express = require('express');
const app = express();
const bodyParser = require('body-parser');

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

app.get('/', function(req, res) {
    let data = {
        message: 'Hello World!'
    };
    res.status(200).send(data);
});

app.post('/', function(req, res) {
    let data = {
        response: 'You sent: ' + req.body.message
    };

    // Do something, like query a database or save data

    res.status(200).send(data);
});

module.exports = app;
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
'use strict';

//
// server.js
//

const app = require('./app');
const port = 4040;

app.listen(port, function() {
    console.log('Express server listening on port ' + port);
});

El diseño de app.js es muy similar al ejemplo generado por el servidor. La única diferencia real es que devolvemos un objeto JSON como respuesta del método get(). Vamos a desglosarlo.

En la parte superior, nuevamente requerimos express y creamos un objeto app. Pero, también requerimos body-parser. Este es un increíble módulo Middleware exprés para analizar el cuerpo de una solicitud HTTP entrante. Agrega un objeto al objeto Express' req dentro de los métodos app. Entonces, cuando publicamos algunos datos en la ruta '/', tenemos acceso a esos datos en el objeto req.body. ¡Impresionante!

Para probar esto, inicie una herramienta como Postman o cualquier otra herramienta de prueba de cliente REST que desee. Si nunca has oído hablar de esto antes, no entres en pánico, Puedes verificarlo aquí..

Inicie server.js y abra Postman.

1
$ node server.js

En Postman (o cualquier otra herramienta de cliente REST), comience enviando una solicitud GET a http://localhost:4040/:

Solicitud GET del cartero{.img-responsive}

Ahora envíe una solicitud POST a la misma URL:

Solicitud POST del cartero{.img-responsive}

Ingrese un "mensaje" como datos JSON en el cuerpo de la solicitud (use "x-www-form-urlencoded" en este caso) y presione "Enviar". El mensaje que envíe al punto final debería ser devuelto a usted de esta manera:

1
2
3
{
    "response": "You sent: Hello World!"
}

Vuelva al código y expliquemos qué está pasando. En la ruta POST, tomamos el valor de req.body.message y lo asignamos a la variable data con nuestro propio mensaje corto. Luego devolvemos los datos en la respuesta con un estado de 200.

Las solicitudes como estas, que se utilizan únicamente como medio para transferir datos hacia y desde un servidor, se utilizan para almacenar datos en almacenamiento persistente, como bases de datos. Esto es en lo que las API REST son increíbles. En el mundo de hoy prosperan porque funcionan al unísono con las aplicaciones móviles y web como almacenamiento de datos.

Si te saltaste algún paso, puedes consultar el código aquí.

Sitios web estáticos

¿Qué pasa si no necesitamos ninguna representación de plantilla genial, ni interacción con una base de datos? ¿Qué pasa si solo queremos una página de destino genial, una página de prueba de concepto increíble o un servidor de archivos estáticos?

Ignoremos todos los casos de uso complicados que mencionamos anteriormente y concentrémonos en los cimientos en los que se basa la World Wide Web. Entrega de documentos HTML.

Express se puede convertir en un servidor web HTTP simple para servir páginas HTML estáticas. El proceso es muy simple. Lo que se necesita es especificar una ubicación que se verá como un directorio estático.

Vamos a sumergirnos.

Cree un nuevo directorio, cree los mismos dos archivos que en los ejemplos anteriores, una aplicación.js y un servidor.js. Solo necesitará instalar express para este ejemplo.

1
$ npm init && install express --save
1
2
3
4
5
6
7
// app.js
const express = require('express');
const app = express();

app.use('/', express.static('html'));

module.exports = app;

La aplicación está configurada para .use() la carpeta html para servir archivos estáticos. Lo que significa que la ruta al recurso en la URL no buscará rutas en la aplicación Express, sino que buscará en el sistema de archivos el archivo solicitado.

Simplemente puede reutilizar server.js de los ejemplos anteriores.

1
2
3
4
5
6
7
// server.js
const app = require('./app');
const port = 5050;

app.listen(port, function() {
    console.log('Express server listening on port ' + port);
});

Cree una carpeta llamada 'html' y agregue dos archivos llamados 'index.html' y 'about.html'. El contenido de los archivos no importa, solo agregué un poco de texto para saber cuál es cuál.

1
2
3
4
5
<!-- index.html -->
<h1>index</h1>

<!-- about.html -->
<h1>about</h1>

Eso es todo. Continúe, active el servidor y abra un navegador y diríjase a http://localhost:5050, que debería mostrar una página con la palabra "index".

Puede ver al solicitar la ruta '/' que index.html se ha cargado de forma predeterminada. Puede cambiar a '/about.html' y se cargará el archivo HTML 'about'. Este principio funciona con cualquier tipo de archivo. También puede agregar una imagen a esta carpeta, y se mostrará de la misma manera si navegó hasta ella a través de la URL.

Si te saltaste algún paso, tómate un descanso y revisa el código aquí.

Aplicaciones híbridas

No, no vamos a hablar del Toyota Prius. Este es otro tipo de híbrido. Digamos que desea la versatilidad, la potencia y la facilidad de uso de una API REST, pero también la velocidad de una aplicación de página única (SPA).

Información rápida: los SPA son aplicaciones de JavaScript de front-end que solo tienen un único archivo index.html principal. Todos los demás archivos html son plantillas que se inyectan en el archivo principal cuando es necesario. Debido a que la lógica y el enrutamiento se manejan en el front-end, son increíblemente rápidos. Pero al final, se comportan como una simple página web estática a la hora de atenderlos.

Si este es el caso, puede pensar en este escenario. ¿Por qué no ejecutar una API REST, con un SPA servido estáticamente en el mismo servidor? Suena bien para mí.

Inicie una terminal, cree un nuevo directorio y escriba:

1
$ npm init && npm install --save express body-parser

Vamos a introducirnos en la estructura de carpetas.

1
2
3
4
5
6
> app       // folder that will hold all of our files for the SPA
> node_modules
- app.js
- package-lock.json
- package.json
- server.js

La estructura es la misma que en el ejemplo de servicio de archivos estáticos, con la diferencia en el nombre de la carpeta donde guardaremos nuestros archivos estáticos.

Aquí hay algo de código:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
// app.js
const express = require('express');
const app = express();
const path = require('path');
const bodyParser = require('body-parser');

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

/**
 * API
 */
app.get('/api', function(req, res, next) {
    let data = {
        message: 'Hello World!'
    };
    res.status(200).send(data);
});
app.post('/api', function(req, res, next) {
    let data = req.body;
    // query a database and save data
    res.status(200).send(data);
});

/**
 * STATIC FILES
 */
app.use('/', express.static('app'));

// Default every route except the above to serve the index.html
app.get('*', function(req, res) {
    res.sendFile(path.join(__dirname + '/app/index.html'));
});

module.exports = app;

Esta estructura parece familiar ahora, ¿no es así? Hemos combinado la API REST con los archivos estáticos de servicio. La única excepción es el último .get() en la parte inferior. El * coincide con todas las rutas, excepto las anteriores, se establecerá de forma predeterminada para enviar el index.html de vuelta al cliente. Lo que significa que cada ruta servirá el index.html principal. ¡Exactamente lo que queremos!

Ahora, cuando queramos recuperar algunos datos de la API, simplemente podemos presionar la ruta '/api' y recuperar los datos JSON. De lo contrario, la aplicación siempre servirá el archivo HTML principal ubicado en la carpeta de la aplicación.

Si desea entrar en más detalles, puede consultar el ejemplo completo usando Angular.js en [aquí](https://github.com/adnanrahic/a-gentle-intro-to-express/tree /maestro/muestra4-híbrido).

¿Cuándo usar qué?

Ningún tipo de aplicación es el mejor en todos los escenarios. Todos tienen su lugar en el mundo de la programación. Todo depende de su caso de uso y de lo que quiera construir.

Si desea un back-end robusto sin preocuparse demasiado por el front-end, realmente le encantarían las aplicaciones renderizadas por el servidor. Tienen excelentes motores de plantillas que simplifican la forma en que escribe HTML, lo que facilita la creación de plantillas complejas. También brindan un gran soporte para almacenar y recuperar datos.

Las API de REST son las aplicaciones preferidas cuando tiene varios front-end para administrar. Los datos que recibes se pueden solicitar tanto desde aplicaciones móviles como web. ¿No es increíble que pueda crear un back-end que puedan consumir todas las aplicaciones del lado del cliente que desee? ¡Seguro que lo creo!

El servicio de archivos estáticos se utiliza en varios casos. Ofrece archivos HTML, imágenes, hojas de estilo CSS y scripts JavaScript. Todos se ven como archivos estáticos y todos se pueden servir con Express. Esto se usa más para crear páginas de destino y otras aplicaciones de front-end, como las aplicaciones de una sola página. Siéntase libre de usar esta técnica para todas sus aplicaciones. ¡Siempre será útil saber cómo servir archivos estáticos como imágenes y CSS!

¿Qué hay que decir sobre las aplicaciones híbridas? Pues, ante todo. Por favor, si tiene acceso a dos servidores web, mantenga las aplicaciones separadas. Cree la API REST en uno y el SPA en el otro. Pero si no tienes ese lujo, está bien mantenerlo en uno. De lo contrario, esta combinación de aplicaciones es la mejor en cuanto a rendimiento.

¡Empieza a construir cosas!

Todas estas técnicas son válidas y perfectamente adecuadas para su uso. ¡Solo elige uno y comienza a construir! Aprenderás más si lo haces tú mismo.

Espero que hayan disfrutado leyendo esto tanto como yo disfruté escribiéndolo. Hasta la próxima, sé curioso y diviértete.

¿Crees que este tutorial será de ayuda para alguien? No dudes en compartir. Si te gustó, házmelo saber en los comentarios a continuación.