A lot of web applications these days require fast and lightweigh real time communication.
Real time analytics, real time measurement, games, chat applications, syncing with other devices, syncing with other people when coloborating on a document, etc.
Last time I showed you a solution to all of those problems with WebSockets. It works, most of the time, but often it is too complex.
What’s more it uses a completely different protocol from HTTP. Some users don’t support it and some host providers don’t allow it.
Wouldn’t it be nice if you could have
- realtime communication but only over HTTP?
- very simple to use that can be easily added to any web stack?
- reconnection automatically without your intervention?
Everybody is talking only about the syxy WebSockets and as a result, we often forget its little sister Server Sent Events (SSE).
SSE can help you with all of the above and give you a little bit more, too.
What is SSE?
Server Sent Events is another technology for real time communication with the server.
Its main purpose is to stream events from the server to the clients because unlike WebSockets it works only in this direction.
Clients cannot use SSE to send back events to the server.
One of the big advantages of SSE is that it is done only over HTTP. You don’t require a fancy new protocol, and you avoid all of the problems that come with it.
Another nice feature is automatic reconnection. Whenever, the connection drops your browser is resopnsible for automatically reestablishing it. You don’t have to do anything yourself.
You will see that SSE is that simple that you can actually implement it yourself even on clients which are not browsers like mobile devices for example.
Web is often only one way realtime
Now that you know that SSE is capable of sending lightweight real time events only from the server to the client, maybe you are a little disappointed and you want to go back to WebSockets.
However, for many applications this is all they need. For example, receiving status updates on Twitter can be done with SSE, also getting the current stock price and its updates.
Even the usual example of WebSockets tutorials with chat application needs real time communication only from the server to the client and SSE is more than enough.
No matter how fast you write your messages AJAX is more than enough to sent them and SSE to provide you with all messages from your friends.
You only need two way real time communication when you have a lof of messages in both ways. More often than not, you only need events sent from the server and AJAX is enough for the rest.
How SSE works?
Server sent events are very simple. All you have to do is to construct a plain text response with the Content-Type header set to text/event-stream and then keep the connection open. Then you can send more plain text responses over the same connection.
This is it.
Your plane text response is expected to be a single line like this:
The double “\n\n” (new line character) is how you signal the end of the message to the browser.
Only after you do that it is delivered. The text after data: is the actual message that the browser will receive.
However, sometimes you might want to send a message on multiple lines. In this case it should look like this
This whole piece is delivered as a single multiline message. Again \n\n signals
the end of the message and between lines you are using only a single \n. However,
don’t forget that every line should start with data:
.
On the client side in the browser you can listen for those messages in the following way:
As you can see it is extremely simple. First, you check whetehr SSE is supported on the borwser.
Then you connect to your web app and it creates a source, an EventSource, where you can listen for events.
In e.data you will find your messages from the server and it works for both single and multiline messsages.
As you can see by default there are three type of events. First, an event when a connection is open, then an event when it is closed or reconnecting and finally an event when you receive a new message.
A neat little feature is that you can attach unique id to each event:
If the connection drops, when the browser restores it automatically. You will receive on the server a header Last-Event-ID containing the last id it received, which can help you with replying all missed events.
By default the browser reconnects after 3 seconds, but you can control this
This value is in milliseconds so the browser will try to reconnect after 10 seconds in case of a lost connection.
Last but not least, by default you only have three events: open, error and message. The first two are automatically generated by the browser.
You can easily create more events like this
Then you can listen for this event
This will not fire the message event, only the spilledWater event.
Example: Voting system
Let’s see all of this in action. We are going to build a real time voting app.
It will have two pages. One page for people to answer. Another where the overall results of the answers will be updated in real time.
For example during a conference the participants can vote and they can see the result of their vote on a big screen in real time.
We are going to use Express with Jade as templating language.
Our project structure will be very simple
Unlike WebSockets and other technologies, we are not going to install an NPM module to help us.
SSE is so simple that instead, we are going to create a middleware to handle our needs.
SSE middleware
This is all you need. On method to setup SSE and one more to send events, after you’ve called the previous method.
Your App
The entry point of your application is app.js
This is a standard Express application. It renders a voting page and a result page. It also provides a url to reiceive votes and a url to listen to a stream of events.
You can see that the simple SSE middleware is enough to create this advance real time app.
You only have to load it with app.use(sse)
or even directly with app.use(require('./sse'))
.
However, don’t forget to load it before you define the url which will use it.
Client Side Voting
Let’s see how the part where the users vote looks like
There is yes and no on the page. Cliking either of it send an AJAX request to your server with the chosen value.
As you saw in the server code above, it accumulates those responses and send them back to all connections.
Client Side Results
Next is where all the magic happen. The results of the voting are displayed with this.
This page is not only updating the number of votes, but it is also keeping up to date with the current connection state.
Let’s play
You built it. Let’s play and vote to see how it will work.
First, try to open several tabs. Two with results and two more for voting. It is even better if you open them in different windows and put them side by side.
Then vote and watch how the pages with the results update immediately.
Then kill your node server, but keep the results pages open and you will see the state chaning to Connecting, because the browser is try to restore the lost connection.
Run the server again and the state will automatically return to Connected, but the results will be nulified because we stored them in the memory.
Isn’t it fun? :-)
As you can see building real time apps with SSE is very easy.
It’s not all roses
Just like with WebSockets, it is not all roses for SSE. There are still clients which don’t support it.
SSE is also producing long open connections, which altough lightweight, might still saturate your server abilities to accept new connections.
Next
Real time is shiny but you better use it with care only when you need it. It is very easy to fall into a trap of always using the latest technology.
Everybody is talking about WebSockets, and use it without much thinking about it whenever they need real time communication. You should check very well wether you need duplex comunication like in WebSockets or SSE is all that you want.
Finally, the SSE middleware that you built above is very simple. Try to enhance it by using unique ids and custom events.
Other articles that you may like