Building Real-time Apps with Websockets & Server-Sent Events

This article was peer reviewed by Craig Bilner and Dan Prince. Thanks to all of SitePoint’s peer reviewers for making SitePoint content the best it can be!

An important part of writing rich internet applications is reacting to data changes. Consider the following quote by Guillermo Rauch, taken from his 2014 BrazilJS talk, The 7 Principles of Rich Web Applications.

When data changes on the server, let the clients know without asking. This is a form of performance improvement that frees the user from manual refresh actions (F5, pull to refresh). New challenges: (re)connection management, state reconciliation.

In this article we’ll look at examples of how to use the raw WebSocket API as well as the lesser known EventSource for server-sent events (SSE) to build “real-time” UI’s that are self-updating. If you’re unsure what I mean by that, I recommend watching the video referenced above, or reading the corresponding blog post.

A Brief History

[author_more]

In the past we had to simulate server-push, the most notable method being long polling. This involved the client making a long request that would remain open until the server was ready to push a message. After receiving a message the request would be closed and a new request would be made. Other solutions involved <iframe> hacks and Flash. This was not ideal.

Then, in 2006, Opera introduced server-sent events (SSE) from the WHATWG Web Applications 1.0 specification. SSE allowed you to stream events continuously from your web server to the visitor’s browser. Other browsers followed suit and started implementing SSE in 2011 as part of the HTML5 spec.

Things continued to get interesting in 2011 when the WebSocket protocol was standardised. WebSockets allow you to open a two-way persistent connection between client and server, giving you the ability to push data back to the clients whenever data changes on the server without the client having to request it. This is hugely important for the responsiveness of an application with a lot of concurrent connections and quickly changing content—a multiplayer online game for example. However, it wasn’t until socket.io—the most prominent effort to bring WebSockets to the masses—was released in 2014 that we saw a lot more experimentation happening with real time communication.

Suffice to say, that today we have much simpler ways of achieving server-push without issuing new requests or relying on non-standard plugins. These technologies give you the ability to stream data back to the client the moment things happen on the server.

WebSockets

The easiest way to understand what a persistent connection allows you to do is to run a working demo, we’ll step through the code later but for now download the demo and have a play.

Demo

git clone https://github.com/sitepoint-editors/websocket-demo.git
cd websocket-demo
npm install
npm start

Open http://localhost:8080/ in multiple browser windows and observe the logs in both the browser and the server to see messages going back and forth. More importantly note the time it takes to receive a message on the server and for the rest of the connected clients to be made aware of the change.

The Client

The WebSocket constructor initiates a connection with the server over the ws or wss(Secure) protocols. It has a send method for pushing data to the server and you can provide an onmessage handler for receiving data from the server.

Here’s an annotated example showing all of the important events:

// Open a connection
var socket = new WebSocket('ws://localhost:8081/');

// When a connection is made
socket.onopen = function() {
  console.log('Opened connection 🎉');

  // send data to the server
  var json = JSON.stringify({ message: 'Hello 👋' });
  socket.send(json);
}

// When data is received
socket.onmessage = function(event) {
  console.log(event.data);
}

// A connection could not be made
socket.onerror = function(event) {
  console.log(event);
}

// A connection was closed
socket.onclose = function(code, reason) {
  console.log(code, reason);
}

// Close the connection when the window is closed
window.addEventListener('beforeunload', function() {
  socket.close();
});

The Server

By far, the most popular Node library for working with WebSockets on the server is ws, we’ll use that to simplify things as writing WebSocket servers is not a trivial task.

Continue reading %Building Real-time Apps with Websockets & Server-Sent Events%


Source: Sitepoint