The rapid evolution in communication technology has exponentially increased the demand for real-time applications. Whether it’s a gaming platform, a collaborative tool, or a simple chat application, real-time communication is a game-changer. Among the various technologies available for implementing real-time communication, WebSockets stand out as one of the most efficient. In this article, we’ll delve into how to use WebSockets in NestJS to build a real-time chat application with TypeScript.
Introduction to NestJS
NestJS is a progressive Node.js framework that builds efficient, reliable, and scalable server-side applications. The framework is built with TypeScript and combines elements of Object-Oriented Programming (OOP), Functional Programming (FP), and Functional Reactive Programming (FRP).
NestJS leverages many tools, including WebSockets, to build real-time applications with minimal hassle. In this article, we will focus on how to integrate WebSockets into a NestJS application to build a real-time chat environment.
Setting Up the Environment
Before we dive into the coding part, let’s set up our NestJS application. Begin by installing the NestJS CLI if you haven’t done so already.
npm i -g @nestjs/cli
Create a new NestJS project named “chat-app”.
nest new chat-app
Navigate to the newly created project directory.
cd chat-app
Installing Dependencies
To enable WebSocket communication in our NestJS application, we’ll need to install the @nestjs/websockets
and @nestjs/platform-socket.io
packages.
npm install @nestjs/websockets @nestjs/platform-socket.io
Implementing the WebSocket Gateway
In NestJS, Gateways are the WebSocket equivalent of Controllers in a RESTful API. They allow us to define message handlers and event listeners.
Create a new gateway using the CLI.
nest generate gateway chat
This command will generate a file named chat.gateway.ts
. Let's configure this file to handle chat messages.
import {
WebSocketGateway,
SubscribeMessage,
MessageBody,
ConnectedSocket,
WebSocketServer,
OnGatewayInit,
OnGatewayConnection,
OnGatewayDisconnect,
} from '@nestjs/websockets';
import { Server, Socket } from 'socket.io';
@WebSocketGateway()
export class ChatGateway
implements OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect
{
@WebSocketServer() server: Server;
private connectedUsers: Set<string> = new Set();
afterInit(server: Server) {
console.log('WebSocket server initialized');
}
handleConnection(@ConnectedSocket() client: Socket) {
console.log(`Client connected: ${client.id}`);
}
handleDisconnect(@ConnectedSocket() client: Socket) {
console.log(`Client disconnected: ${client.id}`);
this.connectedUsers.delete(client.id);
this.server.emit('users', Array.from(this.connectedUsers));
}
@SubscribeMessage('message')
handleMessage(
@MessageBody() message: { sender: string; content: string },
@ConnectedSocket() client: Socket
) {
this.server.emit('message', message);
}
@SubscribeMessage('join')
handleJoin(
@MessageBody() username: string,
@ConnectedSocket() client: Socket
) {
this.connectedUsers.add(username);
this.server.emit('users', Array.from(this.connectedUsers));
}
}
In this code:
- WebSocketGateway: Indicates that this class is a WebSocket gateway.
- WebSocketServer(): Decorator to inject the WebSocket server instance.
- @SubscribeMessage(): Decorator to listen for a specific event, such as ‘message’ or ‘join’.
- OnGatewayInit, OnGatewayConnection, OnGatewayDisconnect: Interfaces to handle gateway lifecycle events.
Creating the Chat Service
While a simple chat application can function solely with a gateway, it is a good practice to separate logic into services. This keeps your codebase scalable and maintainable.
Create a new service using the CLI.
nest generate service chat
Modify the chat.service.ts
file to include basic chat logic (optional based on the features you need). For simplicity, we will keep it empty for now.
import { Injectable } from '@nestjs/common';
@Injectable()
export class ChatService {
// Future chat logic can go here
}
Modifying the Chat Module
The chat.module.ts
file will be modified to include both the gateway and the service.
import { Module } from '@nestjs/common';
import { ChatGateway } from './chat.gateway';
import { ChatService } from './chat.service';
@Module({
providers: [ChatGateway, ChatService],
})
export class ChatModule {}
Running the Application
Ensure that your src/app.module.ts
includes the ChatModule
.
import { Module } from '@nestjs/common';
import { ChatModule } from './chat/chat.module';
@Module({
imports: [ChatModule],
controllers: [],
providers: [],
})
export class AppModule {}
Now, run the NestJS application.
npm run start
Your WebSocket server should be up and running, ready to handle connections and messaging.
Conclusion
Integrating WebSockets into a NestJS application for real-time chat functionality is straightforward and efficient. NestJS provides an organized and scalable way to handle WebSocket connections and messaging, making it an excellent choice for building real-time applications. By following the steps outlined above, you can create a robust chat application that leverages the power of WebSockets in NestJS with TypeScript.