Real-time applications have become an integral part of modern web development, enabling instant communication and dynamic interactions. NestJS, with its powerful framework and support for WebSockets, makes it easy to build such applications. In this article, we'll explore how to create real-time applications with NestJS and WebSockets, covering key concepts, implementation steps, and best practices.
Why Use WebSockets?
WebSockets provide a full-duplex communication channel over a single TCP connection, allowing real-time data exchange between the client and server. Unlike traditional HTTP requests, WebSockets maintain an open connection, enabling instant updates without the need for polling.
Setting Up a NestJS Project
First, create a new NestJS project:
nest new real-time-app
Navigate to the project directory:
cd real-time-app
Installing WebSocket Dependencies
NestJS provides a WebSocket module out of the box. Install the necessary package:
npm install @nestjs/websockets @nestjs/platform-socket.io
Creating a WebSocket Gateway
A gateway in NestJS acts as a controller for WebSocket events. Create a new gateway using the NestJS CLI:
nest generate gateway chat
This will create a new chat.gateway.ts file. Let's define our gateway to handle real-time chat messages:
import {
SubscribeMessage,
WebSocketGateway,
OnGatewayInit,
OnGatewayConnection,
OnGatewayDisconnect,
WebSocketServer,
} from '@nestjs/websockets';
import { Logger } from '@nestjs/common';
import { Socket, Server } from 'socket.io';
@WebSocketGateway()
export class ChatGateway implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect {
@WebSocketServer() server: Server;
private logger: Logger = new Logger('ChatGateway');
@SubscribeMessage('message')
handleMessage(client: Socket, payload: string): void {
this.server.emit('message', payload);
}
afterInit(server: Server) {
this.logger.log('Init');
}
handleConnection(client: Socket, ...args: any[]) {
this.logger.log(`Client connected: ${client.id}`);
}
handleDisconnect(client: Socket) {
this.logger.log(`Client disconnected: ${client.id}`);
}
}
Explanation
- @WebSocketGateway(): Decorator to mark the class as a WebSocket gateway
- @WebSocketServer(): Decorator to inject the WebSocket server instance
- handleMessage(): Method to handle incoming messages and broadcast them to all connected clients
- afterInit(): Lifecycle hook called after the gateway is initialized
- handleConnection(): Lifecycle hook called when a client connects
- handleDisconnect(): Lifecycle hook called when a client disconnects
Handling Events on the Client-Side
To handle WebSocket events on the client side, you can use the socket.io-client library. Install it using:
npm install socket.io-client
Here’s an example of a simple client-side implementation in an HTML file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Chat App</title>
<script src="https://cdn.socket.io/4.0.1/socket.io.min.js"></script>
<script>
document.addEventListener('DOMContentLoaded', () => {
const socket = io('http://localhost:3000');
const form = document.getElementById('form');
const input = document.getElementById('input');
const messages = document.getElementById('messages');
form.addEventListener('submit', (e) => {
e.preventDefault();
if (input.value) {
socket.emit('message', input.value);
input.value = '';
}
});
socket.on('message', (message) => {
const item = document.createElement('li');
item.textContent = message;
messages.appendChild(item);
});
});
</script>
</head>
<body>
<ul id="messages"></ul>
<form id="form" action="">
<input id="input" autocomplete="off" /><button>Send</button>
</form>
</body>
</html>
Explanation
- Socket.IO: The socket.io-client library is used to handle WebSocket connections
- Connecting to the Server: io('http://localhost:3000') establishes a connection to the WebSocket server
- Sending Messages: The form submission event sends messages to the server using socket.emit('message', input.value)
- Receiving Messages: The socket.on('message') event handler updates the DOM with new messages
Best Practices
Authentication and Authorization: Ensure that WebSocket connections are authenticated and authorized. Use middlewares or guards to secure your WebSocket endpoints
Error Handling: Implement proper error handling for your WebSocket events to ensure robustness
Scalability: Use tools like Redis for pub/sub patterns if you need to scale your WebSocket server
Monitoring and Logging: Integrate monitoring tools to keep track of WebSocket connections and events
Conclusion
Building real-time applications with NestJS and WebSockets is straightforward and efficient. By leveraging NestJS's WebSocket module, you can create highly interactive and responsive applications. Follow best practices for authentication, error handling, and scalability to ensure your real-time application is robust and secure.
My way is not the only way!
Top comments (0)