关于博客对接Firebase的无奈失败,做一个总结。

424 阅读2分钟

我自己觉得推送功能是一个应用非常重要的部分。我也想给我的博客加一个消息推送的功能。目前市面上消息推送做的最好的应该就是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中。

截屏2023-09-03 12.29.07.png

截屏2023-09-03 12.29.16.png

缓存优先级这一块浅浅看了一下,内存缓存 => service woker => disk cache =>cdn