Implementing push notifications for a react app is pretty straightforward until you have to do this on an app built with Create React App, you might have a new service worker file to work with.
As someone modestly familiar with the folder structure of a CRA app you will know that this will cause conflicts or one service worker trying to overwrite the others.
It simply gets complicated.
Three reasons for this:
- Using the default scaffold flow for CRA
npm run build, the service worker is generated automatically. Might take a while to understand all it is doing if you went through it now.
- You can not simply edit this file to include your firebase service worker methods and imports. You will have to do
npm run ejectparticularly and that means you will have to be on your own onwards.
- You have to use Webpack plugins to generate the proper service worker when next you
npm run buildyour project.
An example of this is the npm package ServiceWorkerWebpackPlugin
The way these plugins work is to release a dynamic service worker file in place of the default sw with a runtime helper.
The alternative is to avoid modifying the default service worker in the root of your ./src and the one generated at the /build(we do not really have a business with this), it will most likely be named something like “registerServiceWorker.js”.
You should try to put your new service worker in the public/assets folder, this is the folder that is used to hold our assets. My service worker is named “firebase-messaging-sw.js”
The idea is that webpack will not bundle the js files in the public/assets folder unlike those in ./src and then we can call it and register it at the root of our react app.
I decided to structure my app like so:
On the initializePush() function we will be asking the users if they want us to be sending them notifications. And it is only called after registering/updating a service worker file.
A service worker is updated after the browser does a binary comparison between the old and new file; on finding a difference in output after the comparison it will install the new service worker and then generate a new token.
Below is the modal that shows on the first-ever request for permission to send push notifications to users.
And next getting the token based off your current instance of firebase. You will notice this function has the requestPermission() function and also the messaging.getToken() and then the sendTokenToServer() all in the .then() chain. Does this mean we are getting a new token from firebase every time we reach that point in the code?
Apparently, it turns out we don’t. We are not getting a new token every time the function is called. What actually happens is that the first time the getToken method is called, a network call is made, once retrieved and used (sent to our backend) subsequent calls to getToken() the token will return from the cache.
Receives messages sent to this client when the client has the app open.
Called when a client clicks on the notification that is sent from the app server somewhere.
This method handles the messages received when a client does not have the app open.
Remember to instantiate your firebase instance in another directory, in case you missed it, it was used here;
import messaging from 'config/firebase'