perf(pwa): add in memory storage to reduce fs and network access

This commit is contained in:
Julien Oculi 2024-07-18 14:21:50 +02:00
parent d7716a88a8
commit 6d29321e88

View file

@ -8,20 +8,37 @@ import type { JsonValue } from '$std/json/common.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
// global RAM cache
const memory = new Map()
// Pseudo storage API for SW // Pseudo storage API for SW
const swStorage = { const swStorage = {
__memory: new Map<string, JsonValue | null>(),
async getItem<T extends JsonValue>(key: string): Promise<T | null> { async getItem<T extends JsonValue>(key: string): Promise<T | null> {
// RAM cache
if (this.__memory.has(key)) {
return this.__memory.get(key) as T
}
// FS cache
const cache = await caches.open('$SW_STORAGE') const cache = await caches.open('$SW_STORAGE')
const request = new Request(`http://null/${encodeURIComponent(key)}`) const request = new Request(`http://null/${encodeURIComponent(key)}`)
const response = await cache.match(request) const response = await cache.match(request)
if (response !== undefined) { if (response !== undefined) {
return response.json() const item = await response.json()
this.__memory.set(key, item)
return item
} }
this.__memory.set(key, null)
return null return null
}, },
async setItem<T extends JsonValue>(key: string, item: T): Promise<void> { async setItem<T extends JsonValue>(key: string, item: T): Promise<void> {
// RAM cache
this.__memory.set(key, item)
// FS Cache
const cache = await caches.open('$SW_STORAGE') const cache = await caches.open('$SW_STORAGE')
const request = new Request(`http://null/${encodeURIComponent(key)}`) const request = new Request(`http://null/${encodeURIComponent(key)}`)
const response = Response.json(item) const response = Response.json(item)
@ -42,12 +59,22 @@ async function getPreCachedUrls(): Promise<string[]> {
async function getPreCache(): Promise<Cache> { async function getPreCache(): Promise<Cache> {
const version = await swStorage.getItem<string>('$sw.pre-cache.version') const version = await swStorage.getItem<string>('$sw.pre-cache.version')
// Get "cache" from ram
if (memory.has(version)) {
return memory.get(version) as Cache
}
// Get cache from server // Get cache from server
if (version === null) { if (version === null) {
await openPreCache() await openPreCache()
return getPreCache() return getPreCache()
} }
return caches.open(version)
// Get "cache" from fs
const cache = await caches.open(version)
memory.set(version, cache)
return cache
} }
const IS_SW = 'onpushsubscriptionchange' in self const IS_SW = 'onpushsubscriptionchange' in self
@ -132,8 +159,17 @@ async function fetchHandler(event: FetchEvent) {
// Network only // Network only
return fetch(event.request) return fetch(event.request)
} }
async function getDynCache(): Promise<Cache> { async function getDynCache(): Promise<Cache> {
const lifeTime = 1 * 24 * 3_600 * 1000 //1 day
const now = Date.now()
const version = await swStorage.getItem<number>('$sw.dyn-cache.version') const version = await swStorage.getItem<number>('$sw.dyn-cache.version')
// Get "cache" from ram
if (memory.has(version)) {
return memory.get(version)
}
// Create cache // Create cache
if (version === null) { if (version === null) {
await swStorage.setItem<number>('$sw.dyn-cache.version', now + lifeTime) await swStorage.setItem<number>('$sw.dyn-cache.version', now + lifeTime)
@ -147,12 +183,22 @@ async function getDynCache(): Promise<Cache> {
return getDynCache() return getDynCache()
} }
// Get "cache" from fs
const cache = await caches.open(version.toString())
memory.set(version, cache)
return cache return cache
} }
// Network only async function updatePreCache(): Promise<void> {
return fetch(event.request) const lifeTime = Date.now() + 1 * 24 * 3_600 * 1000 // 1 day
} const now = Date.now()
const memoryKey = 'last-update-pre-cache'
// Refresh on sw start or 1 times / day
if (memory.get(memoryKey) > now) {
return
}
const serverVersion = await getServerPreCacheVersion() const serverVersion = await getServerPreCacheVersion()
const clientVersion = await swStorage.getItem<string>('$sw.pre-cache.version') const clientVersion = await swStorage.getItem<string>('$sw.pre-cache.version')
@ -164,6 +210,8 @@ async function getDynCache(): Promise<Cache> {
await openPreCache() await openPreCache()
// Delete old pre-cache // Delete old pre-cache
caches.delete(clientVersion) caches.delete(clientVersion)
// Update memory
memory.set(memoryKey, lifeTime)
} }
async function getServerPreCacheVersion(): Promise<string | undefined> { async function getServerPreCacheVersion(): Promise<string | undefined> {