Split service worker image cache into multiple
This commit is contained in:
@@ -28,7 +28,7 @@ export const ImagesSettings = () => {
|
|||||||
|
|
||||||
const clearCache = async () => {
|
const clearCache = async () => {
|
||||||
try {
|
try {
|
||||||
await Promise.all([triggerClearServerCache(), ImageCache.clear()]);
|
await Promise.all([triggerClearServerCache(), ImageCache.clearAll()]);
|
||||||
makeToast(t`Cleared the cache`, 'success');
|
makeToast(t`Cleared the cache`, 'success');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
makeToast(t`Could not clear the cache`, 'error', getErrorMessage(e));
|
makeToast(t`Could not clear the cache`, 'error', getErrorMessage(e));
|
||||||
|
|||||||
@@ -6,12 +6,41 @@
|
|||||||
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const CACHE_NAME = 'image-cache';
|
import { defaultPromiseErrorHandler } from '@/lib/DefaultPromiseErrorHandler.ts';
|
||||||
|
|
||||||
|
// !!! IMPORTANT !!! - Update along with vite.config.ts workbox config
|
||||||
|
export enum ImageCacheKey {
|
||||||
|
OTHER = 'image-cache-other',
|
||||||
|
EXTENSION_ICONS = 'image-cache-extension-icons',
|
||||||
|
MANGA_THUMBNAILS = 'image-cache-manga-thumbnails',
|
||||||
|
CHAPTER_PAGES = 'image-cache-chapter-pages',
|
||||||
|
}
|
||||||
|
|
||||||
|
const IMAGE_CACHE_KEYS = Object.values(ImageCacheKey);
|
||||||
|
|
||||||
|
caches.delete('image-cache').catch(defaultPromiseErrorHandler('ImageCache: delete removed "image-cache"'));
|
||||||
|
|
||||||
export class ImageCache {
|
export class ImageCache {
|
||||||
static async has(url: string): Promise<boolean> {
|
// !!! IMPORTANT !!! - Update along with vite.config.ts workbox config
|
||||||
|
static getKeyFor(url: string): ImageCacheKey {
|
||||||
|
if (url.match(/\/chapter\/[0-9]+\/page\/[0-9]+/g)) {
|
||||||
|
return ImageCacheKey.CHAPTER_PAGES;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (url.match(/\/manga\/[0-9]+\/thumbnail/g)) {
|
||||||
|
return ImageCacheKey.MANGA_THUMBNAILS;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (url.includes('/extension/icon/')) {
|
||||||
|
return ImageCacheKey.EXTENSION_ICONS;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ImageCacheKey.OTHER;
|
||||||
|
}
|
||||||
|
|
||||||
|
static async has(url: string, key: ImageCacheKey = this.getKeyFor(url)): Promise<boolean> {
|
||||||
try {
|
try {
|
||||||
const cache = await caches.open(CACHE_NAME);
|
const cache = await caches.open(key);
|
||||||
const response = await cache.match(url, { ignoreVary: true });
|
const response = await cache.match(url, { ignoreVary: true });
|
||||||
|
|
||||||
return response !== undefined;
|
return response !== undefined;
|
||||||
@@ -20,9 +49,9 @@ export class ImageCache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async get(url: string): Promise<Response | null> {
|
static async get(url: string, key: ImageCacheKey = this.getKeyFor(url)): Promise<Response | null> {
|
||||||
try {
|
try {
|
||||||
const cache = await caches.open(CACHE_NAME);
|
const cache = await caches.open(key);
|
||||||
const response = await cache.match(url);
|
const response = await cache.match(url);
|
||||||
|
|
||||||
return response || null;
|
return response || null;
|
||||||
@@ -31,10 +60,14 @@ export class ImageCache {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static async clear(): Promise<void> {
|
static async clear(key: ImageCacheKey): Promise<void> {
|
||||||
const cache = await caches.open(CACHE_NAME);
|
const cache = await caches.open(key);
|
||||||
const keys = await cache.keys();
|
const imageKeys = await cache.keys();
|
||||||
|
|
||||||
await Promise.all(keys.map((key) => cache.delete(key)));
|
await Promise.all(imageKeys.map((imageKey) => cache.delete(imageKey)));
|
||||||
|
}
|
||||||
|
|
||||||
|
static async clearAll(): Promise<void> {
|
||||||
|
IMAGE_CACHE_KEYS.forEach(ImageCache.clear);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,23 +61,67 @@ export default defineConfig(({ command }) => ({
|
|||||||
globPatterns: [],
|
globPatterns: [],
|
||||||
runtimeCaching: [
|
runtimeCaching: [
|
||||||
{
|
{
|
||||||
urlPattern: ({ request, url }) => {
|
urlPattern: ({ url }) => {
|
||||||
if (request.destination === 'image') {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
const { pathname } = url;
|
const { pathname } = url;
|
||||||
return (
|
return pathname.match(/\/chapter\/[0-9]+\/page\/[0-9]+/g);
|
||||||
pathname.match(/\/chapter\/[0-9]+\/page\/[0-9]+/g) ||
|
|
||||||
pathname.match(/\/manga\/[0-9]+\/thumbnail/g) ||
|
|
||||||
pathname.includes('/extension/icon/')
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
handler: 'CacheFirst',
|
handler: 'CacheFirst',
|
||||||
options: {
|
options: {
|
||||||
cacheName: 'image-cache',
|
// !!! IMPORTANT !!! - Update along with ImageCache.ts
|
||||||
|
cacheName: 'image-cache-chapter-pages',
|
||||||
expiration: {
|
expiration: {
|
||||||
maxEntries: 10000,
|
maxEntries: 2500,
|
||||||
|
purgeOnQuotaError: true,
|
||||||
|
},
|
||||||
|
cacheableResponse: {
|
||||||
|
statuses: [0, 200],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
urlPattern: ({ url }) => {
|
||||||
|
const { pathname } = url;
|
||||||
|
return pathname.match(/\/manga\/[0-9]+\/thumbnail/g);
|
||||||
|
},
|
||||||
|
handler: 'CacheFirst',
|
||||||
|
options: {
|
||||||
|
// !!! IMPORTANT !!! - Update along with ImageCache.ts
|
||||||
|
cacheName: 'image-cache-manga-thumbnails',
|
||||||
|
expiration: {
|
||||||
|
maxEntries: 5000,
|
||||||
|
purgeOnQuotaError: true,
|
||||||
|
},
|
||||||
|
cacheableResponse: {
|
||||||
|
statuses: [0, 200],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
urlPattern: ({ url }) => {
|
||||||
|
const { pathname } = url;
|
||||||
|
return pathname.includes('/extension/icon/');
|
||||||
|
},
|
||||||
|
handler: 'CacheFirst',
|
||||||
|
options: {
|
||||||
|
// !!! IMPORTANT !!! - Update along with ImageCache.ts
|
||||||
|
cacheName: 'image-cache-extension-icons',
|
||||||
|
expiration: {
|
||||||
|
maxEntries: 300,
|
||||||
|
purgeOnQuotaError: true,
|
||||||
|
},
|
||||||
|
cacheableResponse: {
|
||||||
|
statuses: [0, 200],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
urlPattern: ({ request }) => request.destination === 'image',
|
||||||
|
handler: 'CacheFirst',
|
||||||
|
options: {
|
||||||
|
// !!! IMPORTANT !!! - Update along with ImageCache.ts
|
||||||
|
cacheName: 'image-cache-other',
|
||||||
|
expiration: {
|
||||||
|
maxEntries: 500,
|
||||||
purgeOnQuotaError: true,
|
purgeOnQuotaError: true,
|
||||||
},
|
},
|
||||||
cacheableResponse: {
|
cacheableResponse: {
|
||||||
|
|||||||
Reference in New Issue
Block a user