Error Handling and SSR

Back

Loading concept...

๐Ÿ›ก๏ธ Error Handling & SSR in Svelte: Your Appโ€™s Safety Net

Analogy: Think of your Svelte app like a circus act. Error Boundaries are the safety nets that catch performers when they fall. Hydration is like bringing a statue to lifeโ€”the server sculpts it, and the browser breathes life into it!


๐ŸŽช The Big Picture

Imagine youโ€™re watching a circus show. The acrobats are doing amazing flips (your components rendering). But what if someone slips? Without a safety net, the whole show stops!

In Svelte:

  • Error Boundaries = Safety nets that catch falling components
  • Hydration = The magical moment when a still statue starts moving

๐ŸŽฏ What Youโ€™ll Learn

graph TD A["Error Handling & SSR"] --> B["๐Ÿ›ก๏ธ Error Boundaries"] A --> C["๐Ÿ’ง Hydration"] B --> D["Catch errors gracefully"] B --> E["Show fallback UI"] C --> F["Server renders HTML"] C --> G["Browser makes it interactive"]

๐Ÿ›ก๏ธ Part 1: Error Boundaries

What Are Error Boundaries?

Simple Answer: A special wrapper that catches errors from its children and shows something helpful instead of crashing everything.

๐ŸŽˆ Kid-Friendly Example

Imagine you have a toy box (your app). Inside are many toys (components). One toy is broken and makes a loud noise when you touch it (an error).

Without Error Boundary:

  • Touch broken toy โ†’ CRASH! All toys stop working!

With Error Boundary:

  • Touch broken toy โ†’ Only that toy is put aside
  • A sign appears: โ€œThis toy is being fixed!โ€
  • All other toys keep working!

How Error Boundaries Work in Svelte

In SvelteKit, you use a special file called +error.svelte:

<!-- +error.svelte -->
<script>
  import { page } from '$app/stores';
</script>

<div class="error-box">
  <h1>Oops! ๐Ÿ˜…</h1>
  <p>Error: {$page.error.message}</p>
  <a href="/">Go Home</a>
</div>

๐Ÿ“ File Structure

src/routes/
โ”œโ”€โ”€ +page.svelte      (Your page)
โ”œโ”€โ”€ +error.svelte     (Catches errors!)
โ””โ”€โ”€ +layout.svelte    (Wraps everything)

Creating Custom Error Boundaries

For component-level errors, create your own boundary:

<!-- ErrorBoundary.svelte -->
<script>
  let hasError = false;
  let errorMessage = '';

  // Catch errors from children
  export function handleError(error) {
    hasError = true;
    errorMessage = error.message;
  }
</script>

{#if hasError}
  <div class="fallback">
    <p>Something went wrong!</p>
    <p>{errorMessage}</p>
    <button onclick={() => hasError = false}>
      Try Again
    </button>
  </div>
{:else}
  <slot />
{/if}

Using Your Error Boundary

<ErrorBoundary>
  <RiskyComponent />
</ErrorBoundary>

๐ŸŒŸ Error Boundary Best Practices

Do โœ… Donโ€™t โŒ
Wrap risky components Wrap entire app in one
Show helpful messages Show technical jargon
Provide recovery options Leave users stuck
Log errors for debugging Ignore error details

Real-World Error Handling

<script>
  import { onMount } from 'svelte';

  let data = null;
  let error = null;
  let loading = true;

  onMount(async () => {
    try {
      const res = await fetch('/api/data');
      if (!res.ok) throw new Error('Failed!');
      data = await res.json();
    } catch (e) {
      error = e.message;
    } finally {
      loading = false;
    }
  });
</script>

{#if loading}
  <p>Loading... โณ</p>
{:else if error}
  <div class="error">
    <p>๐Ÿ˜ข {error}</p>
    <button onclick={() => location.reload()}>
      Retry
    </button>
  </div>
{:else}
  <div>{data}</div>
{/if}

๐Ÿ’ง Part 2: Hydration

What Is Hydration?

Simple Answer: The server sends HTML (like a frozen statue), and the browser โ€œwakes it upโ€ to make it interactive!

๐ŸŽญ The Statue Story

  1. Server: Sculpts a beautiful marble statue (HTML)
  2. Browser receives: A perfect but lifeless statue
  3. Hydration happens: Magic breath brings it to life!
  4. Result: The statue can move, talk, respond!
graph TD A["๐Ÿ–ฅ๏ธ Server"] -->|Sends HTML| B["๐Ÿ“„ Static Page"] B -->|Browser loads JS| C["โšก Hydration"] C -->|Attaches listeners| D["๐ŸŽฎ Interactive App"]

How Hydration Works

Step 1: Server Renders HTML

// +page.server.js
export async function load() {
  const data = await fetchData();
  return { data };
}

Step 2: HTML Arrives at Browser

<!-- What user sees immediately -->
<div>
  <h1>Welcome!</h1>
  <button>Click me</button>
</div>
<!-- Button exists but doesn't work yet! -->

Step 3: JavaScript Hydrates

<!-- +page.svelte -->
<script>
  export let data;

  function handleClick() {
    alert('Now I work!');
  }
</script>

<h1>Welcome!</h1>
<button onclick={handleClick}>
  Click me
</button>
<!-- Now the button actually works! -->

Why Hydration Matters

Without Hydration (Client-Only)

User visits โ†’ Blank page โ†’ JS loads โ†’ Content appears
โฑ๏ธ User waits... waits... waits...
๐Ÿ˜ž Bad experience!

With Hydration (SSR)

User visits โ†’ Content appears INSTANTLY โ†’ JS loads โ†’ Becomes interactive
โฑ๏ธ User sees content immediately!
๐Ÿ˜Š Great experience!

Hydration Challenges

โš ๏ธ The Mismatch Problem

Server and client must produce the same HTML!

Bad Example:

<script>
  // Different on server vs client!
  let time = new Date().toLocaleTimeString();
</script>

<p>Time: {time}</p>
<!-- Server: "10:30:00 AM" -->
<!-- Client: "10:30:01 AM" -->
<!-- MISMATCH! Hydration error! -->

Good Example:

<script>
  import { onMount } from 'svelte';
  import { browser } from '$app/environment';

  let time = '';

  onMount(() => {
    // Only runs in browser!
    time = new Date().toLocaleTimeString();
  });
</script>

<p>Time: {time || 'Loading...'}</p>

Handling Browser-Only Code

<script>
  import { browser } from '$app/environment';
  import { onMount } from 'svelte';

  let windowWidth = 0;

  onMount(() => {
    if (browser) {
      windowWidth = window.innerWidth;
    }
  });
</script>

{#if browser}
  <p>Window width: {windowWidth}px</p>
{:else}
  <p>Measuring window...</p>
{/if}

Partial Hydration Tips

Sometimes you donโ€™t need everything to be interactive:

<!-- Static content - no JS needed -->
<header>
  <h1>My Blog</h1>
  <nav>Links here</nav>
</header>

<!-- Interactive part - needs hydration -->
<main>
  <CommentSection />
  <LikeButton />
</main>

๐ŸŽฏ Hydration Quick Rules

Concept Remember
SSR Server makes HTML first
Hydration Browser adds interactivity
Mismatch Server + Client must match!
onMount Runs only in browser
browser Check if in browser

๐Ÿš€ Putting It All Together

<script>
  import { browser } from '$app/environment';
  import { onMount } from 'svelte';
  import { page } from '$app/stores';

  let mounted = false;
  let error = null;

  onMount(() => {
    mounted = true;
  });

  function riskyOperation() {
    try {
      // Do something risky
    } catch (e) {
      error = e.message;
    }
  }
</script>

{#if error}
  <!-- Error Boundary fallback -->
  <div class="error-state">
    <p>๐Ÿ˜ข {error}</p>
    <button onclick={() => error = null}>
      Try Again
    </button>
  </div>
{:else}
  <!-- Hydration-safe content -->
  {#if mounted}
    <InteractiveWidget />
  {:else}
    <div class="skeleton">Loading...</div>
  {/if}
{/if}

๐ŸŽช Circus Finale: Summary

graph TD A["Your Svelte App"] --> B{Error Occurs?} B -->|Yes| C["๐Ÿ›ก๏ธ Error Boundary Catches"] C --> D["Shows Fallback UI"] D --> E["User Can Recover"] B -->|No| F["๐Ÿ’ง Hydration Process"] F --> G["Server Renders HTML"] G --> H["Browser Receives Page"] H --> I["JS Loads &amp; Hydrates"] I --> J["๐ŸŽฎ Fully Interactive!"]

๐ŸŒŸ Key Takeaways

  1. Error Boundaries = Safety nets for your components
  2. Use +error.svelte for page-level errors in SvelteKit
  3. Hydration = Server HTML + Browser JS = Interactive App
  4. Always match server and client rendering
  5. Use onMount for browser-only code
  6. Check browser before using window/document

๐ŸŽฏ Remember This!

Error Boundaries: โ€œIf a clown falls, the show goes on!โ€

Hydration: โ€œThe server paints the picture, the browser brings it to life!โ€

Youโ€™ve got this! Your Svelte apps are now crash-proof and lightning-fast! ๐Ÿš€

Loading story...

Story - Premium Content

Please sign in to view this story and start learning.

Upgrade to Premium to unlock full access to all stories.

Stay Tuned!

Story is coming soon.

Story Preview

Story - Premium Content

Please sign in to view this concept and start learning.

Upgrade to Premium to unlock full access to all content.