此 Codelab 将逐步介绍如何构建推送通知客户端。 完成此 Codelab 后,您将拥有一个符合以下条件的客户端:
- 为用户订阅推送通知。
- 接收推送消息并将其显示为通知。
- 为用户退订推送通知。
此 Codelab 主要是帮助您在实践中学习 结账 推送通知的工作原理 以了解推送通知概念。
此 Codelab 的服务器代码已完成。您只会 如何实现该客户端要了解如何实现 推送通知服务器,请参阅Codelab:构建推送通知 服务器。
请查看 push-notifications-client-codelab-complete (来源) 查看完整代码。
浏览器兼容性
此 Codelab 已知可与下列操作系统和浏览器组合配合使用:
- Windows:Chrome、Edge
- macOS:Chrome、Firefox
- Android:Chrome、Firefox
此 Codelab 已知不适合以下操作系统 (或操作系统和浏览器组合):
- macOS:Brave、Edge、Safari
- iOS
设置
获取代码的可修改副本
在这些说明右侧显示的代码编辑器将称为 Glitch 界面。
- 点击 Remix to Edit 以使项目可修改。
设置身份验证
您需要先完成设置,然后才能让推送通知正常运行 向服务器和客户端授予身份验证密钥。 请参阅对 Web 推送协议请求进行签名 以了解具体原因。
- 在 Glitch 界面中,点击 Tools(工具),然后点击 Terminal(终端)以打开 Glitch 终端。
- 在 Glitch 终端中,运行
npx web-push generate-vapid-keys
。复制私钥 和公钥值。 - 在 Glitch 界面中,打开
.env
并更新VAPID_PUBLIC_KEY
和VAPID_PRIVATE_KEY
。设置VAPID_SUBJECT
至mailto:test@test.test
。所有这些值都应换行 。完成更新后,您的.env
文件应如下所示: 类似于以下内容:
VAPID_PUBLIC_KEY="BKiwTvD9HA…"
VAPID_PRIVATE_KEY="4mXG9jBUaU…"
VAPID_SUBJECT="mailto:test@test.test"
- 关闭 Glitch 终端。
- 打开
public/index.js
。 - 将
VAPID_PUBLIC_KEY_VALUE_HERE
替换为您的公钥的值。
注册 Service Worker
客户端最终需要一个 Service Worker 来接收和显示 通知。最好尽早注册 Service Worker。 请参阅接收推送的消息并将其显示为 通知以获得更多背景信息。
- 将
// TODO add startup logic here
注释替换为以下代码:
// TODO add startup logic here
if ('serviceWorker' in navigator && 'PushManager' in window) {
navigator.serviceWorker.register('./service-worker.js').then(serviceWorkerRegistration => {
console.info('Service worker was registered.');
console.info({serviceWorkerRegistration});
}).catch(error => {
console.error('An error occurred while registering the service worker.');
console.error(error);
});
subscribeButton.disabled = false;
} else {
console.error('Browser does not support service workers or push messages.');
}
subscribeButton.addEventListener('click', subscribeButtonHandler);
unsubscribeButton.addEventListener('click', unsubscribeButtonHandler);
- 如需预览网站,请按查看应用。然后按 全屏 。
- 按 `Ctrl+Shift+J`(在 Mac 上,按 `Command+Option+J`)打开开发者工具。
- 点击 Console(控制台)标签。您应该会看到以下消息:
Service worker was registered.
已记录到控制台。
请求推送通知权限
您绝不能请求在网页加载时发送推送通知的权限。 相反,您的界面应询问用户是否要接收推送通知。 一旦他们明确确认(例如点击按钮),您就可以 启动从浏览器获取推送通知权限的正式流程。
- 在 Glitch 界面中,点击 View Source 以返回到您的代码。
- 在
public/index.js
中,替换// TODO
中的注释subscribeButtonHandler()
替换为以下代码:
// TODO
// Prevent the user from clicking the subscribe button multiple times.
subscribeButton.disabled = true;
const result = await Notification.requestPermission();
if (result === 'denied') {
console.error('The user explicitly denied the permission request.');
return;
}
if (result === 'granted') {
console.info('The user accepted the permission request.');
}
- 返回应用标签页,然后点击订阅以推送。您的浏览器 或者操作系统可能会询问您是否允许该网站 向您发送推送通知点击允许(或任何等效的词组) 。在控制台中,您应该会看到一条消息 请求是被接受还是被拒绝。
订阅推送通知
订阅过程涉及与受控 这称为“推送服务”。获得 发送到服务器所需的推送通知订阅信息 并让服务器长期将其存储在数据库中 请参阅为客户端订阅推送通知 了解有关订阅流程的更多背景信息。
- 将以下突出显示的代码添加到
subscribeButtonHandler()
:
subscribeButton.disabled = true;
const result = await Notification.requestPermission();
if (result === 'denied') {
console.error('The user explicitly denied the permission request.');
return;
}
if (result === 'granted') {
console.info('The user accepted the permission request.');
}
const registration = await navigator.serviceWorker.getRegistration();
const subscribed = await registration.pushManager.getSubscription();
if (subscribed) {
console.info('User is already subscribed.');
notifyMeButton.disabled = false;
unsubscribeButton.disabled = false;
return;
}
const subscription = await registration.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: urlB64ToUint8Array(VAPID_PUBLIC_KEY)
});
notifyMeButton.disabled = false;
fetch('/add-subscription', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify(subscription)
});
userVisibleOnly
选项必须为 true
。也许有一天
推送消息,而不显示用户可见的通知
(静默推送),但浏览器目前不支持该功能
保护隐私
applicationServerKey
值依赖于一个实用函数,
将 base64 字符串转换为 Uint8Array。该值用于
身份验证。
退订推送通知
用户订阅推送通知后,您的界面需要 提供退订方法,以防用户改变主意 并且不想再接收推送通知。
- 替换
unsubscribeButtonHandler()
中的// TODO
注释 替换为以下代码:
// TODO
const registration = await navigator.serviceWorker.getRegistration();
const subscription = await registration.pushManager.getSubscription();
fetch('/remove-subscription', {
method: 'POST',
headers: {
'Content-Type': 'application/json'
},
body: JSON.stringify({endpoint: subscription.endpoint})
});
const unsubscribed = await subscription.unsubscribe();
if (unsubscribed) {
console.info('Successfully unsubscribed from push notifications.');
unsubscribeButton.disabled = true;
subscribeButton.disabled = false;
notifyMeButton.disabled = true;
}
接收推送消息并将其显示为通知
如前所述,您需要一个 Service Worker 来处理 接收并显示推送到客户端的消息 。请参阅接收推送的消息并将其显示为 通知了解更多详情。
- 打开
public/service-worker.js
并替换// TODO
注释 在 Service Worker 的push
事件处理脚本中,使用以下代码:
// TODO
let data = event.data.json();
const image = 'https://cdn.glitch.com/614286c9-b4fc-4303-a6a9-a4cef0601b74%2Flogo.png?v=1605150951230';
const options = {
body: data.options.body,
icon: image
}
self.registration.showNotification(
data.title,
options
);
- 返回应用标签页。
- 点击通知我。您应该会收到一条推送通知。
- 尝试在其他浏览器(甚至 完成订阅工作流程,然后 点击全部通知。您应该也会收到相同的推送通知 。请返回 浏览器兼容性:用于查看浏览器/操作系统列表 组合。
您可以通过多种方式自定义通知。查看
ServiceWorkerRegistration.showNotification()
了解详情。
在用户点击通知时打开网址
在现实世界中,您可能会将通知当作一种 以再次吸引您的用户并提示他们访问您的网站。 为此,您需要进一步配置 Service Worker。
- 替换 Service Worker 的
notificationclick
中的// TODO
注释 事件处理程序:
// TODO
event.notification.close();
event.waitUntil(self.clients.openWindow('https://web.dev'));
- 请返回应用标签页,再给自己发送一条通知
点击该通知。您的浏览器应该会打开一个新标签页并加载
https://web.dev
。
后续步骤
- 查看
ServiceWorkerRegistration.showNotification()
了解自定义通知的各种不同方式。 - 阅读推送通知概览 以便从概念上更深入地了解推送通知的工作原理。
- 查看 Codelab:构建推送通知服务器 学习如何构建管理订阅和发送 Web 推送协议的服务器 请求。
- 试用通知生成器 测试自定义通知的所有方式。