Realtime Chat With Express and Faye (Bayeux Protocol)

Technology 7 min read

If you Google around with keywords like “Realtime chat with Express”, the one library that will definitely come up most often is Socket.IO. It is a great library, no doubt. However, if you check the tutorials, you will almost always find that they are giving a simplified version of using it.

What I mean is that all their server-side logic, including bootstrapping Express, adding routing, and configuring sockets, is contained inside a single file. Again, that is perfectly fine for a tutorial, but when you try to extrapolate these teachings into your own workflow and/or a running codebase, you might face certain small but irksome implementation hiccups. At least I did! I eventually managed to sort them out, thanks to the collective wisdom that Google bestows upon us, but it still felt somewhat hackish and unclean.

So, when one of the ongoing projects that the firm I’m associated with needed a simple real-time communication module, I set out to look for an alternative.

Businesses requiring messaging, notifications, or other specialized functionality can use custom software solutions to integrate these capabilities into their existing systems.

Luckily, it turned out that such a solution does exist. It’s a beautiful little library called Faye, which is a “publish-subscribe messaging system based on the Bayeux protocol”.

We will not go much into the subtle differences between Socket.IO and Faye/Bayeux. There are technical differences, though cosmetically they may seem similar. Instead, we will put the latter to good use and build a simple little real-time chat interface that would be minimally invasive on a standard Express app.

Real-time messaging is also a core feature covered in this complete guide to social app development from idea validation and technology selection through launch and scaling.

On this page

Server Side

To begin with, we’ll scaffold an Express app using the official Express Application Generator I assume you already have it installed globally via npm.

express real-time-chat-example --ejs
cd real-time-chat-example
npm install

We’ll be using EJS as our templating engine here. That’s only because EJS is the one I personally use; other engines should work perfectly fine as well.

Now let’s just have Faye join the fray:

npm install --save faye

Next, we add our code to bootstrap Faye, and what better place to do so than where all the Express bootstrapping happens, the entry point of your Express app, the bin/www file!

var app = require('../app');
var debug = require('debug')('faye-express:server');
var http = require('http');
var faye = require('faye');

var bayeux = new faye.NodeAdapter({
  mount: '/faye',
  timeout: 45
});

var server = http.createServer(app);

bayeux.attach(server);

That’s it! You can now run the Express app as usual using./bin/www. Once the server is running, open your local development server in your browser. The only difference here with a stock Express app is that Faye has quietly started a central message server mounted at the path/faye.

Now all we need is a client or two to use the message server.

Client Side

The Welcome to Express message you see comes from theviews/index.ejsfile, which is rendered when you visit the root route of your app. This is where we’ll add our Faye client.

We’ll modify the file, starting with the
<head>
part:

<head>
  <title><%= title %></title>
  <link rel="stylesheet" href="/stylesheets/style.css">
</head>

jQuery, which we’ll need for rudimentary DOM manipulations, has been included from a CDN.

We’d have expected to add the Faye client library from some CDN as well, but Faye provides itsclient.jsfile at a convenient location relative to your app’s root as soon as you’ve set it up on the server.

Thepublic/javascripts/script.js
file, which we need to create, shall contain our custom JavaScript code.

Now, we’ll add some more HTML to constitute our rather spartan chat UI. If you need some spice, simply add your CSS in the
public/stylesheets/style.css
file.

<body>

  <form id="message-form">
    <input
      type="text"
      id="new-message"
      placeholder="Your Message Here"
    />

    <input
      type="submit"
      id="submit-btn"
      value="Enter"
    />
  </form>

  <h4>Messages:</h4>

  <ul id="messages-list"></ul>

  <script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
  <script src="/faye/client.js"></script>
  <script src="/javascripts/script.js"></script>

</body>

Understanding PubSub

Before writing the actual client-side code, we should perhaps make a brief mention here about PubSub because that’s the paradigm Faye/Bayeux is using.

In this model, we have Clients which can Publish and/or Subscribe to Channels. Whenever one client publishes to a channel, all client-subscribers currently listening to that channel will be informed, in real time, of that publication, and they can act accordingly.

The role of the message server here is that of a Broker who manages the entire process transparently and behind the scenes, invisible for all practical purposes to the clients. It gives the impression that the clients are communicating amongst themselves directly.

Note that Faye/Bayeux, which uses this PubSub paradigm, is fundamentally different from the various implementations or emulations of the standard Sockets Protocol, such as Socket.IO.

Armed with the above knowledge, it’s time to add our JavaScript code to the
public/javascripts/script.js
file. The code should be pretty self-explanatory, especially if you peruse the comments.

// Create the Faye client.
// All you need is the mount point for the Faye server
// you want to connect to.
var client = new Faye.Client('/faye');

$(document).ready(function () {

  // Handle message form submission.
  $('#message-form').on('submit', function (evt) {
    evt.preventDefault();

    var newMessage = $('#new-message').val().trim();

    if (!newMessage) {
      return;
    }

    // Publish the new message to the /messages channel.
    client.publish('/messages', {
      text: newMessage
    });

    // Clear the input after sending.
    $('#new-message').val('');
  });

  // Subscribe to the /messages channel.
  // Every subscribed client will receive new messages.
  client.subscribe('/messages', function (newMessage) {

    $('#messages-list').append(
      $('
  • ‘).text(newMessage.text) );});});

And that’s all! Start the Express app using./bin/www. Once the server is running, open two separate browser windows or tabs and navigate to your local development server. Any message you enter in one window will be instantly displayed in the other, demonstrating real-time communication between connected clients.

So, in just a few lines of simple code, you have a working, albeit rudimentary, real-time chat system. You can see the complete code in its GitHub repository .

Addendum: Saving Chats on the Server

While our real-time chat example works fine, aside from the looks obviously, we would really like to save our chat history somewhere on the server. This can be done in two different ways.

The first option is to set up your server-side Express routes the usual way. Have a POST route, sayPOST /message, whose handler should receive the message content in itsreq.bodyand suitably save it to a database using the usual code.

On the client side, we can simply add an AJAX call to this route with the new message content as its payload. This AJAX call can occur in tandem with our existing Faye publish call.

This method would work particularly well if you already have your Express routing system in place and just need to add real-time functionality without changing the existing code or workflow.

The other method is to use Faye on the server as well with Server Side Clients .It may sound like an oxymoron, but is extremely simple to implement.

Just create a new JavaScript file anywhere on the server, require it inside
app.js
(or, for that matter, you can use the
app.js
file itself as well), and add the following code in it:

var Faye = require('faye');

var client = new Faye.Client('http://localhost:3000/faye');

client.subscribe('/messages', function (newMessage) {
  console.log('New Message:', newMessage);
});

If the above snippet looks familiar, that’s because it is! Faye’s client code is
isomorphic,
i.e. the same in essence irrespective of whether it appears on the server side or the client side.

Also, you can add this code at any suitable place on the server with no friction with your existing codebase.

WE DESIGN, DEVELOP AND MARKET BEAUTIFUL WEB & MOBILE APPS


Contact us

Work with us

Building something that cannot afford to break?

Book a Strategy Call

Leave a comment

Your email address will not be published.