跳转到内容

Web Push:订阅、权限与投递

一句话: Web Push 将 Push API(绑定到浏览器推送服务的 service worker 订阅) 与 Notifications API(展示消息)配对。你的服务器加密负载,POST 到订阅的 endpoint, 推送服务唤醒 service worker 的 push 事件,你再调用 self.registration.showNotification()。 在 iOS/Safari 上,这仅对用户已安装到主屏幕的 PWA 生效。

  1. 订阅。 在 service worker 注册激活后,调用 registration.pushManager.subscribe({ userVisibleOnly: true, applicationServerKey }), 传入你的 VAPID 公钥。浏览器返回包含 endpoint URL 以及 p256dhauth 密钥的 PushSubscription
  2. 存储。 将订阅 JSON 发送到服务器,按用户/设备持久化。
  3. 发送。 服务器加密负载(RFC 8291)、签发 VAPID JWT(RFC 8292),并 POST 到订阅的 endpoint——由浏览器厂商运营的推送服务。
  4. 接收。 推送服务投递到设备,设备唤醒 service worker 并触发 push 事件,即使没有页面打开。
  5. 展示。push 处理器中调用 showNotification();点击会触发 notificationclick, 你在其中聚焦或打开正确的窗口。

Notification.requestPermission()(或 subscribe() 期间的隐式提示)必须由用户手势触发 ——点击或轻触,而非页面加载时。应在有上下文时询问:在用户做出能说明通知价值的操作之后。 权限有三种状态:

  • default —— 尚未决定;你可以礼貌地提示一次。
  • granted —— 你可以订阅并展示通知。
  • denied —— 实际上不可逆;你无法再次提示,所以切勿反复请求。

由于 userVisibleOnly: true 是必需的,你发送的每条推送都必须呈现可见通知——不允许静默后台推送。

在 service worker 中处理推送与点击

Section titled “在 service worker 中处理推送与点击”
self.addEventListener('push', (event) => {
const data = event.data?.json() ?? {};
event.waitUntil(
self.registration.showNotification(data.title ?? '更新', {
body: data.body,
icon: '/icons/icon-192.png',
data: { url: data.url ?? '/' },
})
);
});
self.addEventListener('notificationclick', (event) => {
event.notification.close();
event.waitUntil(clients.openWindow(event.notification.data.url));
});

event.waitUntil() 包裹异步工作,让 service worker 在通知展示或点击处理完成前保持存活。

Browser / PlatformSupportSinceConfidenceSourceNotes
Chrome (Android)✅ yes50highref
Chrome (Desktop)✅ yes50highref
Edge (Desktop)✅ yes17highref
Safari (iOS)⚠️ partial16.4mediumrefOnly for home-screen-installed web apps; requires user-gesture permission and Web Push via APNs.
Safari (macOS)✅ yes16mediumref
Firefox (Desktop)✅ yes44highref
Samsung Internet✅ yes5.0highref

Ecosystem & commercial policy

EntityTypeContextStatusSponsoredNotes
Apple Push (APNs)delivery_policyiOS⚠️ partialNoiOS Web Push requires the user to add the app to the Home Screen first.

Source: spec · MDN · Last verified 2026-06-24 · Confidence: high

决策问题 建议行为 理由
何时请求权限? 在能提供上下文的用户手势之后。 浏览器忽略非手势触发的提示;冷提示会被拒绝。
用什么凭据来发送? VAPID(应用服务器密钥)。 向推送服务标识你的服务器;无需按厂商注册账户。
需要加密负载吗? 任何负载都需要(RFC 8291)。 推送服务只转发密文;浏览器用 p256dh/auth 解密。
需要触达 iOS 用户? 先要求安装到主屏幕。 iOS/Safari 仅向已安装的 PWA 投递 web push。
发送返回 404/410? 删除该订阅。 endpoint 已失效或过期;停止向其发送。
  • 注册 service worker,并在订阅前确认其已 active
  • 从真实用户手势、有上下文地请求权限——切勿在加载时。
  • 使用 userVisibleOnly: true 与你的 VAPID applicationServerKey 订阅。
  • 在服务器端持久化完整的 PushSubscription(endpoint + p256dh + auth)。
  • 发送时加密负载(RFC 8291)并签发 VAPID JWT(RFC 8292)。
  • 始终在 push 处理器中调用 showNotification()userVisibleOnly 要求)。
  • 处理 notificationclick:聚焦已有客户端或打开目标 URL。
  • 在推送服务返回 404/410 时清理订阅。
  • 对 iOS/Safari,将提示限定在已安装(主屏幕)的 PWA 之后。