HowTo: Websocket-HTML-Express

The websocket protocol is an extremely powerful protocol for bidirectional communication over the internet. It is used already by many websites to refresh data incrementally and/or periodically. Once a websocket connection is established, both server and client can send messages over the connection repeatedly with no limits on the number of messages or on the duration of the connection. After a connection has been established the protocol is symmetric in the sense that both server and client can send and receive messages. There is in fact no difference between client and server after a connection has been made. The protocol is very easy to use. I have made a minimal example of the use of a websocket connection that is initiated from a browser. It is also possible to initiate a websocket connection from a JavaScript program; the details are slightly different from the browser case and are described here.

Web service build with Express, containing a single websocket service published on the path ‘/socket’ (file webservice.js):

var express = require('express');
var app = express();
var expressWs = require('express-ws')(app);
app.ws('/socket', function(ws, req) {
    var counter = 0;
    setInterval(() => {
        counter += 1;
        ws.send('Server generated message #' + counter);
    }, 1000);
    ws.on('message', function(mes) {
        console.log('Message received from client: ' + mes);
    });
})
app.listen(6060, function() {
    console.log('WS server listening on port 6060...');
});

Web page, containing a WebSocket object that encapsulates the websocket connection. The easiest way to serve one static HTML page is to embed it in an Express web service accessible via one fixed path (file httpserver.js).

var express = require('express');
var app = express();
app.get('/page.html', function(req, res) {
    res.send(`
<!DOCTYPE html>
<html>
    <head>
        <title>Websocket Bidirectional Communication</title>
    </head>
    <body>
        <h1>Value received via websocket connection</h1>
        <p id='pid1'></p>
        <h1>Value send via websocket connection</h1>
        <p id='pid2'></p>
        <script>
            const socket = new WebSocket('ws://localhost:6060/socket');
            // Connection opened
            socket.addEventListener('open', function (event) {
                console.log('Connection Opened ');
                let counter = 0
                setInterval(() => {
                    counter += 1;
                    const message = 'Client generated message #' + counter
                    socket.send(message);
                    document.getElementById('pid2').innerHTML = message;
                }, 1370);
            });
            // Listen for messages
            socket.addEventListener('message', function (event) {
                const message = event.data;
                console.log('Message from server ', message);
                document.getElementById('pid1').innerHTML = message;
            });
        </script>
    </body>
</html>`);
});
app.listen(5050, function() {
    console.log('HTTP server listening on port 5050...');
});

To make things work, one has to set up a JavaScript project with the following package.json file:

{
    "name": "MinimalWebsocketHtmlExpress",
    "version": "1.0.0",
    "description": "",
    "keywords": [],
    "author": "J.C. Verheul",
    "license": "ISC",
    "dependencies": {
        "express": "^4.14.0",
        "express-ws": "^4.0.0"
    }
}

The project is build and executed with NPM and Node, so both tools should be installed on your workstation. For this example I used NPM version 5.5.1 and Node version 8.9.3. Older and newer versions of these tools should most likely work as well, since the project is extremely simple. Proceed as follows:

* Put the files webservice.js, httpserver.js and package.json in one working directory, or clone the little project from GitHub.
* Execute npm install
* Execute node webservice.js
* Execute node httpserver.js (from a different command prompt)
* Use a browser to visit http://localhost:5050/page.html