messaging.onMessage is not a function

I’m trying to create a firebase cloud messaging web app and using the latest SDK. However, I don’t know why, but my code is not working and I’m getting the errors such as: “messaging.onMessage” is not a function. If I’m checking official google repo where they have used firebase-messeging-compat.js instead of regular firebase-messaging.js, it is working fine, but not my code. https://github.com/firebase/quickstart-js/tree/master/messaging Can someone please help me?

<!DOCTYPE html>
<html lang="en">

<head>
  <script type="module">
    // Import the functions you need from the SDKs you need
    import { initializeApp } from "https://www.gstatic.com/firebasejs/9.0.2/firebase-app.js";
    import { getAnalytics } from "https://www.gstatic.com/firebasejs/9.0.2/firebase-analytics.js";
    import { getMessaging } from "https://www.gstatic.com/firebasejs/9.0.2/firebase-messaging.js";
    // TODO: Add SDKs for Firebase products that you want to use
    // https://firebase.google.com/docs/web/setup#available-libraries

    // Your web app's Firebase configuration
    // For Firebase JS SDK v7.20.0 and later, measurementId is optional
    const firebaseConfig = {
      apiKey: "AIzaSyDOVN1qOGzsD6AI-2jA05LpfQIJ5aoCuD4",
      authDomain: "clouding-aa740.firebaseapp.com",
      projectId: "clouding-aa740",
      storageBucket: "clouding-aa740.appspot.com",
      messagingSenderId: "1059589787087",
      appId: "1:1059589787087:web:cdd636057d2a921ccdd6ba",
      measurementId: "G-CD2BEK39LZ"
    };

    // Initialize Firebase
    const app = initializeApp(firebaseConfig);
    const analytics = getAnalytics(app);
    const messaging = getMessaging(app);
    function initFirebaseMessagingRegistration() {
      messaging
      .requestPermission()
      .then(function () {
        messageElement.innerHTML = "Got notification permission";
        console.log("Got notification permission");
        return messaging.getToken();
      })
      .then(function (token) {
        // print the token on the HTML page
        tokenElement.innerHTML = "Token is " + token;
      })
      .catch(function (err) {
        errorElement.innerHTML = "Error: " + err;
        console.log("Didn't get notification permission", err);
      });
    }
    messaging.onMessage(function (payload) {
      console.log("Message received. ", JSON.stringify(payload));
      notificationElement.innerHTML = notificationElement.innerHTML + " " + payload.data.notification;
    });
    messaging.onTokenRefresh(function () {
      messaging.getToken()
      .then(function (refreshedToken) {
        console.log('Token refreshed.');
        tokenElement.innerHTML = "Token is " + refreshedToken;
      }).catch(function (err) {
        errorElement.innerHTML = "Error: " + err;
        console.log('Unable to retrieve refreshed token ', err);
      });
    });

  </script>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Clouding</title>
</head>

<body>
  <main>
    <h1>Welcome to Clouding</h1>
    <div id="token" style="color:lightblue"></div>
    <div id="message" style="color:lightblue"></div>
    <div id="notification" style="color:green"></div>
    <div id="error" style="color:red"></div>
    <script>
      messageElement      = document.getElementById("message")
      tokenElement        = document.getElementById("token")
      notificationElement = document.getElementById("notification")
      errorElement        = document.getElementById("error")
    </script>
    <button onclick="initFirebaseMessagingRegistration()">Enable Firebase Messaging</button>
  </main>
</body>
</html>

Answer

You are using the old syntax but don’t import the compat packages. Change this:

 import { initializeApp } from "https://www.gstatic.com/firebasejs/9.0.2/firebase-app.js";
    import { getAnalytics } from "https://www.gstatic.com/firebasejs/9.0.2/firebase-analytics.js";
    import { getMessaging } from "https://www.gstatic.com/firebasejs/9.0.2/firebase-messaging.js";

to this:

import { initializeApp } from "https://www.gstatic.com/firebasejs/9.0.2/firebase-app-compat.js";
    import { getAnalytics } from "https://www.gstatic.com/firebasejs/9.0.2/firebase-analytics-compat.js";
    import { getMessaging } from "https://www.gstatic.com/firebasejs/9.0.2/firebase-messaging-compat.js";

That way you would import the compat packages. But you are still mixing some of new and old SDK. For example you use getMessaging from the new SDK but try to use messaging.onMessage what is the old SDK.

Pls. Let me know if you want to use the new or old SDK and I can rewriet the whole code to the specific SDK version.

UPDATE:

The code with the new syntax:

// Import the functions you need from the SDKs you need
import { initializeApp } from "https://www.gstatic.com/firebasejs/9.0.2/firebase-app.js";
import { getAnalytics } from "https://www.gstatic.com/firebasejs/9.0.2/firebase-analytics.js";
import { getMessaging } from "https://www.gstatic.com/firebasejs/9.0.2/firebase-messaging.js";
// TODO: Add SDKs for Firebase products that you want to use
// https://firebase.google.com/docs/web/setup#available-libraries

// Your web app's Firebase configuration
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
  apiKey: "AIzaSyDOVN1qOGzsD6AI-2jA05LpfQIJ5aoCuD4",
  authDomain: "clouding-aa740.firebaseapp.com",
  projectId: "clouding-aa740",
  storageBucket: "clouding-aa740.appspot.com",
  messagingSenderId: "1059589787087",
  appId: "1:1059589787087:web:cdd636057d2a921ccdd6ba",
  measurementId: "G-CD2BEK39LZ",
};

// Initialize Firebase
const app = initializeApp(firebaseConfig);
const analytics = getAnalytics(app);
const messaging = getMessaging(app);

function initFirebaseMessagingRegistration() {
  // Don't forget your vapidKey here
  getToken(messaging, { vapidKey: "publicVapidKey" })
    .then((t) => {
      tokenElement.innerHTML = "Token is " + r;
    })
    .catch(function (err) {
      errorElement.innerHTML = "Error: " + err;
      console.log("Didn't get notification permission", err);
    });

  onMessage(messaging, (payload) => {
    console.log("Message received. ", JSON.stringify(payload));
    notificationElement.innerHTML =
      notificationElement.innerHTML + " " + payload.data.notification;
  });