Reputation: 22916
I'm trying to integrate firebase messaging into my NextJS web app but getting errors that potentially look like they're coming from the serverside. To get registrations working in _app.tsx I do the following:
useEffect(() => {
if ("serviceWorker" in navigator) {
window.addEventListener("load", function () {
const config = process.env.NEXT_PUBLIC_FIREBASE;
navigator.serviceWorker.register("/firebase-messaging-sw.js?firebaseConfig=" + Buffer.from(config).toString('base64'), {
type: 'module'
}).then(
function (registration) {
console.log("Service Worker registration successful with scope: ", registration.scope);
},
function (err) {
console.log("Service Worker registration failed: ", err);
}
);
});
}
}, [])
Where NEXT_PUBLIC_FIREBASE is the firebase config object.
Then in public/firebase-messaging-sw.js I have this:
import { initializeApp } from "https://www.gstatic.com/firebasejs/9.8.1/firebase-app.js";
import { getMessaging } from "https://www.gstatic.com/firebasejs/9.8.1/firebase-messaging.js";
const swScriptUrl = new URL(self.location);
const base64Config = swScriptUrl.searchParams.get('firebaseConfig')
let decoded = atob(base64Config);
const firebaseConfig = JSON.parse(decoded);
const app = initializeApp(firebaseConfig);
// Retrieve an instance of Firebase Messaging so that it can handle background
const messaging = getMessaging(app);
When getMessaging is called I get this error:
Uncaught SyntaxError: Cannot use import statement outside a module (at firebase-messaging-sw.js:1:1)
index.esm2017.js?f614:823 Uncaught (in promise) FirebaseError: Messaging: We are unable to register the default service worker. Failed to register a ServiceWorker for scope ('http://localhost:3000/firebase-cloud-messaging-push-scope') with script ('http://localhost:3000/firebase-messaging-sw.js'): ServiceWorker script evaluation failed (messaging/failed-service-worker-registration).
at registerDefaultSw (index.esm2017.js?f614:823:1)
at async updateSwReg (index.esm2017.js?f614:847:1)
at async getToken$1 (index.esm2017.js?f614:910:1)
at async FirebaseMessagingWeb.getToken (web.js?00d2:24:1)
registerDefaultSw @ index.esm2017.js?f614:823
Promise.then (async)
asyncGeneratorStep @ ios-notification.ts?89f7:2
_next @ ios-notification.ts?89f7:2
eval @ ios-notification.ts?89f7:2
eval @ ios-notification.ts?89f7:2
addListeners @ ios-notification.ts?89f7:4
eval @ notification-context.tsx?dccb:38
Promise.then (async)
registerForNotifications @ notification-context.tsx?dccb:37
registerForNotifications @ notification-context.tsx?dccb:62
onClick @ profile-box.tsx?a1b7:280
callCallback @ react-dom.development.js?ac89:4161
invokeGuardedCallbackDev @ react-dom.development.js?ac89:4210
invokeGuardedCallback @ react-dom.development.js?ac89:4274
invokeGuardedCallbackAndCatchFirstError @ react-dom.development.js?ac89:4288
executeDispatch @ react-dom.development.js?ac89:9038
processDispatchQueueItemsInOrder @ react-dom.development.js?ac89:9070
processDispatchQueue @ react-dom.development.js?ac89:9083
dispatchEventsForPlugins @ react-dom.development.js?ac89:9094
eval @ react-dom.development.js?ac89:9285
batchedUpdates$1 @ react-dom.development.js?ac89:26096
batchedUpdates @ react-dom.development.js?ac89:3988
dispatchEventForPluginEventSystem @ react-dom.development.js?ac89:9284
dispatchEventWithEnableCapturePhaseSelectiveHydrationWithoutDiscreteEventReplay @ react-dom.development.js?ac89:6462
dispatchEvent @ react-dom.development.js?ac89:6454
dispatchDiscreteEvent @ react-dom.development.js?ac89:6427
firebase-messaging-sw.js:1 Uncaught SyntaxError: Cannot use import statement outside a module (at firebase-messaging-sw.js:1:1)
I've checked the config object and it definitely is correct and making it to the service worker (also tried just copying the config in to no avail).
Have tried getting this to work both locally and on a https server to no avail, I've also tried a none module import which produced the same error.
Upvotes: 5
Views: 6609
Reputation: 21
The current newest importScripts firebase with firebase-messaging-sw.js using Next.js + next-pwa, is working for me on Windows and Android out of the box. For macOS, you need to enable Chrome notifications in the System Preferences. Note: I haven't tested iOS yet, but it should work. I hope it helps someone. Good luck
//public/firebase-messaging-sw.js
importScripts('https://www.gstatic.com/firebasejs/10.10.0/firebase-app-compat.js');
importScripts('https://www.gstatic.com/firebasejs/10.10.0/firebase-messaging-compat.js');
firebase.initializeApp({
apiKey: "...",
authDomain: "...",
projectId: "...",
storageBucket: "...",
messagingSenderId: "...",
appId: "...",
measurementId: "..."
});
// firebase.initializeApp(firebaseConfig);
const messaging = firebase.messaging();
messaging.onBackgroundMessage((payload) => {
console.log(
"[firebase-messaging-sw.js] Received background message ",
payload
);
const notificationTitle = payload.notification.title;
const notificationOptions = {
body: payload.notification.body,
icon: payload.notification.image,
};
self.registration.showNotification(notificationTitle, notificationOptions);
});
Upvotes: 1
Reputation: 31
This work for me
importScripts(
'https://www.gstatic.com/firebasejs/9.18.0/firebase-app-compat.js'
);
importScripts(
'https://www.gstatic.com/firebasejs/9.18.0/firebase-messaging-compat.js'
);
var FIREBASE_CONFIG = {
apiKey: "...",
authDomain: "...",
projectId: "...",
storageBucket: "...",
messagingSenderId: "...",
appId: "...",
measurementId: "...",
};
// Initialize Firebase
firebase.initializeApp(FIREBASE_CONFIG);
const messaging = firebase.messaging();
Upvotes: 2
Reputation: 307
The same thing happened to me, the first is to use importScripts , and the second is to downgrade to 8.0.0 and change the function calls a bit. As I show you below:
importScripts("https://www.gstatic.com/firebasejs/8.0.0/firebase-app.js");
importScripts("https://www.gstatic.com/firebasejs/8.0.0/firebase-messaging.js");
const swScriptUrl = new URL(self.location);
const base64Config = swScriptUrl.searchParams.get('firebaseConfig')
let decoded = atob(base64Config);
const firebaseConfig = JSON.parse(decoded);
const app = firebase.initializeApp(firebaseConfig);
// Retrieve an instance of Firebase Messaging so that it can handle background
const messaging = firebase.messaging();
Upvotes: 4