Web Push Notifications with Service Workers
We are as web developers, on the golden age of our history. Web technologies are evolving very fast and browsers release a new feature every single day..
Web Push is not a new feature and there are already so many API’s such as Firebase. However I see most of the developers still having problems with implementing push notifications with service workers.
What is a Service Worker ?
It is HTML5 spec which enables browsers to run different javascript files in different threads, which continues running even if the tab or window is closed. Service Worker file runs, in a different thread and has its own scope which means that you have no access to window
or document
Object for instance. Let ‘s see an example of service worker file and try to understand what’s going on there.
Now you can see that, the service worker is only basic event listener. All you have to do is, adding some event listeners, and your service worker file will call them when the event occurs. The thing is, these events are not connected to browser window. So you don’t have to open window to listen the file.
This basic script listens for push
events and displays them when the push comes. One of the use case of service workers’ is push notification yes, but not only. There are so many things you can do with service workers, like caching files, mocking data etc. See the Google Reference for service worker lifecycle.
Things you should be careful about service workers:
- You don’t have access to window objects.
- Service worker file run only over HTTPS server or your localhost
- Service worker file must registered at the root directory of your website. If you don’t want to register it on your root, see the next bullet.
For example:
Correct: https://example.com/service-worker.js
Wrong: https://example.com/path-name/service-worker.js
I’ve spend 15 hours to learn that fact. You guys are lucky !
- Service Worker’s scope is important fact that you have to consider. Service worker file can be run only the child paths of itself.
For Example if your service worker script is at /assets/service-worker.js location, than you can only use that script at https://www.example.com/assets/ location and its children such as https://www.example.com/assets/page.html, https://www.example.com/assets/dir/other-page.html.
To prevent this situation, you must give a scope config when registering the service worker. See the example below:
Wait ! It’s not over yet !
Once you register the service worker with a scope which is parent of the service worker file’s path, You must add a Service-Worker-Allowed header to your server which serves the service worker file. Otherwise, the browser will block your registration for security reasons.
Service-Worker-Allowed: ‘/’
Note that the header’s value is same as the scope’s value.
Communication Between Client and Service Worker
Suppose you want to get a data from your push notification, and show it on your web application. It is as easy as it sounds. Let’s have a look.
First, give a look at the service-worker.js file. Here is the explanation of the code:
- When the push notification arrives, if data exists in the push, start (17–19).
- If push data is valid json, wait until the show notification with the data ( 20 — 21).
- After push notification has been shown, find all clients (24 — 25).
clients.matchAll is important here, that methods searches for all of the clients asynchronously and return list of clients (Array).
Note that, when the notification showed, If no client exists ( which means your web application is not open on any tab of the browser) rest of the code will not run. Communication is not possible if no client exists obviously.
- If any client exists, send message to the first client. (26–29)
Why first ? Well, it is my choice. You can choose to send to every client, or whichever you want to.
Let’s see how we communicate now. Explanation of the messageToClient function: - Create a message channel object. (3)
See the API Reference for message channel object: https://developer.mozilla.org/en-US/docs/Web/API/MessageChannel - Create an onmessage into port1.
Why port1 ? No answer. There are two ports, and you can choose one. - If data has no error, post it to the client, via port2.
Why port2 ? Because, we’ve chosen the port1 for the service worker. So, client will listen the port2.
Now let’s see the index.html . We only added an event listener and now we’re able to get the data from push notification !
More:
https://developer.mozilla.org/en-US/docs/Web/API/MessageChannel/port1
http://craig-russell.co.uk/2016/01/29/service-worker-messaging.html
https://dbwriteups.wordpress.com/2015/11/16/service-workers-part-3-communication-between-sw-and-pages/