DEV Community

Fima Taf
Fima Taf

Posted on • Updated on

How to add FCM (Firebase Cloud Messaging) to VueJS

Lately I had a task to implement FCM (Firebase Cloud Messaging) to a vue application I am working on, and I've found out that there are few guides but they didn't helped me too much because FCM's API, vue cli and vue it self were updated since then, so I've decided to write down a small and updated guide for it.

Step 1 - Add the service worker file

The first thing that we need to do is to add the service worker file firebase-messaging-sw.js to the public folder (It's important to use this file name because firebase will look for this file with that specific name, it can be changed tough but not in this guide - sorry).
(If you are not familiar with the words 'service worker' you can learn more about it Here or Here)

//firebase-messaging-sw.js

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

var firebaseConfig = {
  apiKey: <API-KEY>,
  authDomain: <AUTH-DOMAIN>,
  projectId: <PROJECT-ID>,
  storageBucket: <STORAGE-BUCKET>,
  messagingSenderId: <MESSAGING-SENDER-ID>,
  appId: <APP-ID>,
  measurementId: <MEASUREMENT-ID>
}

const app = firebase.initializeApp(firebaseConfig)
Enter fullscreen mode Exit fullscreen mode

Replace the config json above with the one you got from firebase
Go to your project home page at firebase -> Press on the Settings icon -> click 'Project Settings' -> Scroll down -> firebaseConfig object

Step 2 - Register the service worker

The next step is to register the service worker.
We have few ways of doing that:

* If you prefer using firebase package jump to Step 3.

* Using vue cli's PWA plugin

If you've created your application through vue cli (v3+) and you've added the PWA support option (or added this plugin manually after the installation) you can register the service worker with registerServiceWorker.js file as follows:

//registerServiceWorker.js

import { register } from 'register-service-worker'

register('firebase-messaging-sw.js')
Enter fullscreen mode Exit fullscreen mode

You can learn more about the above plugin and its events Here

* Using vanilla JS

If you prefer to register the service worker using only JS, you can add the following code (anywhere in your application):

if ('serviceWorker' in navigator) {
  navigator.serviceWorker.register('firebase-messaging-sw.js')
    .then(reg => {
      console.log(`Service Worker Registration (Scope: ${reg.scope})`);
    })
    .catch(error => {
      const msg = `Service Worker Error (${error})`;
      console.error(msg);
    });
} else {
  // happens when the app isn't served over HTTPS or if the browser doesn't support service workers
  console.warn('Service Worker not available');
}
Enter fullscreen mode Exit fullscreen mode

Step 3 - Using firebase module

Another way to register the service worker and subscribe to FCM is by installing the firebase package.
npm install firebase
After you've installed the package, create a file called firebase.js (or any other name you want) and add the following:

//firebase.js

import firebase from 'firebase/app'
import 'firebase/firebase-messaging'

var firebaseConfig = {
  apiKey: <API-KEY>,
  authDomain: <AUTH-DOMAIN>,
  projectId: <PROJECT-ID>,
  storageBucket: <STORAGE-BUCKET>,
  messagingSenderId: <MESSAGING-SENDER-ID>,
  appId: <APP-ID>,
  measurementId: <MEASUREMENT-ID>
}

firebase.initializeApp(firebaseConfig)

export default firebase.messaging()
Enter fullscreen mode Exit fullscreen mode

Why do I need to instanciate firebase again? I already did it on step 1...

Because the service worker is running on another thread and not on the main one, therefor we cannot pass the instance to our main application.

Add FCM in vue 2

To add FCM as a global in your vue 2 application go to your main.js file and add the following:

//main.js

...
import firebaseMessaging from './firebase'

Vue.prototype.$messaging = firebaseMessaging

new Vue({
...
Enter fullscreen mode Exit fullscreen mode

Now you can access FCM instance everywhere in your application by calling this.$messaging.

Add FCM in vue 3

Add as a global

You can add FCM as a global in vue 3 but then it won't be accessible in composition's API setup() method.

//main.js

...
import firebaseMessaging from './firebase'

const app = createApp(App)

app.config.globalProperties.$messaging = firebaseMessaging

app.mount('#app')
Enter fullscreen mode Exit fullscreen mode

Now you can call it in every component:

//RandomComponent.vue

...
  mounted () {
    console.log('Firebase cloud messaging object', this.$messaging)
  }
...
Enter fullscreen mode Exit fullscreen mode

Use Provide/Inject

Another way that vue 3 is providing to pass data is the Provide/Inject feature. (You can learn more about it Here)
In your App.vue (or any other component you want the 'Super Parent' to be) add the following:

//App.vue

...
<script>
import { provide } from 'vue'
import firebaseMessaging from './firebase'

export default {
  //options api
  provide: {
    messaging: firebaseMessaging
  }
  //composition api
  setup() {
    provide('messaging', firebaseMessaging)
  }
}
</script>
...
Enter fullscreen mode Exit fullscreen mode

And Now you can call it by injecting it into any child component you want, for example:

//RandomChildComponent.vue

...
<script>
import { inject } from 'vue'

export default {
  //options api
  inject: ['messaging'],
  mounted () {
    console.log('Firebase cloud messaging object', this.$messaging)
  }
  //composition api
  setup() {
    const messaging = inject('messaging')

    console.log('Firebase cloud messaging object', messaging)
  }
}
</script>
...
Enter fullscreen mode Exit fullscreen mode

Step 4 - Subscribe

After the service worker has been registered we can subscribe our client to FCM by calling the getToken() function.
Go back to firebase-messaging-sw.js (if you used step 2) or call firebase's messaging object (if you used step 3) and add the following code:

...
//firebase-messaging-sw.js (step 2)
app.messaging().getToken({ vapidKey: <KEY> })

//RandomChildComponent.vue (step 3)
messaging.getToken({ vapidKey: <KEY> })
...
Enter fullscreen mode Exit fullscreen mode

To get the vapidKey go to firebase console:

Go to your project home page at firebase -> Press on the Settings icon -> click 'Project Settings' -> 'Cloud Messaging' tab -> 'Web configuration' > 'Web Push certificates'

  • In case you want to get the specific token of each client you can add the following to your getToken() function:
app.messaging().getToken({ vapidKey: <KEY> })
.then((currentToken) => {
  if (currentToken) {
    console.log('client token', currentToken)
  } else {
    console.log('No registration token available. Request permission to generate one.');
  }
}).catch((err) => {
  console.log('An error occurred while retrieving token. ', err);
})
Enter fullscreen mode Exit fullscreen mode
In case you used step 3 (firebase package) getToken() method will also register the service worker for you.

The getToken() function will subscribe to FCM and since this moment your client will get push notification from FCM. yey :)

Hope it helped you somehow, enjoy :)

Discussion (15)

Collapse
devsmk profile image
S M Khalilullah

Thanks a lot!

I could be able to complete all the steps successfully following this article.

Collapse
abdullahch profile image
M.Abdullah Ch

I am getting an error

ERROR  Failed to compile with 1 error                                         1:17:23 AM

This dependency was not found:

* https://www.gstatic.com/firebasejs/9.6.3/firebase-app.js in ./node_modules/firebase/firebase-messaging.js

To install it, you can run: npm install --save https://www.gstatic.com/firebasejs/9.6.3/firebase-app.js
Enter fullscreen mode Exit fullscreen mode
Collapse
sdenman profile image
SimonD

Hi,
I'm getting this too - on build.
Do you remember how you fixed it - assuming you did :)
Thanks

Collapse
devsmk profile image
S M Khalilullah

This is due to a firebase npm package version 9 bug.
Solution: steps-

  1. npm uninstall firebase
  2. npm install firebase@8.10.0
Collapse
vbanditv profile image
Fima Taf Author

Are you trying to install firebase npm package? If you do, then what is the version ?

Collapse
shalemperez profile image
Shalem Pérez

How can i get access to the generated "currentToken" in vue ?

Collapse
vbanditv profile image
Fima Taf Author

Hey,
You can call the getToken() function again - you will get the registered token.

Collapse
watsonc profile image
Watson-Halu • Edited on

Hello,
Is it necessary to put firebase.js in a specific folder on step 3?
Can you give me the advice to tell me should put this file (firebase.js) in which folder?

Collapse
vbanditv profile image
Fima Taf Author

Hey, you can place the firebase.js file where-ever you want, you can even place the content of the file inside main.js and delete firebase.js.

Collapse
twt_aliso profile image
AliSo

Hi Fima!
How to post currentToken to some API by axios?
I cannot use import statement outside vue module!

Collapse
vbanditv profile image
Fima Taf Author

Hey,
I guess you are trying to send the request from the service worker and not from the app itself, as far as I know you can't access axios inside service workers - but you can use fetch instead:

//firebase-messaging-sw.js
...
messaging.getToken({ vapidKey: <KEY> }).then((currentToken) => {
if (currentToken) {
    fetch('http://some.api', {
      method: 'GET',
    })
    .then(function (data) {
      console.log('Request Succeeded: ', data);
    })
    .catch(function (error) {
      console.log('Request Failed: ', error);
    });
  }
...
Enter fullscreen mode Exit fullscreen mode
Collapse
flosegueda profile image
Moises Flores

it is necessary to import something to use messaging.getToken in Step 4 ?

Collapse
devsmk profile image
S M Khalilullah

Yes, you need to import firebaseMessaging from the src/firebase.js file. Then you can use it like firebaseMessaging.getToken()

Collapse
adamfilk profile image
Aung Chan Oo

How to subscribe to specific topics with this approach bro? Thanks in advance.

Collapse
izazkhattak profile image
izazkhattak

Step3, firebase.js code throw an error like this, why?