What Is The Web Push In JavaScript And How To Use It?
Web-Push + Service Workers (SW). We will open the veil to you and tell you how to succeed in Internet services.
In this article, we will talk about the basic application of SW. From the feedback and questions, we realized that people are interested in directing SW + Web Push. Let’s figure out what it is together, and how to use this magic couple in practice.
What is Push Notification?
When you receive notifications on your e-mail: and you go to the mail client and look at incoming mail. In this case, it’s pulling technology, that is, you go to the site and “pull” data from it when you need it.
In the case of push notifications, the resource pushes new data to you. At the same time, you immediately receive the latest data, because in this technology there is no certain period of data verification, they come online. Use of pushes is not limited to receiving notifications. So, through the push technology, you can synchronize the data during the upgrade.
Push notifications are small pop-ups. They can appear on the screen, where there is an area of alerts or there is the possibility of displaying the received data. Push notifications work even when the user has left the site. This means that you can deliver messages about new materials and new events to attract the user’s attention to your application.
Blanks for the bundling SW and Web-push
To write your own SW to work with Web-push, we will as always need:
All you need to do is add index.js in index.html, which will register the file sw.js.
In the server.js file, we will only specify the endpoint (the entry point in the server application API) for registering push notifications.
The sample of code for server.js
// We use the web-push library to hide the details of the communication implementation // between the application server and the push service. // For more information // see https://tools.ietf.org/html/draft-ietf-webpush-protocol // and https://tools.ietf.org/html/draft-ietf-webpush-encryption. var webPush = require ('web-push'); // About GCM_API_KEY you can learn more from // https://developers.google.com/cloud-messaging/ webPush.setGCMAPIKey (process.env.GCM_API_KEY || null); // In this example, we will only consider routes in express.js module.exports = function (app, route) { app.post (route + 'register', function (req, res) { res.sendStatus (201); }); app.post (route + 'sendNotification', function (req, res) { setTimeout (function () { // To send a message with payload, the subscription must have the keys 'auth' and 'p256dh'. webPush.sendNotification ({ endpoint: req.body.endpoint, TTL: req.body.ttl, keys: { p256dh: req.body.key, auth: req.body.authSecret } }, req.body.payload) .then (function () { res.sendStatus (201); }) .catch (function (error) { res.sendStatus (500); console.log (error); }); }, req.query.delay * 1000); }); };};
In the article, we will consider the options for sending push notifications and how to apply them. Let’s get acquainted with the magic outside Hogwarts together.
Push Payload
This simple magic spell shows how to send and receive strings, but the data can be extracted from a push message in various formats: strings, the ArrayBuffer buffer, the BLOB object in JSON.
Mode of application
If you just need push notifications – this is the example for you. The message can deliver not only text but also payload – enriched data for the application. The code below shows how you can deliver payload for your application.
- For demonstration, we use data from the text field to be sent to the server and then displayed as a push notification via SW.
index.js
var endpoint; var key; var authSecret; navigator.serviceWorker.register ('service-worker.js') .then (function (registration) { // Use PushManager to get a user subscription from the push service. return registration.pushManager.getSubscription () .then (function (subscription) { // If the subscription already exists, return it. if (subscription) { return subscription; } // Otherwise, sign the user. // userVisibleOnly is the flag indicating that the returned push subscription // will be used only for messages, // the effect of which will be visible to the user. return registration.pushManager.subscribe ({userVisibleOnly: true}); }); } then. (function (subscription) { // Get the public key for the user. var rawKey = subscription.getKey? subscription.getKey ('p256dh'): ''; key = rawKey ? btoa (String.fromCharCode.apply (null, new Uint8Array (rawKey))) : ''; var rawAuthSecret = subscription.getKey? subscription.getKey ('auth'): ''; authSecret = rawAuthSecret ? btoa (String.fromCharCode.apply (null, new Uint8Array (rawAuthSecret))) : ''; endpoint = subscription.endpoint; // Send details about subscribing to the server using the Fetch API fetch ('./ register', { method: 'post', headers: { 'Content-type': 'application / json' }, body: JSON.stringify ({ endpoint: subscription.endpoint, key, authSecret, }), }); }); // To demonstrate the functionality. // This code is not needed on "Battle" applications, because the generation of notifications always takes place on the server. document.getElementById ('doIt'). onclick = function () { var payload = document.getElementById ('notification-payload'). value; var delay = document.getElementById ('notification-delay'). value; var ttl = document.getElementById ('notification-ttl'). value; fetch ('./ sendNotification', { method: 'post', headers: { 'Content-type': 'application / json' }, body: JSON.stringify ({ endpoint: endpoint, payload: payload, delay: delay, ttl: ttl, key: key, authSecret: authSecret }), }); };};
service-worker.js
// Register the function to the 'push' event self.addEventListener ('push', function (event) { var payload = event.data? event.data.text (): 'Alohomora'; event.waitUntil ( // Show the notification with the header and body of the message. self.registration.showNotification ('My first spell', { body: payload, }) ); });
Rich notifications
We will complicate the previous version and add special effects, everything depends on your desires and fantasies. We help the complete notification API. The API provides an interface for using “live” push-Referrals to the user with the locale, vibration pattern, image.
Mode of application
The example is similar to the one described above but can use the more advanced notification API to select an image, set the locale and the notification template – that is, make the notification unique.
service-worker.js
// The key difference compared to Push Payload is in use // Notitfication API in SW self.addEventListener ('push', function (event) { var payload = event.data // At us all the same the magic world with fantastic creatures, therefore // try .. catch we do not put ¯ \ _ (ツ) _ / ¯ ? JSON.parse (event.data) : { name: 'Expecto patronum!', icon: 'buck.jpg', locale: 'en' };}; event.waitUntil ( // Show the notification with the header and body of the message. // Set other parameters: // * language // * vibration pattern // * image // there are a lot of parameters about which you can learn here // https://notifications.spec.whatwg.org/ self.registration.showNotification ('Summoning spell', { lang: payload.locale, body: payload.name, icon: payload.icon, vibrate: [500, 100, 500], }) ); });
Push Tag
The next spell will demonstrate the accumulation and replacement of the previous spell more powerful. Use the tag for notification to replace old notifications with new ones. Allows to show the muggle only the current information or minimize several notifications into one.
Mode of application
The option is suitable for those applications where there are chats or notifications about new content (examples: Tproger and Tinder). The code below demonstrates how to manage the notification queue so that previous notifications can be discarded or merged into a single notification. It’s useful to have a fallback in case we wrote a chat where you can edit the messages. The client will see not a ton of notifications with corrections, but only one.
service-worker.js
var num = 1; self.addEventListener ('push', function (event) { event.waitUntil ( // Show the notification with the header and body of the message. // The number that is incremented for each notification received. // The tag field allows you to replace the old notification with a new one // (a notification with the same tag of another will replace it) self.registration.showNotification ('Attacking Spell', { body: ++ num> 1? 'Bombarda Maxima': 'Bombarda', tag: 'spell', }) ); });
Push Clients
When the muggle clicks on the notification generated from the push event, it will focus it on the application tab or even reopen it if it was closed.
Mode of application
Below is the code for three cases of using notification delivery, depending on the status of the application.
- It can recognize when you are on a page or need to switch to an open tab or reopen a tab.
The method will help you increase the conversion of the application if you want to return the mage. Just do not bend the stick, the muggle may not like the excessive attention of the application.
The most classic examples of use:
- there was a message in the chat (Tinder),
- Interesting news (Tproger),
- the task in the bug-tracker was refreshed,
- successfully/failed CI before the release,
- the customer paid the order / made a deal (whether an online store or CRM).
In all these cases, clicking the push client opens our application or it will be focused already on the open tab.
service-worker.js
self.addEventListener ('install', function (event) { event.waitUntil (self.skipWaiting ()); }); self.addEventListener ('activate', function (event) { event.waitUntil (self.clients.claim ()); }); self.addEventListener ('push', function (event) { event.waitUntil ( // Get a list of clients for SW self.clients.matchAll (). then (function (clientList) { // Check if there is at least one focused client. var focused = clientList.some (function (client) { return client.focused; }); var notificationMessage; if (focused) { notificationMessage = 'Imperio! You \ 're still here, thanks!'; } else if (clientList.length> 0) { notificationMessage = 'Imperio! You haven \ 't closed the page,' + 'click here to focus it!'; } else { notificationMessage = 'Imperio! You have closed the page, '+ 'click here to re-open it!'; } // Display a notification with the title "Unforgiveable Curses" // and the body, depending on the state of SW clients // (three different bodies: // * 1, the page is focused; // * 2, the page is still open, but not focused; // * 3, the page is closed). return self.registration.showNotification ('Unforgiveable Curses', { body: notificationMessage, }); }) ); }); // Register the 'notificationclick' event handler. self.addEventListener ('notificationclick', function (event) { event.waitUntil ( // Get the list of SW clients. self.clients.matchAll (). then (function (clientList) { // If there is at least one client, focus it. if (clientList.length> 0) { return clientList [0] .focus (); } // Otherwise, open a new page. return self.clients.openWindow ('our / url / page'); }) ); });
Push Subscription
It’s time to get hold of the minds of our Muggles. Magicians call this “telepathy” or reading thoughts, but we will do otherwise. Let’s learn how to put our information and make it attach to our application. This example shows how to use push notifications with subscription management, allowing users to subscribe to an application and keep in touch with it. We try to remember about Azkaban!
Mode of application
- After the SW is registered, the client checks whether it is signed by the notification service. Depending on this, the text of the button is set.
- After a successful subscription (index.js:: push manager.subscribe), the client sends a post-request to the application server to register the subscription.
- The server periodically sends a notification using the web-push library to all registered endpoints. If the endpoint is no longer registered (the subscription has expired or is canceled), the current subscription is removed from the list of subscriptions.
- After a successful unsubscription (index.js:: pushSubscription.unsubscribe), the client sends a post-request to the application server to cancel the subscription registration. The server no longer sends a notification. SW also monitors the events of push subscription change and resubscribes.
Subscription can be canceled by the user outside the page in the browser settings or UI-notifications. In this case, the backend will stop sending notifications, but the frontend does not know about it. In order for magic to work, it is important to periodically check whether registration in the notification service is active.
index.js
// For simplicity, we'll use the button. // It's better to use events on the combat version. var subscriptionButton = document.getElementById ('subscriptionButton'); // Since the subscription object is required in several places, let's create a method, // which returns Promise. function getSubscription () { return navigator.serviceWorker.ready .then (function (registration) { return registration.pushManager.getSubscription (); }); } if ('serviceWorker' in navigator) { navigator.serviceWorker.register ('service-worker.js') .then (function () { console.log ('SW registered'); subscriptionButton.removeAttribute ('disabled'); }); getSubscription () .then (function (subscription) { if (subscription) { console.log ('Already invaded', subscription.endpoint); setUnsubscribeButton (); } else { setSubscribeButton (); } }); } // Get "registration" from SW and create a new one // subscribe using `registration.pushManager.subscribe`. // Then register a new subscription by sending a POST request. function subscribe () { navigator.serviceWorker.ready.then (function (registration) { return registration.pushManager.subscribe ({userVisibleOnly: true}); } then. (function (subscription) { console.log ('Legilimens!', subscription.endpoint); return fetch ('register', { method: 'post', headers: { 'Content-type': 'application / json' }, body: JSON.stringify ({ endpoint: subscription.endpoint }) }); then) (setUnsubscribeButton); } // Get an existing subscription from SW, // unsubscribe (`subscription.unsubscribe ()`) and // unregister the server with a POST request // to stop sending push messages. function unsubscribe () { getSubscription (). then (function (subscription) { return subscription.unsubscribe () .then (function () { console.log ('Unsubscribed', subscription.endpoint); return fetch ('unregister', { method: 'post', headers: { 'Content-type': 'application / json' }, body: JSON.stringify ({ endpoint: subscription.endpoint }) }); }); then) (setSubscribeButton); } // For demonstration (or training). Change the text of the button. function setSubscribeButton () { subscriptionButton.onclick = subscribe; subscriptionButton.textContent = 'Open mind!'; } function setUnsubscribeButton () { subscriptionButton.onclick = unsubscribe; subscriptionButton.textContent = 'Protego!'; }
service-worker.js
// Listen to the 'push' event. self.addEventListener ('push', function (event) { event.waitUntil (self.registration.showNotification ('Your mind', { body: 'Wizard invaded to your mind!' })); }); // Listen to the 'pushsubscriptionchange' event, which is started, // when the subscription expires. // Subscribe again and register a new subscription on the server, // Send a POST request. // The ID or token will most likely be used on the combat application // to identify the user. self.addEventListener ('pushsubscriptionchange', function (event) { console.log ('Spell expired'); event.waitUntil ( self.registration.pushManager.subscribe ({userVisibleOnly: true}) .then (function (subscription) { console.log ('Another invade! Legilimens!', subscription.endpoint); return fetch ('register', { method: 'post', headers: { 'Content-type': 'application / json' }, body: JSON.stringify ({ endpoint: subscription.endpoint }) }); }) ); });
server.js
var webPush = require ('web-push'); var subscriptions = []; var pushInterval = 10; webPush.setGCMAPIKey (process.env.GCM_API_KEY || null); // Send notification to push-service. // Delete the subscription from the common `subscriptions` array, // if the push service responds to the error, or the subscription is canceled or expired. function sendNotification (endpoint) { webPush.sendNotification ({ endpoint: endpoint }). then (function () { }). catch (function () { subscriptions.splice (subscriptions.indexOf (endpoint), 1); }); } // Actually, the application sends a notification only in case // the occurrence of the event. // To simulate it, the server sends a notification every `pushInterval` seconds // each subscriber setInterval (function () { subscriptions.forEach (sendNotification); }, pushInterval * 1000); function isSubscribed (endpoint) { return (subscriptions.indexOf (endpoint)> = 0); } module.exports = function (app, route) { app.post (route + 'register', function (req, res) { var endpoint = req.body.endpoint; if (! isSubscribed (endpoint)) { console.log ('We invaded into mind' + endpoint); subscriptions.push (endpoint); } res.type ('js'). send ('{"success": true}'); }); // Unregister a subscription by removing it from the `subscriptions` array app.post (route + 'unregister', function (req, res) { var endpoint = req.body.endpoint; if (isSubscribed (endpoint)) { console.log ('It was counterspell from' + endpoint); subscriptions.splice (subscriptions.indexOf (endpoint), 1); } res.type ('js'). send ('{"success": true}'); }); };};
Conclusion
Above we considered the magical ways to use SW and Web Push for applications.
This tandem contains many interesting applications.
If you only need to sometimes call the muggle to your application or tell him about corrections or changing the status of his order, then use Push Payload. You can add a little imagination and use the Notification API – then the colors and the icon of your application will be visible to the user in Rich Push.
If you want to get hold of all the attention of the muggle and establish contact with him – examples of Push Client and Push Subscription for you. The main thing – remember about Azkaban, otherwise, you will start losing your audience.