Can i use service worker caching function in firebase-messaging-sw.js?

核能气质少年 提交于 2020-01-25 06:49:12

问题


So I want to cache my web app assets in a service worker, but I already have firebase messaging SW, can I put my code there or create a new service worker?


回答1:


This is what worked for me: - create two service workers: sw.js (for caching and fetch handler) and the firebase-messaging-sw.js

  • as mentioned, sw.js will handle your caching. DO NOT create a "push" or "notificationclick" handler in sw.js

  • create your "push" and "notificationclick" handlers in firebase-messaging-sw.js. I do NOT call any firebase instantiating code in firebase-messaging-sw.js, and I DO NOT use the firebase messaging object or the setBackgroundMessageHandler method. I only use the "push" and "notificationclick" handlers. Reason for this is that if you instantiate the firebase messaging sdk in your app, it will automatically look for and install firebase-messaging-sw.js, and by putting your "push" handler there, you're golden.

  • I only register "sw.js". The firebase sdk will automatically register firebase-messaging-sw.js when you initialize it.

index.html:

    <!-- Firebase App (the core Firebase SDK) is always required and must be listed first -->
  <script src="https://www.gstatic.com/firebasejs/7.5.0/firebase-app.js"></script>
  <!-- Add Firebase products that you want to use -->
  <script src="https://www.gstatic.com/firebasejs/7.5.0/firebase-messaging.js"></script>
  <script>
    // Your web app's Firebase configuration
    var firebaseConfig = {...config props...};
    // Initialize Firebase
    firebase.initializeApp(firebaseConfig);
    var messaging = firebase.messaging();

    // Project Settings => Cloud Messaging => Web Push certificates

      //REGISTER SERVICE WORKER
    window.addEventListener('load', () => {
        if ('serviceWorker' in navigator) {
        navigator.serviceWorker.register('sw.js').then(function(swReg) {  
          return navigator.serviceWorker.ready;
        })
        .catch(function(error) {
          console.error('Service Worker Error', error);
        });
      }
   });

sw.js:

(function(){
  //IMPORTANT: DO NOT use this service worker for push!! That is handled in firebase-messaging-sw.js
  var cache_v = '1.0.43';
  var cache_list = [...];

  self.addEventListener('install', function(e) {...});

  // intercept network requests:
  self.addEventListener('fetch', function(event) {...});

  // delete unused caches
  self.addEventListener('activate', function(e) {...});

  self.addEventListener('sync', function(event) {...});
})();

firebase-messaging-sw.js:

(function(){ 
  self.addEventListener('push', function(event) {
    let title = "Push Default Title";
    let options = {};
    const fallback_url = "https://www.[yourdomain.com]"; //used clicking "see all"

    //promise for parsing json. firebase will send over json, but other push services, incl chrome's serviceworker push test, may just send text.
    const parse_payload = (payload_obj) => {
      return new Promise((resolve, reject) => {
        try {
          if(JSON.parse(payload_obj)){ //firebase struct
            let json = JSON.parse(payload_obj);
            if(json.hasOwnProperty("notification")){ //resolve to this only if notification is a property. otherwise reject
              resolve(json);
            } else {
              reject(payload_obj);
            }
          }
          reject(payload_obj);
        } catch(e){
          reject(payload_obj); //other push is just a text string
        }
      });
    };      

    //struct of event.data.text() is: {"data": {"url (custom options)": [custom value]}, ..., "notification": {"title": "", "body": "", "tag": "campaign_[xxx]"}}
    parse_payload(event.data.text()).then((notif) => {
      title = notif.notification.title; //only resolves if notif.notification exists
      console.log(notif);
      options = {
        body: notif.notification.body,
        icon: './images/push_icon.png',
        badge: './images/notif_badge.png',
        data: {
          url: notif.data.url || fallback_url //would have to change by item
        },
        actions: [{
          action: 'purchase',
          title: 'Purchase'
        }, {
          action: 'see_all',
          title: '...'
        }]
      };

      event.waitUntil(self.registration.showNotification(title, options));
    }, (notif) => {
      options = {
        body: notif,
        icon: './images/push_icon.png',
        badge: './images/notif_badge.png',
        data: {url: fallback_url}
      };

      event.waitUntil(self.registration.showNotification(title, options));
    });
  });

  self.addEventListener('notificationclick', function(event) {
    const url = event.notification.data.url;
    event.notification.close(); //by default, this doesn't even close the notif. need to do that.
    if(!event.action){ //did not click on an action
      if (clients.openWindow && url) {
        event.waitUntil(clients.openWindow(url));
      }
    } else { //action click, as defined in push handler
      switch(event.action){
        case 'purchase':
          if (clients.openWindow && url) {
            event.waitUntil(clients.openWindow(url)); //if clicking purchase, use specific url sent over in push
          }
          break;
        case 'see_all':
          if (clients.openWindow) {
            event.waitUntil(clients.openWindow(fallback_url)); //clicking see all, so send to fallback
          }
          break;
      }
    }
  });
})();

I was going absolutely crazy trying to figure this out, and could not for the life of me get the setBackgroundMessageHandler event to fire, and I wanted to show push notifs even in the foreground. Ultimately the solution above is what worked.



来源:https://stackoverflow.com/questions/58533634/can-i-use-service-worker-caching-function-in-firebase-messaging-sw-js

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!