perf(pwa): ⚡ add in memory storage to reduce fs and network access
This commit is contained in:
parent
d7716a88a8
commit
6d29321e88
|
|
@ -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,11 +183,21 @@ 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()
|
||||||
|
|
@ -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> {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue