75 lines
3.0 KiB
JavaScript
75 lines
3.0 KiB
JavaScript
/* 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)
|