mirror of
https://github.com/immich-app/immich.git
synced 2025-05-21 21:01:13 +02:00
feat: service worker cache static app resources, and all entry points
This commit is contained in:
parent
15d431ba6a
commit
9032c7e021
1 changed files with 73 additions and 2 deletions
|
@ -2,7 +2,7 @@
|
|||
/// <reference no-default-lib="true"/>
|
||||
/// <reference lib="esnext" />
|
||||
/// <reference lib="webworker" />
|
||||
import { version } from '$service-worker';
|
||||
import { build, files, version } from '$service-worker';
|
||||
|
||||
const useCache = true;
|
||||
const sw = globalThis as unknown as ServiceWorkerGlobalScope;
|
||||
|
@ -11,8 +11,15 @@ const pendingLoads = new Map<string, AbortController>();
|
|||
// Create a unique cache name for this deployment
|
||||
const CACHE = `cache-${version}`;
|
||||
|
||||
const APP_RESOURCES = [
|
||||
...build, // the app itself
|
||||
...files, // everything in `static`
|
||||
];
|
||||
|
||||
sw.addEventListener('install', (event) => {
|
||||
event.waitUntil(sw.skipWaiting());
|
||||
// Create a new cache and add all files to it
|
||||
event.waitUntil(addFilesToCache());
|
||||
});
|
||||
|
||||
sw.addEventListener('activate', (event) => {
|
||||
|
@ -26,8 +33,16 @@ sw.addEventListener('fetch', (event) => {
|
|||
return;
|
||||
}
|
||||
const url = new URL(event.request.url);
|
||||
if (/^\/api\/assets\/[a-f0-9-]+\/(original|thumbnail)/.test(url.pathname)) {
|
||||
if (APP_RESOURCES.includes(url.pathname)) {
|
||||
event.respondWith(appResources(url, event));
|
||||
} else if (/^\/api\/assets\/[a-f0-9-]+\/(original|thumbnail)/.test(url.pathname)) {
|
||||
event.respondWith(immichAsset(url));
|
||||
} else if (
|
||||
/^(\/(link|auth|admin|albums|archive|buy|explore|favorites|folders|maps|memory|partners|people|photos|places|search|share|shared-links|sharing|tags|trash|user-settings|utilities))(\/.*)?$/.test(
|
||||
url.pathname,
|
||||
)
|
||||
) {
|
||||
event.respondWith(ssr(new URL(event.request.url).origin));
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -39,6 +54,28 @@ async function deleteOldCaches() {
|
|||
}
|
||||
}
|
||||
|
||||
async function addFilesToCache() {
|
||||
const cache = await caches.open(CACHE);
|
||||
await cache.addAll(APP_RESOURCES);
|
||||
}
|
||||
|
||||
async function ssr(origin: string) {
|
||||
const cache = await caches.open(CACHE);
|
||||
const url = new URL('/', origin);
|
||||
let response = useCache ? await cache.match(url) : undefined;
|
||||
if (response) {
|
||||
return response;
|
||||
}
|
||||
response = await fetch(url);
|
||||
if (!(response instanceof Response)) {
|
||||
return Response.error();
|
||||
}
|
||||
if (response.status === 200) {
|
||||
cache.put(url, response.clone());
|
||||
}
|
||||
return response;
|
||||
}
|
||||
|
||||
async function immichAsset(url: URL) {
|
||||
const cache = await caches.open(CACHE);
|
||||
let response = useCache ? await cache.match(url) : undefined;
|
||||
|
@ -66,6 +103,40 @@ async function immichAsset(url: URL) {
|
|||
}
|
||||
}
|
||||
|
||||
async function appResources(url: URL, event: FetchEvent) {
|
||||
const cache = await caches.open(CACHE);
|
||||
// `build`/`files` can always be served from the cache
|
||||
if (APP_RESOURCES.includes(url.pathname)) {
|
||||
const response = await cache.match(url.pathname);
|
||||
if (response) {
|
||||
return response;
|
||||
}
|
||||
}
|
||||
// for everything else, try the network first, but
|
||||
// fall back to the cache if we're offline
|
||||
try {
|
||||
const response = await fetch(event.request);
|
||||
// if we're offline, fetch can return a value that is not a Response
|
||||
// instead of throwing - and we can't pass this non-Response to respondWith
|
||||
if (!(response instanceof Response)) {
|
||||
throw new TypeError('invalid response from fetch');
|
||||
}
|
||||
|
||||
if (response.status === 200) {
|
||||
cache.put(event.request, response.clone());
|
||||
}
|
||||
|
||||
return response;
|
||||
} catch {
|
||||
const response = await cache.match(event.request);
|
||||
if (response) {
|
||||
return response;
|
||||
}
|
||||
// if there's no cache, then just error out
|
||||
return Response.error();
|
||||
}
|
||||
}
|
||||
|
||||
const broadcast = new BroadcastChannel('immich');
|
||||
// eslint-disable-next-line unicorn/prefer-add-event-listener
|
||||
broadcast.onmessage = (event) => {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue