即時站內通知
回覆、提及與核准一發生,就在使用者每個開著的分頁裡顯示;使用者離線時改用推播通知。
事情一發生產品就有反應,使用者是感受得到的:自己的貼文有了留言、申請被核准、隊友提到了自己。每 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 方案上,請在應用程式設定裡把你網站的網域列為允許的來源。