一句话:Web Push 让你即使在应用标签页已经关闭时也能通知用户。它就是浏览器标准的 Web Push(VAPID)流程——需要 HTTPS、一个 service worker,以及用户授权。SDK 的 client.push 在浏览器里做两件事:用 isSupported() 做能力检测,用 subscribe() 注册你的 service worker、弹出权限提示,并把用户的订阅对象存到后端。发送通知是另一个独立的服务端步骤——你从函数或托管应用向已存储的订阅对象推送,而不是从浏览器发送。
大多数人想要的「通知」其实是看似一体、实则两半的东西。浏览器这一半的关键是赢得授权并捕获送达地址——这发生在你的页面里,用户就在旁边看着。送达那一半,则是某件事真正发生时,由服务器去戳那个已保存的地址。LingCode Cloud 处理掉中间那段尴尬的衔接:它把每个用户的订阅对象绑定到其账号上存起来,这样标签页早已关闭后你依然能触达他们。本页把浏览器这一半从头讲到尾,并指引你去看服务端那一半。
推送通知必须在你的代码没有运行时送达——用户几小时前就关掉了标签页。正因如此,标准要求一开始就具备三样东西:
要订阅,浏览器还需要你后端的 VAPID 公钥——这个身份让推送服务能信任那些声称来自你的推送确实来自你。LingCode Cloud 替你管理这个密钥;SDK 在底层把它取回来。订阅创建后,它会存到后端并绑定到已登录用户,这样你之后才能精准触达他们。
浏览器负责订阅;服务器负责发送。你无法从刚刚调用了 subscribe() 的那个页面发出通知——页面只捕获了地址而已。真正推送一条消息,是从函数或托管应用在服务端向用户已存储的订阅对象发起。先把订阅流程搭好,确认那行记录确实落库,再去接通发送。
在 /try 和 Mac 预览里,window.lingcode 已经存在。在你自己的应用里,先创建客户端(参见总览),再跑下面这三步。
并非每个浏览器或上下文都能做推送。在展示任何「启用通知」UI 之前先检查一下——提供一个根本无法工作的按钮没有意义。
if (!lingcode.push.isSupported()) {
// 隐藏你的「启用通知」按钮——这里不支持推送。
return;
}
isSupported() 同步返回一个布尔值。
在用户手势(例如点击按钮)的响应中调用 subscribe()。它会注册你的 service worker,通过浏览器的 PushManager 订阅,并把订阅对象按当前用户存到后端。这个调用会触发浏览器的权限提示。
const { data, error } = await lingcode.push.subscribe({
serviceWorker: '/sw.js'
});
if (error) {
// 用户拒绝了授权,或这里不支持推送——优雅降级。
console.warn('Could not enable push:', error);
} else {
// 订阅对象已存到服务端;现在可以触达该用户了。
}
opts 参数是可选的;{ serviceWorker?: string } 指向你的 service worker 文件。每个调用都返回 { data, error }。
/sw.js(或你传给 subscribe() 的任意路径)就没有推送。确保该文件确实在你引用的那个路径上、同源地提供出来。
SDK 封装了两个端点。你很少直接调用它们,但了解其结构在调试时很有帮助。
浏览器在能订阅之前需要后端的 VAPID 公钥。SDK 替你取回:
GET https://lingcode.dev/api/cloud/be/<backend-id>/push/vapid-public
→ { "key": "<vapid-public-key>" }
当浏览器的 PushManager 产出一个订阅对象后,SDK 把它 POST 到后端,按当前用户存起来:
POST https://lingcode.dev/api/cloud/be/<backend-id>/push/subscribe
{
"subscription": {
"endpoint": "https://<push-service>/...",
"keys": {
"p256dh": "<client-public-key>",
"auth": "<auth-secret>"
}
}
}
push_not_available——浏览器或上下文无法做推送,或该后端未配置推送。invalid_subscription——订阅对象格式不正确。仅限 HTTPS。它在你托管应用的安全 URL 上可用——*.run.lingcode.dev 或你的自定义域名——以及用于开发的 http://localhost。任何其它主机上的纯 http:// 都不支持推送。
isSupported() 做能力检测,并处理未授权的情况(来自 subscribe() 的 error),而不是假定订阅对象一定存在。
/sw.js)——推送送达要经过它。