From 2654d762b631224a1eeb309ba7a17ce848a3038c Mon Sep 17 00:00:00 2001 From: iamacook Date: Tue, 8 Aug 2023 18:41:50 +0200 Subject: [PATCH] fix: move to custom `next-pwa` worker --- .gitignore | 1 + next.config.mjs | 5 ++- .../settings/Notifications/index.tsx | 6 +-- src/hooks/useFirebaseNotifications.ts | 44 +++++++++---------- src/services/firebase.ts | 31 ------------- tsconfig.json | 2 +- worker/index.ts | 29 ++++++++++++ 7 files changed, 58 insertions(+), 60 deletions(-) delete mode 100644 src/services/firebase.ts create mode 100644 worker/index.ts diff --git a/.gitignore b/.gitignore index 85fdc04a8a..21b916e6d8 100644 --- a/.gitignore +++ b/.gitignore @@ -51,4 +51,5 @@ yalc.lock /public/sw.js.map /public/workbox-*.js /public/workbox-*.js.map +/public/worker-*.js /public/fallback* \ No newline at end of file diff --git a/next.config.mjs b/next.config.mjs index 722e9f3c76..322dd8e4c7 100644 --- a/next.config.mjs +++ b/next.config.mjs @@ -1,9 +1,10 @@ import path from 'path' import withBundleAnalyzer from '@next/bundle-analyzer' -import NextPwa from'next-pwa' +import NextPwa from 'next-pwa' +// If we disable this, it will also disable the Firebase SW +// @see https://github.com/safe-global/safe-wallet-web/pull/2369/commits/92106a828084a1b25763fb6e3e4aa058e491265b const withPWA = NextPwa({ - disable: process.env.NODE_ENV === 'development', dest: 'public', reloadOnOnline: false, /* Do not precache anything */ diff --git a/src/components/settings/Notifications/index.tsx b/src/components/settings/Notifications/index.tsx index 849489e8d7..28815fc689 100644 --- a/src/components/settings/Notifications/index.tsx +++ b/src/components/settings/Notifications/index.tsx @@ -10,7 +10,6 @@ import useSafeInfo from '@/hooks/useSafeInfo' import useLocalStorage from '@/services/local-storage/useLocalStorage' import { useCurrentChain } from '@/hooks/useChains' import EthHashInfo from '@/components/common/EthHashInfo' -import { getFirebaseSwRegistrationPath } from '@/services/firebase' const NOTIFICATIONS_LS_REGISTRATION_KEY = 'firebaseCloudMessaging' @@ -34,8 +33,9 @@ type RegisterDeviceDto = { } const getFirebaseToken = async () => { - const firebaseSwPath = getFirebaseSwRegistrationPath() - const swRegistration = await navigator.serviceWorker.getRegistration(firebaseSwPath) + const NEXT_PWA_SW_PATH = '/sw.js' + + const swRegistration = await navigator.serviceWorker.getRegistration(NEXT_PWA_SW_PATH) // Get token const messaging = getMessaging() diff --git a/src/hooks/useFirebaseNotifications.ts b/src/hooks/useFirebaseNotifications.ts index 418357e8c9..7600b09c48 100644 --- a/src/hooks/useFirebaseNotifications.ts +++ b/src/hooks/useFirebaseNotifications.ts @@ -4,32 +4,20 @@ import { getMessaging, onMessage } from 'firebase/messaging' import { useAppDispatch } from '@/store' import { showNotification } from '@/store/notificationsSlice' -import { FIREBASE_CONFIG, getFirebaseSwRegistrationPath } from '@/services/firebase' +import { + FIREBASE_API_KEY, + FIREBASE_AUTH_DOMAIN, + FIREBASE_DATABASE_URL, + FIREBASE_PROJECT_ID, + FIREBASE_STORAGE_BUCKET, + FIREBASE_MESSAGING_SENDER_ID, + FIREBASE_APP_ID, + FIREBASE_MEASUREMENT_ID, +} from '@/config/constants' export const useFirebaseNotifications = (): null => { const dispatch = useAppDispatch() - // Register servicer worker - useEffect(() => { - if (typeof window === 'undefined' || !('serviceWorker' in navigator)) { - return - } - - const registerFirebaseSw = () => { - // Firebase normally registers a service worker when calling `getToken` - // but we register it manually to pass custom config from the env - const serviceWorkerPath = getFirebaseSwRegistrationPath() - - navigator.serviceWorker.register(serviceWorkerPath).catch(() => null) - } - - window.addEventListener('load', registerFirebaseSw) - - return () => { - window.removeEventListener('load', registerFirebaseSw) - } - }, []) - // Listen for messages useEffect(() => { if (typeof navigator === 'undefined' || !('serviceWorker' in navigator)) { @@ -37,7 +25,17 @@ export const useFirebaseNotifications = (): null => { } // TODO: Should this be added to the privacy policy? - const _app = initializeApp(FIREBASE_CONFIG) + const _app = initializeApp({ + apiKey: FIREBASE_API_KEY, + authDomain: FIREBASE_AUTH_DOMAIN, + databaseURL: FIREBASE_DATABASE_URL, + projectId: FIREBASE_PROJECT_ID, + storageBucket: FIREBASE_STORAGE_BUCKET, + messagingSenderId: FIREBASE_MESSAGING_SENDER_ID, + appId: FIREBASE_APP_ID, + measurementId: FIREBASE_MEASUREMENT_ID, + }) + const messaging = getMessaging(_app) const unsubscribe = onMessage(messaging, (payload) => { diff --git a/src/services/firebase.ts b/src/services/firebase.ts deleted file mode 100644 index 9863142a98..0000000000 --- a/src/services/firebase.ts +++ /dev/null @@ -1,31 +0,0 @@ -import { - FIREBASE_API_KEY, - FIREBASE_AUTH_DOMAIN, - FIREBASE_DATABASE_URL, - FIREBASE_PROJECT_ID, - FIREBASE_STORAGE_BUCKET, - FIREBASE_MESSAGING_SENDER_ID, - FIREBASE_APP_ID, - FIREBASE_MEASUREMENT_ID, -} from '@/config/constants' - -// TODO: Add these and VAPID_KEY to README.md -export const FIREBASE_CONFIG = { - apiKey: FIREBASE_API_KEY, - authDomain: FIREBASE_AUTH_DOMAIN, - databaseURL: FIREBASE_DATABASE_URL, - projectId: FIREBASE_PROJECT_ID, - storageBucket: FIREBASE_STORAGE_BUCKET, - messagingSenderId: FIREBASE_MESSAGING_SENDER_ID, - appId: FIREBASE_APP_ID, - measurementId: FIREBASE_MEASUREMENT_ID, -} - -export const FIREBASE_SW_PATH = '/firebase-messaging-sw.js' - -export const getFirebaseSwRegistrationPath = (): string => { - const config = new URLSearchParams(FIREBASE_CONFIG).toString() - - // Service workers don't conflict as they are registered with params - return `${FIREBASE_SW_PATH}?${config}` -} diff --git a/tsconfig.json b/tsconfig.json index 045cbd3169..cb1274960b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -1,7 +1,7 @@ { "compilerOptions": { "target": "es2015", - "lib": ["dom", "dom.iterable", "esnext"], + "lib": ["dom", "dom.iterable", "esnext", "webworker"], "allowJs": true, "skipLibCheck": true, "strict": true, diff --git a/worker/index.ts b/worker/index.ts new file mode 100644 index 0000000000..f61aff3fb1 --- /dev/null +++ b/worker/index.ts @@ -0,0 +1,29 @@ +import { initializeApp } from 'firebase/app' +import { getMessaging } from 'firebase/messaging/sw' +import { onBackgroundMessage } from 'firebase/messaging/sw' + +declare let self: ServiceWorkerGlobalScope + + // To disable all workbox logging during development, you can set self.__WB_DISABLE_DEV_LOGS to true + // https://developers.google.com/web/tools/workbox/guides/configure-workbox#disable_logging +;(self as any).__WB_DISABLE_DEV_LOGS = true + +const app = initializeApp({ + apiKey: process.env.NEXT_PUBLIC_FIREBASE_API_KEY, + authDomain: process.env.NEXT_PUBLIC_FIREBASE_AUTH_DOMAIN, + databaseURL: process.env.NEXT_PUBLIC_FIREBASE_DATABASE_URL, + projectId: process.env.NEXT_PUBLIC_FIREBASE_PROJECT_ID, + storageBucket: process.env.NEXT_PUBLIC_FIREBASE_STORAGE_BUCKET, + messagingSenderId: process.env.NEXT_PUBLIC_FIREBASE_MESSAGING_SENDER_ID, + appId: process.env.NEXT_PUBLIC_FIREBASE_APP_ID, + measurementId: process.env.NEXT_PUBLIC_FIREBASE_MEASUREMENT_ID, +}) + +const messaging = getMessaging(app) + +onBackgroundMessage(messaging, (payload) => { + self.registration.showNotification(payload.notification?.title || '', { + body: payload.notification?.body, + icon: payload.notification?.image, + }) +})