logo My Digital Garden

Websockets from Node in Express

By James Kolean on May 1, 2023
Source repository: https://gitlab.com/jameskolean/simple-node-websockets
JavaScript
banner

WebSockets are a modern way of creating real-time communication channels between a client (usually a web browser) and a server. Unlike traditional HTTP requests, which are stateless and require the client to initiate each request and wait for a response, WebSockets provide a persistent connection between the client and server that allows for bidirectional communication. A persistent connection means that both the client and server can initiate messages, enabling the creation of interactive applications that update in real-time.

WebSockets are essential because they provide web applications with a more responsive and interactive user experience. They eliminate the need for workarounds such as polling (sending requests at fixed intervals to check for updates) or long-polling (keeping a request open until there is new data to return), which can be inefficient and resource-intensive. With WebSockets, updates are pushed to the client as soon as they become available, reducing latency and improving performance. WebSockets are well-suited for various applications, including online gaming, chat systems, stock trading platforms, and collaborative document editing tools.

With the rise of real-time web applications, WebSockets have become essential for developers looking to build highly interactive and engaging user experiences. In addition to their performance benefits, WebSockets are also easy to use and integrate into existing web applications. Most modern web browsers support WebSockets out of the box, and many libraries and frameworks are available for server-side implementations in languages like Node.js, Python, and Ruby.

Let’s implement WebSockets in NodeJS using an Express server.

Server.js

// src/server.js
import express from "express";
import * as http from "http";
import {
    WebSocketServer
} from "ws";
import path, {
    dirname
} from "path";
import {
    fileURLToPath
} from "url";

const __filename = fileURLToPath(
    import.meta.url);
const __dirname = dirname(__filename);
const app = express();
app.get("/", function(req, res) {
    res.sendFile(path.join(__dirname, "/index.html"));
});
const server = http.createServer(app);

function handleOnMessage(ws) {
    return (message) => {
        const messageString = message.toString();
        console.log(`received: ${messageString}`);
        const broadcastRegex = /^broadcast\:/;
        if (broadcastRegex.test(messageString)) {
            const messageBody = messageString.toString().replace(broadcastRegex, "");
            //send back the message to the other clients
            wss.clients.forEach((client) => {
                if (client != ws) {
                    client.send(messageBody);
                }
            });
        } else {
            ws.send(messageString);
        }
    };
}
const wss = new WebSocketServer({
    server: server,
    path: "/ws"
});
wss.on("connection", (ws) => {
    ws.on("message", handleOnMessage(ws));
    ws.send("Opened connection");
});

const port = 3000;
server.listen(port, () => {
    console.log(`Server started on port ${server.address().port} :)`);
});

This code demonstrates the basic setup for a WebSocket server using Node.js.

The code is a Node.js script that uses the express and ws libraries to set up a WebSocket server. The server listens on port 3000 and serves an HTML file when a client visits the root URL.

const wss = new WebSocketServer({
    server: server,
    path: "/ws"
});
wss.on("connection", (ws) => {
    ws.on("message", handleOnMessage(ws));
    ws.send("Opened connection");
});

We create a WebSocket server using the WebSocketServer class from the ws library. When a new client connects to the server, the ‘connection’ event is emitted, and a new WebSocket object is created to represent the connection. The ‘message’ event is then registered on the WebSocket object, triggered when the client sends a message to the server.

Index.html

This file exercises the web sockets.

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />
    <title>Page Title</title>
    <meta name="viewport" content="width=device-width, initial-scale=1" />
</head>

<body>
    <div>Last Message: <span id="msg"></span></div>
    <div>Last Update: <span id="message-timestamp"></span></div>
    <div>
        Send Message: <input id="message" type="text" />
        <button id="send-btn">send</button>
    </div>
    <div>To broadcast send: <code>broadcast: something</code></div>
</body>
<script>
    // Create WebSocket connection.
    const socket = new WebSocket("ws://localhost:3000/ws");

    // Listen for messages
    socket.addEventListener("message", (event) => {
        document.getElementById("msg").innerHTML = event.data;
        document.getElementById("message-timestamp").innerHTML =
            new Date().toTimeString();
    });
    document.getElementById("send-btn").addEventListener("click", (event) => {
        const message = document.getElementById("message").value;
        console.log("blur", message);
        socket.send(message);
    });
</script>

</html>
© Copyright 2023 Digital Garden cultivated by James Kolean.