Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add event listeners to create-react-app default sw.js file

I want to use the default service-worker (sw.js) file of Create-React-App module.

sw.js file looks like the following code:

const isLocalhost = Boolean(
  window.location.hostname === 'localhost' ||
    window.location.hostname === '[::1]' ||
    window.location.hostname.match(
      /^127(?:\.(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)){3}$/
    )
);

export function register(config) {
  if (process.env.NODE_ENV === 'production' && 'serviceWorker' in navigator) {
    console.log('[Service Worker] Service Worker Registered!');
    const publicUrl = new URL(process.env.PUBLIC_URL, window.location.href);
    if (publicUrl.origin !== window.location.origin) {
      return;
    }

    window.addEventListener('load', () => {
      const swUrl = `${process.env.PUBLIC_URL}/service-worker.js`;

      if (isLocalhost) {
        checkValidServiceWorker(swUrl, config);

        navigator.serviceWorker.ready.then(() => {
          console.log(
            'hello'
          );
        });
      } else {
        registerValidSW(swUrl, config);
      }
    });

  }
}

function registerValidSW(swUrl, config) {
  navigator.serviceWorker
    .register(swUrl)
    .then(registration => {
      registration.onupdatefound = () => {
        const installingWorker = registration.installing;
        if (installingWorker == null) {
          return;
        }
        installingWorker.onstatechange = () => {
          if (installingWorker.state === 'installed') {
            if (navigator.serviceWorker.controller) {
              console.log(
                'link'
              );

              if (config && config.onUpdate) {
                config.onUpdate(registration);
              }
            } else {
              console.log('Content is cached for offline use.');

              if (config && config.onSuccess) {
                config.onSuccess(registration);
              }
            }
          }
        };
      };
    })
    .catch(error => {
      console.error('Error during service worker registration:', error);
    });
}

function checkValidServiceWorker(swUrl, config) {
  fetch(swUrl)
    .then(response => {
      const contentType = response.headers.get('content-type');
      if (
        response.status === 404 ||
        (contentType != null && contentType.indexOf('javascript') === -1)
      ) {

        navigator.serviceWorker.ready.then(registration => {
          registration.unregister().then(() => {
            window.location.reload();
          });
        });
      } else {
        registerValidSW(swUrl, config);
      }
    })
    .catch(() => {
      console.log(
        'No internet connection found. App is running in offline mode.'
      );
    });
}

export function unregister() {
  if ('serviceWorker' in navigator) {
    navigator.serviceWorker.ready.then(registration => {
      registration.unregister();
    });
  }
}

What I want is to add some more event listener to this file, I have tried different part of the above code to add listeners but it doesn't work! As an example I added the following, but I don't know where it should be placed to work properly:

window.addEventListener('fetch', (e){
    console.log('[service worker] fetch')
})

The other events are install, activate, beforeinstallprompt and etc.

My main purpose of asking this question is to understand how to add install banner to my react project!

like image 361
Mostafa Ghadimi Avatar asked Oct 27 '25 18:10

Mostafa Ghadimi


1 Answers

You can not modify the generated service worker file in create-react-app without ejecting.. as a workaround you can create a sw-epilog.js file where you add all the service worker specific code and have a script in the package.json that appends that file to the generated service worker file as mentioned in https://github.com/facebook/create-react-app/issues/5890#issuecomment-450915616

I have a gist to demonstrate this here https://gist.github.com/khaledosman/de3535c8873831153efdf6c10a4b4080 see the last two files

// sw-epilog.js
// Add a listener to receive messages from clients
self.addEventListener('message', function(event) {
  // Force SW upgrade (activation of new installed SW version)
  if ( event.data === 'skipWaiting' ) {
    self.skipWaiting();
  }
});
//package.json
"scripts": {
  "build": "rm -rf build/ && react-scripts build && npm run-script sw-epilog",
  "sw-epilog": "cat src/sw-epilog.js >> build/service-worker.js",
},

for a full implementation you can also see https://github.com/khaledosman/create-react-pwa

like image 181
Khaled Osman Avatar answered Oct 29 '25 09:10

Khaled Osman



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!