实时站内通知
回复、提及与审批一发生,就在用户每个打开的标签页里显示;用户离线时改用推送通知。
事情一发生产品就有反应,用户是感受得到的:自己的帖子有了留言、申请被批准、队友提到了自己。每 30 秒轮询一次既慢又浪费请求。用 Hibira,你的服务器只送一次通知,用户开着的每个标签页与设备都会在几毫秒内显示。用户离线时,改由推送通知接手。
用户得到什么
- 事情一发生,铃铛徽章与提示就在每个开着的标签页里更新。
- App 关着时,手机上也收到同一条通知。
- 不必刷新就能看到新动态,计数也不会过时。
用到的功能
- 用户验证(
pusher.signin()),每位用户都有只有自己能读的频道。 - 官方服务器 SDK 的
sendToUser,送到该用户在每个节点上的每个连接。 - 通过兼容 Beams 的 API 发送推送通知,给没有连接的用户。
- 通知内容需要端到端加密时,使用私有加密频道(
private-encrypted-)。
步骤 1:让用户在连接上登录
在频道授权路由旁边加上用户验证路由。它在你的服务器上运行,使用应用密钥。
// Express
app.post('/pusher/user-auth', requireLogin, express.urlencoded({ extended: false }), (req, res) => {
const auth = pusher.authenticateUser(req.body.socket_id, {
id: String(req.user.id),
user_info: { name: req.user.name },
});
res.json(auth);
});在浏览器里,照 JavaScript 指南连接并登录:
const pusher = new Pusher(import.meta.env.VITE_PUSHER_APP_KEY, {
cluster: 'ap',
wsHost: 'ws.hibira.io',
wsPort: 443,
wssPort: 443,
forceTLS: true,
enabledTransports: ['ws', 'wss'],
userAuthentication: { endpoint: '/pusher/user-auth', transport: 'ajax' },
});
pusher.signin();
pusher.user.bind('notification', (n) => {
bell.increment();
toast.show(n.title, { href: n.url });
});步骤 2:从服务器发送
先把通知存进数据库,刷新后清单才还在,然后再发送:
const n = await db.notifications.create({ userId, title: 'Ann replied to your comment', url: '/posts/42#c7' });
await pusher.sendToUser(String(userId), 'notification', { id: n.id, title: n.title, url: n.url });一次 sendToUser 会送到用户所有的标签页与设备,不论有多少连接收到,都只算一条消息。
步骤 3:离线时改用推送
让每个已登录的页面订阅一个私有频道,例如 private-user-42,并让 webhook 端点订阅 channel_occupied 与 channel_vacated。这样你的服务器不必询问就知道谁在线:
app.post('/pusher/webhook', express.raw({ type: 'application/json' }), async (req, res) => {
const webhook = pusher.webhook({ headers: req.headers, rawBody: req.body.toString() });
if (!webhook.isValid()) return res.sendStatus(401);
for (const e of webhook.getEvents()) {
const id = e.channel.match(/^private-user-(.+)$/)?.[1];
if (id) await db.users.update(id, { online: e.name === 'channel_occupied' });
}
res.sendStatus(200);
});用户离线时,照推送通知指南发送到他们的设备:
if (!(await db.users.isOnline(userId))) {
await beams.publishToUsers([String(userId)], {
web: { notification: { title: n.title, deep_link: 'https://your-site.example' + n.url } },
fcm: { notification: { title: n.title } },
apns: { aps: { alert: { title: n.title } } },
});
}小提醒
- 内容保持精简(ID、标题和链接),用户打开时再加载细节。事件上限是 10 KB(Free 方案为 4 KB)。
- 在服务器上把通知标为已读,并送出
notifications-read事件,每个标签页的徽章就会同时清除。 - 健康、金融或人事数据,请改送到
private-encrypted-user-42频道:Hibira 只转送密文。 - 在 Free 方案上,请在应用设置里把你网站的域名列为允许的来源。