BasesDeDatos

Motores de vistas y bases de datos con Express en Node.js

Por: Pedro Cruz

Introducción

Si se ha sumergido al entorno de Node.js y se encuentra trabajando con Express, es importante entender que se va encontrar con algunas necesidades durante el desarrollo de una aplicación, estas pueden ser la obtención de los datos que deberá procesar o la generación de las vistas que podrá mostrar al usuario que haga peticiones al servidor. En la pasada publicación, referente a middleware, se presentó la parte de dirigir peticiones y mostrar la respuesta a través de generar el procedimiento necesario, sin embargo, existe la posibilidad de ir a un siguiente paso, el cual es utilizar el lenguaje de marcado HTML y empezar a presentar la información a través de las vistas necesarias. Por otro lado, también los datos que se deben procesar, no siempre vienen de la petición de un cliente, sino que ya se encuentran almacenados mediante bases de datos que necesitan ser consultadas por el servidor, para resolver está necesidad, se verá el uso de las conexiones a bases de datos.

Motores de vistas

Una de las características que permite Express al crear un servidor con este framework, es la definición de una estructura en forma de documento de salida, mediante el uso de plantillas que puedan generar una vista, una plantilla permite utilizar variables que serán cambiadas por datos que son llenados cuando es construida, comúnmente se utiliza el lenguaje de marcado HTML. Esta herramienta de generación de la estructura y el cambio de variables a datos, se le conoce como motor de plantilla o motor de vistas y además, Express es compatible con diferentes motores, existen los más populares como Pug, Mustache o Dust.

Antes de trabajar con un motor en específico, en la documentación de Express, se conoce que los motores compatibles con el framework exportan una función conocida como __express(filePath, options, callback), que es utilizada por la función res.render(), la cual sirve para generar la vista utilizado el código de la plantilla. También se debe conocer que existe una configuración para una aplicación con Express, con el cual, se configura el motor de vistas y se indica la ubicación de los archivos que representan las vistas para ser generadas por el framework. Esto se realiza con la función app.set(), donde se debe agregar una primera vez con el primer parámetro que se denomina views y agregar de nuevo la función, pero con el primer parámetro conocido como view engine, para clarificar la configuración se muestra un ejemplo a continuación:

const path = require('path');
const express = require('express');
const app = express();

// Indica el directorio donde se encuentran los archivos de las vistas ('views')
app.set('views', path.join(__dirname, 'views'));

// Indica el motor de plantilla que se utiliza, en este ejemplo la variable se llama 'some_template_engine_name' y representa a un motor de vistas.
app.set('view engine', 'some_template_engine_name');

Después que ha realizado la configuración correspondiente, se procede a instalar el paquete npm. que indica el motor de vistas a utilizar. Si se utiliza Pug, la instrucción en una terminal sería la siguiente:

$ npm install pug --save

Si convertimos, el primer ejemplo, en una aplicación que utiliza el motor de vistas Pug y se crea una ruta para utilizar un archivo de plantilla, denominado index.pug, entonces debemos tener dos archivos generados, el primero de la aplicación, app.js, y una carpeta llamada views con el segundo archivo indicado anteriormente. Para tener una referencia de los archivos, se muestra el código a continuación:

app.js

const path = require('path');
const express = require('express');
const app = express();

// Indica el directorio donde se encuentran los archivos de las vistas ('views')
app.set('views', path.join(__dirname, 'views'));

// Indica el motor de plantilla que se utiliza, en este ejemplo se utiliza 'pug'
app.set('view engine', 'pug');

// Ruta raíz que genera la representación en HTML mediante el archivo de vista 'index'
app.get('/', function (req, res) {
  res.render('index', { title: 'Aquí un título es ingresado', header: 'Aquí un encabezado se agrega', paragraph: 'Aquí se añade un párrafo'});
});

/* Se utiliza el método listen() para iniciar un servidor y realiza la escucha de las conexiones en el puerto que se le ha indicado a través del primer parámetro (3000) */
app.listen(3000, function () {
  console.log('Escuchando en el puerto 3000');
});

views/index.pug

html
  head
    title= title
  body
    h1= header
    p= paragraph

Ya que tenemos el código generado, se tiene la siguiente estructura para la aplicación:

Estructura para la aplicación

Si está todo listo, entonces se procede a ejecutar la aplicación, se puede utilizar la terminal con la instrucción node app.js y genera la siguiente respuesta en la terminal:

Corriendo servidor de Node.js

Si se realiza la prueba en el navegador, con la ruta http://localhost:3000/, el servidor contestará desplegando la siguiente vista:

Respuesta de petición localhost:3000/ mediante navegador web

Si se revisa la información de la vista, se puede conocer que se encuentra representada utilizando HTML, como se muestra en la siguiente imagen:

Revisión de la representación de la respuesta en HTML

Como se puede observar, se ha presentado el concepto de motores de vistas y se ha realizado un pequeño ejemplo con el uso de Pug y su visualización mediante la aplicación de Node.js con Express.

Bases de datos

En esta segunda sección, comenzamos con el lado de los datos, como se comentó en la introducción, generalmente una aplicación requiere procesar cierta información para proporcionarla al usuario que realiza una petición y existe la posibilidad de que la información se haya almacenado con anterioridad. Por lo tanto, el almacenamiento de los datos puede guardarse a través de un archivo o en un programa que los almacena de manera estructurada, con el beneficio de ser consultados a través de características selectivas que se deseen, esto se le conoce como base de datos.

Si se analiza la opción de las bases de datos, se entiende que debe existir una conexión a estos programas que almacenan los datos y que permite obtener la información requerida, en el caso de Node.js, este cuenta con soporte a diferentes manejadores de base de datos, ya sean de tipo relacional o no relacional. También se entiende que el uso de la base datos no depende directamente de Express, sin embargo, al tener un framework para crear aplicaciones con ciertas características, puede ser un complemento para conectar una base de datos y utilizar esta información en un posible servidor con Express.

Para realizar un ejemplo de servidor con Express y el uso de la base de datos, en este caso, se puede usar el sistema de base de datos MongoDB y se realiza un ejemplo donde se requiere tener información de los usuarios al realizar una petición y esta se muestra mediante una representación de HTML. A continuación se describe el proceso del ejercicio.

Primero se crea la base de datos con MongoDB, en este caso se genera con el nombre de prueba y la colección se denomina con el nombre de usuarios, para este último, se generan 4 documentos de información como se indica en el siguiente tabla:

Colección usuarios

nombre edad
Pedro 15
Oscar 20
Mario 25
Uriel 30

Después, se pasa a instalar el paquete npm, en la ubicación donde se encuentra la aplicación de Node.js. Este paquete indica el manejador de bases de datos utilizado y la instrucción en una terminal sería la siguiente:

$ npm install mongodb --save

Luego que se ha instalado el paquete de MongoDB, se debe enfocar en realizar la configuración de Express, utilizar la conexión de la base de datos y al final, utilizar una ruta y una vista para mostrar la información de los usuarios, para esto se realizan los siguientes archivos:

app.js

const path = require('path');
const express = require('express');
const app = express();
// Importar módulo de cliente para MongoDB
const MongoClient = require('mongodb').MongoClient;
var db;

// Inicia la conexión al servidor local de MongoDB
MongoClient.connect("mongodb://localhost:27017/", function(err, client) {
  if(err) throw err;

  // Se almacena la referencia de la base de datos en la variable, utiliza la base de datos 'prueba'
  db = client.db('prueba');

  // Inicia la aplicación después de que la conexión a la base de datos está lista
  app.listen(3000, function () {
    console.log('Escuchando en el puerto 3000');
  });
});

// Indica el directorio donde se encuentran los archivos de las vistas ('views')
app.set('views', path.join(__dirname, 'views'));

// Indica el motor de plantilla que se utiliza, en este ejemplo se utiliza 'pug'
app.set('view engine', 'pug');

// Ruta raíz que genera la representación en HTML consultando la información de la base de datos
app.get('/', function (req, res) {
  // Se consulta la colección denominada 'usuarios' y se trae todos los documentos
  db.collection("usuarios").find({}, function(err, docs) {
    // Se genera la variable 'usuarios', para guardar la información obtenida
    let usuarios = '';
    // Cada documento puede ser obtenido mediante el método docs.each()
    docs.each(function(err, doc) {
      if(err) throw err;
      if (doc !== null) {
        //Se generan el texto obteniendo los nombres y las edades de los usuarios
        texto = 'La edad de' + ' ' + doc.nombre + ' ' + 'es de' + ' ' + doc.edad + ' ' + 'años.';
        toConcatAndRender(texto);
      } else {
        toConcatAndRender('end');
      }
    });
    // Función que concatenará los datos de cada documento y generará la vista en HTML
    function toConcatAndRender(texto) {
      if (texto !== 'end') {
        usuarios = usuarios + texto;
      } else {
        res.render('index', { title: 'Lista de usuarios', header: 'Edad de los usuarios', paragraph: usuarios});
      }
    }
  });
});

views/index.pug

html
  head
    title= title
  body
    h1= header
    p= paragraph

Ya que tenemos el código generado, se tiene la siguiente estructura para la aplicación:

Estructura para la aplicación

Si está todo listo, entonces se procede a ejecutar la aplicación, se puede utilizar, con la terminal, la instrucción node app.js y genera la siguiente respuesta:

Corriendo servidor de Node.js

Si se realiza la prueba en el navegador, con la ruta http://localhost:3000/, el servidor contestará desplegando la siguiente vista:

Respuesta de petición localhost:3000/ mediante navegador web

Si se revisa la información de la vista, se puede conocer que se encuentra representada utilizando HTML, como se muestra en la siguiente imagen:

Revisión de la representación de la respuesta en HTML

Como se puede comprender, se ha obtenido información de una base de datos a través de Node.js y programando con Express, se ha realizado su representación en una vista con lenguaje HTML, que puede ser visualizada como una página desde un navegador web.

Conclusión

En esta publicación se han presentado nuevas características que puede requerir una aplicación de Node.js, por un lado se tiene la representación de la información mediante el uso de motores de vistas y por otro lado, se ha trabajado una introducción al manejo de base de datos, mediante el uso de una aplicación para solicitar la información necesaria. Es importante conocer este último tema, porque existen diferentes opciones para obtener la información de un mismo manejador de bases de datos y debido a que se pude utilizar en la aplicación, se podrá analizar en próximas publicaciones.

Pedro Cruz (@pedcru)

Av. Cerro Gordo del Campestre 201
Int. 303
Col. Las Quintas
León, Gto.
C.P. 37125

ROCKTECH R+D © 2020