Import Service Workers in Next.js

20 lines

Webpack is very fussy when it comes to importing Service Workers. The format of the navigator.serviceWorker.register(new URL('./serviceWorker.js', import.meta.url)) call is fixed.

This hack works around that, patching the URL.toString() function so that the URL points to the chunk, emitted to the public folder - which is served at the server root, allowing full Service Worker scope. In other words this emulates publicPath inline.

import {patch} from './serviceWorkerPatch'

const serviceWorker = patch(() =>
  navigator.serviceWorker.register(
    new URL(/* webpackChunkName: "../../../public/_" */ './serviceWorker.js', import.meta.url)
  )
)
export const patch = fn => {
  const originalToString = URL.prototype.toString

  URL.prototype.toString = function(){
   return originalToString.call(this).replace('public/', '')
  }

  const result = fn()

  URL.prototype.toString = originalToString

  return result
}