From 1e3a04f4de80ff30188b13adebd544ef5022b3ef Mon Sep 17 00:00:00 2001 From: "alexei.dolgolyov" Date: Fri, 10 Apr 2026 19:04:35 +0300 Subject: [PATCH] perf: optimize cold start by lazy-loading icons and parallelizing DB queries - Replace barrel `import * as icons` in DynamicIcon with dynamic per-icon imports - Eagerly connect Prisma client at startup to avoid first-request latency - Parallelize 4 sequential DB queries in layout server load with Promise.all --- src/lib/components/ui/DynamicIcon.svelte | 34 ++++++--- src/lib/server/prisma.ts | 5 ++ src/routes/+layout.server.ts | 87 +++++++----------------- 3 files changed, 53 insertions(+), 73 deletions(-) diff --git a/src/lib/components/ui/DynamicIcon.svelte b/src/lib/components/ui/DynamicIcon.svelte index 5405ec5..3706246 100644 --- a/src/lib/components/ui/DynamicIcon.svelte +++ b/src/lib/components/ui/DynamicIcon.svelte @@ -1,6 +1,4 @@ {#if iconComponent} diff --git a/src/lib/server/prisma.ts b/src/lib/server/prisma.ts index ee2b5c5..d92f58f 100644 --- a/src/lib/server/prisma.ts +++ b/src/lib/server/prisma.ts @@ -7,3 +7,8 @@ export const prisma = globalForPrisma.prisma || new PrismaClient(); if (process.env.NODE_ENV !== 'production') { globalForPrisma.prisma = prisma; } + +// Eagerly connect so the first request doesn't pay the connection cost +prisma.$connect().catch(() => { + // Connection will be retried lazily on first query +}); diff --git a/src/routes/+layout.server.ts b/src/routes/+layout.server.ts index f4c6a0a..7349592 100644 --- a/src/routes/+layout.server.ts +++ b/src/routes/+layout.server.ts @@ -3,49 +3,20 @@ import { prisma } from '$lib/server/prisma.js'; import { isOnboardingNeeded } from '$lib/server/services/onboardingService.js'; export const load: LayoutServerLoad = async ({ locals }) => { - // Fetch sidebar boards for the layout - let boards: Array<{ id: string; name: string; icon: string | null }> = []; - - try { - if (locals.user) { - // Authenticated user: fetch boards they can access - if (locals.user.role === 'admin') { - boards = await prisma.board.findMany({ - select: { id: true, name: true, icon: true }, - orderBy: [{ isDefault: 'desc' }, { name: 'asc' }] - }); - } else { - // Regular users: fetch all boards (permission filtering done at page level) - boards = await prisma.board.findMany({ - select: { id: true, name: true, icon: true }, - orderBy: [{ isDefault: 'desc' }, { name: 'asc' }] - }); - } - } else { - // Guest: only guest-accessible boards - boards = await prisma.board.findMany({ + // Build all queries upfront and run them in parallel + const boardsQuery = locals.user + ? prisma.board.findMany({ + select: { id: true, name: true, icon: true }, + orderBy: [{ isDefault: 'desc' }, { name: 'asc' }] + }) + : prisma.board.findMany({ where: { isGuestAccessible: true }, select: { id: true, name: true, icon: true }, orderBy: [{ isDefault: 'desc' }, { name: 'asc' }] }); - } - } catch { - // Fail gracefully — sidebar will just be empty - boards = []; - } - // Fetch user preferences if authenticated - let userPreferences: { - themeMode: string | null; - primaryHue: number | null; - primarySaturation: number | null; - backgroundType: string | null; - locale: string | null; - } | null = null; - - if (locals.user) { - try { - const dbUser = await prisma.user.findUnique({ + const preferencesQuery = locals.user + ? prisma.user.findUnique({ where: { id: locals.user.id }, select: { themeMode: true, @@ -54,38 +25,28 @@ export const load: LayoutServerLoad = async ({ locals }) => { backgroundType: true, locale: true } - }); - userPreferences = dbUser ?? null; - } catch { - // Fail gracefully - } - } + }) + : Promise.resolve(null); - // Fetch system-level custom CSS - let systemCustomCss: string | null = null; - try { - const settings = await prisma.systemSettings.findUnique({ - where: { id: 'singleton' }, - select: { customCss: true } - }); - systemCustomCss = settings?.customCss ?? null; - } catch { - // Fail gracefully - } + const settingsQuery = prisma.systemSettings.findUnique({ + where: { id: 'singleton' }, + select: { customCss: true } + }); - // Check if onboarding is needed - let onboardingNeeded = false; - try { - onboardingNeeded = await isOnboardingNeeded(); - } catch { - // Fail gracefully — don't block the app - } + const onboardingQuery = isOnboardingNeeded(); + + const [boards, userPreferences, settings, onboardingNeeded] = await Promise.all([ + boardsQuery.catch(() => [] as Array<{ id: string; name: string; icon: string | null }>), + preferencesQuery.catch(() => null), + settingsQuery.catch(() => null), + onboardingQuery.catch(() => false) + ]); return { user: locals.user, sidebarBoards: boards, userPreferences, - systemCustomCss, + systemCustomCss: settings?.customCss ?? null, onboardingNeeded }; };