I try to migrate my chrome-extension from manifest version 2 to v3, and was wondering if it is possible to use FCM in chrome extension Manifest version 3.
As I could not find helpful documentation/guides on this topic, I hope this thread will also be helpful to others.
In manifest version 2 I use the following code:
firebase-messaging-sw.js:
import { initializeApp } from "firebase/app";
import { getMessaging, onBackgroundMessage } from "firebase/messaging/sw";
const firebaseConfig = {
apiKey: "<api-key>",
authDomain: "<auth-domain>",
projectId: "<project-id>",
storageBucket: "<storage-bucket>",
messagingSenderId: "<messaging-sender-id>",
appId: "<app-id>",
};
// Initialize Firebase
initializeApp(firebaseConfig);
const messaging = getMessaging();
onBackgroundMessage(messaging, async (payload) => {
console.log('[firebase-messaging-sw.js] Received background message ', payload);
const allClients = await self.clients.matchAll({ includeUncontrolled: true, type: 'all' })
allClients.forEach((client: any) => {
client.postMessage({ type: 'msg_type', payload });
});
});
In the background.js (now my SW):
if ('serviceWorker' in navigator) {
const firebaseConfig = {
apiKey: "<api-key>",
authDomain: "<auth-domain>",
projectId: "<project-id>",
storageBucket: "<storage-bucket>",
messagingSenderId: "<messaging-sender-id>",
appId: "<app-id>",
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
// Initialize Firebase Cloud Messaging and get a reference to the service
const messaging = getMessaging(app);
getToken(messaging, { vapidKey: "<vapid-key>" })
.then((registrationToken: string) => {
onMessage(messaging, async (payload) => {
//doSomething
});
});
navigator.serviceWorker.addEventListener('message', async (message: MessageEvent) => {
if (message.data.type === 'msg_type') {
//doSomething
}
});
}
I try to follow this guide, and other related threads/videos,
But there is no guide for firebase-messaging-sw.js or other alternatives that I have found.
Hope you can help with this.
Related
I am trying to add Cloud messaging feature in my project but facing this messaging.getToken() error which I am trying to solve from last 6 hours. Please help.
Thank you
== file firebase.js
import { getMessaging, getToken } from "firebase/messaging";
export const requestPermission = () => {
Notification.requestPermission()
.then( permission => {
if (permission === 'granted') {
messaging.getToken()
.then(currToken => console.log(currToken))
.catch(err => console.log(err))
}
})
.catch(err => console.log(err))
}
== file main.js
<button onClick={requestPermission}>
<p> New Task </p>
</button>
== file firebase-messaging-sw.js
importScripts('https://www.gstatic.com/firebasejs/6.2.3/firebase-app.js');
importScripts('https://www.gstatic.com/firebasejs/6.2.3/firebase-messaging.js');
// Your web app's Firebase configuration
const firebaseConfig = {
apiKey: "My api key",
authDomain: "my domain name",
projectId: "my project id",
storageBucket: "my storage bucket address",
messagingSenderId: "id",
appId: "my app Id"
};
// Initialize Firebase
const app = initializeApp(firebaseConfig);
// Initialize Firebase Cloud Messaging
export const messaging = getMessaging();
export default app;
I have followed the steps according to the firebase docs and also one video on youtube, but still have this error TypeError: WEBPACK_IMPORTED_MODULE_2__.messaging.getToken is not a function
I'm new to react-native and JS. My project is a chat app and I'm trying to create button that onPress creating new chat, using the following function:
const createChat = async () =>{
await db
.collection("chats")
.add({
chatName: input,
})
.then(() => {
navigation.goBack();
})
.catch((error) => alert(error));
}
this my firebase.js file:
import firebase from 'firebase/compat/app';
import 'firebase/compat/auth';
import 'firebase/compat/firestore';
import 'firebase/compat/database';
const firebaseConfig = {
apiKey: "*",
authDomain: "*",
projectId: "*",
storageBucket: "*",
messagingSenderId: "*",
appId: "*",
measurementId: "*"
};
let app;
if (firebase.apps.length === 0){
app = firebase.initializeApp(firebaseConfig);
} else {
app = firebase.app();
}
const db = firebase.app();
const auth = firebase.auth();
export {db , auth};
const db = firebase.app(); // an instance of FirebaseApp
should be
const db = firebase.firestore(); // an instance of Firestore
Instead of learning using the compatibility library, consider learning the new Modular SDK instead as this will be the way forward.
I'm very new to next.js, and I'm developing an API with it, side that API I want to use firebase, so I set up firebase but when I try to call it, this error appears: "unhandledRejection: ReferenceError: Cannot access 'firestore' before initialization"
Code below.
Firebase config file
import firebase from 'firebase/app';
import "firebase/firestore";
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
const firebaseConfig = {
apiKey: "*******",
authDomain: "********",
projectId: "*****",
storageBucket: "*****",
messagingSenderId: "****",
appId: "****",
measurementId: "****"
};
//if(!firebase.apps.length){
//}
firebase.initializeApp(firebaseConfig);
const firestore = firebase.firestore();
export { firestore };
Firestore service
import { firestore } from './firebase';
export class Firestore {
async getOne(collection, uid){
const data = await firestore.collection(`${collection}/${uid}`).get();
return await data.docs();
}
}
API page
import {Firestore} from '../../utils/firestore';
const firestore = new Firestore();
const getBanners = () => {
return firestore.getOne('settings','client');
//return data;
}
export default function Handler(req,res){
res.status(200).json({
'name':"getBanners",
'data': getBanners()
});
}
I solved this issue by adding import firebase from 'firebase/compat/app'; and also import 'firebase/compat/firestore';. And works!
I've been working on integrating FCM in my Vue PWA app. So far I've managed to get the background notification working, but handling notifications when the app's on the foreground doesn't work. Here's my code.
src/App.vue
import firebase from './plugins/firebase'
export default {
// Other stuff here...
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 occured to 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 stuff...
const firebaseConfig = {
apiKey: '...',
authDomain: '...',
databaseURL: '...',
projectId: '...',
storageBucket: '...',
messagingSenderId: '123456789',
appId: '...'
}
firebase.initializeApp(firebaseConfig)
export default firebase
What did I do wrong?
I've found a solution in another QA here in StackOverflow (which I can't find anymore for some reason).
Turns out you have to use Firebase API v7.8.0 instead of 5.5.6 like the docs said at the time. So those first two lines in public/firebase-messaging-sw.js should read like this instead:
importScripts('https://www.gstatic.com/firebasejs/7.8.0/firebase-app.js')
importScripts('https://www.gstatic.com/firebasejs/7.8.0/firebase-messaging.js')
Same issue i was faced. In my case firebase version in "package.json" and "firebase-messaging-sw.js" importScripts version was different. After set same version in "firebase-messaging-sw.js" importScripts which was in
"package.json", my issue is resolved.
Before change
**"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');
After change
**"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');
In my case the version on package.json (8.2.1) was different from the actual SDK_VERSION (8.0.1)
After changed service-workers with the same version worked..
I had a bunch of issues setting firebase push notifications for Vue 3 (with Vite), and I had PWA support enabled with vite-plugin-pwa, so it felt like I was flying blind half the time. I was finally able to set up support for PWA, but then I ran into the following issues:
I was getting notifications in the background (when my app was not in focus), but not in the foreground.
When I did get notifications in the background, it appeared twice.
Here's my complete setup. I have the latest firebase as of this post (9.12.1)
// firebase-messaging-sw.js file in the 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);
});
I've seen some posts online provide the onBackgroundMessage here in the service worker, but I experimented with commenting it out and it seemed to fix the issue of notifications appearing twice.
Next, is a firebase.js file with which I retrieve tokens and subsequently listen for foreground notifications.
// firebase.js in same location with 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);
And then 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
And finally, in App.vue (or wherever you wish to get tokens and send to your serverside)...
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);
});
}
}
Of course don't forget the vapidKey. Took a minute, but it worked perfectly.
For now, I am not offering any opinion as to what the foreground notification should look like, so I am merely logging the payload. But feel free to show it however you deem fit.
I want to enable offline data in my project.
I found the right code for this but I don't know where to implement the code
I implement the code inside the firebaseConfig.js file:
import firebase from 'firebase'
import 'firebase/firestore'
// firebase init
// init code goes here
var config = {
apiKey: '',
authDomain: '',
databaseURL: '',
projectId: '',
storageBucket: '',
messagingSenderId: ''
}
firebase.initializeApp(config)
firebase.firestore().enablePersistence()
.then(function () {
// Initialize Cloud Firestore through firebase
var db = firebase.firestore();
})
.catch(function (err) {
console.log(err)
})
// firebase utils
const db = firebase.firestore()
const oldRealTimeDb = firebase.database()
const auth = firebase.auth()
const currentUser = auth.currentUser
// date issue fix according to firebase
const settings = {
timestampsInSnapshots: true
}
db.settings(settings)
// firebase collections
const usersCollection = db.collection('users')
const postsCollection = db.collection('posts')
export {
db,
auth,
currentUser,
postsCollection,
usersCollection
}
main.js
import Vue from 'vue'
import App from './App.vue'
import router from './router'
import {store} from './store'
import './registerServiceWorker'
import Vuetify from 'vuetify'
import 'vuetify/dist/vuetify.min.css' // Ensure you are using css-loader
const fb = require('./firebaseConfig.js')
Vue.config.productionTip = false
export const bus = new Vue()
Vue.use(Vuetify)
let app
fb.auth.onAuthStateChanged(user => {
if (!app) {
app = new Vue({
el: '#app',
store,
router,
template: '<App/>',
components: {
App
},
render: h => h(App)
}).$mount('#app')
}
})
I got this error:
The sample code provided in the documentation suggests that you should call enablePersistence() and possibly make note if it fails for some given reason:
firebase.initializeApp({
apiKey: '### FIREBASE API KEY ###',
authDomain: '### FIREBASE AUTH DOMAIN ###',
projectId: '### CLOUD FIRESTORE PROJECT ID ###',
});
firebase.firestore().enablePersistence()
.catch(function(err) {
if (err.code == 'failed-precondition') {
// Multiple tabs open, persistence can only be enabled
// in one tab at a a time.
// ...
} else if (err.code == 'unimplemented') {
// The current browser does not support all of the
// features required to enable persistence
// ...
}
});
Subsequent queries after calling enablePersistence() will be internally queued until it fully completes, which means that the query may or may not be using locally cached data, depending on the result of enablePersistence(). If it's important to your app to be able to use local persistence, you may wish to wait on its result (triggering on the returned promise) before performing the query.
Just remove the second firebase.firestore() and call the enablePersistence as follows:
import firebase from 'firebase'
import 'firebase/firestore'
// firebase init
// init code goes here
var config = {
apiKey: '',
authDomain: '',
databaseURL: '',
projectId: '',
storageBucket: '',
messagingSenderId: ''
}
firebase.initializeApp(config)
const db = firebase.firestore();
const auth = firebase.auth();
const currentUser = auth.currentUser;
// date issue fix according to firebase
const settings = {
timestampsInSnapshots: true
};
db.settings(settings);
db.enablePersistence();
// firebase utils
//const db = firebase.firestore() // <---- Remove this line
const oldRealTimeDb = firebase.database()
const auth = firebase.auth()
const currentUser = auth.currentUser