Push notification has become an integral part of the web whether you are building a complex social media platform or you are building a simple blog, push notification just makes it easier to get messages across to users on the web easy.
We would be building a mini project to show how push notifications works on the server and client side
Content
- What are Push Notifications
- How It Works
- Prequisites
- Let's Begin
- Generating Vapid Keys
- Registering Push Notification
- Subscribing To Push Notification
- Sending Push Notification
- Recieving and Displaying Push Notification
- Conclusion
So...
What are Push Notifications
Push Notifications are messages sent to a users device whether or not they are currently interacting with your website or application.
How It Works
For push notification to work over the web we need something called Service Workers
Service Worker is a script that works on browser background without user interaction independently.If you need more info on that Click Here
Prequisites
Basic Knowledge of
Let's Begin
We would be starting on the server side
Create a folder for your project let's call our folder my-push-notifier
and
Open your terminal and navigate to the folder created then run these commands
npm init -y
npm install express web-push
Create an app.js
file
In the package.json
file generated add this to the script
object
"start": "node app.js",
Start your server with npm run start
or node app.js
your server should be running if everything was done correctly
Generating Vapid Keys
Vapid keys are needed before we can send push notifications. Why ?
Well two reasons
The first is to restrict the validity of a subscription to a specific application server (so, by using VAPID, only your server will be able to send notifications to a subscriber).
The second is to add more information to the push notification, so that the push service operator knows who is sending the notifications. If something is going wrong with your notifications, the operator knows who you are and can contact you. Moreover, they can offer you some kind of interface to monitor your push notifications.
Vapid keys can be generated online using
OR
In your terminal run this command to install web-push
npm install web-push
Then generate your keys with this command
./node_modules/.bin/web-push generate-vapid-keys
Copy the keys generated and save it somewhere.
In the app.js
file set up the webpush with your keys
Replace {YOUR_EMAIL}
with your any email you want to set up with
Registering Push Notification
In our app.js
file we would be creating an endpoint that allows users subscribe for push notification,
Create a subscribers.json
file, in file add an empty array []
, The endpoint gets the subscriber's detail from the request body and saves it to a file
app.post("/subscribe", async (req, res) => {
try {
// Subscription Details From the client side , We would get back to this
const subscription = req.body;
subscribers.push(subscription);
// Save the new subscrber to the subscribers file
fs.writeFileSync("./subscribers.json", JSON.stringify(subscribers));
res.status(201).send("Subscription Saved");
} catch (error) {
console.error(error);
}
});
Subscribing To Push Notification
Now on the client side, create a client
folder in our project folder and create the following files in the client
folder
index.html
with the following code
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Push Notifications Using Node</title>
</head>
<body>
<h1>Push Notifications Using Node</h1>
</body>
<script src="client.js"></script>
</html>
client.js
worker.js
Before we move forward add the following code to your app.js
on the server side so html is rendered from the server
const path = require("path")
app.use(express.static(path.join(__dirname, 'client')))
Fist we would be creating a function in client.js
that subscribes for push notification on our server for we would be using the browser window navigator
const publicVapidKey = "{VAPID_PUBLIC_KEY}";
async function subscribeToPush() {
console.log("Registering service worker...");
const register = await navigator.serviceWorker.register("/worker.js", {
scope: "/"
});
console.log("Service Worker Registered...");
console.log("Registering Push...");
const subscription = await register.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlBase64ToUint8Array(publicVapidKey)
});
console.log("Push Registered...");
console.log("Subscribing for Push ...");
await fetch("http://localhost:1999/subscribe", {
method: "POST",
body: JSON.stringify(subscription),
headers: {
"Content-Type":"application/json"
}
});
}
function urlBase64ToUint8Array(base64String) {
const padding = "=".repeat((4 - base64String.length % 4) % 4);
const base64 = (base64String + padding)
.replace(/\-/g, "+")
.replace(/_/g, "/");
const rawData = window.atob(base64);
const outputArray = new Uint8Array(rawData.length);
for (let i = 0; i < rawData.length; ++i) {
outputArray[i] = rawData.charCodeAt(i);
}
return outputArray;
}
Sending Push Notification
For the tutorial we would be sending notifications every minutes to our subscribers to do that we would create a function in our app.js
on the server side
// Sending push notification to subscribers
const subscribers = require("./subscribers.json")
const fs = require("fs")
async function sendPushNotificaiton() {
for (let i = 0; i < subscribers.length; i++) {
const subscription = subscribers[i];
//Notification Payload, this could contain more information about the notification
const payload = {
title: "Push Test",
body: " Push Notification Message",
icon: "https://blog.mensaiah.com/assets/round_logo.png",
};
//Pass object into sendNotification
await webpush.sendNotification(subscription, JSON.stringify(payload));
}
}
//Send Notification Every Minute
const durationInMillisecond = 60 * 1000
setInterval(sendPushNotificaiton,durationInMillisecond);
Recieving and Displaying Push Notification
Remember our worker.js
file created on the client side. We would be listen for a push notification so it can be displayed
self.addEventListener("push", e => {
// Data from service
const data = e.data.json();
console.log("Push Recieved...");
self.registration.showNotification(data.title, {
body: data.body,
icon: data.icon,
});
});
You can find more information on displaying push notification here;
Run Application
In our client.js
call the subscribeToPush
function we created above, NB: Not all browsers support service workers so we would be doing this
// Only subscribe to push notification when browser supports service worker
if ('serviceWorker' in navigator) {
subscribeToPush().catch(console.log);
}
On your browser (I recommend using chrome), visit http://localhost:1999/
to start recieving notification form the server.
Click on allow when a prompt ask if you want to show notifications
Conclusion
This tutorial does not exhaust all possibilities of service workers, so I suggest reading and trying out more on the topic. Below are articles I recommend