Push Notifications - Progressive Web Apps

推送可以在浏览器中实现和原生App中的通知一样的功能。

The Push API gives web applications the ability to receive messages pushed to them from a server, whether or not the web app is in the foreground, or even currently loaded, on a user agent. This lets developers deliver asynchronous notifications and updates to users that opt in, resulting in better engagement with timely new content.

要通过Service Worker来发送通知,需要使用HTML5的Notification API。

Notificaton的三种状态

  • granted(用户同意接收通知)
  • denied(用户不同意接收通知)
  • default(通知时提示)

Server Push Work Flow

Push Server -> Push Service(Google) -> PWA App

应用服务器生成公私钥,客户端利用公钥,请求Google通知服务器,Google通知服务器返回Subscription Object,应用服务器利用该对象向客户端发送消息。

subscription object example

{
  "endpoint": "https://fcm.googleapis.com/fcm/send/da6nAuGjSxA:APA91bGTMoI8y1UlQgvkU-xIhorpDgVzOHHw-IalL8Yyk2v1T8M6BxCz8yE8oawHJUrzNr4DXELK7sAKkrD0YUf-yOOZ4slI-RBcZx-UU5E2T-TAnzAN2-Fakm7QdGAdWJTY1OU1zQ_Q",
  "expirationTime": null,
  "keys": {
    "p256dh": "BNBnYTHlMDZRGlNOW3ulmxoNIua94THU9QCFT0nlztuZaFU-HU8k1OR2YeK1CfQn7adBDQMw3dlQnWW9L0gPtd4",
    "auth": "Krh9e8ATlfyEKKOqeGIO8A"
  }
}

客户端代码及配置

请参考完整示例scripts/main.jssw.js

服务器端推送程序

push-server.js

// Web-push Module
const webpush = require('web-push');
const vapid = require('./vapid.json');

// Configure keys
webpush.setVapidDetails(
  'mailto:ray@stackacademy.tv',
  vapid.publicKey,
  vapid.privateKey
);

const pushSubscription = {
  endpoint: "https://fcm.googleapis.com/fcm/send/f8dKsZEPSlA:APA91bFXvGYKwG6Ey1aPuZsISV1cJrRzCPaGkYuf6QZf_jF-uPWJrS7a60hhKc0_O7-pFVUQtW8owl_9_ex9xWHZqZhJxwf7ciSsUas6qcHBooKyB8osXVT_dVmKihm2-K1xpsg-7mlJ",
  keys: {
    auth: "BaoLgoJHMGnrTFHGzaCnvg",
    p256dh: "BDh1-EPnFjeYqnORIls2NZCd2JpVbL1BLJ-ZaRnSf8H5_8_4dkXAKX72qrz2MMV0IYzYSWSnJA_GPCmGi6vZjQQ"
  }
};

webpush.sendNotification(pushSubscription, 'A notification from the push server')
  .then((res) => {
    console.log(res)
  })
  .catch((err) => {
    console.log(err)
  })
console.log('Push sent to client');

发送通知

$ node push-server.js

服务器端记录用户的订阅

服务器端存储客户端生成的订阅对象,在发送时使用web-push根据订阅对象来发送。

我实验过的完整示例

这个完整示例,包括对 向网络应用添加推送通知这篇教程的实践和web-push库的使用示例。

注意事项

发送和接收都要联通Google服务器。客户端和服务器端都要联通。

Resources