PWA资料整理(三):Service Worker 消息推送

PWA资料整理(三):Service Worker 消息推送

  • 系列链接
  • 消息推送
    • 消息推送整体架构
    • 消息推送具体流程
  • 参考资料

本篇是 PWA 资料整理的第三篇,主要介绍 Service Worker 所实现的消息推送相关内容。

系列链接

  1. Manifest 添加到桌面
  2. Service Worker 离线缓存
  3. Service Worker 消息推送(本篇)

消息推送

说到消息推送就想到 HTTP2 push。实际上 HTTP2 push 就是一个缓存相关的机制,与消息推送没有关联。
拓展资料:Http/2 push is tougher than I thought(我之前的博客中也有对该文章的阅读理解,如果懒得看英文原文的话可以直接看我的内容概括)。

事实上,同 SW 实现的消息推送一样,SW 本身仅仅是提供类似 Web Worker 的功能,需要结合 cache api 才能实现离线缓存功能。使用 SW 实现消息推送需结合 notification api,具体功能就不介绍,可以查看 MDN 文档。

消息推送整体架构

消息推送看起来似乎很简单,就是服务端给客户端发送消息这样简单粗暴的东西嘛,其实并不是。
实际上,服务端无法直接给客户端发送消息,而必须借助 Push Service 进行消息的推送。Webpush 的整体架构如下图所示:
PWA资料整理(三):Service Worker 消息推送_第1张图片
这里的 UA 即 user agent,也就是用户代理;Application Server 为应用的服务端;Push Service 也就是推送服务,指的是 google 的 fcm (以前叫 gcm),或者 apple 的 APNs(苹果现在还不支持 webpush)等。

消息推送具体流程

在使用消息推送之前,客户端需要通过 SW 进行消息订阅:

  • 同样是在注册 service worker 时,先通过 pushManager.getSubscription方法获取当前客户端是否已经订阅过了,没有订阅则需要对推送订阅对象进行生成;
  • 在向 push server 发送请求(pushManager.subsribe)之前,浏览器已经生成了一个推送订阅对象;
  • 得到响应之后,客户端会将推送服务生成的地址(end point)加入这个推送订阅对象中;
  • 之后,客户端将推送订阅对象发送给服务端。

一个完整的推送订阅对象数据结构如下:

{
    "endpoint": "https://fcm.googleapis.com/fcm/send/...",
    "keys": {
        "p256dh" : "BNcRd...",
        "auth"   : "tBHI..."
    }
}

注意:订阅信息会过期,所以不要忘了在 servier worker 中监听 pushsubscriptionchange事件,当订阅过期后自动重新订阅。

SW 可以通过监听 push 事件来获取服务端所推送的消息。并通过 registration.showNotification方法显示消息。
参考代码如下所示:

// service-worker.js
// ...
const onPush = function(event) {
    event.waitUntil(_self.registration.showNotification('New Post Arrival', {
        icon: '/logo.png'
    }));
};

_self.addEventListener('push', onPush);

服务端需要 push 消息时,只需要向用户订阅信息中的 url post 消息内容就行了,具体的消息分发由 push server 代为实现。服务端代码如下:

// publish.js
// ...
    .post('/broadcast', async ctx => {
        await readEndpoints()
            .then(endpoints => {
                ctx.status = 200;
                ctx.body = {};

                endpoints.forEach(endpoint => {
                    webPush.sendNotification({ endpoint })
                        .catch(console.error);
                });
            })
            .catch(err => {
                ctx.status = 500;
                ctx.body = err;
            });
    });

在消息推送的过程中,必不可免的存在一些安全性相关的问题,不过这些都交由 Push Server 完成,开发者只需要关心客户端和服务端就可以了。需要注意的是:浏览器关闭时,SW 的线程会被回收,也就意味着消息无法接收。

参考资料

  1. Web 推送技术
  2. Lavas how-push-works
  3. 简单了解HTML5中的Web Notification桌面通知
  4. MDN notification api
  5. Notification with Service Workers push events

你可能感兴趣的:(前端杂物筐)