Changelog 2024/48 aka we 🖤 Svelte 5

We have rewritten our platform's frontend using Svelte 5, streamlining our workflow and refining our codebase to develop a more flexible and sustainable codebase. The following elements were notable.

What We Appreciate in Svelte 5

  1. Reusable Snippets Replacing Slots
  2. Callbacks Replacing Dispatchers
  3. Simplified Prop Handling with $props
  4. Improved Component Typing
  5. Explicit Reactivity with Runes
  6. Reduced Bundle Sizes

1. Reusable Snippets Replacing Slots

Svelte 5's new snippets system provides a powerful alternative to the slot-based system from Svelte 4. Where we previously used named slots with <svelte:fragment slot="name">, we now leverage the more flexible snippet syntax {#snippet name()}. This allows passing parameters to template fragments and maintaining reactivity, making complex UI patterns like recursive components and compound components more straightforward. Our modal and dropdown components benefit from this change, as content can be dynamically injected while preserving state and context.

<!-- Parent.svelte -->
<Card>
  <svelte:fragment slot="title">
    My Card Title
  </svelte:fragment>
  <svelte:fragment slot="content">
    Card content here
  </svelte:fragment>
</Card>

<!-- Card.svelte -->
<div class="card">
  <div class="title">
    <slot name="title" />
  </div>
  <div class="content">
    <slot name="content" />
  </div>
</div>

Svelte 4

<!-- Parent.svelte -->
<Card>
  {#snippet title()}
    My Card Title
  {/snippet}
  
  {#snippet content()}
    Card content here
  {/snippet}
</Card>

<!-- Card.svelte -->
<script>
  let { title, content } = $props();
</script>

<div class="card">
  <div class="title">
    {@render title()}
  </div>
  <div class="content">
    {@render content()}
  </div>
</div>

Svelte 5

2. Callbacks Replacing Dispatchers

Component communication is more straightforward with Svelte 5's approach to props and callbacks compared to event dispatchers. Where Svelte 4 required using createEventDispatcher pattern with dispatch('submit', { data })  and handling it with on:submit event listeners, Svelte 5 enables passing callback functions directly through props <Child onSubmit={handleSubmission} />. This reduces boilerplate, provides better TypeScript integration, and makes data flow more explicit throughout the application.

<!-- Child.svelte -->
<script>
  import { createEventDispatcher } from 'svelte';
  const dispatch = createEventDispatcher();
  
  function handleSubmit(data) {
    dispatch('submit', { data });
  }
</script>

<!-- Parent.svelte -->
<Child on:submit={({ detail }) => handleSubmission(detail.data)} />

Svelte 4

<!-- Child.svelte -->
<script>
  let { onSubmit } = $props();
  
  function handleSubmit(data) {
    onSubmit?.(data);
  }
</script>

<!-- Parent.svelte -->
<Child onSubmit={handleSubmission} />

Svelte 5

3. Simplified Prop Handling with $props

Svelte 5's $props rune brings a cleaner approach to component properties. The verbose export let syntax from Svelte 4 is replaced with a single destructuring statement let { prop1 = defaultValue, prop2 } = $props(). This approach significantly reduces code verbosity, improves TypeScript integration, significantly reduces prop-related boilerplate in components, and strengthens type checking.

4. Improved Component Typing

The typing improvements in Svelte 5 have been another standout feature for us. Built-in typed properties like placeholder and maxlength now function seamlessly, while custom traits can be defined with precision to ensure type safety. These enhancements have not only reduced the risk of runtime errors but have also made our code more robust and maintainable. Additionally, the deeper integration with TypeScript has significantly improved productivity and reliability.

5. Explicit Reactivity with Runes

Svelte 5's runes system represents a fundamental shift in reactivity management. Instead of Svelte 4's implicit reactivity with let declarations and $: statements, Svelte 5 uses explicit runes like $state() and $derived(). A typical example shows this evolution:

// Svelte 4
let count = 0;
$: tripled = count * 3;

// Svelte 5
let count = $state(0);
let tripled = $derived(count * 3);

6. Reduced Bundle Sizes

The new compiler in Svelte 5 has brought significant optimisations, leading to bundle size reductions of up to 50% compared to Svelte 4. This efficiency boost not only improves performance but also aligns with our commitment to delivering a lightweight and fast platform.

A Worthwhile?

While adopting Svelte 5 and its new features—like snippets, callbacks, and runes—required some adjustments to our workflow, the results have been well worth the effort. The new features we’ve integrated have allowed us to create a cleaner, more scalable codebase. These changes are already helping us work more efficiently and will undoubtedly lead to fewer bugs and a smoother development experience in the long term.


To stay updated on what’s new at Nomodo, follow us on Twitter or join our Nomodo.io Discord channel. Also, don’t miss exploring MedusaJS.

From all of us at Nomodo.io, thank you for being part of our journey!

Subscribe to nomodo.io

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe