Service Worker Magic

  • Server (Cloudflare Workers) code is sw.js.
  • Browser ( Service Worker ) code is sw.js.
  • Cloudflare Workers sw.js serves sw.js.
  • Service Worker sw.js will be registered on /. The scope is /sw/*.
  • /server/hello => from the server.
  • /sw/hello => from the browser not from a server. Request is intercepted by Service Worker.

It's magic.

Demo

Screencast

SS

Walkthrough

Server

Run Cloudflare Workers on your terminal:

$ wrangler dev sw.js

sw.js is served by sw.js.

Browser

Access /. Your browser will load sw.js:

navigator.serviceWorker.register('/sw.js', { scope: '/sw/', type: 'module' })

Service Worker is registered.

Then...

  • /server/hello => content is returned from the server.
  • /sw/hello => content is returned from the browser. Not from the server.

Attention

If Service Worker does not work, clear the cache on your browser.

Code

Just sw.js.

Short version

It does not work well.

import { Hono } from './hono.js'
import { serveStatic } from './hono.serve-static.js'
import { logger } from './hono.logger.js'

let from = 'Service Worker'

try {
  from = FROM // "Server" is set on Cloudflare Workers environment variables
}

const app = new Hono()

// Middleware
app.use('/sw/*', logger())
app.use('/server/*', logger())
app.use('/:name{.+.js}', serveStatic({ root: './' }))


// Top page
app.get('/', (c) => {
  const html = `<html><body>
  <script>
    navigator.serviceWorker.register('/sw.js', { scope: '/sw/', type: 'module' })
  </script>
  </body></html>`
  return c.html(html)
})

// Handler
const handler = (c) => {
  const text = `Hello! from ${from}!`
  return c.text(text)
}

// Route
app.get('/server/hello', handler)
app.get('/sw/hello', handler)

// addEventListener('fetch'...
app.fire()

Related projects

sw.js is using Hono as Service Worker framework.

Author

Yusuke Wada https://github.com/yusukebe

License

MIT