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
This commit is contained in:
2026-04-10 19:04:35 +03:00
parent 7beca05eec
commit 1e3a04f4de
3 changed files with 53 additions and 73 deletions
+24 -10
View File
@@ -1,6 +1,4 @@
<script lang="ts"> <script lang="ts">
import * as icons from 'lucide-svelte';
interface Props { interface Props {
name: string | null; name: string | null;
size?: number; size?: number;
@@ -9,17 +7,33 @@
let { name, size = 16, class: className = '' }: Props = $props(); let { name, size = 16, class: className = '' }: Props = $props();
// Convert kebab-case to PascalCase: "layout-dashboard" → "LayoutDashboard" // Convert PascalCase or kebab-case to kebab-case filename
function toPascalCase(str: string): string { // "LayoutDashboard" → "layout-dashboard", "layout-dashboard" stays as-is
function toKebabCase(str: string): string {
return str return str
.split('-') .replace(/([a-z0-9])([A-Z])/g, '$1-$2')
.map((part) => part.charAt(0).toUpperCase() + part.slice(1)) .replace(/([A-Z])([A-Z][a-z])/g, '$1-$2')
.join(''); .toLowerCase();
} }
const iconComponent = $derived( let iconComponent = $state<typeof import('svelte').SvelteComponent | null>(null);
name ? ((icons as Record<string, unknown>)[toPascalCase(name)] as typeof import('svelte').SvelteComponent | undefined) ?? null : null $effect(() => {
); const currentName = name;
iconComponent = null;
if (!currentName) return;
const kebab = toKebabCase(currentName);
import(/* @vite-ignore */ `lucide-svelte/icons/${kebab}`)
.then((mod) => {
// Only apply if name hasn't changed during load
if (name === currentName) {
iconComponent = mod.default;
}
})
.catch(() => {
// Icon not found
});
});
</script> </script>
{#if iconComponent} {#if iconComponent}
+5
View File
@@ -7,3 +7,8 @@ export const prisma = globalForPrisma.prisma || new PrismaClient();
if (process.env.NODE_ENV !== 'production') { if (process.env.NODE_ENV !== 'production') {
globalForPrisma.prisma = prisma; 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
});
+19 -58
View File
@@ -3,49 +3,20 @@ import { prisma } from '$lib/server/prisma.js';
import { isOnboardingNeeded } from '$lib/server/services/onboardingService.js'; import { isOnboardingNeeded } from '$lib/server/services/onboardingService.js';
export const load: LayoutServerLoad = async ({ locals }) => { export const load: LayoutServerLoad = async ({ locals }) => {
// Fetch sidebar boards for the layout // Build all queries upfront and run them in parallel
let boards: Array<{ id: string; name: string; icon: string | null }> = []; const boardsQuery = locals.user
? prisma.board.findMany({
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 }, select: { id: true, name: true, icon: true },
orderBy: [{ isDefault: 'desc' }, { name: 'asc' }] orderBy: [{ isDefault: 'desc' }, { name: 'asc' }]
}); })
} else { : prisma.board.findMany({
// 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({
where: { isGuestAccessible: true }, where: { isGuestAccessible: true },
select: { id: true, name: true, icon: true }, select: { id: true, name: true, icon: true },
orderBy: [{ isDefault: 'desc' }, { name: 'asc' }] orderBy: [{ isDefault: 'desc' }, { name: 'asc' }]
}); });
}
} catch {
// Fail gracefully — sidebar will just be empty
boards = [];
}
// Fetch user preferences if authenticated const preferencesQuery = locals.user
let userPreferences: { ? prisma.user.findUnique({
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({
where: { id: locals.user.id }, where: { id: locals.user.id },
select: { select: {
themeMode: true, themeMode: true,
@@ -54,38 +25,28 @@ export const load: LayoutServerLoad = async ({ locals }) => {
backgroundType: true, backgroundType: true,
locale: true locale: true
} }
}); })
userPreferences = dbUser ?? null; : Promise.resolve(null);
} catch {
// Fail gracefully
}
}
// Fetch system-level custom CSS const settingsQuery = prisma.systemSettings.findUnique({
let systemCustomCss: string | null = null;
try {
const settings = await prisma.systemSettings.findUnique({
where: { id: 'singleton' }, where: { id: 'singleton' },
select: { customCss: true } select: { customCss: true }
}); });
systemCustomCss = settings?.customCss ?? null;
} catch {
// Fail gracefully
}
// Check if onboarding is needed const onboardingQuery = isOnboardingNeeded();
let onboardingNeeded = false;
try { const [boards, userPreferences, settings, onboardingNeeded] = await Promise.all([
onboardingNeeded = await isOnboardingNeeded(); boardsQuery.catch(() => [] as Array<{ id: string; name: string; icon: string | null }>),
} catch { preferencesQuery.catch(() => null),
// Fail gracefully — don't block the app settingsQuery.catch(() => null),
} onboardingQuery.catch(() => false)
]);
return { return {
user: locals.user, user: locals.user,
sidebarBoards: boards, sidebarBoards: boards,
userPreferences, userPreferences,
systemCustomCss, systemCustomCss: settings?.customCss ?? null,
onboardingNeeded onboardingNeeded
}; };
}; };