NodeJS Live Chat With WebSockets (A Simple Example)

Welcome to a tutorial and example on how to create a NodeJS live chat application with WebSockets. Yes, it is possible to build an entire live chat driven by pure Javascript.

The general mechanics of a live chat are:

  1. Create a WebSocket server to accept and manage the connections.
  2. Create a live chat page that will connect to the server, send and receive messages.
  3. When a message is sent to the server, simply forward the message to all connected clients.

It’s really that simple – Read on for the full example!

ⓘ I have included a zip file with all the source code at the start of this tutorial, so you don’t have to copy-paste everything… Or if you just want to dive straight in.

 

 

TABLE OF CONTENTS

Download & Notes Node Chat Useful Bits & Links
The End

 

DOWNLOAD & NOTES

Firstly, here is the download link to the example code as promised.

 

QUICK NOTES

  • The ws module is required – npm install ws.
  • Run node 1-server.js in the command line, that will deploy the chat server at ws://localhost:8080.
  • Access 2-client.html in the browser. Technically, WebSockets are not bound by the same-origin policy… So even file://2-client.html should work just file.
If you spot a bug, feel free to comment below. I try to answer short questions too, but it is one person versus the entire world… If you need answers urgently, please check out my list of websites to get help with programming.

 

EXAMPLE CODE DOWNLOAD

Click here to download all the example source code, I have released it under the MIT license, so feel free to build on top of it or use it in your own project.

 

 

NODEJS LIVE CHAT

All right, let us now get into the live chat example.

 

PART 1) NODE LIVE CHAT SERVER

1-server.js
// (A) INIT + CREATE WEBSOCKET SERVER AT PORT 8080
var ws = require("ws"),
    wss = new ws.Server({ port: 8080 }),
    users = {};
 
// (B) ON CLIENT CONNECT
wss.on("connection", (socket, req) => {
  // (B1) REGISTER CLIENT
  let id = 0;
  while (true) {
    if (!users.hasOwnProperty(id)) { users[id] = socket; break; }
    id++;
  }
 
  // (B2) DEREGISTER CLIENT ON DISCONNECT
  socket.on("close", () => { delete users[id]; });
 
  // (B3) FORWARD MESSAGE TO ALL ON RECEIVING MESSAGE
  socket.on("message", (msg) => {
    let message = msg.toString();
    for (let u in users) { users[u].send(message); }
  });
});

First, we need the WebSocket module to make this work, run npm install ws in your project folder. Then how this works is very simple:

  1. Load the ws module, create a WebSocket server. Take note of the empty users object here.
  2. Handle the live chat.
    • When a user connects to the WebSocket server, “save” the connection into users.
    • When the user disconnects, we remove the connection from users.
    • Finally, when the user sends a message to the server, we simply forward it to all connected clients.

 

 

PART 2A) LIVE CHAT HTML CLIENT PAGE

2-client.html
<!-- (A) CHAT HISTORY -->
<div id="chatShow"></div>
 
<!-- (B) CHAT FORM -->
<form id="chatForm" onsubmit="return chat.send();">
  <input id="chatMsg" type="text" required disabled/>
  <input id="chatGo" type="submit" value="Go" disabled/>
</form>

This should be self-explanatory, just a simple HTML chat page.

  • <div id="chatShow"> is where we show the chat messages.
  • <form id="chatForm"> is the HTML form where we enter and send a message.

 

 

PART 2B) LIVE CHAT CLIENT JAVASCRIPT

2-client.js
var chat = {
  // (A) INIT CHAT
  name : null, // USER'S NAME
  socket : null, // CHAT WEBSOCKET
  ewrap : null, // HTML CHAT HISTORY
  emsg : null, // HTML CHAT MESSAGE
  ego : null, // HTML CHAT GO BUTTON
  init : () => {
    // (A1) GET HTML ELEMENTS
    chat.ewrap = document.getElementById("chatShow");
    chat.emsg = document.getElementById("chatMsg");
    chat.ego = document.getElementById("chatGo");
 
    // (A2) USER'S NAME
    chat.name = prompt("What is your name?", "John");
    if (chat.name == null || chat.name=="") { chat.name = "Mysterious"; }
 
    // (A3) CONNECT TO CHAT SERVER
    chat.socket = new WebSocket("ws://localhost:8080");
 
    // (A4) ON CONNECT - ANNOUNCE "I AM HERE" TO THE WORLD
    chat.socket.addEventListener("open", () => {
      chat.controls(1);
      chat.send("Joined the chat room.");
    });
 
    // (A5) ON RECEIVE MESSAGE - DRAW IN HTML
    chat.socket.addEventListener("message", (evt) => {
      chat.draw(evt.data);
    });
 
    // (A6) ON ERROR & CONNECTION LOST
    chat.socket.addEventListener("close", () => {
      chat.controls();
      alert("Websocket connection lost!");
    });
    chat.socket.addEventListener("error", (err) => {
      chat.controls();
      console.log(err);
      alert("Websocket connection error!");
    });
  },
 
  // (B) TOGGLE HTML CONTROLS
  controls : (enable) => {
    if (enable) {
      chat.emsg.disabled = false;
      chat.ego.disabled = false;
    } else {
      chat.emsg.disabled = true;
      chat.ego.disabled = true;
    }
  },
 
  // (C) SEND MESSAGE TO CHAT SERVER
  send : (msg) => {
    if (msg == undefined) {
      msg = chat.emsg.value;
      chat.emsg.value = "";
    }
    chat.socket.send(JSON.stringify({
      name: chat.name,
      msg: msg
    }));
    return false;
  },
 
  // (D) DRAW MESSAGE IN HTML
  draw : (msg) => {
    // (D1) PARSE JSON
    msg = JSON.parse(msg);
    console.log(msg);
 
    // (D2) CREATE NEW ROW
    let row = document.createElement("div");
    row.className = "chatRow";
    row.innerHTML = `<div class="chatName">${msg["name"]}</div> <div class="chatMsg">${msg["msg"]}</div>`;
    chat.ewrap.appendChild(row);
 
    // AUTO SCROLL TO BOTTOM MAY NOT BE THE BEST...
    window.scrollTo(0, document.body.scrollHeight);
  }
};
window.addEventListener("DOMContentLoaded", chat.init);

This seems a little crazy at first, but keep calm and look carefully.

  • (A) On page load, chat.init() will run. We ask for the user’s name, connect to the chat server, and enable the HTML chat form.
  • (C) When the user enters a message, we simply send it to the chat server.
  • (A5 & D) Remember that the chat server will forward messages to all connected clients? All we do here is display the received message in HTML.

 

 

USEFUL BITS & LINKS

That’s all for the tutorial, and here is a small section on some extras and links that may be useful to you.

 

NOT PERFECT. DUH.

Of course, this simple chat is but a barebones example. Plenty can be done to make this better:

  • Better security – Restrict the number of users or who can connect to the chat server.
  • More security – Remove all HTML and scripts in the messages.
  • Name check – Don’t allow duplicate names?
  • Restricted words – Automatically censor bad words.
  • Announce users who left the chat?
  • Better HTML interface – Keep only N messages? Prevent too many messages and browser from crashing.

 

COMPATIBILITY CHECKS

Suprise. Web Socket goes all the back, supported even on the old Internet Exploders.

 

LINKS & REFERENCES

 

THE END

Thank you for reading, and we have come to the end. I hope that it has helped you to better understand, and if you want to share anything with this guide, please feel free to comment below. Good luck and happy coding!

Leave a Comment

Your email address will not be published. Required fields are marked *