fix(pwa): rewrite and update service worker related to fit recent refactors
This commit is contained in:
parent
09e4f401e9
commit
125e645ffd
|
|
@ -1,5 +0,0 @@
|
||||||
import RegisterServiceWorker from ':islands/RegisterServiceWorker.tsx'
|
|
||||||
|
|
||||||
export function ProgressiveWebApp() {
|
|
||||||
return <RegisterServiceWorker />
|
|
||||||
}
|
|
||||||
|
|
@ -26,6 +26,7 @@
|
||||||
"packages/"
|
"packages/"
|
||||||
],
|
],
|
||||||
"imports": {
|
"imports": {
|
||||||
|
"@deno/emit": "jsr:@deno/emit@^0.46.0",
|
||||||
"@deno/gfm": "jsr:@deno/gfm@^0.10.0",
|
"@deno/gfm": "jsr:@deno/gfm@^0.10.0",
|
||||||
"@std/fs": "jsr:@std/fs@^1.0.6",
|
"@std/fs": "jsr:@std/fs@^1.0.6",
|
||||||
"@std/path": "jsr:@std/path@^1.0.8",
|
"@std/path": "jsr:@std/path@^1.0.8",
|
||||||
|
|
|
||||||
|
|
@ -1,10 +1,8 @@
|
||||||
import { requestApi } from ':src/utils.ts'
|
import { requestApi } from ':src/utils.ts'
|
||||||
|
import { useEffect } from 'preact/hooks'
|
||||||
|
|
||||||
export default function RegisterServiceWorker() {
|
async function register() {
|
||||||
if ('serviceWorker' in navigator) {
|
const registration = await navigator.serviceWorker.register('/sw', {
|
||||||
import(':islands/StartServiceWorker.tsx').then(async (mod) => {
|
|
||||||
const href = mod.default()
|
|
||||||
const registration = await navigator.serviceWorker.register(href, {
|
|
||||||
scope: '/',
|
scope: '/',
|
||||||
type: 'module',
|
type: 'module',
|
||||||
})
|
})
|
||||||
|
|
@ -40,8 +38,12 @@ export default function RegisterServiceWorker() {
|
||||||
} catch (cause) {
|
} catch (cause) {
|
||||||
console.error('Push subscription is not available', { cause })
|
console.error('Push subscription is not available', { cause })
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
}
|
|
||||||
|
export default function RegisterServiceWorker() {
|
||||||
return <></>
|
useEffect(() => {
|
||||||
|
if ('serviceWorker' in navigator) register()
|
||||||
|
}, [])
|
||||||
|
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,10 +0,0 @@
|
||||||
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
|
|
||||||
}
|
|
||||||
|
|
@ -2,8 +2,8 @@ import { asset, Partial } from 'fresh/runtime'
|
||||||
import { type PageProps } from 'fresh'
|
import { type PageProps } from 'fresh'
|
||||||
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 { ProgressiveWebApp } from ':components/ProgressiveWebApp.tsx'
|
|
||||||
import IsOnline from ':islands/IsOnline.tsx'
|
import IsOnline from ':islands/IsOnline.tsx'
|
||||||
|
import RegisterServiceWorker from ':islands/RegisterServiceWorker.tsx'
|
||||||
|
|
||||||
export default function App(
|
export default function App(
|
||||||
{ Component, data }: PageProps<{ title?: string } | undefined>,
|
{ Component, data }: PageProps<{ title?: string } | undefined>,
|
||||||
|
|
@ -54,7 +54,7 @@ export default function App(
|
||||||
<Component />
|
<Component />
|
||||||
</Partial>
|
</Partial>
|
||||||
</main>
|
</main>
|
||||||
<ProgressiveWebApp />
|
<RegisterServiceWorker />
|
||||||
<Footer />
|
<Footer />
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
|
||||||
|
|
@ -1,7 +1,6 @@
|
||||||
import { useCache } from ':src/cache/middleware.ts'
|
import { useCache } from ':src/cache/middleware.ts'
|
||||||
import { useCsp } from ':src/csp/middleware.ts'
|
import { useCsp } from ':src/csp/middleware.ts'
|
||||||
import { useSecurityHeaders } from ':src/security_headers/middleware.ts'
|
import { useSecurityHeaders } from ':src/security_headers/middleware.ts'
|
||||||
import { useServiceworker } from ':src/serviceworker/middleware.ts'
|
|
||||||
import { useSession } from ':src/session/middleware.ts'
|
import { useSession } from ':src/session/middleware.ts'
|
||||||
import { SessionStore } from ':src/session/mod.ts'
|
import { SessionStore } from ':src/session/mod.ts'
|
||||||
import { define } from '../utils.ts'
|
import { define } from '../utils.ts'
|
||||||
|
|
@ -23,7 +22,6 @@ export default define.middleware(async (ctx) => {
|
||||||
useSecurityHeaders(request, response, ctx)
|
useSecurityHeaders(request, response, ctx)
|
||||||
await useCsp(request, response, ctx)
|
await useCsp(request, response, ctx)
|
||||||
useSession(request, response, ctx)
|
useSession(request, response, ctx)
|
||||||
useServiceworker(request, response, ctx)
|
|
||||||
useCache(request, response, ctx)
|
useCache(request, response, ctx)
|
||||||
|
|
||||||
return response
|
return response
|
||||||
|
|
|
||||||
|
|
@ -1,37 +1,28 @@
|
||||||
import { expandGlob } from '@std/fs'
|
import { expandGlob } from '@std/fs'
|
||||||
import { SessionHandlers } from ':src/session/mod.ts'
|
import { SessionHandlers } from ':src/session/mod.ts'
|
||||||
import { respondApi } from ':src/utils.ts'
|
import { respondApi } from ':src/utils.ts'
|
||||||
import { BUILD_ID } from '$fresh/src/server/build_id.ts'
|
import { BUILD_ID } from '../../../utils.ts'
|
||||||
import { encodeBase64 } from '@std/encoding'
|
|
||||||
|
|
||||||
export type PrecacheResponse = { version: string; preCachedUrls: string[] }
|
export type PrecacheResponse = { version: string; preCachedUrls: string[] }
|
||||||
|
|
||||||
async function getVersion() {
|
|
||||||
const versionBytes = new TextEncoder().encode(BUILD_ID)
|
|
||||||
const versionHash = await crypto.subtle.digest('SHA-256', versionBytes)
|
|
||||||
return encodeBase64(versionHash)
|
|
||||||
}
|
|
||||||
|
|
||||||
export const handler: SessionHandlers = {
|
export const handler: SessionHandlers = {
|
||||||
async GET() {
|
async GET() {
|
||||||
try {
|
try {
|
||||||
const preCachedUrls: string[] = ['/', '/imports/markdown_css']
|
const preCachedUrls: string[] = ['/', '/imports/markdown_css']
|
||||||
const paths = ['/static/**', '/_fresh/static/**']
|
const paths = ['/static/**', '/_fresh/static/**']
|
||||||
const routes = '/routes/*/index.tsx'
|
const routes = '/routes/*/index.tsx'
|
||||||
const version = await getVersion()
|
const version = BUILD_ID
|
||||||
|
|
||||||
//Pre-cache routes
|
//Pre-cache routes
|
||||||
for await (const route of expandGlob(routes, { root: '.' })) {
|
for await (const route of expandGlob(routes, { root: '.' })) {
|
||||||
if (!route.isFile) continue
|
if ('isFile' in route && !route.isFile) continue
|
||||||
//@ts-expect-error parentPath is missing from type definition
|
preCachedUrls.push(strip('/routes/**', route.path))
|
||||||
const path = route.parentPath as string
|
|
||||||
preCachedUrls.push(path.replace('routes', '').replace('\\', '/'))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Pre-cache files
|
// Pre-cache files
|
||||||
for (const path of paths) {
|
for (const path of paths) {
|
||||||
for await (const entry of expandGlob(path, { root: '.' })) {
|
for await (const entry of expandGlob(path, { root: '.' })) {
|
||||||
if (!entry.isFile) continue
|
if ('isFile' in entry && !entry.isFile) continue
|
||||||
preCachedUrls.push(strip(path, entry.path))
|
preCachedUrls.push(strip(path, entry.path))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -47,12 +38,10 @@ export const handler: SessionHandlers = {
|
||||||
}
|
}
|
||||||
|
|
||||||
function strip(root: string, path: string) {
|
function strip(root: string, path: string) {
|
||||||
return path
|
|
||||||
// Force unix/web separator
|
|
||||||
.replaceAll('\\', '/')
|
|
||||||
.replace(
|
|
||||||
// Remove root slash and glob *
|
// Remove root slash and glob *
|
||||||
root.slice(1).replaceAll('*', ''),
|
const base = root.slice(1).replaceAll('*', '').replaceAll('\\', '/')
|
||||||
'/',
|
// Force unix/web separator
|
||||||
)
|
const pathname = path.replaceAll('\\', '/').replace('/index.tsx', '')
|
||||||
|
|
||||||
|
return `/${pathname.slice(base.length)}`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
import { FreshContext } from 'fresh'
|
|
||||||
|
|
||||||
export function useServiceworker(
|
|
||||||
_request: Request,
|
|
||||||
response: Response,
|
|
||||||
ctx: FreshContext,
|
|
||||||
) {
|
|
||||||
// Allow service worker to serve root scope
|
|
||||||
if (ctx.url.pathname.endsWith('island-startserviceworker.js')) {
|
|
||||||
response.headers.set('Service-Worker-Allowed', '/')
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -4,7 +4,7 @@
|
||||||
import type { JsonValue } from '@std/json'
|
import type { JsonValue } from '@std/json'
|
||||||
import { ApiPayload } from ':src/utils.ts'
|
import { ApiPayload } from ':src/utils.ts'
|
||||||
import type { PrecacheResponse } from '../../routes/api/serviceworker/precache.tsx'
|
import type { PrecacheResponse } from '../../routes/api/serviceworker/precache.tsx'
|
||||||
import { FetchStrategy } from './src/fetch_strategy.ts'
|
import { FetchStrategy } from ':src/serviceworker/src/fetch_strategy.ts'
|
||||||
|
|
||||||
// Force load service worker types
|
// Force load service worker types
|
||||||
const self = globalThis as unknown as ServiceWorkerGlobalScope
|
const self = globalThis as unknown as ServiceWorkerGlobalScope
|
||||||
|
|
@ -120,6 +120,14 @@ if (IS_SW) {
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
self.addEventListener('notificationclick', (event) => {
|
||||||
|
console.log('SW - NOT_CLICK', event)
|
||||||
|
})
|
||||||
|
|
||||||
|
self.addEventListener('notificationclose', (event) => {
|
||||||
|
console.log('SW - NOT_CLOSE', event)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
async function fetchHandler(event: FetchEvent) {
|
async function fetchHandler(event: FetchEvent) {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue