MENU
Service Worker- Notification
A Service Worker is great for providing notifications too.

RESETRUNFULL
<!DOCTYPE html><html><body><script>
navigator.serviceWorker.register('service-worker.js');
async function showNotification() {
var result = await Notification.requestPermission();
if (result === 'granted') {
var registration = await navigator.serviceWorker.ready;
await registration.showNotification('Title', {
icon: '/shared/doraemon.jpg',
body: 'This is a simple local notification.',
vibrate: [200, 100, 200, 100, 200, 100, 200],
tag: 'vibration-sample'
});
var notifications = await registration.getNotifications({tag:'vibration-sample'});
console.log(notifications);
}
}
showNotification();
</script></body></html>
The above only works if the service worker has not been registered before, ie. when the webpage is being loaded the first time. You can manually unregister a service worker by pressing F12 on a browser and navigating to Application:

Able to work even after the browser has been closed, the Web Push API relies on a service worker to catch notifications pushed from the server.

RESETRUNFULL
// server.js
var express = require('express');
var app = express();
var bodyParser = require('body-parser');
var fs = require('fs');
var http = require('http');
var https = require('https');
const webPush = require('web-push');
app.use(bodyParser.urlencoded({ extended: false }));
app.use(bodyParser.json());
// VAPID keys should only be generated only once.
// const vapidKeys = webPush.generateVAPIDKeys();
var vapidPublic = 'BP_6miS1aKl……B04xr8';
var vapidPrivate = 'ZPMo7IB3……FE1o';
webPush.setVapidDetails(
'https://my-site.com/',
vapidPublic, // process.env.VAPID_PUBLIC_KEY,
vapidPrivate //process.env.VAPID_PRIVATE_KEY
);
var subscriptions = {};
var pushInterval = 10; // 10s
function sendNotification(subscription) {
webPush.sendNotification(subscription)
.then(function() {
console.log('Push Application Server - Notification sent to ' + subscription.endpoint);
}).catch(function() {
console.log('ERROR in sending Notification, endpoint removed ' + subscription.endpoint);
delete subscriptions[subscription.endpoint];
});
}
app.get('/vapidPublicKey', function(req, res) {
res.send(vapidPublic);
});
app.post('/register', function(req, res) {
var subscription = req.body.subscription;
if (!subscriptions[subscription.endpoint]) {
console.log('Subscription registered ' + subscription.endpoint);
subscriptions[subscription.endpoint] = subscription;
}
res.sendStatus(201);
});
app.post( '/unregister', function(req, res) {
var subscription = req.body.subscription;
if (subscriptions[subscription.endpoint]) {
console.log('Subscription unregistered ' + subscription.endpoint);
delete subscriptions[subscription.endpoint];
}
res.sendStatus(201);
});
app.get('/:file', async function(req,res,next){
res.sendFile(__dirname+'\\'+req.params.file);
});
var ssl_options = {
ca: [fs.readFileSync('../ssl/cert1.crt','utf-8'),
fs.readFileSync('../ssl/cert2.crt','utf-8'),
fs.readFileSync('../ssl/cert3.crt','utf-8')],
key: fs.readFileSync('../ssl/mykey.key','utf-8'),
cert: fs.readFileSync('../ssl/mycert.crt','utf-8')
};
var server = https.createServer(ssl_options,app);
server.listen(443,"0.0.0.0");
setInterval(function() {
Object.values(subscriptions).forEach(sendNotification);
}, pushInterval * 1000);
// service-worker.js
self.addEventListener('push', function(event) {
event.waitUntil(
self.registration
.showNotification('ServiceWorker Cookbook', {
lang: 'en',
body: 'Please be notified that you have been notified.',
icon: 'doraemon.jpg',
vibrate: [500, 100, 500],
})
);
});
self.addEventListener('notificationclick', function(event) {
event.waitUntil(
clients.matchAll().then(function(clis) {
var client = clis.find(c=>(c.visibilityState === 'visible')); // tab is active
// console.log(client,clis);
if (!client) {
client.navigate('push.html');
client.focus();
} else { // browser/tab not open
clients.openWindow('push.html');
event.notification.close();
}
})
);
});
<!DOCTYPE html><html lang="en">
<body>
<button id='subscribe' onclick="register()">Subscribe</button>
<button id='unsubscribe' onclick="unregister()">UnSubscribe</button>
<script>
var subscription=null;
function urlBase64ToUint8Array(base64String) {
var padding = '='.repeat((4 - base64String.length % 4) % 4);
var base64 = (base64String + padding).replace(/\-/g, '+').replace(/_/g, '/');
var rawData = window.atob(base64);
var outputArray = new Uint8Array(rawData.length);
for (var i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}
function register(){
fetch('./register', {
method: 'post',
headers: {'Content-type': 'application/json'},
body: JSON.stringify({subscription: subscription}),
});
}
function unregister(){
fetch('./unregister', {
method: 'post',
headers: {'Content-type': 'application/json'},
body: JSON.stringify({subscription: subscription}),
});
}
navigator.serviceWorker.register('./service-worker.js');
navigator.serviceWorker.ready.then(async function(registration) {
subscription = await registration.pushManager.getSubscription();
if (!subscription){
const response = await fetch('vapidPublicKey');
const vapidPublicKey = await response.text();
const convertedVapidKey = urlBase64ToUint8Array(vapidPublicKey);
subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: convertedVapidKey
});
}
});
</script>
</body></html>
To run the Node.js application:
npm init -y
npm install express web-push body-parser
node server.js
Then launch the site on a browser by entering into the address box:
https://mysite.com/push.html
To receive the notifications, make sure you have enabled the option to receive them on your browser. This can be done, for instance, by long-pressing the browser icon on your Android device and switching the Notifications setting. On Windows PC, you will need to go the Notifications settings:

You will also need to make sure you have allowed notifications to be sent from the URL on the browser settings.