在Node.js中使用服务工作者推送通知的入门方法

331 阅读5分钟

使用服务工作者在Node.js中推送通知的入门方法

推送通知是指当手机或Web应用在进行另一项活动时,屏幕上弹出的消息。在现代网络应用中,推送通知有着更广泛的地位。

简介

推送通知可以吸引用户,让他们注意到网络应用中发生的新活动,即使他们没有在使用该应用。

推送通知的好处包括。

  • 提高应用程序的参与度,因为用户即使不使用应用程序也会被吸引。
  • 通过向用户发送个性化的优惠和广告,提高用户的保留率。
  • 跟踪用户指标,以确定应用程序的成功水平。
  • 通过向用户方便地提供重要信息,增强用户体验。

目标

在这篇文章中,我们将逐步介绍在Node.js应用程序中使用服务工作者实现推送通知的情况。

前提条件

  • 你需要在你的电脑上安装Node.js。
  • 对Node.js有基本了解
  • 一个代码编辑器。我将使用Visual studio代码。

创建Node.js应用程序

启动应用程序

通过运行以下命令设置Node.js应用程序。

npm init -y

该命令将为我们的应用程序创建一个空的package.json 文件。package.json 将保存项目的元数据,包括依赖性、脚本和版本。

安装依赖项

接下来,我们将安装所需的依赖项。

我们将使用express 作为Node.js的后端框架,body-parser 来解析HTTP请求体,web-push 来发送应用程序后端触发的消息。

要安装这些依赖项,请在终端运行以下命令。

npm install –save express, body-parser, web-push

构建服务器端

导入依赖项

我们都准备好了。现在,让我们开始实施,创建我们应用程序的服务器端。我们将创建应用程序的入口点,这也将是我们的服务器。

在根目录下,我们将创建一个新的文件,并将其命名为index.js 。在这个文件中,我们将引入我们已安装的依赖项,如下所示。

//Express
const express = require('express');

//web-push
const webpush = require('web-push');

//body-parser
const bodyParser = require('body-parser');

//path
const path = require('path');

//using express 
const app = express();

//using bodyparser
app.use(bodyParser.json())

生成VAPID密钥

接下来,我们将为应用程序创建一组VAPID密钥。VAPID(Voluntary Application Server Identification)密钥将允许我们发送推送信息,而不需要建立一个信息服务。它们还能识别谁在发送推送通知。

Vapid密钥成对出现。一个私钥和另一个公钥。

要生成VAPID密钥。在终端运行下面的命令。

./node_modules/.bin/web-push generate-vapid-keys

该命令应该给出如下的密钥。

=======================================
Public Key:
BKd0FOnmkngVtRSf7N3ogMcnnDQGtu5PSMcbzmt_uvrcDTpL424TE6W92qpnMGZPeh1XqHi1rA_MT0iUL0gBXuY

Private Key:
GyXqHJJVtw7uXgCx9mXw9QK65SsCnALClWNHpPHy2pQ

=======================================

请注意,您的Vapid密钥将与我的不同。

通过网络推送设置VAPID密钥

为了设置VAPID密钥,我们首先将我们的密钥存储在变量中,然后调用web-push 模块的setVapiddetails 方法。在index.js 文件中,我们将添加以下代码块。

//storing the keys in variables
const publicVapidKey = 'Your public vapid key';
const privateVapidKey = 'Your private vapid key';

//setting vapid keys details
webpush.setVapidDetails('mailto:mercymeave@section.com', publicVapidKey,privateVapidKey);

创建订阅路由

我们将需要一个路由,客户端在那里发送帖子请求。我们将称这个路由为订阅路由。它将向服务工作者发送通知。下面的代码块指明了如何设置路由。

//subscribe route
app.post('/subscribe', (req, res)=>{
    //get push subscription object from the request
    const subscription = req.body;

    //send status 201 for the request
    res.status(201).json({})

    //create paylod: specified the detals of the push notification
    const payload = JSON.stringify({title: 'Section.io Push Notification' });

    //pass the object into sendNotification fucntion and catch any error
    webpush.sendNotification(subscription, payload).catch(err=> console.error(err));
})

对客户端进行编码

设置静态路径

现在我们已经设置了我们的服务器。下一步,是对客户端进行编码,从那里发送帖子请求。

首先,我们将在index.js 文件中设置我们的静态文件夹路径。在依赖项下,我们将包括下面这段代码,以指定我们的静态文件夹被称为client

//set the static path 
app.use(express.static(path.join(__dirname, "client")));

创建所需文件

接下来,在根文件夹中,按照上面的规定创建一个名为client 的文件夹。在客户端文件夹中,我们将创建三个文件。index.js 将有我们的前端代码,一个client.js 用于我们的客户端,一个service.js 用于我们的服务工作者。

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>Push Notification using Node</title>
</head>
<body>
    <h1>Section.io push Notification</h1>

    <script src="client.js"></script>
</body>
</html>

设置服务工作者

服务工作者是一个由浏览器在后台运行的脚本,它独立于网页,是浏览器和网络之间的桥梁。它通常拦截浏览器中的文档所发出的请求,并将请求重定向到缓存中,以允许离线访问。

为了设置我们的服务工作者,在client.js 文件中,我们将导入我们的公共vapid密钥。

const publicVapidKey = 'Your public key';

接下来,由于我们在网络应用中使用VAPID密钥,我们使用下面的函数将公钥转换为Uint8Array,以传递给订阅调用。

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;
}    

接下来,我们将检查服务工作者是否在当前浏览器中被启用,并触发发送方法。

//check if the serveice worker can work in the current browser
if('serviceWorker' in navigator){
    send().catch(err => console.error(err));
}

在发送方法中,我们将注册服务工作者,然后触发发送通知功能,如下所示。

//register the service worker, register our push api, send the notification
async function send(){
    //register service worker
    const register = await navigator.serviceWorker.register('/worker.js', {
        scope: '/'
    });

    //register push
    const subscription = await register.pushManager.subscribe({
        userVisibleOnly: true,

        //public vapid key
        applicationServerKey: urlBase64ToUint8Array(publicVapidKey)
    });
   
    //Send push notification
    await fetch("/subscribe", {
        method: "POST",
        body: JSON.stringify(subscription),
        headers: {
            "content-type": "application/json"
        }
    });
}

我们将在worker.js 文件中对下一步进行编码。我们将为推送添加一个事件监听器,并指定推送通知的选项,如标题、正文、图像和图标。我们将在worker.js 文件中添加下面的代码块。

self.addEventListener("push", e => {
    const data = e.data.json();
    self.registration.showNotification(
        data.title, // title of the notification
        {
            body: "Push notification from section.io", //the body of the push notification
            image: "https://pixabay.com/vectors/bell-notification-communication-1096280/",
            icon: "https://pixabay.com/vectors/bell-notification-communication-1096280/" // icon 
        }
    );
});

运行服务器

为了测试该应用程序,在index.js 文件中添加下面的代码块。然后在你的终端运行命令npm start

const port = 3000;
app.listen(port, ()=>{
    console.log(`server started on ${port}`)
});

现在,应用程序将在你每次刷新浏览器时发送推送通知,如下图所示。

The push notification of the application

结论和进一步阅读

在这篇文章中,我们学习了如何使用服务工作者来实现Web应用程序中的推送通知。