The purpose of this article is to understand the basics of websockets and cache with a common known example : a Chat.
Usually, a Chat have to be really reactive with very good performance. There are many ways to achieve different levels of performance.
In this article, we'll build a basic sample high-performance Chat together with Typescript, Redis and Websockets. I'll guide you step-by-step as if I was doing it with you.
First, let's take a look at our architecture.
To the keep things simple, we'll be doing the frontend in plain HTML/JS without framework
The Nodejs server will be written with express as it's most known.
A Redis server to cache messages
Tips : If you wanna enhance performance further, you can opt for another framework like fastify, websocket.io, uWebSocket or whatever you want. We'll stay with express as it's well commonly known.
importexpressfrom"express";import{WebSocketServer}from"ws";importredisClientfrom"./redisClient";import{ChatMessage}from"./chatMessage";constapp=express();constport=3000;app.get("/",(req,res)=>{res.send("Chat server is running");constserver=app.listen(port,()=>{console.log(`Web server is running on http://localhost:${port}`);constwss=newWebSocketServer({server});wss.on("connection",(ws)=>{console.log("Client connected");// Send chat history to new clientredisClient.lRange("chat_message",0,-1).then((messages)=>{messages.forEach((message)=>{ws.send(message);(error)=>{console.error("Error retrieving messages from Redis",error);return;ws.on("message",(data)=>{constmessage:ChatMessage=JSON.parse(data.toString());message.timestamp=Date.now();constmessageString=JSON.stringify(message);// Save message to RedisredisClient.rPush("chat_messages",messageString);redisClient.lTrim("chat_messages",-100,-1);// Keep only the last 100 messages// Broadcast message to all clientswss.clients.forEach((client)=>{if (client.readyState===ws.OPEN){client.send(messageString);ws.on("close",()=>{console.log("Client disconnected");console.log("WebSocket server is running on ws://localhost:3000");
First, we setup the Web and WebSocket servers.
Second, on the websocket connection, we pull the Chat history from redis
Third, we listen for new messages and record them in redis, keeping only the 100 last message anytime
Fourth, we broadcast each messages to all the connected clients of the Chat
If you wanna go further, you can implement an observer pattern where each websocket client is an observer. But for now, let's keep the things simple.
For barrels fans, don’t forget to add your app entrypoint in ./src/index.ts :