Photo by Eduardo Sánchez on Unsplash

Build a Chat App With Socket.IO and RethinkDB

Sascha Trifunovic
The Startup
Published in
5 min readAug 17, 2020

--

A lot of tutorials can be found that teach you how to build a chat app with Socket.io. However, have you ever wondered how to best persist those chat messages?

Enter RethinkDB, a realtime schema-less database. You can store and handle documents easily, just like in MongoDB, but it has reactivity built into it. That means you can subscribe to queries and get notified when data changes, making it the perfect choice when it comes to storing chat messages.

In this article, you will learn how to create a simple chat app with Socket.io and persist the messages in RethinkDB. To show the usefulness of a reactive database, we will also add a simple bot that reacts when you address it.

You can also try the running app, or check out the code repository.

Application setup

We will build a Node.js app, so you need to have node and npm installed. If you want to deploy your app to Heroku, you will also need a Heroku account, as well having their CLI installed. To run your app locally, you need to install and run a RethinkDB instance.

To create the application, run the following in a terminal.

$ mkdir rethink-chat && cd rethink-chat
$ npm init -y
$ npm install rethinkdb express morgan http socket.io lorem-ipsum

This will initialize a Node.js app and install all required dependencies.

Prepare a Heroku app

In order to deploy the application to Heroku we need to create a Heroku app:

$ git init
$ heroku create

We will also need a RethinkDB instance to store and subscribe to the chat messages sent between users. You can do this via the RethinkDB Cloud add-on as follows:

$ heroku addons:create rethinkdb

The RethinkDB Cloud add-on is currently in alpha. Request an invite for your Heroku account email.

Building the server

To begin, let us set up the Node.js server. Create an index.js file and add the following server skeleton. We use an Express.js server to handle http traffic and Socket.io to handle WebSocket connections with clients.

This skeleton serves a static frontend from the public folder. We will create the frontend code later. In addition our server needs to do three things:

  1. Handle connections to the RethinkDB database
  2. Create an Express.js route that will give a user access to the chat room
  3. Configure the Socket.io server to listen to incoming chat messages

RethinkDB connection

We manage our RethinkDB connection lazily, i.e., we only create the (re-)connection when it is actually needed. The connection parameters are parsed from environment variables, or the defaults are used.

On Heroku, the RethinkDB Cloud add-on will set the environment variables. For a locally running instance of RethinkDB, the defaults should work.

Route to access room

As mentioned earlier, the frontend is static. We do however need a route to access a chat room. The route will return the message history of a given room, as well as a WebSocket handle to access it.

This is where the RethinkDB magic happens. The first time this route is called for a particular room (when the first person joins), we subscribe to a RethinkDB query to get notified whenever a new chat message is available. We send new chat messages via Socket.io to any clients listening for the room’s handle.

Listen for new messages

The last puzzle piece of the server is to listen and save all incoming chat messages. Whenever a message comes in via the chats handle of the Socket.io connection, we save it to the chats table in RethinkDB.

Saving a value in the chats table will trigger the subscription we added above, causing the message to be sent to all clients listening to this room, including the sender of the message.

Frontend

For our frontend we will use an embedded Vue.js app. This makes the frontend simple, but gives us access to all of Vue’s awesome features. The frontend consists of a layout file as well as JavaScript and CSS assets.

  • The layout file only serves as a mount point for the Vue app in addition to importing the dependencies.
  • The CSS asset contains the styling of the frontend. It is long, not very interesting, and can be found here.
  • The JavaScript asset app.js contains the actual Vue app.

The Vue app contains two routes. The/ path points to the main view and the /:roomId path points to the room view.

Main view

The main view lets you choose a username (default is a random string) and allows you to join a room with a given name.

Whenever you join a room, the Vue router will load the chat room view.

Chat room

The chat room, a room view containing a chat room component. makes a request to the Express route to join the given room when it is created. It also registers a Socket.io handler that listens for incoming chat messages and adds them to the list of messages.

The chat room allows the user to type and send a message which will then be sent to the server via the WebSocket handled by Socket.io.

Now we have a working server and frontend. The last thing we need is to make sure the chats table actually exists in the RethinkDB database when we run the app.

Database migration

The app does not work without a chats table. We thus need a database migration that adds the table.

This migration checks if the chats table exists, and if it is missing, it creates it.

A simple chat bot

As we saw, one of RethinkDBs great features is the baked in reactivity that allows us to subscribe to queries. This feature also comes in handy when creating a simple chat bot. The bot simply needs to subscribe to changes in the chats table and react to them whenever appropriate.

Our Lorem bot will reply with a random section of Lorem Ipsum whenever prompted with @lorem. The bot subscribes to the chats table and scans the beginning of the message. If it starts with@lorem, it will reply with a message in the same room.

Deploy the application to Heroku

To deploy our working application and bot to Heroku we need to create a Procfile. This file basically tells Heroku what processes to run.

// Procfilerelease: node migrate.js
web: node index.js
lorem-bot: node lorem-bot.js

The release and web processes are recognized by Heroku as the command to run upon release and the main web app respectively. The lorem-bot process is just a worker process that could have any name.

Deploy the app to Heroku with

$ echo "node_modules/" > .gitignore
$ git add .
$ git commit -m 'Working rethink-chat app'
$ git push heroku master

You will need to manually enable the lorem-bot process in your Heroku app. You can do so on the Resources tab.

Conclusion

In less than 15 minutes we managed to create and deploy a chat application with a simple bot. This shows the power and ease of use of RethinkDB. The ability to subscribe to queries makes it easy to build a reactive app and a natural fit to interact with Socket.io. Further, Heroku makes deployment a breeze, and with the RethinkDB Cloud add-on you will never have to do the tedious work of managing a database server yourself.

Originally published at https://www.rethinkdb.cloud on August 17, 2020.

--

--