Web世界中是如何实现消息推送的
首先,我们需要说明的是,我们讨论的推送是指按照 Web Push Protocol 发送和接受的推送消息。
Web的推送可以简单的分为三类:
- 本地推送 (Local Push) - 由浏览器或应用程序在本地生成和触发的通知
- 服务器推送 (Server Push) - 服务器主动向客户端发送数据的技术
- 第三方服务器代理推送 - 例如Firebase,代理推送服务,无需自己实现推送的服务器
本地推送
本地推送顾名思义直接本地推送,无需通过服务器的步骤,所以只需要通过new一个Notification就可以唤起本地的消息通知:
function notifyMe() { if (!("Notification" in window)) { // Check if the browser supports notifications alert("This browser does not support desktop notification"); } else if (Notification.permission === "granted") { // Check whether notification permissions have already been granted; // if so, create a notification const notification = new Notification("Hi there!"); // … } else if (Notification.permission !== "denied") { // We need to ask the user for permission Notification.requestPermission().then((permission) => { // If the user accepts, let's create a notification if (permission === "granted") { const notification = new Notification("Hi there!"); // … } }); } // At last, if the user has denied notifications, and you // want to be respectful there is no need to bother them anymore. }
具体可以查看 Notification API
Github demo
服务器推送
服务器推送就复杂很多,我们需要用到web-push这个库,以下是其推送详细步骤:
- 当用户打开浏览器网页时,会注册一个service worker,这个service worker用于处理接受到推送后的业务逻辑
- 当service worker注册成功后,获取到registration,通过registration的pushManager的subscribe方法创建一个订阅,需要使用publickKey(Key的获取方式请参考web-push)
- 在调用pushManager的subscribe方法时,会询问用户是否授予推送权限
- 当用户接受了推送权限后,才会生成新的subscription,将subscription发送到后端持久化保存,并与用户进行绑定
- 当网站运维需要向订阅了本站的用户推送消息时,会向服务器发送一个请求,请求中包含了消息的具体内容
- 服务器接受到请求后会通过
vapid-keys
,subscription和payload进行request包装,向FCM服务器发送请求,FCM会将payload发送到指定的subscription
- 客户端浏览器通过service worker的事件监听,获取到推送内容,并对内容进行加工,最后调用Notification API发布推送
第三方服务器代理推送
这种与第二种其实很相似,只是将subscription托管给第三方进行管理。只需要在第二种的基础上加
gcmAPIKey
就可以实现firebase托管