推送通知和离线缓存不是一回事

PWA 有两块常被混在一起:一块是离线缓存(之前讲过的 Service Worker 加 Cache,让网页没网也能开),另一块是推送通知——即使网页没打开,服务器也能给用户的浏览器发一条系统通知。这篇聚焦后者:怎么在网页没开着时,也能把消息推到用户面前。

本文核心知识点
  • Web Push标准化的浏览器推送协议。
  • Service Worker没开网页也能收推送的关键。
  • push 事件到达时在后台弹出通知。
  • Background Sync网络恢复后自动补做请求。
PWA 推送通知配图:蓝色渐变背景右上角云朵浏览器方块向下发光信号波纹连中央手机轮廓方块,手机弹出空白通知卡片,底部工人方块,扁平科技插画
云端向手机推送通知、Service Worker 在后台兜底,正是 Web Push 的意象。

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处理通知点击跳转。
  • 消息克制频率过高会被用户关权限。