Notification issues in Vue with Firebase Cloud Messaging while in foreground

I have been working on implementing FCM in my Vue PWA application. I have successfully configured background notifications, but I am facing issues with handling notifications when the app is open. Here is the code I am using.

src/App.vue

import firebase from './plugins/firebase'

export default {
  // Other content...

  methods: {
    prepareFcm () {
      var messaging = firebase.messaging()
      messaging.usePublicVapidKey(this.$store.state.fcm.vapidKey)
      messaging.getToken().then(async fcmToken => {
        this.$store.commit('fcm/setToken', fcmToken)
        messaging.onMessage(payload => {
          window.alert(payload)
        })
      }).catch(e => {
        this.$store.commit('toast/setError', 'An error occurred while processing push notification.')
      })
    }
  },

  mounted () {
    this.prepareFcm()
  }
}

public/firebase-messaging-sw.js

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

firebase.initializeApp({
  messagingSenderId: '123456789'
})

const messaging = firebase.messaging()

messaging.setBackgroundMessageHandler(function (payload) {
  return self.registration.showNotification(payload)
})

src/plugins/firebase.js

import firebase from '@firebase/app'
import '@firebase/messaging'
// import other firebase libraries...

const firebaseConfig = {
  apiKey: '...',
  authDomain: '...',
  databaseURL: '...',
  projectId: '...',
  storageBucket: '...',
  messagingSenderId: '123456789',
  appId: '...'
}

firebase.initializeApp(firebaseConfig)

export default firebase

What could be the issue with my setup?

Answer №1

I came across a solution in a previous question and answer on StackOverflow (although I seem to have lost the link).

It turns out that using Firebase API version 7.8.0 is necessary instead of the previously recommended 5.5.6. Therefore, the initial lines in public/firebase-messaging-sw.js should be adjusted as follows:

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

Answer №2

I encountered the same issue recently. The problem was that the firebase version specified in my "package.json" file did not match the version imported in my "firebase-messaging-sw.js" file using importScripts. Once I aligned both versions to be the same as the one in "package.json", the issue was resolved.

Initial setup

 **"package.json"**
 
 "firebase": "^8.2.1",
 
  **"firebase-messaging-sw.js"**

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

Corrected setup

 **"package.json"**

 "firebase": "^8.2.1",

 **"firebase-messaging-sw.js"**

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

Answer №3

I encountered a discrepancy between the version on my package.json (8.2.1) and the actual SDK_VERSION (8.0.1)

Once I updated the service-workers to match the correct version, everything worked smoothly.

Answer №4

Tackling firebase push notifications in Vue 3 (with Vite) was a bit of a challenge for me, especially with PWA support enabled through vite-plugin-pwa. It often felt like navigating blindly through uncharted territory. Despite successfully setting up PWA support, I encountered some persistent issues:

  • Notifications were received in the background but not in the foreground.
  • Background notifications appeared duplicated at times.

Below is my complete setup utilizing the latest version of Firebase (9.12.1) at the time of writing this post:

// Store this file as firebase-messaging-sw.js in public folder
   
importScripts(
      "https://www.gstatic.com/firebasejs/9.12.1/firebase-app-compat.js"
    );
importScripts(
      "https://www.gstatic.com/firebasejs/9.12.1/firebase-messaging-compat.js"
    );
// Initialize Firebase
firebase.initializeApp({
  apiKey: "",
  authDomain: "",
  projectId: "",
  storageBucket: "",
  messagingSenderId: "",
  appId: "",
  measurementId: "",
});
const messaging = firebase.messaging();

    
messaging.onBackgroundMessage(function (payload) {
// Customize notification here
  const notificationTitle = payload.notification.title;
  const notificationOptions = {
  body: payload.notification.body,
  icon: "/icon.png",
};

self.registration.showNotification(notificationTitle, notificationOptions);
});

Suggestions online placed the onBackgroundMessage function in the service worker, but after experimenting and commenting it out, the issue of duplicate notifications seemed to be resolved.

Next, in a file named firebase.js, tokens are retrieved along with listening for foreground notifications:

// Place this firebase.js file alongside main.js
    
import firebase from "firebase/compat/app";
import { getMessaging } from "firebase/messaging";
    
const firebaseConfig = {
  apiKey: "",
  authDomain: "",
  projectId: "",
  storageBucket: "",
  messagingSenderId: "",
  appId: "",
  measurementId: "",
};
    
const app = firebase.initializeApp(firebaseConfig);
export default getMessaging(app);

In main.js:

import App from "./App.vue";
import firebaseMessaging from "./firebase";

const app = createApp(App)
app.config.globalProperties.$messaging = firebaseMessaging; //register as a global property

Lastly, in App.vue (or any desired location for token retrieval and server-side transfer):

import {getToken, onMessage} from "firebase/messaging";

export default {
  mounted() {
    getToken(this.$messaging, {
      vapidKey:
        "XXX-XXX",
    })
      .then((currentToken) => {
        if (currentToken) {
          console.log("client token", currentToken);
          onMessage(this.$messaging, (payload) => {
            console.log("Message received. ", payload);
          });
          
          //send token to server-side
        } else {
          console.log(
            "No registration token available. Request permission to generate one"
          );
        }
      })
      .catch((err) => {
        console.log("An error occurred while retrieving token.", err);
      });
  }
}

Remember to include the necessary vapidKey. It may take some trial and error, but the solution worked smoothly in the end.

As for designing the appearance of foreground notifications, I have refrained from providing an opinion and simply logged the payload. Feel free to customize it to your liking.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Vue 3 template refs doesn't quite mirror the true state of the DOM

I'm working on a website to help users plan study schedules. Currently, I'm developing an Add/Remove subject section which allows users to add, edit, or remove subjects with an id and name. The subjects added will be displayed as a list of <i ...

Once invoked by an ajax request, the $().ready function is executed

The functionality of this code is flawless when running on its own. However, once I make an ajax call to it, the code fails to execute. I suspect that the issue lies within $().ready, but I haven't yet identified a suitable replacement. Any suggestio ...

Guide to profiling resources in Node.js applications

When developing Node.js applications, it's important to keep track of how your code is performing in terms of memory and IO. By monitoring these metrics, you can identify which parts of your code are causing delays or consuming excessive resources. Th ...

Incorporating an offset with the I18nPluralPipe

Having trouble with my multiselect dropdown and the text pluralization. I attempted to use the I18nPluralPipe, but can't seem to set an offset of 1. ListItem = [Lion, Tiger, Cat, Fox] Select 1 Item(Tiger) = "Tiger", Select 3 Item(Tiger, Cat, Fox) = ...

Error: Material-UI X is unable to locate the data grid context

Utilizing the Data Grid Pro feature from Material-UI in my React application. I attempted to craft a personalized toolbar for the DataGridPro component by incorporating the GridToolbarColumnsButton, GridToolbarFilterButton, GridToolbarDensitySelector, and ...

Issue encountered: Inability to implement asynchronous functionality within a forEach loop while making an API request

When making a GET API call, the code looks like this router.get('/review', async (req, res) => { try { const entity = await Entity.find(); const entityId = []; Object.keys(entity).forEach((key) => { entityId.push(entity[ ...

Deciphering the Cause of mapStateToPropsCall in Redux and React

When handling an unsuccessful http call resulting in an error message being displayed, I encounter subsequent state changes triggering multiple render calls. Is there a technique to identify the cause of these state changes and mapStateToProps calls? Alter ...

Can JavaScript be used to dynamically assign events to elements on a webpage?

I am currently using the following code: if ( $.support.touch == true ) { $(window).on('orientationchange', function(event){ if ( full == false ) { self.hideAllPanels("7"); } }); } else { $(window).on(&apo ...

Vue SPA authentication

After following various guides on implementing authentication in my Vue application with a .NET Core API backend, I have some questions. You can check out this guide: https://medium.com/dev-bits/a-guide-for-adding-jwt-token-based-authentication-to-your-si ...

Directive unable to recognize ng-pattern functionality

I am attempting to encapsulate an <input> within a directive in order to manage date validation, conversion from string to Date object, and keep the Date version in the original scope. The functionality seems to be working as intended. However, the n ...

Swapping out bullet points for delicious food icons in an unordered list on an HTML page

I am working with the following code snippet: <div id="instructions"> <h3>Get it done</h3> <ol> <li>In a blender add the eggs, chocolate powder, butter, flour, sugar and milk.</li> <li>Then whisk ...

Ways to navigate through a webpage without encountering any overflow issues

My window is too small to scroll, but I still need the ability to do so. Is it possible to scroll even when the height of the container is not large enough to display the scrollbar? Below is the code I am using to achieve scrolling: setTimeout(function() ...

The Node.js application encounters a blank response when making a GET request to the API

As a newcomer to node.js, I'm attempting to describe the issue at hand as clearly as possible. If clarification is needed, please let me know. In my current node.js project, I am faced with a challenge where I need to take a code received from the re ...

A JavaScript regular expression for identifying IMDB URLs

Could someone please help me identify the issue with this JavaScript code? "http://www.imdb.com/title/tt2618986/".match("~http://(?:.*\.|.*)imdb.com/(?:t|T)itle(?:\?|/)(..\d+)~i"); I tested it here https://regex101.com/r/yT7bG4/1 and it wo ...

Avoiding the need to wait for completion of the jQuery $.get function

Currently, I am executing a basic jQuery GET request as shown below and it is functioning correctly. $.get("http://test.example.com/do-something", function (data) { console.log("test work done"); }); The GET request is initiated without affecting the ...

What is causing the issue with Next.js Json.map function not functioning correctly?

I am looking to develop a basic component that sources its data from a JSON list. While I am able to see the output of console.log(dat.CardId) on the website, it only works for console.log(). I cannot view the cards rendered by the .map function. The sty ...

Is it possible to activate the nearby dropdown based on the user's selection?

On my html webpage, I have a form that consists of three dropdown menus each with different options: The first dropdown (A) includes choices from 1 to 6, as well as 'not set'. The second dropdown (B) allows selections from 1 to 7, and also has ...

Checking the validity of subdomain names using JavaScript/jQuery

For users signing up, my form allows them to choose a subdomain for their account. The valid characters allowed in the subdomain are letters, numbers, and dashes. Spaces and most special characters should be filtered out. http://_________.ourapp.com To r ...

The code is running just fine when tested locally, but it seems to encounter an issue when accessed remotely, yielding

Currently, I am in the process of developing a dual twin setup using a Raspberry Pi. The goal is to simulate a continuous transmission of body temperature data, which is then sent to a server that stores the information in a MongoDB database. Everything fu ...

The submit option fails to appear on the screen in the JsonForm library

I've been using the JsonForm library ( https://github.com/jsonform/jsonform ) to define a form in HTML. I have set up the schema and form of the JsonForm structure, but for some reason, the "onSubmit" function that should enable the send button is not ...