Skip to main content
Svelte Fundamentals
CHAPTER 23 Beginner

Performance Optimization in Svelte

Updated: May 18, 2026
5 min read

# CHAPTER 23

Performance Optimization in Svelte

1. Chapter Introduction

Svelte is already the most performant frontend framework out of the box — no virtual DOM means fewer allocations and faster updates. But as applications grow, performance still requires intentional optimization. This chapter covers practical techniques to keep Svelte apps blazing fast.

2. Learning Objectives

  • Implement component lazy loading.
  • Optimize reactive updates with $: discipline.
  • Use keyed each loops for efficient list updates.
  • Implement virtual scrolling for large datasets.
  • Measure and profile Svelte app performance.

3. Why Svelte is Already Fast

text
12345678
React/Vue:            Svelte:
1. setState()         1. count = count + 1
2. Create new vDOM    2. ← (nothing)
3. Diff old vs new    3. ← (nothing)
4. Reconcile          4. ← (nothing)
5. Update DOM         5. Update DOM directly (targeted)

Svelte skips steps 2-4 entirely!

4. Lazy Loading Components

svelte
123456789101112131415161718192021
<!-- Dynamically import heavy components only when needed -->
<script>
  let HeavyChart;
  let showChart = false;

  async function loadChart() {
    if (!HeavyChart) {
      const module = await import(&#039;./HeavyChart.svelte');
      HeavyChart = module.default;
    }
    showChart = true;
  }
</script>

<button on:click={loadChart}>Show Analytics Chart</button>

{#if showChart && HeavyChart}
  <svelte:component this={HeavyChart} />
{:else if showChart}
  <p>Loading chart...</p>
{/if}

5. SvelteKit Route Code Splitting

SvelteKit automatically code-splits by route — each page is its own JavaScript chunk:
javascript
123
// Each route is automatically a separate bundle
// /src/routes/heavy-feature/+page.svelte → loaded ONLY when visited
// Initial bundle only contains the home page code

6. Optimizing Reactive Updates

svelte
123456789101112131415161718
<script>
  // ❌ BAD: Reactive block runs on every keystroke if 'name' changes
  let name = &#039;';
  $: {
    expensiveOperation(name); // Runs on every letter typed!
  }

  // ✅ GOOD: Debounce the expensive operation
  let timer;
  $: {
    clearTimeout(timer);
    timer = setTimeout(() => expensiveOperation(name), 300);
  }

  // ✅ BETTER: Only run when the final name is set
  let submittedName = &#039;';
  function handleSubmit() { expensiveOperation(submittedName); }
</script>

7. Keyed {#each} Optimization

svelte
123456789
<!-- ❌ No key: Svelte reuses DOM nodes by position — wrong with add/remove -->
{#each items as item}
  <ItemComponent {item} />
{/each}

<!-- ✅ With key: Svelte reuses DOM nodes by identity — correct always -->
{#each items as item (item.id)}
  <ItemComponent {item} />
{/each}

8. Store Optimization

javascript
12345678
// ❌ BAD: One giant store — EVERY component re-renders when ANY field changes
const appStore = writable({ user, products, cart, theme, notifications });

// ✅ GOOD: Split into focused stores — components only re-render when their slice changes
export const userStore = writable(null);
export const cartStore = writable([]);
export const themeStore = writable(&#039;light&#039;);
export const notificationStore = writable([]);

9. Virtual Scrolling (Large Lists)

svelte
123456789101112131415161718192021222324252627282930313233343536
<script>
  import { onMount } from &#039;svelte';

  let items = Array.from({ length: 10000 }, (_, i) => ({ id: i, name: `Item ${i}` }));
  let containerHeight = 500;
  let itemHeight = 40;
  let scrollTop = 0;

  $: startIndex = Math.floor(scrollTop / itemHeight);
  $: visibleCount = Math.ceil(containerHeight / itemHeight) + 1;
  $: visibleItems = items.slice(startIndex, startIndex + visibleCount);
  $: totalHeight = items.length * itemHeight;
  $: offsetY = startIndex * itemHeight;

  function handleScroll(e) {
    scrollTop = e.target.scrollTop;
  }
</script>

<div
  class="scroll-container"
  style="height:{containerHeight}px; overflow-y:auto;"
  on:scroll={handleScroll}
>
  <!-- Spacer for total scrollable height -->
  <div style="height:{totalHeight}px; position:relative;">
    <!-- Only render visible items -->
    <div style="transform:translateY({offsetY}px)">
      {#each visibleItems as item (item.id)}
        <div class="item" style="height:{itemHeight}px;">
          {item.name}
        </div>
      {/each}
    </div>
  </div>
</div>

10. Build Optimizations

bash
12345678
# Production build — tree-shaking + minification + SSR
npm run build

# Analyze bundle size
npx vite-bundle-visualizer

# Preload critical resources in SvelteKit
# src/routes/+layout.svelte
svelte
123
<svelte:head>
  <link rel="preload" href="/fonts/inter.woff2" as="font" crossorigin />
</svelte:head>

11. Common Mistakes

  • Reactive statements with side effects on frequently-changing state: $: console.log(mouseX, mouseY) inside a mousemove handler logs hundreds of times/second.
  • Loading all components upfront: Import heavy components lazily using dynamic import().

12. MCQs

Question 1

Why is Svelte faster than React/Vue by default?

Question 2

What is code splitting?

Question 3

How do you lazily import a Svelte component?

Question 4

What optimization does {#each items as item (item.id)} provide?

Question 5

How do you optimize a reactive statement that triggers on rapid changes?

Question 6

What is virtual scrolling?

Question 7

What is the performance benefit of splitting large stores into smaller focused stores?

Question 8

What build tool command analyzes which packages are taking the most bundle space?

Question 9

What does SvelteKit automatically do for performance with file-based routes?

Question 10

What HTML <link> attribute preloads critical resources before they are needed?

13. Interview Questions

  • Q: Svelte is often described as "disappearing at build time." What does this mean for performance?
  • Q: What is virtual scrolling and when is it necessary?

14. Summary

Svelte's compiler architecture gives a performance head start that React and Vue cannot match. On top of this foundation, lazy loading, code splitting, keyed loops, focused stores, and virtual scrolling ensure Svelte applications remain fast even at enterprise scale with millions of data points.

15. Next Chapter Recommendation

In Chapter 24: Testing in Svelte, we write unit tests for component logic and integration tests for component rendering using Vitest and Svelte Testing Library.

Finish this Chapter

Save your progress on your learning path and prepare for coding interview challenges.

Discussion

Join the discussion

Log in or create a free account to participate.

Sort: ·