Beginner's Guide to Using HTML Web Sockets with NestJS

In this post, I will explain how to integrate HTML native web sockets in NestJs.

I assume you have the NodeJs LTS version installed on your machine.

Please install the NestJs CLI if you haven't already.

npm i -g @nestjs/cli

Step 1: Setting Up the Backend

Let's set up our backend first. Please open your terminal and type the following command:

nest new web-socket-integration

Press enter when prompted to choose a package manager (select npm).

Which package manager would you ❤️ to use? (Use arrow keys)

❯ npm

yarn

pnpm

This sets up our basic app. Please navigate to this folder.

cd web-socket-integration

Let's start our server.

npm run start:dev

Step 2: Setting Up the Chat Gateway

The ws library is used in NodeJs to handle WebSocket connections. We will use the NestJs implementation of this library with @nestjs/platform-ws.

Let's first install the dependencies.

npm i --save @nestjs/websockets @nestjs/platform-ws

Let's set up our WebSocket adapter.

Open the main.ts file and add the following code:

import { WsAdapter } from '@nestjs/platform-ws';

Now let's use this adapter.

app.useWebSocketAdapter(new WsAdapter(app));

So your main.ts file will look like this:

import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';
import { WsAdapter } from '@nestjs/platform-ws';
async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  app.useWebSocketAdapter(new WsAdapter(app));
  await app.listen(3000);
}
bootstrap();

Let's set up our chat gateway with the following command:

nest g gateway chat

This creates our chat gateway, which we will use to communicate with the front end.

Step 3: Understanding What Happened

In NestJs, we use adapters to set up WebSocket connections. According to the official documentation, there are certain methods that an adapter must implement.

createCreates a socket instance based on passed arguments
bindClientConnectBinds the client connection event
bindClientDisconnectBinds the client disconnection event (optional*)
bindMessageHandlersBinds the incoming message to the corresponding message handler
closeTerminates a server instance

In the main.ts file, we imported WsAdapter and set up the adapter with:

 app.useWebSocketAdapter(new WsAdapter(app));

We created a gateway, which is used to handle our connection with the client.

nest g gateway chat

This creates our gateway. The @WebSocketGateway in chat.gateway.ts indicates that ChatGateway is a gateway.

@SubscribeMessage('message')
  handleMessage(client: any, payload: any): string {
    return 'Hello world!';
  }

This helps us handle client data for an event called "message."

Step 4: Setting Up the Front End

Note: Here, I am setting up the front end with HTML, but you can use any framework or library you prefer.

We will add an input element and a button to send the input element's value to our backend client.

Create a file named front-end.html and add the following code:

<!doctype html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Web Socket</title>
  </head>
  <body>
    <input id="data-input" />
    <button onclick="sendMessage()">Send message</button>
  </body>
  <script>
    let socketConnection = new WebSocket('http://localhost:3000');
    socketConnection.onmessage = (data) => {
      console.log(data);
    };

    function sendMessage() {
      const data = document.getElementById('data-input');

      socketConnection.send(
        JSON.stringify({
          data: data.value,
          event: 'message',
        }),
      );
    }
  </script>
</html>

Step 5: Understanding the Front End

In the script, we establish a socket connection.

We have an input field with the id "data-input" and a button that calls the sendMessage() function. First, we enter our value in the input field and click the "Send message" button to send our message to the backend.

In the sendMessage function, we use socketConnection.send to send a stringified object with two keys:

  1. data - This is the information we want to send to the server.

  2. event - This is the event for which we are sending data. In the file chat.gateway.ts, we use @SubscribeMessage to subscribe to the message event. In the handleMessage function, please add the following code:

    console.log(payload)

  1.  @SubscribeMessage('message')
       handleMessage(client: any, payload: any): string {
         console.log(payload)
         return 'Hello world!';
       }
    

    Now we can see the data we receive from the front end in the terminal where the server is running.

Step 6: Testing Integration

Please open front-end.html in a browser. Enter a value in the input field and click the "Send message" button. You will see the value appear in the terminal of our backend server.

The complete setup can be found here.

If you want to learn more about Nest WebSockets, you can read more here.

Thank you for reading this.