5 min read
Svelte 5 brings runes for universal reactivity, snippets for reusable markup, and compiler improvements.
With its compiler-first approach, fine-grained reactivity, and ability to integrate with any JavaScript project, Svelte stands apart from other frameworks.
At Vercel, we're big fans of Svelte—deeply invested in its success and constantly working to make our platform the best place to build and deploy Svelte apps.
With the arrival of Svelte 5, let's explore what makes this release exciting.
Runes
Svelte 5 introduces runes to manage reactivity. These symbols give you explicit control over application state.
The $state
, $derived
, and $effect
runes
At the heart of Svelte 5's updated reactivity system are the $state
, $derived
, and $effect
runes. These provide concise ways to manage state and its dependencies within your components.
$state
: Declares a reactive variable, replacing top-levellet
declarations from Svelte 4. Whenever a$state
variable's value changes, Svelte automatically updates the value anywhere it's used in your component. This eliminates manual updates and simplifies state management.$derived
: Creates reactive values based on other$state
or$derived
values. When a dependency changes, Svelte marks the$derived
value for recalculation upon its next read. This ensures consistency and simplifies complex calculations. It replaces the$:
syntax from Svelte 4, offering more granular reactivity with fewer gotchas.$effect
: Runs code in response to state changes (e.g., rendering to a<canvas>
or interacting with an external library). While powerful, use$effect
sparingly, as excessive side effects can make your code harder to follow. Svelte encourages declarative approaches whenever possible.
Signals and fine-grained reactivity
Frameworks like Solid have popularized signals, which offer a responsive approach to reactivity. A signal is a container that notifies subscribers when its value changes. This lets frameworks track dependencies precisely and update only necessary parts of the application, improving performance.
Runes like $state
and $derived
let you work with reactive values directly, while Svelte's compiler handles the underlying signal management.
For example, writing a counter component in Svelte 5 is as straightforward as:
<script> let count = $state(0); let doubled = $derived(count * 2);</script>
<button onclick={() => count++}> Clicks: {count}</button>
<p>Click doubled: {doubled}</p>
Universal reactivity with .svelte.js
files
Previously, managing global state in Svelte often involved stores, which had a different API and behavior than component-level reactivity. This created a disconnect and sometimes led to inconsistencies.
With .svelte.js
and .svelte.ts
files, you define shared state and logic in a single place and access it from any component using runes. This eliminates prop drilling, simplifies complex store setups, reduces boilerplate, and improves code maintainability.
Svelte now treats reactivity as a first-class language construct, blurring the lines between components and application logic for a more cohesive and intuitive development experience. This is a shift from Svelte 3 and 4, where reactivity was primarily confined to components.
Other runes
Svelte 5 introduces other runes that simplify common tasks and reduce boilerplate code. Learn more about runes.
Compiler improvements
Svelte has always been compiler-first. Unlike traditional frameworks that perform calculations and virtual DOM diffing at runtime, Svelte shifts this work to compile time. It compiles your components into highly optimized vanilla JavaScript, eliminating the need for a runtime library.
This results in smaller bundles, faster initial load times, and improved runtime performance. It also means you can use compiled Svelte components in any JavaScript project, including those that don't use Svelte.
Svelte 5 builds on this foundation with compiler improvements that enhance performance, reduce bundle sizes, and streamline development.
Components as functions
In Svelte 5, components are now plain JavaScript functions. This simplifies optimization, as build tools and JavaScript engines optimize functions effectively. For example, function components can be inlined into their caller, reducing overhead.
Svelte is the first major framework where components directly call each other, eliminating intermediary functions or complex component creation mechanisms. This contributes to Svelte's performance and excellent Core Web Vital scores.
Native TypeScript support
Svelte 5 introduces native TypeScript support. Previous versions used a preprocessor, which added moving parts (like source maps) and slowed down builds.
Native TypeScript support means faster builds and the ability to use TypeScript annotations directly in your Svelte markup—for instance, inside inline event handlers.
This, combined with the new approach to event handling and simplified state management with runes, makes for easier development and library authoring.
Snippets
Svelte 5 introduces snippets, which let you define reusable blocks of markup and logic within a component, which can then be rendered multiple times or passed to other components. They also replace Svelte 4’s slots.
Let’s look at an example:
<script> let items = [ { id: 1, name: 'Apple', price: 0.5 }, { id: 2, name: 'Banana', price: 0.25 }, { id: 3, name: 'Orange', price: 0.75 } ]</script>
<ul> {#each items as item} {@render row(item)} {/each}</ul>
{#snippet row(item)} <li> <span>{item.name}:</span> <span>${item.price.toFixed(2)}</span> </li>{/snippet}
In this example, we define a row
snippet that encapsulates the markup for each item in the list. The snippet is then rendered for each item using the {@render}
tag within the {#each}
block.
Snippets can also be passed as props to other components:
<script> import ItemList from './ItemList.svelte'; let items = [ { id: 1, name: 'Apple', price: 0.5 }, { id: 2, name: 'Banana', price: 0.25 }, { id: 3, name: 'Orange', price: 0.75 } ];</script>
<ItemList {items}> // Implicitly pass this snippet as a prop. {#snippet row(item)} <li> <span>{item.name}:</span> <span>${item.price.toFixed(2)}</span> </li> {/snippet}</ItemList>
<script> let { row, items } = $props()</script>
{#each items as item} {@render row(item)}{/each}
In this case, we pass a row
snippet from App.svelte
to ItemList.svelte
. This separation of concerns makes it easy to reuse the ItemList
component with different item rendering styles without modifying its internal structure.
Vite benefits
SvelteKit uses Vite, so you benefit from its growing ecosystem. Any tool that works in Vite also works in SvelteKit.
You can access a wide range of tools and plugins that enhance the development experience with minimal configuration. For example:
Vitest for unit and integration testing
Storybook for component development
@sveltejs/enhanced-img
for static image optimization
Svelte also benefits from Vite's optimized development server and hot module replacement (HMR), which speeds up development workflows.
Svelte's growing community
Svelte's growth and popularity are evident in industry surveys like the 2024 Stack Overflow Developer Survey (itself built with Svelte), which ranks Svelte at 73% developer satisfaction, and the State of JavaScript 2023 survey, which ranks Svelte highly for positivity and retention.
Many companies, large and small, use Svelte:
And Vercel customers like Dbrand and Hugging Face.
Svelte has allowed to us to ship quickly and with confidence, helping us keep pace with a dynamic AI ecosystem, despite a minority of the team being frontend developers. Our latest version of Gradio is also built on top of SvelteKit, bringing all of the power and performance of a best-in-class framework to around 1 million developers every month. The future is equally exciting; now that we are using SvelteKit, we can release a whole host of new features that would otherwise be costly to implement and support.
Join the Svelte community on Discord.
Svelte on Vercel
Vercel is invested in making our platform the best place to deploy Svelte apps. We collaborate closely with Svelte maintainers, and several members of the Svelte core team work at Vercel to ensure a sustainable future for the framework and a premier deployment experience.
The Build Output API enables SvelteKit (and other frameworks) to implement Vercel features like Incremental Static Regeneration (ISR), streaming serverless function responses, dynamic image optimization, and Skew Protection. Vercel is committed to open standards that can benefit the entire web development ecosystem.
Recent SvelteKit improvements on Vercel include:
Enhanced toolbar support for streamlined debugging
Improved analytics for deeper insights into application performance
Integrated feature flagging for controlled rollouts
Speed Insights for performance monitoring and optimization (used on
svelte.dev
for consistently passing Core Web Vitals).
Getting started with Svelte
Svelte 5 makes frontend development easier while staying flexible and powerful. To get started, try the interactive Svelte tutorial, deploy a SvelteKit templates, or view the official Svelte 5 migration guide.