diff --git a/src/main.ts b/src/main.ts index 7852eeab..e7a99ac4 100755 --- a/src/main.ts +++ b/src/main.ts @@ -20,7 +20,7 @@ const router = createRouter({ if (!isElectron && PWA) { // disable local storage cache when there is PWA: // we need to keep local storage when running dev server without PWA - // to avoid call iconify server api + // to avoid send requests to iconify server api disableCache('all') router.isReady().then(async () => { const { registerSW } = await import('virtual:pwa-register') diff --git a/src/sw.ts b/src/sw.ts index 60750faf..0d8e2c10 100644 --- a/src/sw.ts +++ b/src/sw.ts @@ -6,7 +6,8 @@ import { getIcons } from '@iconify/utils' declare let self: ServiceWorkerGlobalScope // self.__WB_MANIFEST is default injection point -precacheAndRoute(self.__WB_MANIFEST) +const swManifest = self.__WB_MANIFEST +precacheAndRoute(swManifest) // clean old assets cleanupOutdatedCaches() @@ -19,23 +20,71 @@ registerRoute(new NavigationRoute( self.skipWaiting() clientsClaim() +function buildCollectionResponseHeaders(cachedResponse: Response) { + const age = cachedResponse.headers.get('age') + const date = cachedResponse.headers.get('date') + const etag = cachedResponse.headers.get('etag') + const contentType = cachedResponse.headers.get('content-type') + const cacheControl = cachedResponse.headers.get('cache-control') + + const headers: Record = { + 'access-control-allow-headers': 'Origin, X-Requested-With, Content-Type, Accept, Accept-Encoding', + 'access-control-allow-methods': 'GET, OPTIONS', + 'access-control-allow-origin': '*', + 'access-control-max-age': '86400', + 'cache-control': 'public, max-age=604800, min-refresh=604800, immutable', + 'content-type': 'application/json; charset=utf-8', + 'cross-origin-resource-policy': 'cross-origin', + } + + if (age) + headers.age = age + + if (date) + headers.date = date + + if (etag) + headers.etag = etag + + if (contentType) + headers['content-type'] = contentType + + if (cacheControl) + headers['cache-control'] = cacheControl + + return headers +} + +const swManifestMap = new Map( + swManifest.map((entry) => { + if (typeof entry === 'string') { + const e = entry[0] === '/' ? entry : `/${entry}` + return [e, e] + } + else { + const e = entry.url[0] === '/' ? entry.url : `/${entry.url}` + return [e, entry.revision ? `${e}?__WB_REVISION__=${entry.revision}` : e] + } + }), +) + async function getCollection(request: Request, name: string, icons: string[]) { try { const cache = await caches.open(cacheNames.precache) - const url = `/collections/${name}-raw.json` + const collectionUrl = `/collections/${name}-raw.json` + const url = swManifestMap.get(collectionUrl) ?? collectionUrl let cachedResponse = await cache.match(url) if (!cachedResponse) { cachedResponse = await fetch(url) await cache.put(url, cachedResponse.clone()) } + const collection = await cachedResponse.json() - return new Response(JSON.stringify(getIcons( - collection, - icons, - )), { - headers: { - 'Content-Type': 'application/json; charset=utf-8', - }, + + return new Response(JSON.stringify(getIcons(collection, icons)), { + status: cachedResponse.status, + statusText: cachedResponse.statusText, + headers: buildCollectionResponseHeaders(cachedResponse), }) } catch {