推送通知和离线缓存不是一回事
PWA 有两块常被混在一起:一块是离线缓存(之前讲过的 Service Worker 加 Cache,让网页没网也能开),另一块是推送通知——即使网页没打开,服务器也能给用户的浏览器发一条系统通知。这篇聚焦后者:怎么在网页没开着时,也能把消息推到用户面前。
本文核心知识点
- Web Push标准化的浏览器推送协议。
- Service Worker没开网页也能收推送的关键。
- push 事件到达时在后台弹出通知。
- Background Sync网络恢复后自动补做请求。
Web Push 与 Service Worker
普通网页关了就停了,收不到服务器消息。PWA 靠 Service Worker——一个在浏览器后台独立运行的脚本,网页关了它还活着。Web Push 协议让服务器能把消息推给 Service Worker,由它弹出系统通知。这就是网页没打开也能收到推送的原理。
订阅与推送权限
先要用户授权 Notification 权限,再用 pushManager.subscribe 生成一个订阅对象,里面有一个推送端点(endpoint)和密钥。把这个订阅信息发给服务端存起来,以后服务端就知道往哪个地址推这个用户。
const reg = await navigator.serviceWorker.ready;
const sub = await reg.pushManager.subscribe({
userVisibleOnly: true,
applicationServerKey: vapidPublicKey
});
await fetch("/subscribe", { method:"POST", body: JSON.stringify(sub) });
push 事件与通知展示
消息推到 Service Worker 后,会触发 push 事件。在这个事件里,用 self.registration.showNotification 弹出一条系统通知,可以带标题、正文、图标,还能定义点击通知后打开哪个页面。
VAPID 加密推送与通知点击
服务端不能随便往订阅端点推,要用 VAPID 密钥对做身份鉴权,并用公共密钥把消息加密,浏览器才能识别这是合法站点发的推送、而不是匿名骚扰。点击通知后还能在 notificationclick 事件里处理跳转:打开指定页面、聚焦已有标签页,或者把通知关掉。
落地要点
- VAPID公私钥对用于推送鉴权与加密。
- notificationclick处理通知点击跳转。
- 消息克制频率过高会被用户关权限。
后台同步 Background Sync
和推送配套的还有 Background Sync:用户在弱网下提交了一个表单,请求失败了,可以登记一个后台同步任务,等网络恢复时 Service Worker 自动把请求补上。这让离线、弱网场景下的操作不会丢,体验接近原生应用。
落地清单
- 先请求通知权限,再订阅并上报服务端。
- Service Worker 里处理 push 事件弹通知。
- 服务端按订阅端点加密推送,用 VAPID。
- 弱网操作用 Background Sync 自动补传。
- 推送要克制,别滥用被用户关掉权限。