Arquitectura del servidor

Vamos a ver cuáles son los principales componentes y las diferentes tecnologías que utiliza una aplicación basada en Node.js.

Comunicación entre el frontend y el backend de la aplicación

El foco principal aquí es que aprendamos a conectar React con la parte backend de nuestra aplicación, en este caso formada por un servidor Express/Node y una base de datos MongoDB.

Tecnologías utilizadas

Cada vez que un usuario acceda dentro de su navegador a nuestro sitio web, https://example.com, el servidor le enviará un documento HTML y algunos archivos JavaScript que contendrán toda la parte de React.

Ahora, si la aplicación es dinámica, es decir, necesita mostrar ciertos datos que dependen, por ejemplo, del usuario que está accediendo a la web, entonces React debe conectarse de alguna manera con el servidor para pedirle esos datos.

Los datos van a estar guardados en la base de datos, así que realmente la pregunta aquí es, ¿cómo hacemos para que React se comunique con MongoDB?

La comunicación entre ambas partes no va a ser directa, sino que entre medias vas a tener un Express API, que va a contener toda la lógica para:

  1. Manejar las peticiones HTTP entrantes procedentes de React.
  2. Pedir la información necesaria a la base de datos MongoDB.
  3. Enviar dicha información de vuelta a React, donde será utilizada para mostrar cierto contenido al usuario.

Entrando un poco más en detalle, la comunicación entre React y Express va a ser a través de HTTP Requests o AJAX Requests, en formato JSON. Por otro lado, Express y MongoDB se van a comunicar a través de un sistema de comunicación interno del que no nos vamos a preocupar por ahora.

Relación entre Node.js y Express

Una duda que te puede surgir en este momento es saber cuál es la diferencia entre Node.js y Express y cómo se relacionan entre sí.

  • Node.js es un entorno de ejecución creado para ejecutar código JavaScript en el lado del servidor.
  • Express es una librería que utiliza Node.js, que nos ayuda a manejar de forma sencilla las peticiones HTTP en el servidor.

Node.js vs. Express

En el siguiente diagrama vamos a entender un poco más en profundidad qué es lo que hace cada uno de ellos.

Peticiones HTTP en Express

Lo primero que debemos saber es que nuestro servidor local va a estar siempre escuchando tráfico HTTP por un único puerto. Un puerto es como una pequeña puerta a través de la cual pueden llegar las peticiones HTTP.

Entonces, lo que tenemos que hacer es configurar Node y Express para que escuchen las peticiones HTTP por dicho puerto.

Más en detalle, Node va a ser quien coja el tráfico HTTP entrante, ya que es el core de la aplicación, y se lo va a mandar a Express, que va a manejar la petición como lo hayamos indicado en lo que se llaman route handlers. Estos últimos se encargan de manejar peticiones HTTP para un servicio específico. Por ejemplo, podríamos tener un handler responsable del login de usuarios y otro responsable del logout.

Estos handlers, una vez hayan hecho procesado la petición, generarán una respuesta que será enviada de nuevo a Node, y posteriormente al navegador que realizó la petición HTTP.

Express route handlers

Vamos a ver más en detalle como maneja Express las peticiones HTTP a través de los route handlers.

Un route handler en Express se escribe de la siguiente manera:

app.get('/', (req, res) => {
  res.send({
    hi: 'there',
  });
});

Y así es como lo interpreta Express internamente:

Tipos de peticiones HTTP

  • app es un objeto que representa el servidor Express creado, al que vamos a asociar el manejador de ruta.
  • get es la función con la que vamos a crear el route handler, y que va a estar escuchando peticiones HTTP de tipo GET.
  • / es la ruta a la que tendremos que acceder desde el navegador para llegar a este manejador.
  • req es un objeto que representa la petición entrante, que contendrá información sobre quién ha hecho la petición y otros datos procedentes del navegador.
  • res es un objeto que representa la respuesta que va a ser enviada de vuelta al navegador.

Inmediatamente después de los route handlers tendremos una línea como esta, donde Express le indica a Node que escuche tráfico entrante por el puerto 5000:

app.listen(5000);

Comunicación entre el backend y la base de datos de la aplicación

Ahora sí, vamos a entrar más en detalle en la comunicación interna entre el backend y la base de datos:

Mongoose

Si nos fijamos bien, se trata del mismo diagrama que vimos al inicio de esta sección, con una pieza adicional llamada "mongoose.js".

Mongoose es la librería que vamos a utilizar para conectar Express con la base de datos MongoDB.

MongoDB

Antes de nada, vamos a ver cómo se almacenan los datos dentro de MongoDB.

MongoDB

MongoDB almacena los datos en colecciones, y dentro de estas es donde se almacenan los registros.

Los registros son objetos JavaScript en formato key/value, y estos objetos no tienen por qué contener las mismas propiedades.

Mongoose

Ahora que ya hemos visto cómo se almacenan los datos en la base de datos, podemos ver cómo se traduce esta representación en el mundo de JavaScript, gracias a Mongoose:

Instancias de los modelos

  • Model Class: representa una colección de la base de datos; tendrá diferentes acciones asociadas para poder trabajar con los registros de dicha colección.
  • Model Instance: representa un único registro dentro de una colección de la base de datos.

Estructura de carpetas

Una de las muchas maneras posibles de organizar la estructura de carpetas dentro de nuestro servidor es la siguiente:

Estructura de directorios del servidor

  • config: contiene todos los ajustes y la configuración de la aplicación; por ejemplo, las claves de acceso a las APIs que utilicemos.
  • routes: contiene un archivo por cada grupor de rutas que tengamos; por ejemplo, podríamos tener un archivo authRoutes.js para las rutas de autenticación.
  • services: contiene toda la lógica de la aplicación.

Además de estos directorios, podemos añadir los siguientes:

  • models: contiene las clases creadas por Mongoose; por ejemplo, User.js para manejar los usuarios de la aplicación.