How to send notifications to the browser (wep push) using Node.js and Service Workers

in hive-133716 •  4 years ago 


Today I will teach you how to create web notifications from our Node - Express.js server to an HTML web application, the notifications will be created from the API provided by the browser, we will use a module called web push ( web-push ) that will help us create them, additionally we will use what is called Service workers ( processes that are kept running from the browser)

NODE.js

We will start by creating a folder on our desktop web-notification-app-node / and activating the console of our favorite code editor, and we will install the following dependencies:

   npm  init --yes
 
 
And
   npm  i express morgan dotenv web-push
 
 

We will create a file called .env where we will place our public and private keys provided by the web-push module

.env

  PUBLIC_KEY = tu_public_key_here
 PRIVATE_KEY = you_private_key_here
 
 


Once our environment variables file is created, we proceed to generate these keys, for this we will write the following in the console

  npx web-push generate-vapid-keys
 
 

This will return something like



Those keys are the ones that we will place in the .env file

We will create a file called webpush.js with the following configuration

src / webpush.js

  const webpush = require ('web-push')
 webpush.setVapidDetails (
     `mailto: $ {process.env.EMAIL}`,
     process.env.PUBLIC_KEY,
     process.env.PRIVATE_KEY
   );
 module.exports = webpush
 
 


src / index.js

  require ('dotenv'). config ()
 const express = require ('express')
 const morgan = require ('morgan')
 const path = require ('path')
 const app = express ()
 // MIDDLEWARES
 app.use (morgan ('dev'))
 app.use (express.urlencoded ({extended: false}))
 app.use (express.json ())
 // ROUTES
 app.use (require ('./ routes /'))
 // STATICS FILES
 app.use (express.static (path.join (__ dirname, 'public')))
 app.listen (process.env.PORT || 3000, () => console.log ('Server on port', process.env.PORT || 3000))
 
 


We create a folder routes/ and inside an index.js file with our 2 routes

routes / index.js

  const {Router} = require ('express')
 const router = Router ()
 const webpush = require ('../ webpush')
 let pushSubscripton;
 router.post ('/ subscribeUser', async (req, res) => {
     pushSubscripton = req.body;
     res.status (200) .json ();
 })
 router.post ('/ new-msg', async (req, res) => {
     const {title, message} = req.body;
     const payload = JSON.stringify ({
         title,
         message
       });
       res.status (200) .json ();
       try {
         await webpush.sendNotification (pushSubscripton, payload);
       } catch (error) {
         console.log (error);
       }
 })
 module.exports = router
 
 


We will create a public / folder and inside a file index.html, main.js and serviceWorker.js

public / index.html

  <! DOCTYPE html>
 <html lang = "en">
 <head>
     <meta charset = "UTF-8">
     <meta http-equiv = "X-UA-Compatible" content = "IE = edge">
     <meta name = "viewport" content = "width = device-width, initial-scale = 1.0">
     <title> How to send notifications to the browser (wep push) using Node.js and Service Workers </title>
     <link href = "https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel = "stylesheet"
         integrity = "sha384-BmbxuPwQa2lc / FVzBcNJ7UAyJxM6wuqIj61tLrc4wSX0szH / Ev + nYRRuWlolflfl" crossorigin = "anonymous">
 </head>
 <body>
     <div class = "container mt-5 mb-2">
         <h2> How to send notifications to the browser (wep push) using Node.js and Service Workers - <code> <a href="https://hive.blog/@jfdesousa7"> Jfdesousa7 </a> </code> </h2>
         <div class = "col-md-4 mt-5 mx-auto">
             <div class = "card">
                 <div class = "card-body">
                     <form id = "form">
                         <div class = "mb-4">
                             <input type = "text" id = "title" placeholder = "Enter the title of the message"
                                 class = "form-control" autofocus>
                         </div>
                         <div class = "mb-4">
                             <textarea class = "form-control" id = "message" rows = "2"
                                 placeholder = "Enter the message"> </textarea>
                         </div>
                         <div class = "mb-4>
                             <button type = "submit" class = "btn btn-primary"> Send notification </button>
                         </div>
                     </form>
                 </div>
             </div>
         </div>
     </div>
     <script src = "./ main.js"> </script>
 </body>
 </html>
 
 


public / main.js

  const PUBLIC_KEY = "BPU1qVu0bNbIFdC15E4EooVBhjuOV8w40rk5NO3xR-UtF_3I7l5h5EQxeT2yXvEBS4ArrUfE7-YfKEPoLAYVi9k";
 async function subscribeUser () {
   const register = await navigator.serviceWorker.register ("/ serviceWorker.js", {
     scope: "/",
   });
   const subscribe = await register.pushManager.subscribe ({
     userVisibleOnly: true,
     applicationServerKey: urlBase64ToUint8Array (PUBLIC_KEY),
   });
   await fetch ("/ subscribeUser", {
     method: "POST",
     body: JSON.stringify (subscribe),
     headers: {
       "Content-Type": "application / json",
     },
   });
   console.log ("Subscribed!");
 }
 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;
   };
   const form = document.querySelector ('# form')
   const title = document.querySelector ('# title')
   const message = document.querySelector ('# message')
   form.addEventListener ('submit', async (e) => {
       e.preventDefault ()
      await fetch ('/ new-msg', {
           method: "POST",
           body: JSON.stringify ({
               title: title.value,
               message: message.value
           }),
           headers: {
               "Content-Type": "application / json"
           }
       })
       form.reset ()
   })
   subscribeUser ();
 
 


public / serviceWorker.js

  self.addEventListener ("push", (e) => {
   const data = e.data.json ();
   self.registration.showNotification (data.title, {
     body: data.message,
     icon: "./images/jfdesousa7.png",
   });
 });
 
 


Once we run our example with node src / index.js we must allow the browser to send notifications





And with those friends we reached the end of the tutorial, I hope you enjoyed it and until next time!


Visit my official website for budges and much more

TupaginaOnline.net

Authors get paid when people like you upvote their post.
If you enjoyed what you read here, create your account today and start earning FREE STEEM!
Sort Order:  

Your post has been upvoted by Steem Sri Lanka Community Curation Trail.

Steem Sri Lanka Discord Channel

✵✵✵✵✵✵✵✵✵✵✵✵✵✵✵✵✵✵✵✵✵✵✵✵✵✵✵✵✵

Join With
steem-sri.lanka
Curation Trail For Better Curation Rewards