Streamline creating workbox image caches

This commit is contained in:
schroda
2026-04-27 17:48:21 +02:00
parent 425a9bca5e
commit 5485f2bb0f

View File

@@ -14,6 +14,31 @@ import { VitePWA } from 'vite-plugin-pwa';
import { lingui } from '@lingui/vite-plugin'; import { lingui } from '@lingui/vite-plugin';
import 'dotenv/config'; import 'dotenv/config';
import { d } from 'koration'; import { d } from 'koration';
import type { RuntimeCaching } from 'workbox-build';
const createCacheFirstRuntimeCache = (cache: Omit<RuntimeCaching, 'handler'>): RuntimeCaching => ({
...cache,
handler: 'CacheFirst',
options: {
...cache.options,
expiration: {
purgeOnQuotaError: true,
...cache.options.expiration,
matchOptions: {
ignoreVary: true,
...cache.options.expiration.matchOptions,
},
},
cacheableResponse: {
statuses: [0, 200],
...cache.options.cacheableResponse,
},
matchOptions: {
ignoreVary: true,
...cache.options.matchOptions,
},
},
});
export default defineConfig(({ command }) => ({ export default defineConfig(({ command }) => ({
base: command === 'serve' ? process.env.VITE_SUBPATH || './' : './', base: command === 'serve' ? process.env.VITE_SUBPATH || './' : './',
@@ -59,12 +84,11 @@ export default defineConfig(({ command }) => ({
workbox: { workbox: {
globPatterns: [], globPatterns: [],
runtimeCaching: [ runtimeCaching: [
{ createCacheFirstRuntimeCache({
urlPattern: ({ url }) => { urlPattern: ({ url }) => {
const { pathname } = url; const { pathname } = url;
return pathname.match(/\/chapter\/[0-9]+\/page\/[0-9]+/g); return pathname.match(/\/chapter\/[0-9]+\/page\/[0-9]+/g);
}, },
handler: 'CacheFirst',
options: { options: {
// !!! IMPORTANT !!! - Update along with ImageCache.ts // !!! IMPORTANT !!! - Update along with ImageCache.ts
cacheName: 'image-cache-chapter-pages', cacheName: 'image-cache-chapter-pages',
@@ -72,25 +96,14 @@ export default defineConfig(({ command }) => ({
// Max age from server // Max age from server
maxAgeSeconds: d(1).days.inWholeSeconds, maxAgeSeconds: d(1).days.inWholeSeconds,
maxEntries: 2500, maxEntries: 2500,
purgeOnQuotaError: true,
matchOptions: {
ignoreVary: true,
}, },
}, },
cacheableResponse: { }),
statuses: [0, 200], createCacheFirstRuntimeCache({
},
matchOptions: {
ignoreVary: true,
},
},
},
{
urlPattern: ({ url }) => { urlPattern: ({ url }) => {
const { pathname } = url; const { pathname } = url;
return pathname.match(/\/manga\/[0-9]+\/thumbnail/g); return pathname.match(/\/manga\/[0-9]+\/thumbnail/g);
}, },
handler: 'CacheFirst',
options: { options: {
// !!! IMPORTANT !!! - Update along with ImageCache.ts // !!! IMPORTANT !!! - Update along with ImageCache.ts
cacheName: 'image-cache-manga-thumbnails', cacheName: 'image-cache-manga-thumbnails',
@@ -98,25 +111,14 @@ export default defineConfig(({ command }) => ({
// Max age from server // Max age from server
maxAgeSeconds: d(1).days.inWholeSeconds, maxAgeSeconds: d(1).days.inWholeSeconds,
maxEntries: 5000, maxEntries: 5000,
purgeOnQuotaError: true,
matchOptions: {
ignoreVary: true,
}, },
}, },
cacheableResponse: { }),
statuses: [0, 200], createCacheFirstRuntimeCache({
},
matchOptions: {
ignoreVary: true,
},
},
},
{
urlPattern: ({ url }) => { urlPattern: ({ url }) => {
const { pathname } = url; const { pathname } = url;
return pathname.includes('/extension/icon/'); return pathname.includes('/extension/icon/');
}, },
handler: 'CacheFirst',
options: { options: {
// !!! IMPORTANT !!! - Update along with ImageCache.ts // !!! IMPORTANT !!! - Update along with ImageCache.ts
cacheName: 'image-cache-extension-icons', cacheName: 'image-cache-extension-icons',
@@ -124,41 +126,20 @@ export default defineConfig(({ command }) => ({
// Max age from server // Max age from server
maxAgeSeconds: d(365).days.inWholeSeconds, maxAgeSeconds: d(365).days.inWholeSeconds,
maxEntries: 300, maxEntries: 300,
purgeOnQuotaError: true,
matchOptions: {
ignoreVary: true,
}, },
}, },
cacheableResponse: { }),
statuses: [0, 200], createCacheFirstRuntimeCache({
},
matchOptions: {
ignoreVary: true,
},
},
},
{
urlPattern: ({ request }) => request.destination === 'image', urlPattern: ({ request }) => request.destination === 'image',
handler: 'CacheFirst',
options: { options: {
// !!! IMPORTANT !!! - Update along with ImageCache.ts // !!! IMPORTANT !!! - Update along with ImageCache.ts
cacheName: 'image-cache-other', cacheName: 'image-cache-other',
expiration: { expiration: {
maxAgeSeconds: d(4).days.inWholeSeconds, maxAgeSeconds: d(4).days.inWholeSeconds,
maxEntries: 500, maxEntries: 500,
purgeOnQuotaError: true,
matchOptions: {
ignoreVary: true,
},
},
cacheableResponse: {
statuses: [0, 200],
},
matchOptions: {
ignoreVary: true,
},
}, },
}, },
}),
], ],
}, },
}), }),