DEV Community

Cover image for ๐Ÿš€ Ready-to-Use Node.js, Redis, and Docker Template
shay bush
shay bush

Posted on

๐Ÿš€ Ready-to-Use Node.js, Redis, and Docker Template

With over two years of professional experience in Node.js, I've developed a streamlined template that integrates Node.js, Redis, and Docker. In this article, Iโ€™ll walk you through how to use it effectively. Letโ€™s get started! ๐Ÿฆพ

๐Ÿ“Overview

This project demonstrates a basic integration of Node.js, Redis, and Docker. It showcases two routes, one that directly interacts with a Redis cache and another without caching, allowing you to compare the performance and behavior of both.

๐Ÿ”ง Prerequisites

Before you start, ensure that you have Docker Desktop installed on your machine. This is required to run the Redis container. You can download it here for both macOS and Windows.
link here - docker desktop

1. ๐Ÿš€Setup app.js:

First, require all the necessary dependencies and files:



const express = require('express');
const path = require('path');
const cors = require('cors');
const bodyParser = require('body-parser');
const commentRouter = require('./routers/comment.router');
const indexRouter = require('./routers/index.router')



Enter fullscreen mode Exit fullscreen mode

Next, set up a simple Node.js app with middlewares and an error handler:



const app = express();

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
app.use(cors());
app.use(express.static(path.join(__dirname, '..', 'public')));

app.use((req, res, next) => {
  console.log(req.method, req.originalUrl);
  next();
})

app.use('/', indexRouter);
app.use('/comments', commentRouter);

app.use((err, req, res, next) => {
  console.error(`${req.method}:${req.originUrl}, failed with error:${err}`);
  res.status(500).json({ error: err.message })
});

const PORT = 3001;
app.listen(PORT, () => {
  console.log(`server is up on: http://localhost:${PORT}`);
});


Enter fullscreen mode Exit fullscreen mode

2. Setup commentRouter:

The commentRouter has two versions:

  • v1: Interacts without Redis caching
  • v2: Interacts with Redis caching


const express = require('express');
const { getCommentsService, getCommentsWithRedisService } = require('../services/commentService');
const router = express();

router.get('/v1', getCommentsService);
router.get('/v2', getCommentsWithRedisService);

module.exports = router;


Enter fullscreen mode Exit fullscreen mode

3. ๐Ÿ› ๏ธServices:

  • getCommentsService - is related to v1 without caching.
  • getCommentsWithRedisService - is related to v2 with caching.


const axios = require('axios');
const { getSetRedisCache } = require('../utils/redis.util');

const COMMENTS_API_URL = "https://jsonplaceholder.typicode.com/comments"
const EXPIRATION_TIME = 60 * 60; // 1 hour (3600 seconds)

async function getCommentsService(req, res, next) {
  const postId = req.query.postId;
  try {
    const { data } = await axios.get(COMMENTS_API_URL, { params: { postId } });
    return res.status(200).json(data);
  } catch (error) {
    next(new Error('API request has failed'))
  }
}

async function getCommentsWithRedisService(req, res, next) {
  const postId = req.query.postId;
  const cacheKey = `comments?postId=${postId}`;

  try {
    const data = await getSetRedisCache({
      key: cacheKey,
      callbackFn: async () => {
        const { data } = await axios.get(COMMENTS_API_URL, { params: { postId } });
        return data;
      },
      expirationTime: EXPIRATION_TIME,
    })
    res.json({ data })
  } catch (error) {
    next(new Error(error.message))
  }
}

module.exports = {
  getCommentsService,
  getCommentsWithRedisService
}


Enter fullscreen mode Exit fullscreen mode

4. Implement getSetRedisCache

The function caches all the requests you want to cache. First, we need to connect to Redis.

If you're running Node.js locally, you don't need to specify the url:



const Redis = require('redis');
const redisClient = Redis.createClient({ url: '' })
redisClient.connect().catch(console.error);


Enter fullscreen mode Exit fullscreen mode

If you're running Node.js on a Docker container:



const Redis = require('redis');
const redisClient = Redis.createClient({ url: 'redis://redis:6379' })
redisClient.connect().catch(console.error);


Enter fullscreen mode Exit fullscreen mode

Now, implement the caching function itself. The function should cache your request data. The key should be the request url with the parameters:



exports.getSetRedisCache = ({ key, callbackFn, expirationTime }) => {
  return new Promise((resolve, reject) => {
    redisClient.GET(key)
      .then(async (redisData) => {
        if (redisData && redisData !== null) return resolve(JSON.parse(redisData));
        const newData = await callbackFn();
        redisClient.SETEX(key, expirationTime, JSON.stringify(newData));
        resolve(newData);
      })
      .catch(err => reject(err))
  })
}


Enter fullscreen mode Exit fullscreen mode

5. ๐Ÿ”Check Cached Keys in Redis

Send 3+ requests in Postman or any other API client:



http://localhost:3001/comments/v2
http://localhost:3001/comments/v2?postId=1
http://localhost:3001/comments/v2?postId=2
http://localhost:3001/comments/v2?postId=3


Enter fullscreen mode Exit fullscreen mode

Then, check the container for results:
Redis docker container

Now your data has been cached for 1 hour, and subsequent requests to the server will be faster.

Example:
First iteration:

First API request to spesific URL

Second iteration:
Second API request to spesific URL


Feel free to leave a comment.
don't forget to drop a "๐Ÿ’–๐Ÿฆ„๐Ÿ”ฅ".

๐ŸŒŸ Connect with Me

If you found this template useful, feel free to follow me on LinkedIn for more updates and articles: https://www.linkedin.com/in/shaybushary

๐Ÿ“‚ GitHub Repository

You can find the complete code for this template on GitHub. Don't forget to star the repo if you find it helpful!
https://github.com/Shaybush/nodejs-redis-docker.git

Top comments (1)

Collapse
 
omri_bitan_d616b5c1d9916c profile image
omri bitan

Excellent post, showing a very important use