I have a PWA react app, which I can install like a PWA. So the PWA configuration seems to be setup correctly.
The service worker file is the same file generated when the project was created using create-react-app.
Anyway, I tried adding event listeners but none of them get added:
function registerValidSW(swUrl, config) {
navigator.serviceWorker.register(swUrl).then((registration) => {
// This gets logged
console.log(" ~ file: serviceWorker.js:168 ~ Registered service worker:");
console.log(
" ~ file: serviceWorker.js:168 ~ navigator.serviceWorker.register ~ registration:",
registration
);
registration.addEventListener("activate", function (event) {
// This does not get logged
console.log(" ~ file: Added activate event listener to registration");
});
registration.addEventListener("push", async function (event) {
// This does not get logged
console.log(" ~ file: Added push event listener to registration");
});
registration.addEventListener("fetch", (event) => {
// This does not get logged
console.log(" ~ file: Added fetch event listener to fetch");
});
});
}
activate event listener
Nothing gets triggered after the service worker is activated.
push event listener
It doesn't get triggered if I send a push notification
fetch event listener
It doesn't get triggered if I open a route
Any idea what's going on?
I see event listeners being added to the
registrationobject.But the events like "activate," "push," and "fetch" should be handled inside the service worker itself, not on the registration object.
Meaning this would not work:
The service worker file is a separate JavaScript file that runs in the context of the service worker and not in the main thread of the page.
In the main thread of your page (e.g., in your
serviceWorker.jsfile), register the service worker, like you are doing already. That part is responsible for registering the service worker file and does not handle service worker events like "activate," "push," and "fetch."Inside the service worker file (e.g.,
service-worker.js), you would add the event listeners for "activate","push," and "fetch." That file should be the same one that is being registered by thenavigator.serviceWorker.register(swUrl)call.For example:
That code should be placed in a separate JavaScript file that does not use ES6 imports or other page-level code, as it will run in the service worker context.
You can then check if you see those log messages when the corresponding events are triggered.
I see the "Create React App" (CRA) feature should automatically generate a service worker file for you when you opt into using a service worker (for example, by using the
cra-template-pwatemplate or manually configuring it).In a standard CRA setup, you don't have to write your own service worker file, but it does indeed exist and is usually generated during the build process.
Since the generated service worker file in a Create React App (CRA) project is usually part of the build process, and it gets overwritten every time you build the project, it means that if you modify it directly and then run a build, ... your changes will be lost.
You could instead try and run
npm run eject(oryarn eject), which will expose all the configuration files, including the service worker file. This allows you to modify it directly but comes with the drawback of having to manage the entire build configuration yourself.Another approach is to create your own custom service worker file and include it in your project. You can register it just like the generated service worker. Make sure to handle all the necessary caching and other PWA features yourself in this custom service worker.
For instance, to create and register a custom service worker (
custom-sw.js):Then in your
serviceWorker.jsfile, you can change the registration URL to point to your custom service worker:Make sure that the custom service worker file is served from the correct location. You might need to update your build configuration or place the file in the
publicfolder, depending on how your project is structured.Or you can use Workbox: a set of libraries that can make service worker development easier, and it's often used with CRA to create custom service worker logic.
See "Making a Progressive Web App"
The OP mentions in the comments the page "How to add event listeners to create-react-app default sw.js file", adding:
That method effectively allows you to inject custom code into the generated service worker file without having to modify it directly, preserving the advantages of CRA's build process while still giving you the flexibility to add your custom logic.
You write your custom service worker code in a separate file, such as
sw-epilog.js. That could include event listeners or other code that you want to append to the generated service worker.You use a script in your
package.jsonfile to concatenate this custom code file onto the end of the generated service worker file after the build process is completed. The>>operator in the shell commandcat src/sw-epilog.js >> build/service-worker.jsdoes this by taking the content ofsw-epilog.jsand appending it to the end ofservice-worker.js.You include this concatenation step in your build process so that it happens automatically every time you build your project.