我自己觉得推送功能是一个应用非常重要的部分。我也想给我的博客加一个消息推送的功能。目前市面上消息推送做的最好的应该就是Firebase了。对接Firebase没什么难的跟着官网文档走就行,基本上没什么坑。需要注意的是firebase-messaging-sw.js文件需要放在public,这是一个后台运行的文件,在这个文件内是不能调用浏览器的方法的。你可以在这个文件内通过onMessage事件监听消息。
if (isSupported()) { // 必须要加用于判断是否支持Firebase
onMessage(messaging, (payload) => {
console.log('Message received. ', payload)
if ('Notification' in window && 'serviceWorker' in navigator && 'PushManager' in window) {
const title = payload.notification.title
const content = payload.notification.body
const icon = 'https://blog.xiaomaibu.pro/xiaomaibu.png'
new Notification(title, {
body: content,
icon
})
}
// ...
})
}
整体流程基本是就是,浏览器授权Notification,拿到client token 给到服务端。服务端在通过方法项指定token发起推送。
public void sendMessage(String firebaseToken) {
// This registration token comes from the client FCM SDKs.
// See documentation on defining a message payload.
Message message = Message.builder()
.setNotification(Notification.builder().setTitle("快去看看吧").setBody("有人回复了您的评论").build())
.setToken(firebaseToken)
.build();
// Send a message to the device corresponding to the provided
// registration token.
String response = null;
try {
response = FirebaseMessaging.getInstance().send(message);
} catch (FirebaseMessagingException e) {
e.printStackTrace();
System.out.println(e + "error");
}
// Response is a message ID string.
System.out.println("Successfully sent message: " + response);
}
相对来说是比较简单的。不过需要结合自己的业务流程去进行推送。
不过部署之后依旧是没办法推送,一直报连接超时。后来才发现国内没法用Firebase,其实我服务器装了Clash代理了不过依旧不行。
想着Firebase不能用那我就直接写原生的吧。直到我看见了这句话
:服务和浏览器之间是没有直接的通信的,而是通过FCM服务器来进行通信的;
而FCM服务器是谷歌的服务器,所以我们不管是订阅还是推送消息都需要通过谷歌的服务器,这就是为什么我们推送消息会被墙的原因。
也是很无奈的一件事情😮💨
不过service worker不止可以推送消息还可以用于缓存数据。 Firebase的推送是建立在service worker之上的,service worker是一个后台运行的脚本。在这个脚本里面它提供了caches对象可以将数据直接存储到cache storage中。然后通过match进行匹配。
self.addEventListener('fetch', (event) => {
// console.log('Fetch', event.request)
event.respondWith(
caches.match(event.request).then((res) => {
// console.log(res, 'cache store 里面的数据')
return (
res ||
fetch(event.request)
.then((responese) => {
const responeseClone = responese.clone()
caches.open('v1').then((cache) => {
cache.put(event.request, responeseClone)
})
return responese
})
.catch((err) => {
console.log(err)
})
)
})
)
})
通过Fetch事件拦截所有请求。在通过caches对象下面的match进行匹配。有就直接返回没有就发起请求。再将请求放入cache storage中。
缓存优先级这一块浅浅看了一下,内存缓存 => service woker => disk cache =>cdn