Web 推送通知入门
我听说过 Web 推送通知和 Service Worker 很多次,但一直没能真正实现它们,直到上周为了Just Comments做了一些小改动。所以,我决定分享一下我对这项技术的一点心得。
首先,关于 Web 推送通知的文章和实用文档已经很多了,所以我就不多说了。我会尽量总结一下我认为需要理解和掌握的知识,以便快速上手并实现一个基础版本的 Web 推送通知。
让我们从一些关键事实开始:
#1 推送通知依赖于多个独立的浏览器 API
推送通知的整个功能涉及推送 API 和通知 API,它们可以单独使用。此外,它依赖于 Service Worker,因为只有 Service Worker 才能在后台运行,即使用户关闭了发送通知的网站,也能接收推送通知。
#2 并非所有浏览器都支持推送通知
目前,IE 和 Opera Mini不支持 Service Workers和Push API,此外,iOS Safari、Android 版 Chrome、三星浏览器和 Android 版 UC 浏览器不支持Web Notifications API。
这意味着您在实现推送通知时需要检测浏览器是否支持所需的 API。
工作原理大图
我创建了一个简单的图表来理解不同的 API 和概念。它通过一系列操作/关系将各个部分连接起来。
一切始于网页上的一段 JavaScript 代码,该代码注册 (1) 一个 Service Worker。Service Worker 提供 (2) 一个 Service Worker 注册对象,该对象反过来又提供 (3) 对 Push Manager 实例的访问权限。如果用户允许,推送管理器可以提供 (4) 一个 Push Subscription。此订阅对象可以发送到您的后端 (5)。在服务器上,您可以使用该订阅向用户浏览器发送一条消息 (6)。Service Worker 接收 (7) 该消息,但不会自动显示给用户。Service Worker 会解析该消息并决定如何处理。通常,Service Worker 会使用 Notification API 显示一条 Notification (8)。
编码部分
正如我在关键事实中提到的,并非所有浏览器都支持 API,因此我们需要检查用户的浏览器是否支持服务工作者:
function supportsPushNotifications() {
return 'serviceWorker' in navigator && 'PushManager' in window;
}
supportsPushNotifications() === true // if the browser supports needed APIs
在我们检查可以使用 Service Worker 之后,我们可以从第一步开始并注册一个 Service Worker:
navigator
.serviceWorker
.register('/sw.js')
.then(swRegistration => {
// TODO step 2 & 3 here
})
.catch(err => {
console.log('serviceWorker.register failed', err);
});
此代码sw.js
从您的网站根目录获取数据。该函数返回一个 Promise。因此,我们会在成功和出错时register
处理它。.then
.catch
现在,我们可以执行步骤 2 和 3,这需要swRegistration
:
const applicationServerKey = '';
swRegistration
.pushManager
.getSubscription()
.then(subscription => {
const isSubscribed = !(subscription === null);
if (!isSubscribed) {
return swRegistration.pushManager
.subscribe({
userVisibleOnly: true,
applicationServerKey,
})
.then(sendSubscriptionToServer);
}
sendSubscriptionToServer(subscription);
})
.catch(err => {
console.log('getSubscription failed', err);
});
applicationServerKey
暂时不用担心。applicationServerKey
允许将订阅与您的服务器关联。稍后我会解释如何获取此密钥。
那么这里发生了什么:我们调用该pushManager.getSubscription
方法,如果用户已经允许推送通知,则返回订阅,null
否则返回。如果用户已经订阅,我们可以将其发送到后端。如果没有,我们调用该方法pushManager.subscribe
询问用户是否允许推送通知。
现在,对于步骤 5,您可以使用任何您喜欢的方法将订阅对象发送到服务器。我建议先使用 进行字符串化JSON.stringify(subscription)
。
为了从服务器向客户端发送消息,我建议使用web-push
以下模块:
const webpush = require('web-push');
const vapidKeys = {
publicKey: '',
privateKey: '',
};
webpush.setVapidDetails(
'mailto:your@email',
vapidKeys.publicKey,
vapidKeys.privateKey
);
webpush.sendNotification(
JSON.parse(subscription),
JSON.stringify({
title: 'Title',
icon: 'https://your-site.com/assets/push-icon.png',
body: 'Body',
url: 'https://your-site.com/url-to-open',
})
)
现在在步骤 7 和 8 中,我们回到sw.js
负责接收和显示推送消息的服务工作线程代码:
self.addEventListener('push', function(event) {
const message = JSON.parse(event.data.text());
const title = message.title;
const url = message.url;
const options = {
body: message.body,
icon: message.icon,
badge: message.badge,
data: url,
};
event.waitUntil(self.registration.showNotification(title, options));
});
self.addEventListener('notificationclick', function(event) {
event.notification.close();
event.waitUntil(clients.openWindow(event.notification.data));
});
这里定义了两个事件监听器。通过push
监听器,我们解析消息并调用相应的showNotification
方法来显示通知。然后,notificationclick
我们关闭通知并导航到推送消息发送的 URL。
生成密钥
你可以使用该web-push
库生成密钥。密钥生成只需执行一次。前端和后端都使用相同的公钥,后端仅使用私钥:
const webpush = require('web-push');
const vapidKeys = webpush.generateVAPIDKeys();
console.log(vapidKeys);
您应该在需要的地方指定前面的代码片段中的键。
结论
我发现推送通知的 API 相当简单直接。尽管如此,一开始还是需要花不少时间才能理解所有概念和运作机制。
希望这些笔记对您有所帮助,并在您需要实现推送通知时再次参考。如果这种情况发生,请不要在网页加载时立即请求权限:这很烦人,大多数人都会屏蔽它。
感谢阅读!
鏂囩珷鏉ユ簮锛�https://dev.to/orkon/getting-started-with-web-push-notifications-1poe