Caché de lado del servidor con Express en NodeJS

Por Julio Giampiere Grados Caballero
Caché de lado del servidor con Express en NodeJS

Aprende la técnica de almacenar datos en memoria para mejorar el rendimiento de cualquier aplicación, móvil, web o de escritorio.

Express es sin duda el framework más conocido de node.js, es una extensión del poderoso connect y está inspirado en sinatra. También es robusto, rápido, flexible y simple.


Sin duda el éxito de express radica en lo sencillo que es usarlo, y además abarca un sin número de aspectos que muchos desconocen pero son necesarios.


Express es el framework web más extensible que hemos visto en la actualidad. La arquitectura de middleware que utiliza facilita el plug-in de características adicionales con el mínimo esfuerzo y de manera estandarizada.


Para este tutorial haremos uso de un middleware muy pequeño y simple, pero poderoso y útil que ayudará a aumentar el rendimiento de su aplicación web con express.


A todo esto, ¿qué es un middleware?


Un middleware es un bloque de código que se ejecuta entre la petición que hace el usuario (request) hasta que la petición llega al servidor. Si quieres saber un poco más sobre los middleware tenemos un tutorial sobre en este tema en este enlace.


El caché del lado del servidor


El almacenamiento en caché es una técnica comúnmente utilizada para mejorar el rendimiento de cualquier aplicación, ya sea de escritorio, móvil o web. Al tratar con aplicaciones web, podemos hacer un buen uso del almacenamiento en caché del lado del cliente usando encabezados de respuesta que todos los navegadores actualmente admiten. 




Pero, ¿qué pasa si tenemos una página compleja y pesada que demora 2 segundos para generar el resultado HTML? Incluso si habilitamos el caché del lado del cliente para esta página, el servidor web aún tendrá que representar la página para cada usuario diferente que accede a nuestra web solicitud. Piense en la página de inicio de un gran portal de noticias; ¿procesan su HTML una y otra vez para cada visitante?


Aquí es donde el caché del lado del servidor es útil. El objetivo de la memoria caché del lado del servidor es responder al mismo contenido para la misma solicitud independientemente de la solicitud del cliente. En nuestro ejemplo anterior, la primera solicitud que llega a nuestro servidor demoraría 2 segundos para generar el HTML, pero las siguientes solicitudes golpearían el caché y el servidor podría enviar la respuesta en unos pocos milisegundos.


Hay muchas formas de hacerlo, podría hacerse con NGINX o una CDN como CloudFlare, pero en este ejemplo veremos cómo hacerlo con Node.js y Express con un trabajo mínimo y de una manera flexible.


Código que aplicaremos


Haremos uso del módulo memory-cache npm para poder agregar contenido a la caché. El cual conoceremos a continuación:


Este módulo nos permite eliminar un tiempo de espera en un evento, mientras almacena el contenido en cache. Alguno de sus métodos y forma de uso lo podremos encontrar aquí.


Nuestro middleware de caché es el siguiente.


var cache = (duration) => {

return (req, res, next) => {

let key = '__express__' + req.originalUrl || req.url

let cachedBody = mcache.get(key)

if (cachedBody) {

res.send(cachedBody)

return

} else {

res.sendResponse = res.send

res.send = (body) => {

mcache.put(key, body, duration * 1000);

res.sendResponse(body)

}

next()

}

}

}


Básicamente buscará un valor almacenado en caché utilizando la URL de la solicitud como clave. Si se encuentra, se envía directamente como respuesta. Si no está actualmente en la memoria caché, ajustará la función de envío de Express para almacenar en caché la respuesta antes de enviarla al cliente y luego llamar al siguiente middleware.


Este es un ejemplo muy básico sobre cómo almacenar en caché una página de procesamiento pesado.


Recuerda que nuestra función está para ser determinada en milisegundos, por ellos cuando sea llamada desde la ruta, deberá expresarse en el tiempo necesario.


app.get('/', cache(10), (req, res) => {

  setTimeout(() => {

    res.render('index', { title: Hola, message: '¿Cómo estas?', date: new Date()})

  }, 5000) 

})


setTimeout, se usó para simular una solicitud de procesamiento lento


Ahora que si estas utlizando router, y por ejemplo necesitar almacenar en cache durante un día se debería configurar así:


router.route('/')

.get( function(req, res){

return res.render('main/home.html');

}, cache(60*60*24));


Los resultados despues de ser aplicados nuestro cache, a la página




Tengamos en cuenta que la ruta anterior contiene dos middlewares. El primero es la referencia de caché y el segundo es el middleware real que maneja la solicitud. En este caso, cuando el servidor recibe la primera solicitud para esta ruta, esperará 5 segundos antes de enviarla al cliente. Pero después de eso, las llamadas consecutivas obtendrán el cuerpo de respuesta en caché durante los próximos 10 segundos y, por supuesto, ya no tendrá que esperar esos 5 segundos.


La desventaja es si tienes algo que tiene que ser dinámico. En la ruta anterior, hemos pasado la fecha actual como argumento para el motor de visualización. El cuerpo de respuesta almacenado en caché tendrá esta misma fecha hasta que expire el caché (10 segundos en este caso).


Lo bueno de esto es que funciona para rutas que responden con HTML, JSON, XML o cualquier otro tipo de contenido. Se puede utilizar para impulsar un sitio web simple hasta una aplicación Express pesada, compleja y basada en REST.


Puede conectarlo fácilmente a cualquier aplicación web Express existente simplemente agregando el middleware de caché para cada ruta que desee almacenar en caché.


Importante: los métodos PUT, DELETE y POST nunca se deben almacenar en caché.


Para este ejemplo, hemos utilizado un módulo npm que almacena el contenido en memoria caché, esto tiene algunas buenas y malas implicaciones.


La memoria caché en memoria es la opción más rápida disponible; es fácil trabajar con ella, no se necesita ninguna dependencia externa;

Perderemos el contenido almacenado en caché si el servidor o el proceso deja de funcionar;

Dado que almacena el contenido en caché en su propia memoria de proceso, no se compartirá entre múltiples procesos node.js;

Otra opción para resolver la mayoría de estos problemas es usar un servicio de caché distribuida como Redis. Se podría hacer con un único módulo npm express-redis-cache que ya implementa Express a middleware.


Bien en este tutorial nos hemos referencia de los siguientes enlaces, así que aquí te los comparto:



Y bien esto fue todo sobre como agregar cache de lado del servidor para Express en NodeJS, si tienes alguna duda o inquietud compártela en las discusiones. Gracias


¿Te gustó el tutorial?

Ayúdanos a llegar a más personas

Julio Giampiere Grados Caballero

Julio Giampiere Grados Caballero

CTO y Cofundador de Devcode.la. Full stack JavaScript. React | jQuery | Vanilla | Backbone | Node | MongoDB.