WebSockets are a fascinating technology, a TCP-based network protocol that allows for asynchronous bi-directional communication. The client starts a connection, sends a request and gets a response – just like HTTP. But much unlike HTTP this connection is kept alive! This has many advantages, like
- Faster responses (no re-establishing connections)
- Less trafic (no overhead for HTTP-headers)
- Live updates (no periodic polling, but push notifications)
If you want to learn more about WebSockets, I recommend this introduction. In this post we’re focussing on utilizing WebSockets to build a simple chat application.
We’re building this project on top of the Hello NodeJS Tutorial Series, so we can focus exclusively on adding chat-functionality.
To make working with WebSockets a breeze, there’s a project called ‘socket.io’ that provides a convenient wrapper for it. And of course, there’s an npm package for it as well!
While we’re at it, let’s also install another package that allows us to work with the express-session in the socket.io context:
server.js we tell the server that we would like to use those packages like so:
In order to have changes we make to the session in socket.io available in express-session as well, we need this piece of code:
Listen And Emit
Now here is where the fun really kicks off:
When socket.io detects a new connection, it executes this function. First it grabs the name of the currently logged in user from the session and writes it to console. It then sends a broadcast telling everyone about the new guy in town and greets the user itself. Using socket.broadcast.emit sends messages to everyone BUT the current user, while socket.emit sends messages to ONLY the current user. You can also send messages to ALL connected clients by calling io.emit().
When the user disconnects, there’s a console entry again as well as a broadcast to inform all users (except the one disconnecting) about what’s happening.
Same behaviour on chat messages coming in: “Broadcast the message to all connected clients but the one sending it!”
Notice how socket.io is not just capable of transmitting plain text but also JSON-Objects. When the server receives a chat message, it manipulates the content by adding the sender’s username.
Let that sink in! If you’re like me and get confused about all this
io.emit stuff, here’s a nice little Cheatsheet from the official docs to help you!
Adding A Route
Before we continue with the client-part of socket.io, let’s add a route for our chat! Remember: we manage our routes in the
controllers folder. In there we add a file called
chat.js and write the following to it:
If you followed my Hello NodeJS Tutorial, this should look familiar. All we do is check if the user is logged in and if so, render the chat view. Of course, for this route to take effect, we have to add it to
And since we’re here, lets’s also redirect requests to the main page to the chat:
Adding A View
After we’ve got our route installed, we need to make sure there’s actually content to be found there! For that we create a view for our chat. We do this by creating a folder
views/chat/ and a file
index.hbs inside that folder with the following content:
There’s nothing special in this markup, just a container for messages, an input box for adding new ones, a box to display the user’s name (we passed that in here using the render()-function in our chat-route) and a link to log out.
The styling for this page can be found in
public/css/design.css. It’s quite long, so I won’t put it here as it would only distract from the essential code.
Remember the code block in
server.js where messages were distributed by the server? Here comes the client part in
public/js/chat.js! First, this is how we send messages:
With the socket instance we emit messages (send to everyone but ourself).
Displaying the message in our chat-box is handled seperately in