Files
5chan/src/sw.ts
T
Tommaso CasaburiandGitHub 80e0cabf01 perf(pwa): reduce precache asset fanout
Limit PWA precache to app shell assets and add bounded runtime caching for scoped deployments.
2026-04-20 22:51:31 +07:00

53 lines
2.0 KiB
TypeScript

/// <reference lib="webworker" />
/* eslint-disable no-restricted-globals */
import { clientsClaim } from 'workbox-core';
import { ExpirationPlugin } from 'workbox-expiration';
import { precacheAndRoute, cleanupOutdatedCaches } from 'workbox-precaching';
import { registerRoute } from 'workbox-routing';
import { NetworkFirst, StaleWhileRevalidate } from 'workbox-strategies';
declare const self: ServiceWorkerGlobalScope;
const precacheEntries = self.__WB_MANIFEST.filter((entry) => (typeof entry === 'string' ? entry !== 'index.html' : entry.url !== 'index.html'));
const runtimeAssetDestinations = new Set<RequestDestination>(['font', 'image', 'manifest', 'script', 'style']);
const scopeRoot = self.registration.scope.endsWith('/') ? self.registration.scope : `${self.registration.scope}/`;
const scopePath = (path: string) => new URL(path, scopeRoot).pathname;
const apiPath = scopePath('api');
const apiPathPrefix = scopePath('api/');
const internalPathPrefix = scopePath('_(');
const runtimeAssetPathPrefixes = ['assets/', 'translations/'].map(scopePath);
const isApiPath = (pathname: string) => pathname === apiPath || pathname.startsWith(apiPathPrefix);
// Precache revisioned assets, but let navigations fetch fresh HTML first.
cleanupOutdatedCaches();
precacheAndRoute(precacheEntries);
registerRoute(
({ request, url }) => request.mode === 'navigate' && !isApiPath(url.pathname) && !url.pathname.startsWith(internalPathPrefix),
new NetworkFirst({
cacheName: 'html-cache',
networkTimeoutSeconds: 3,
}),
);
registerRoute(
({ request, url }) =>
url.origin === self.location.origin &&
(runtimeAssetDestinations.has(request.destination) || runtimeAssetPathPrefixes.some((prefix) => url.pathname.startsWith(prefix))),
new StaleWhileRevalidate({
cacheName: 'runtime-static-assets',
plugins: [
new ExpirationPlugin({
maxEntries: 200,
maxAgeSeconds: 60 * 60 * 24 * 30,
purgeOnQuotaError: true,
}),
],
}),
);
// Standard SW lifecycle methods
self.skipWaiting();
clientsClaim();