Real-Time Communication with Server-Sent Events (SSE) in NestJS

Real-Time Communication with Server-Sent Events (SSE) in NestJS

As developers, we're constantly seeking ways to create more dynamic and engaging user experiences. One approach to achieving this is by leveraging real-time communication between the client and server. While WebSockets are a popular choice, Server-Sent Events (SSE) offer a lightweight and efficient alternative. In this post, we'll explore the benefits of using SSE in NestJS and provide a step-by-step guide on how to implement them.

What are Server-Sent Events (SSE)?


Server-Sent Events (SSE) is a standard HTML5 technology that allows servers to push updates to clients in real-time. Unlike WebSockets, which establish a bi-directional communication channel, SSE is a uni-directional communication method where the server sends updates to the client. This approach is particularly useful when you need to push updates from the server to the client without requiring the client to send data back.

Benefits of SSE over WebSockets


So, why choose SSE over WebSockets? Here are a few compelling reasons:

  • Simpler implementation: SSE is relatively easy to implement, especially when compared to WebSockets. With SSE, you don't need to worry about establishing and managing a bi-directional communication channel.

  • Less overhead: SSE requires less overhead than WebSockets, making it a more efficient choice for applications where real-time updates are critical.

  • Better scalability: Since SSE is a uni-directional communication method, it's easier to scale your application to handle a large number of concurrent connections.

Implementing SSE in NestJS


Now that we've covered the benefits of SSE, let's dive into implementing it in NestJS. We'll create a simple example that demonstrates how to use SSE to push updates from the server to the client.

First, create a new NestJS project using the CLI:

npx @nestjs/cli new nest-sse-example

Next, install the required dependencies:

npm install

Create a new controller that will handle SSE requests:

// sse.controller.ts
import { Controller, Get, Res } from '@nestjs/common';
import { interval, map } from 'rxjs';

@Controller('sse')
export class SSEController {
  @Get()
  sse(@Res() res: any) {
    res.writeHead(200, {
      'Content-Type': 'text/event-stream',
      'Cache-Control': 'no-cache',
      Connection: 'keep-alive',
    });

    const timer$ = interval(1000).pipe(
      map((data) => {
        return `data: ${new Date().toLocaleTimeString()}\n\n`;
      }),
    );

    timer$.subscribe((data) => {
      res.write(data);
    });
  }
}

In this example, we're creating an SSE endpoint that sends the current time to the client every second.

Next, add the SSE controller to the NestJS module:

// app.module.ts
import { Module } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { SSEController } from './sse/sse.controller';

@Module({
  imports: [],
  controllers: [AppController, SSEController],
  providers: [AppService],
})
export class AppModule {}

Finally, start the NestJS application:

npm start

Open a new terminal window and use a tool like curl to test the SSE endpoint:

curl http://localhost:3000/sse

You should see the current time being updated every second.

Client-Side Implementation


To consume SSE events on the client-side, you can use the EventSource API. Here's an example of how to use it:

// client.js
const eventSource = new EventSource('http://localhost:3000/sse');

eventSource.onmessage = (event) => {
  console.log(event.data);
};

eventSource.onerror = () => {
  console.log('Error occurred');
};

eventSource.onopen = () => {
  console.log('Connection established');
};

In this example, we're creating an EventSource object that listens for SSE events on the specified endpoint. When an event is received, we're logging the data to the console.

Conclusion


Server-Sent Events (SSE) offer a lightweight and efficient way to push updates from the server to the client in real-time. With NestJS, implementing SSE is relatively straightforward, and it provides a scalable and efficient alternative to WebSockets.