feat(pwa): add service worker and registration

This commit is contained in:
Julien Oculi 2024-06-11 17:02:00 +02:00
parent 8d7ad1dc2f
commit c971542ec8
7 changed files with 70 additions and 5 deletions

View file

@ -17,7 +17,12 @@
"explorer.fileNesting.patterns": { "explorer.fileNesting.patterns": {
"*.tsx": "${capture}.*" "*.tsx": "${capture}.*"
}, },
"cSpell.words": ["technoshop", "Technoshop", "univoq"], "cSpell.words": [
"startserviceworker",
"technoshop",
"Technoshop",
"univoq"
],
"cssvar.enable": true, "cssvar.enable": true,
"cssvar.files": ["./_fresh/*"], "cssvar.files": ["./_fresh/*"],
"conventionalCommits.scopes": ["css", "config", "ui", "pwa"], "conventionalCommits.scopes": ["css", "config", "ui", "pwa"],

View file

@ -0,0 +1,5 @@
import RegisterServiceWorker from '../islands/RegisterServiceWorker.tsx'
export function ProgressiveWebApp() {
return <RegisterServiceWorker />
}

View file

@ -1,6 +1,9 @@
export default function RegisterServiceWorker({ href }: { href: string }) { export default function RegisterServiceWorker() {
if ('serviceWorker' in navigator) { if ('serviceWorker' in navigator) {
navigator.serviceWorker.register(href) import('./StartServiceWorker.tsx').then((mod) => {
const href = mod.default()
navigator.serviceWorker.register(href, { scope: '/', type: 'module' })
})
} }
return <></> return <></>

View file

@ -0,0 +1,10 @@
import { main } from '../src/serviceworker/mod.ts'
const IS_SW = 'onpushsubscriptionchange' in self
export default function StartServiceWorker() {
if (IS_SW) {
main()
}
return new URL(import.meta.url).pathname
}

View file

@ -2,7 +2,7 @@ import { asset, Head, Partial } from '$fresh/runtime.ts'
import { type PageProps } from '$fresh/server.ts' import { type PageProps } from '$fresh/server.ts'
import { Footer } from '../components/Footer.tsx' import { Footer } from '../components/Footer.tsx'
import { Header } from '../components/Header.tsx' import { Header } from '../components/Header.tsx'
import RegisterServiceWorker from '../islands/RegisterServiceWorker.tsx' import { ProgressiveWebApp } from '../components/ProgressiveWebApp.tsx'
export default function App({ Component }: PageProps) { export default function App({ Component }: PageProps) {
return ( return (
@ -53,7 +53,7 @@ export default function App({ Component }: PageProps) {
<Component /> <Component />
</Partial> </Partial>
</main> </main>
<RegisterServiceWorker href={asset('/sw.js')} /> <ProgressiveWebApp />
<Footer /> <Footer />
</body> </body>
</html> </html>

11
routes/_middleware.ts Normal file
View file

@ -0,0 +1,11 @@
import { FreshContext } from '$fresh/server.ts'
export async function handler(request: Request, ctx: FreshContext) {
// Allow service worker to serve root scope
const response = await ctx.next()
const url = new URL(request.url)
if (url.pathname.endsWith('island-startserviceworker.js')) {
response.headers.set('Service-Worker-Allowed', '/')
}
return response
}

31
src/serviceworker/mod.ts Normal file
View file

@ -0,0 +1,31 @@
/// <reference no-default-lib="true"/>
/// <reference lib="webworker" />
// Force load service worker types
const self = globalThis as unknown as ServiceWorkerGlobalScope
const cacheName = 'v1' //TODO dynamique cache key
const _preCachedPaths = ['/', '/css/*', '/assets/*'] //TODO pre-cache these paths
export function main() {
self.addEventListener('install', (event) => {
event.waitUntil(
addToCache([]),
)
})
self.addEventListener('activate', () => {
console.log('sw activated')
})
self.addEventListener('fetch', (_event) => {
//TODO add fetch strategies
})
}
async function addToCache(ressources: string[]) {
const cache = await caches.open(cacheName) //TODO dynamique cache key
await cache.addAll(ressources)
//TODO list statics
}