0

I'm going to try to be as thorough as I can:

We are working on a PWA with nextJS using this package: https://github.com/shadowwalker/next-pwa

As of now, I'm working on the service worker for sending push notifications and the package uses workbox-plugin to create the service workers.

Following the instructions I created my own service worker and used the injectManifest strategy to create the custom worker file (using generateSW won't let you create your own service worker). In order to do this, I had to specify the swSrc in the next.config file.

here is the information in the next-pwa documentation about this

My service worker is created and it's added to the workbox manifest, which is what I had intended, but now I got this error message, this is because it's looking the service worker inside my baseURL (localhost:3000/westnet) and then appending the public/sw.js, where it should be just localhost:3000/westnet/sw.js, here:

sw.js:1 Uncaught (in promise) bad-precaching-response: bad-precaching-response :: [{"url":"http://localhost:3000/westnet/public/sw.js","status":404}]
    at U._handleInstall (http://localhost:3000/westnet/sw.js:1:8246)
    at async U._handle (http://localhost:3000/westnet/sw.js:1:7661)
    at async U._getResponse (http://localhost:3000/westnet/sw.js:1:6731)

So the problem is precaching, reading some information I understood that the service worker should be running on the global scope, kinda like this my-global-scope/sw.js, if I do this on my browser, it's there, but the error is searching in public, and hence I don't specifically register the service worker (next-pwa does it for me) I can't find the options to declare the global scope, I did it in the next.config file and had no luck, tried every option.

Here is the next.config.js:

const withPWA = require('next-pwa')({
  dest: 'public',
  swSrc: 'worker/index.js',
  clientsClaim: true,
  skipWaiting: true,
  cleanupOutdatedCaches: true,
  mode: 'production',
  scope: '/westnet/',
  fallbacks: {
    document: '/westnet/_offline',
  },
});
const basePath = '/westnet';

/** @type {import('next').NextConfig} */
const nextConfig = {
  //  reactStrictMode: true,
  env: {
    basePath: basePath,
  },
  basePath: basePath,
  assetPrefix: basePath,
  swcMinify: true,
  eslint: { dirs: ['pages', 'services', 'components', 'views', 'utils'] },
  output: 'standalone',
};

module.exports = withPWA(nextConfig);

here is the useEffect where I request for notifications permission, it never fullfills because navigator.serviceWorker.ready is never fullfilled

  useEffect(() => {
    console.log('DEBUG useEffect');
    if (typeof window !== 'undefined' && 'serviceWorker' in navigator) {
      console.log('DEBUG serviceWorker');
      Notification.requestPermission()
        .then((permission) => {
          console.log('DEBUG permission', permission);
          if (permission == 'granted') {
            console.log('DEBUG granted');
            navigator.serviceWorker.ready // from this point it's not working, because ready is always pending, it's a promise.
              .then((sw) => {
                console.log('DEBUG sw', sw);
                sw.pushManager
                  .subscribe({
                    userVisibleOnly: true,
                    applicationServerKey:
                      'BH8Z58NqdWO9l5902MgVMLDTXGuq2vAAmP_3tw1wyLAD7cC2X6eT8CEtPuExn96xjx1q52eH6crOeXKeWehKjX0',
                  })
                  .then((subscription) => {
                    console.log(
                      // 'DEBUG subscription',
                      JSON.stringify(subscription)
                    );
                  })
                  .catch((err) => console.error('DEBUG subscription err', err));
              })
              .catch((err) => console.error('DEBUG sw err', err));
          }
        })
        .catch((err) => console.error('DEBUG request permission err', err));
    }
  }, []);

0 Answers0