From harness-claude
Optimizes SvelteKit performance by minimizing bundle size via code splitting, reducing latency with preloading and streaming data, and virtualizing large lists for smooth scrolling and better Core Web Vitals.
npx claudepluginhub intense-visions/harness-engineering --plugin harness-claudeThis skill uses the workspace's default tool permissions.
> Minimize bundle size, reduce perceived latency, and handle large datasets efficiently in SvelteKit applications
Guides SvelteKit development with Svelte 5 runes ($state, $derived, $effect), routing, form actions, load functions, SSR, and deployment best practices.
Enforces Svelte 5 best practices in SvelteKit: runes ($state, $derived, $effect), $props(), $bindable(), load functions, form actions, and SSR patterns to fix outdated Svelte 4 code.
Builds full-stack SvelteKit web apps with file-based routing, SSR, SSG, API routes, form actions, and load functions. Activates for +page.svelte, +layout.svelte, or Svelte full-stack queries.
Share bugs, ideas, or general feedback.
Minimize bundle size, reduce perceived latency, and handle large datasets efficiently in SvelteKit applications
Code splitting — automatic with SvelteKit:
npm run build
# Check .svelte-kit/output/client/_app/immutable/chunks/
<script lang="ts">
let HeavyChart: typeof import('./HeavyChart.svelte').default | null = $state(null)
async function loadChart() {
const module = await import('./HeavyChart.svelte')
HeavyChart = module.default
}
</script>
<button onclick={loadChart}>Show Chart</button>
{#if HeavyChart}
<svelte:component this={HeavyChart} {data} />
{/if}
Link preloading — data-sveltekit-preload-data:
data-sveltekit-preload-data to links:<!-- Preload on hover (default behavior for most links) -->
<a href="/dashboard" data-sveltekit-preload-data="hover">Dashboard</a>
<!-- Preload immediately on page load (for critical next steps) -->
<a href="/getting-started" data-sveltekit-preload-data="eager">Get Started</a>
<!-- Disable preloading (for links with side effects) -->
<a href="/logout" data-sveltekit-preload-data="off">Logout</a>
data-sveltekit-preload-code:<!-- Load the JS bundle for this route on hover, without fetching data yet -->
<a href="/editor" data-sveltekit-preload-code="hover">Open Editor</a>
svelte.config.js:export default {
kit: {
preloadStrategy: 'modulepreload', // 'modulepreload' (default) | 'preload-js' | 'preload-mjs'
},
};
Streaming slow data:
// +page.server.ts
export const load: PageServerLoad = async ({ params }) => {
const product = await getProduct(params.id); // fast — awaited
const reviews = getReviews(params.id); // slow — NOT awaited, returns promise
return { product, reviews };
};
<!-- +page.svelte -->
{#await data.reviews}
<ReviewsSkeleton />
{:then reviews}
<ReviewsList {reviews} />
{:catch error}
<p>Failed to load reviews.</p>
{/await}
Virtualizing large lists:
svelte-virtual-scroll-list or implement a basic version:<script lang="ts">
import { VirtualList } from 'svelte-virtual-scroll-list'
let { items }: { items: Item[] } = $props()
</script>
<VirtualList {items} let:item height={400} itemHeight={50}>
<div class="row">{item.name}</div>
</VirtualList>
Image optimization:
loading="lazy" attribute for below-fold images to defer loading:<img src="/photo.jpg" alt="Description" loading="lazy" decoding="async" />
srcset and sizes for responsive images:<img
src="/image-800.jpg"
srcset="/image-400.jpg 400w, /image-800.jpg 800w, /image-1200.jpg 1200w"
sizes="(max-width: 600px) 400px, (max-width: 1024px) 800px, 1200px"
alt="Hero image"
/>
Reducing reactive overhead:
<!-- Bad: creates new object every render -->
<Component config={{ theme: 'dark', size: 'lg' }} />
<!-- Good: stable reference -->
<script>
const config = { theme: 'dark', size: 'lg' }
</script>
<Component {config} />
$state.raw for large objects that only change by full replacement:// Avoids deep reactivity proxy overhead
let dataset = $state.raw<DataPoint[]>(initialData);
// Update only via full reassignment:
dataset = await fetchNewData();
SvelteKit preloading strategy:
SvelteKit's link preloading works in two steps:
preload-code — fetches the JavaScript chunk for the destination routepreload-data — runs the destination route's load functionDefault behavior: on tap/click, SvelteKit preloads code. With data-sveltekit-preload-data="hover", data preloading starts on hover — making navigation feel instant.
Bundle analysis:
Identify large dependencies causing bundle bloat:
npx vite-bundle-visualizer
# or
npm run build -- --report
Common culprits: moment.js (use date-fns instead), lodash (use individual imports), large chart libraries (load dynamically).
SvelteKit performance vs. React:
Svelte compiles to vanilla JavaScript with no virtual DOM — component updates are surgical DOM mutations. This eliminates reconciliation overhead for interactions but doesn't remove the need for virtualization on very large lists.
Prerender for maximum performance:
For content that doesn't change per-user, prerender pages at build time:
// +page.ts
export const prerender = true;
Prerendered pages are served as static HTML with no server processing time — ideal for marketing pages, docs, and blog posts.
Web Vitals checklist:
setTimeout or scheduler.yield()width/height attributes or CSS aspect-ratio; avoid injecting content above existing contenthttps://kit.svelte.dev/docs/link-options