/* global self */ import { precacheAndRoute } from 'workbox-precaching' import { offlineFallback } from 'workbox-recipes' import { setDefaultHandler } from 'workbox-routing' import { NetworkOnly } from 'workbox-strategies' import { enable } from 'workbox-navigation-preload' import manifest from './precache-manifest.json' import { onPush, onNotificationClick, onPushSubscriptionChange, onMessage } from './eventListener' // comment out to enable workbox console logs self.__WB_DISABLE_DEV_LOGS = true // preloading improves startup performance // https://developer.chrome.com/docs/workbox/modules/workbox-navigation-preload/ enable() // ignore precache manifest generated by InjectManifest // they statically check for the presence of this variable console.log(self.__WB_MANIFEST) // precache the manifest we generated ourselves precacheAndRoute(manifest) // immediately replace existing service workers with this one // (no wait until this one becomes active) self.addEventListener('install', () => self.skipWaiting()) // Using network-only as the default strategy ensures that we fallback // to the browser as if the service worker wouldn't exist. // The browser may use own caching (HTTP cache). // Also, the offline fallback only works if request matched a route setDefaultHandler(new NetworkOnly({ plugins: [{ fetchDidFail: async (args) => { // tell us why a request failed in dev process.env.NODE_ENV !== 'production' && console.log('fetch did fail', ...args) }, fetchDidSucceed: async ({ request, response, event, state }) => { if ( response.ok && request.headers.get('x-nextjs-data') && response.headers.get('x-nextjs-matched-path') && response.headers.get('content-type') === 'application/json' && response.headers.get('content-length') === '2' && response.status === 200) { console.log('service worker detected a successful yet empty nextjs SSR data response') console.log('nextjs has a bug where it returns a 200 with empty data when it should return a 404') console.log('see https://github.com/vercel/next.js/issues/56852') console.log('HACK ... intercepting response and returning 404') const headers = new Headers(response.headers) headers.delete('x-nextjs-matched-path') headers.delete('content-type') headers.delete('content-length') return new Response(null, { status: 404, statusText: 'Not Found', headers, ok: false }) } return response } }] })) // This won't work in dev because pages are never cached. // See https://github.com/vercel/next.js/blob/337fb6a9aadb61c916f0121c899e463819cd3f33/server/render.js#L181-L185 offlineFallback({ pageFallback: '/offline' }) self.addEventListener('push', onPush(self)) self.addEventListener('notificationclick', onNotificationClick(self)) self.addEventListener('message', onMessage(self)) self.addEventListener('pushsubscriptionchange', onPushSubscriptionChange(self), false)