Notifications, Server Side Events, Web Sockets (SocketIO), and Push API

A comparison and tutorial of server to client communication.


Introduction

The Notifications API allows you to use your client's built in notifications so they don't have to be viewing your web page to get a notification. It is purely a UI feature.

Server Side Events, Web Sockets, and the Push API, all allow the server to send data to the client (without the client having to initiate a request).

This quick tutorial will show the basic set up and use of these 4 technologies.

Fully functioning examples can be found at: https://github.com/efossas/WebServerAlerts-POC. It's a proof of concept project for exploring the pros and cons of each technology. In this tutorial, I'll be using modified versions of that code for teaching. They don't all work if you just copy and paste.

Also, all of my examples will use NodeJS on the server side.

What This Tutorial Covers

What This Tutorial Covers
  1. Notification API
  2. Server Side Events
  3. Web Sockets with SocketIO
  4. Push API

What You Need For This Tutorial

What You Need For This Tutorial

Nothing. A browser I suppose and Docker if you want to spin up the POC in the repo mentioned above.


Notification API

The Notification API allows you to use your client's native notifications. This means that even if they're not looking at your web page, or even a browser for that matter, they'll still get a little notification message from you.

IE, Mobile Safari, & Android do not support it.

On a Mac, notifications show up in the upper right hand corner. They can contain a small image and some text. The notification in the POC looks like this:

Before you can use the Notification API, you must ask the user for permission, which will give them a prompt that looks like this:

The javascript to create notifications and request access looks like this:

Server Side Events (SSE)

Server Side Events are for one way communication from a server to a client. They are the easiest to set up without a library. However, since Web Sockets are the only cross-browser compatible server to client technology, SSE isn't used all that often.

IE & Edge do not support it.

Setting up SSE on the client is dead simple. You just make a request to a server path that will start SSE and start listening for messages from the server.

The server has to do a few things for SSE. Most importantly, it must not close the connection. You need some way of keeping it alive. You'll also want to store the response object in a way where other parts of your code can find connected clients and send events to them.

What the actual event looks like is pretty simple (it's similar to HTTP protocol). Each line starts with either id (just an identifier of the event), data (data you want to send), or retry (if the connection to the server is broken, number of milliseconds until the client tries to reconnect) along with some data. An empty new line indicates the end of the event.


id: 12345
retry: 3000
data: put some data here
data: and some more data here
        
      

Below is an example of what an ExpressJS route function might look like for start SSE:

Web Sockets with SocketIO

Web Sockets are for two way communication between servers and clients. Although they're not easy to setup without a library, there are libraries that make it incredibly simple to setup. Plus, most of these libraries have fall backs to AJAX polling, when Web Sockets aren't available. Therefore, we'll be using SocketIO to set up Web Sockets.

Web Sockets are compatible with all modern browsers.

Setting up Web Sockets on the client is just as simple as SSE. If using defaults, it's even simpler. In addition to connecting and listening for events, sockets can also emit events to the server with the emit() function.

SSE was so simple, that we wrote the actual string bytes to the response stream. WS is a little more involved. In fact, it even uses its own protocol prefix, ws:// (unencrypted) & wss:// (encrypted ssl). However, SocketIO abstracts all of that away from us and even handles our connections' lives so we don't have to. Thus, it's pretty simple to set up on the server. Here's an example:

Push API

The Push API allows servers to send data to clients even when the client doesn't have your web page or even their browser open. Therefore, it must be used with Service Workers (these are scripts that are always running for your web page even when it's closed) and the Notification API. It also only works over HTTPS and requires the use of VAPID keys for security. That being said, it's definitely not simple to get it working, but here we go...

IE, Safari, & Mobile Safari do not support it.

These are what the steps for setting up Push notifications should look like on the client side:

  1. Register a service worker (which listens for push notifications).
  2. Once the service worker is registered, check to see if a subscription already exists
  3. If it doesn't, retrieve the server's VAPID public key.
  4. Once you have the VAPID public key, use it to create a subscription with the pushManager.
  5. Now send the subscription info to the server so that it can use it to send push notifications.

By the way, the VAPID public key is used to verify that it is receiving pushes it has subscribed to (or in other words, the push can come from any server that has the private VAPID key).

Here is some example client side code:

And here is what the service worker should look like:

These are what the steps for setting up Push notifications should look like on the server side:

  1. Create public and private VAPID keys.
  2. Create an http route where clients can get the VAPID public key.
  3. Create an http route where clients can send their subscription info.
  4. Create an http route where clients can request to delete their subscription info.
  5. Whenever you want, use subscription info to send push notifications to subscribers.

Here is some example server side code:

Done!

So there's a quick summation of web technology that allows for server to client communication. Unless you have a very specific use case, it's generally best to use Web Sockets over Server Side Events or the Push API.