'Firebase messaging warning messages on service worker install process

I'm using firebase for push web notifications, my file firebase-messaging-ws.js is something like this:


importScripts('https://www.gstatic.com/firebasejs/7.19.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/7.19.0/firebase-messaging.js');

    
fetch('./firebase-data.json')
.then(r => r.json())
.then(fbData => {
    let app = firebase.initializeApp(fbData);    
    firebase.messaging(app);
    console.log('Firebase Service Worker loaded for projectId:', fbData.projectId);
}).catch(err => {
    console.error('Error configuring firebase messaging: ', err)
});

I'm using a json file, firebase-data.json to load the firebase configuration data and It works, I can receive push notifications, however several log warnings appear in the console when I call to firebase.messaging(), If I use a local object (without fetch() command) then all works OK and there is no warning messages.

The log messages are like Event handler of 'XXX' event must be added on the initial evaluation of worker script.: enter image description here

Can I avoid the warning messages when I use an external file to load the firebase configuration data ?



Solution 1:[1]

Basically a service worker script requires synchronous execution, meaning you can't initialize Firebase Messaging within a promise.

Spitballing here, this is untested, but try this:

importScripts('https://www.gstatic.com/firebasejs/7.19.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/7.19.0/firebase-messaging.js');

const response = await fetch('./firebase-data.json');
const fbData = await response.json();

let app = firebase.initializeApp(fbData);    
firebase.messaging(app);
console.log('Firebase Service Worker loaded for projectId:', fbData.projectId);

Alternatively, if it doesn't like await outside of an async function, use JavaScript to export your config data and use importScripts to expose it to your service worker:

firebase-data.js

const fbData = {...};

firebase-messaging-ws.js

importScripts('https://www.gstatic.com/firebasejs/7.19.0/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/7.19.0/firebase-messaging.js');
importScripts('./firebase-data.js');

let app = firebase.initializeApp(fbData);    
firebase.messaging(app);
console.log('Firebase Service Worker loaded for projectId:', fbData.projectId);

Solution 2:[2]

As the other answer explains, moving the fbData to a js file allow the variable to be used inside the Service Worker script.

Just for the record, I did all of this to share the Firebase data between the Service Worker scope and the Angular application scope, The firebase-data.js is something like this:


const FIREBASE_DATA = {
    "apiKey": "***********",
    "authDomain": "***********.firebaseapp.com",
    "databaseURL": "https://***********.firebaseio.com",
    "projectId": "***********",
    "storageBucket": "***********.appspot.com",
    "messagingSenderId": "***********",
    "appId": "1:***************"
}


if (typeof module !== 'undefined') {
    module.exports = { ...FIREBASE_DATA }
}

With this implementation I can use self.FIREBASE_DATA inside the service worker file and I can also import the module in my angualr app, por instance mi environment.ts is something like:

import FIREBASE_DATA from "../firebase-data";

export const environment = {
  production: true,
  url_base: '/api',
  firebase: FIREBASE_DATA
};

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Brian Burton
Solution 2