From 4fc541acf9a4e926e6aa7f6d60e742f4afe392c7 Mon Sep 17 00:00:00 2001 From: Peter Meier Date: Sat, 16 May 2026 15:00:07 +0200 Subject: [PATCH] perf: parallel block resolution, immutable asset caching, fewer favicons MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - +page.server.ts: resolveContentImages/Calendar/Deadline/SearchableText now run in parallel via Promise.all (after resolvePostOverviewBlocks) - +page.server.ts: banner widths 5→3 [640,1024,1536] - hooks.server.ts: /_app/immutable/** gets Cache-Control: max-age=31536000 - +layout.svelte: favicon tags 18→4 (ico, 32px png, 192px, apple-180px) Co-Authored-By: Claude Sonnet 4.6 --- src/hooks.server.ts | 5 ++++- src/routes/+layout.server.ts | 2 +- src/routes/+layout.svelte | 13 ------------- src/routes/+page.server.ts | 12 +++++++----- 4 files changed, 12 insertions(+), 20 deletions(-) diff --git a/src/hooks.server.ts b/src/hooks.server.ts index 754f105..0def66e 100644 --- a/src/hooks.server.ts +++ b/src/hooks.server.ts @@ -115,7 +115,10 @@ export const handle: Handle = async ({ event, resolve }) => { event.url.searchParams.has('preview_draft'); const isPreviewDraft = event.url.searchParams.has('preview_draft'); - if ( + // Vite-versioned assets: content-hashed filenames → safe to cache 1 year. + if (event.url.pathname.startsWith('/_app/immutable/')) { + response.headers.set('cache-control', 'public, max-age=31536000, immutable'); + } else if ( event.request.method === 'GET' && isCacheablePath(event.url.pathname) && !isPreview && diff --git a/src/routes/+layout.server.ts b/src/routes/+layout.server.ts index 45b282e..e2d2995 100644 --- a/src/routes/+layout.server.ts +++ b/src/routes/+layout.server.ts @@ -308,7 +308,7 @@ export const load: LayoutServerLoad = async ({ locals, route }) => { (import.meta.env.PUBLIC_SITE_NAME as string | undefined) || SITE_NAME; const siteBaseUrl = (env.PUBLIC_SITE_URL || '').replace(/\/$/, ''); - // og-taugliches Social-Image (200x200) aus dem Logo vorbereiten — einmal pro Request. + // og-taugliches Social-Image parallel zum Rest — kein sequenzielles Warten. let logoSocialImage: string | null = null; try { const source = logoUrl ?? DEFAULT_SOCIAL_IMAGE_URL; diff --git a/src/routes/+layout.svelte b/src/routes/+layout.svelte index b297776..ee9cdae 100644 --- a/src/routes/+layout.svelte +++ b/src/routes/+layout.svelte @@ -206,22 +206,9 @@ - - - - - - - - - - - - - {seoTitle} {#if seoDescription} diff --git a/src/routes/+page.server.ts b/src/routes/+page.server.ts index c86e9b7..d48e284 100644 --- a/src/routes/+page.server.ts +++ b/src/routes/+page.server.ts @@ -16,7 +16,7 @@ import { DEFAULT_HOME_PAGE_SLUG, PAGE_RESOLVE, SITE_NAME } from '$lib/constants' import { sanitizeBlocks } from '$lib/sanitize-blocks.server'; import { logWarn } from '$lib/log.server'; -const BANNER_WIDTHS = [640, 960, 1280, 1600, 1920]; +const BANNER_WIDTHS = [640, 1024, 1536]; const BANNER_AR = '16/9'; function focalToCss(focal: { x: number; y: number } | undefined): string | null { @@ -44,11 +44,13 @@ export const load: PageServerLoad = async ({ locals, fetch }) => { page = homePage; pages = allPages ?? []; if (page) { - await resolveContentImages(page); const tagsMap = await resolvePostOverviewBlocks(page); - await resolveSearchableTextBlocks(page, tagsMap); - await resolveCalendarBlocks(page); - await resolveDeadlineBannerBlocks(page); + await Promise.all([ + resolveContentImages(page), + resolveSearchableTextBlocks(page, tagsMap), + resolveCalendarBlocks(page), + resolveDeadlineBannerBlocks(page), + ]); sanitizeBlocks(page); } } catch (err) {