Using Speedy Web Compiler
Nest.js version 10 introduces enhancements to the compiler speed, resulting in accelerated project execution times. This advancement leads to a more efficient development experience when building Nest.js applications, as faster compilation directly improves the feedback loop for developers.
Best practices suggest leveraging such improvements to compiler speed by regularly updating to the latest version, ensuring that the development environment is as performant as possible. Additionally, it's advisable to monitor the project's build times after upgrading, to quantify the improvement and identify any areas where the newer version can be further optimized for speed.
Step 1: Uninstall the @nestjs/cli
npm uninstall -g @nestjs/cli
Step 2: Install @nestjs/cli
npm install -g @nestjs/cli
Step 3: Create a new Project
nest new <project-name>
Step 4: Make speedy web compiler
You have to add these two properties in nest-cli.json
"compilerOptions": {
"builder": "swc",
"typeCheck": true
}
Step 5: Install the SWC packages
npm i -D @swr/cli @swr/core
Step 6: Run the Application
npm run start:dev
Create Web Socket Server
What are WebSockets?
WebSockets are a communication protocol that enables real-time, bidirectional communication between a client (such as a web browser) and a server. Unlike traditional HTTP requests, where the client sends a request and the server responds, WebSockets establish a persistent connection between the client and the server, allowing for ongoing communication in both directions.
Here are some key characteristics of WebSockets:
Full-duplex communication: WebSockets enable simultaneous two-way communication between the client and the server. Both parties can send messages to each other independently and in real-time.
Persistent connection: Unlike traditional HTTP connections that are stateless and short-lived, WebSockets maintain a persistent connection between the client and the server. This eliminates the need for repeated connection setup and teardown with each request.
Real-time updates: With WebSockets, data can be pushed from the server to the client or vice versa as soon as it becomes available. This allows for real-time updates and notifications without the need for the client to continuously poll the server for updates.
Low overhead: WebSockets have a minimal overhead compared to other communication protocols like HTTP. Once the initial connection is established, the overhead of subsequent messages is significantly reduced.
WebSockets are commonly used in various applications and use cases that require real-time communication, such as chat applications, collaborative editing tools, real-time analytics, online gaming, and live streaming. They provide a more efficient and responsive alternative to techniques like long-polling or frequent AJAX requests for real-time updates.
Step 1: Install Dependencies
"@nestjs/platform-socket.io": "^10.0.3",
"@nestjs/websockets": "^10.0.3",
First of all, install these two dependencies to work with the websocket.
Step 2: Create Events Module and Gateway
nest g module events
nest g gateway events
In the events.module.ts file, EventsGateway is included as a provider to facilitate real-time bi-directional event-based communication. Best practice dictates isolating such gateways within their dedicated module to streamline scalability and maintain clear boundaries of responsibility within the application.
// Events.module.ts
import { Module } from "@nestjs/common";
import { EventsGateway } from "./events.gateway";
@Module({
providers: [EventsGateway],
})
export class EventsModule {}
Step 3: Create a new Event
//events.gateway.ts
import { OnModuleInit } from "@nestjs/common";
import {
MessageBody,
SubscribeMessage,
WebSocketGateway,
WebSocketServer,
WsResponse,
} from "@nestjs/websockets";
import { Observable, of } from "rxjs";
import { Server } from "socket.io";
@WebSocketGateway({
cors: {
origin: "*",
},
})
export class EventsGateway implements OnModuleInit {
@WebSocketServer()
server: Server;
onModuleInit() {
//3
this.server.on("connection", (socket) => {
console.log(socket.id);
console.log(socket.connected);
});
}
// You can listen to this event
// Client can send message to me by using the message key/event name
@SubscribeMessage("message")
newMessage(
@MessageBody()
data: any
) {
console.log("Message is received from the client");
console.log(data); //Here we did not send a message back to the server
// Save the message to the database and return the reply in the response
// Call the service method to save the record in the DB
}
}
Gateways operate on an event-driven architecture, where events are emitted and consumed by clients and the server. Clients can listen for specific events and the server can emit events to trigger actions on the client side.
Gateways in Nest.js are implemented using decorators and a class-based approach. A gateway class is decorated with the @WebSocketGateway() decorator, which marks it as a WebSocket gateway. Within the gateway class, you can define event handlers to handle WebSocket events like connection, disconnection, and message reception.
Gateways can be treated as providers; this means they can inject dependencies through the class constructor. Also, gateways can be injected by other classes (providers and controllers) as well. 2. You can access to webSocket server by using this decorator. You can find out who has connected to your Gateway and their socket ID 3. I choose onModuleInit to check the WebSocket connection with the client 4. The @SubscribeMessage('message') decorator is applied to the newMessage method. This decorator specifies that this method should be executed when a WebSocket message with the event name 'message' is received from the client.
The @MessageBody() decorator is applied to the data parameter. This decorator instructs Nest.js to extract the message payload from the incoming WebSocket message and bind it to the data parameter.
In summary, it demonstrates a method in a WebSocket gateway that is triggered when a WebSocket message with the event name 'message' is received from the client. It logs the received message to the console and potentially performs further actions such as saving the message to a database using a service method.
Send Message from Frontend Client
Step 1: Consuming Event from the Frontend
When consuming the WebSocket 'message' event, plain JavaScript can be utilized effectively. This approach ensures that the event handling is kept lightweight and free from additional dependencies.
A best practice in this scenario is to ensure robust error handling and validation of incoming messages to prevent potential issues stemming from malformed data. It's also advisable to structure the code for easy maintenance and scalability, possibly by abstracting the event handling into separate, testable functions or classes.
<html>
<head>
<body>
<p>Please check the console for the message reply</p>
</body>
<script
src="https://cdn.socket.io/4.3.2/socket.io.min.js"
integrity="sha384-KAZ4DtjNhLChOB/hxXuKqhMLYvx3b5MlT55xPEiNmREKRzeEm+RVPlTnAn0ajQNs"
crossorigin="anonymous"
></script>
<script>
const socket = io('http://localhost:3000');
socket.on('connect', function () {
console.log('Connected');
// Send Message to Websocket Server
socket.emit('message', { msg: 'THIS IS THE MESSAGE FROM THE CLIENT' });
});
socket.on('message', function (data) {
console.log('event ', data);
});
socket.on('exception', function (data) {
console.log('event', data);
});
socket.on('disconnect', function () {
console.log('Disconnected');
});
</script>
</head>
<body></body>
</html>
Step 2: Return data from the message event using Observable
Returning data from the message event utilizing Observables in Nest.js aligns with reactive programming principles, facilitating a stream-based approach to handle data sequences over time. This method is crucial for scenarios requiring real-time updates or complex asynchronous operations, where Observables can efficiently manage and deliver data payloads as events occur.
As a best practice, it's advisable to leverage the RxJS library, which Nest.js integrates seamlessly with, to create Observables. This enables fine-grained control over event handling, allowing for the composition of sophisticated data handling and transformation strategies, essential for robust and reactive application architectures.
@SubscribeMessage('message')
newMessage(
@MessageBody()
data: any,
): Observable<WsResponse<any>> { //1
console.log('Message is receieved from the client');
console.log(data);
return of({ event: 'message', data: 'Learn Node' });
}
Summary
In the context of Nest.js, the integration of Socket.IO for WebSocket communication is vital for real-time, bi-directional communication between web clients and servers. The setup involves establishing a persistent connection that allows clients to send messages to the server and listen for responses. Best practices include handling exceptions gracefully and ensuring that disconnection events are managed to maintain robust communication. Additionally, logging received data to the console is a useful technique for monitoring and debugging the flow of messages. When implementing this in Nest.js, one would typically encapsulate WebSocket management within a dedicated module or service, leveraging Nest.js's dependency injection to manage lifecycle events and provide a clean separation of concerns.
$7 bundle of my best NestJS + backend developer Courses.
More details coming soon.
Get the latest insights from the marketing world.