Svelte 5 and Runes: Why the Framework Is Gaining Ground in 2025
Hello HaWkers, while React and Vue dominate frontend conversations, a framework has been growing silently and winning over developers: Svelte. With the release of Svelte 5 and its Runes, the framework made a significant leap that deserves your attention.
In this article, we'll explore what makes Svelte special, how Runes work, and why you should consider this framework for your next projects.
What Makes Svelte Different
Unlike React and Vue that work as runtime libraries, Svelte is a compiler. This changes everything.
The fundamental difference:
| Aspect | React/Vue | Svelte |
|---|---|---|
| Execution | Runtime in browser | Compilation at build |
| Bundle | Includes framework | Only your code |
| Reactivity | Virtual DOM | Surgical DOM updates |
| Typical size | 40-100KB+ | 5-15KB |
What this means in practice:
- Svelte apps are smaller and faster
- Less JavaScript for the browser to process
- Better performance especially on mobile devices
- Reduced initial load time
⚡ Benchmark: In comparative tests, Svelte applications often load 2-3x faster than React equivalents.
Svelte 5 and Runes
Version 5 of Svelte brought a paradigm shift: Runes. They represent a new way of handling reactivity.
What Are Runes
Runes are reactivity primitives inspired by Solid.js that use a special syntax with $:
The main Runes:
$state- Declares reactive state$derived- Computed values$effect- Side effects$props- Component props
Before Runes (Svelte 4)
<script>
// State was implicitly reactive
let count = 0;
let doubled = 0;
// Reactive statements with $:
$: doubled = count * 2;
$: console.log('Count changed:', count);
function increment() {
count += 1;
}
</script>
<button on:click={increment}>
{count} x 2 = {doubled}
</button>With Runes (Svelte 5)
<script>
// State explicitly declared
let count = $state(0);
// Derived values are explicit
let doubled = $derived(count * 2);
// Effects are explicit
$effect(() => {
console.log('Count changed:', count);
});
function increment() {
count += 1;
}
</script>
<button onclick={increment}>
{count} x 2 = {doubled}
</button>
Code Comparison
Let's see how Svelte compares with React and Vue in real scenarios:
Counter Component
Svelte 5:
<script>
let count = $state(0);
</script>
<button onclick={() => count++}>
Clicks: {count}
</button>
<style>
button {
padding: 1rem 2rem;
font-size: 1.2rem;
}
</style>React:
import { useState } from 'react';
import './Counter.css';
function Counter() {
const [count, setCount] = useState(0);
return (
<button onClick={() => setCount(count + 1)}>Clicks: {count}</button>
);
}
export default Counter;Vue 3:
<script setup>
import { ref } from 'vue';
const count = ref(0);
</script>
<template>
<button @click="count++">Clicks: {{ count }}</button>
</template>
<style scoped>
button {
padding: 1rem 2rem;
font-size: 1.2rem;
}
</style>Observations:
- Svelte: Built-in scoped CSS, cleaner syntax
- React: Needs separate CSS file or CSS-in-JS
- Vue: Similar to Svelte, but more verbose
Form with Validation
Svelte 5:
<script>
let email = $state('');
let password = $state('');
let errors = $state({});
let isValid = $derived(
email.includes('@') &&
password.length >= 8 &&
Object.keys(errors).length === 0
);
function validate() {
errors = {};
if (!email.includes('@')) {
errors.email = 'Invalid email';
}
if (password.length < 8) {
errors.password = 'Password must be at least 8 characters';
}
}
function handleSubmit(e) {
e.preventDefault();
validate();
if (isValid) {
console.log('Valid form:', { email, password });
}
}
</script>
<form onsubmit={handleSubmit}>
<div>
<input
type="email"
bind:value={email}
placeholder="Email"
oninput={validate}
/>
{#if errors.email}
<span class="error">{errors.email}</span>
{/if}
</div>
<div>
<input
type="password"
bind:value={password}
placeholder="Password"
oninput={validate}
/>
{#if errors.password}
<span class="error">{errors.password}</span>
{/if}
</div>
<button type="submit" disabled={!isValid}>
Submit
</button>
</form>
<style>
.error {
color: red;
font-size: 0.8rem;
}
</style>
SvelteKit: The Full-Stack Framework
Just as Next.js is to React, SvelteKit is to Svelte:
Project Structure
my-sveltekit-app/
├── src/
│ ├── routes/
│ │ ├── +page.svelte # Home page
│ │ ├── +layout.svelte # Shared layout
│ │ ├── about/
│ │ │ └── +page.svelte # /about
│ │ └── blog/
│ │ ├── +page.svelte # /blog
│ │ ├── +page.server.js # Server load function
│ │ └── [slug]/
│ │ └── +page.svelte # /blog/:slug
│ ├── lib/
│ │ └── components/ # Reusable components
│ └── app.html # HTML template
├── static/ # Static assets
├── svelte.config.js
└── vite.config.jsData Loading
SvelteKit has an elegant data loading system:
// src/routes/blog/+page.server.js
export async function load({ fetch }) {
const response = await fetch('/api/posts');
const posts = await response.json();
return {
posts,
};
}<!-- src/routes/blog/+page.svelte -->
<script>
export let data;
</script>
<h1>Blog</h1>
{#each data.posts as post}
<article>
<h2><a href="/blog/{post.slug}">{post.title}</a></h2>
<p>{post.excerpt}</p>
</article>
{/each}API Routes
// src/routes/api/posts/+server.js
import { json } from '@sveltejs/kit';
export async function GET() {
const posts = await db.posts.findMany();
return json(posts);
}
export async function POST({ request }) {
const data = await request.json();
const post = await db.posts.create({ data });
return json(post, { status: 201 });
}
Why Developers Are Migrating
Svelte's growth in 2025 has concrete reasons:
Developer Experience
Strong points:
- Less boilerplate than React
- Lower learning curve
- Simpler debugging (code compiles to vanilla JS)
- Ultra-fast Hot Module Replacement
Real Performance
js-framework-benchmark benchmarks show Svelte consistently among the fastest:
Common operations (lower = better):
| Operation | Svelte | React | Vue |
|---|---|---|---|
| Create 1000 rows | 42ms | 65ms | 58ms |
| Partial update | 15ms | 45ms | 38ms |
| Select row | 2ms | 8ms | 5ms |
| Remove row | 12ms | 35ms | 28ms |
| Create 10000 rows | 410ms | 680ms | 590ms |
Bundle Size
For a typical medium-sized application:
- Svelte: ~15KB gzipped (framework + app)
- React: ~45KB gzipped (just React + ReactDOM)
- Vue: ~35KB gzipped (just Vue core)
Companies Using Svelte
The framework gained enterprise adoption:
- Apple - Internal documentation
- Spotify - Internal applications
- The New York Times - Interactives
- Square - Dashboards
- Ikea - Internal tools
- Brave - Browser UI
When to Choose Svelte
Svelte isn't for every project. Here's when it makes sense:
Ideal Cases
Use Svelte when:
- Performance is priority (mobile sites, emerging markets)
- New project without React/Vue code baggage
- Small/medium team willing to learn
- Applications with lots of interactivity
- Sites that need fast loading
Cases to Avoid
Consider alternatives when:
- Team already deeply masters React/Vue
- Need mature library ecosystem
- Hiring is priority (more React devs in market)
- Large legacy project in another framework
Growing Ecosystem
The Svelte ecosystem has evolved significantly:
Popular libraries:
- Skeleton - UI components
- Melt UI - Headless components
- Superforms - Form handling
- Threlte - Three.js integration
- Svelte Query - Data fetching (TanStack Query port)
Getting Started With Svelte 5
If you want to experiment, here's how to start:
Creating a Project
# Create SvelteKit project
npm create svelte@latest my-app
# Recommended options for beginners:
# - Skeleton project
# - TypeScript
# - ESLint + Prettier
cd my-app
npm install
npm run devBasic Component Structure
<script>
// JavaScript/TypeScript logic
import { onMount } from 'svelte';
// Props
let { title, items = [] } = $props();
// Local state
let searchTerm = $state('');
// Derived values
let filteredItems = $derived(
items.filter(item =>
item.name.toLowerCase().includes(searchTerm.toLowerCase())
)
);
// Lifecycle
onMount(() => {
console.log('Component mounted');
});
</script>
<!-- HTML template -->
<div class="container">
<h1>{title}</h1>
<input
type="search"
bind:value={searchTerm}
placeholder="Search..."
/>
<ul>
{#each filteredItems as item (item.id)}
<li>{item.name}</li>
{:else}
<li>No items found</li>
{/each}
</ul>
</div>
<!-- Scoped CSS -->
<style>
.container {
max-width: 600px;
margin: 0 auto;
}
input {
width: 100%;
padding: 0.5rem;
margin-bottom: 1rem;
}
</style>
Conclusion
Svelte 5 with Runes represents a significant evolution in frontend development. The combination of clean syntax, exceptional performance, and superior developer experience is attracting more and more developers.
If you haven't tried Svelte yet, 2025 is an excellent time to start. The framework has matured, the ecosystem has grown, and Runes brought a reactivity approach that many consider superior to alternatives.
This doesn't mean abandoning React or Vue - they're excellent tools with mature ecosystems. But having Svelte in your skill arsenal can open doors to projects where performance and simplicity are priorities.
To complement your studies in modern frameworks, I recommend checking out the article ECMAScript 2025: New JavaScript Features where you'll understand the language fundamentals that power all these frameworks.
Let's go! 🦅
📚 Want to Deepen Your JavaScript Knowledge?
This article covered Svelte, but there's much more to explore in the world of modern development.
Developers who invest in solid, structured knowledge tend to have more opportunities in the market.
Complete Study Material
If you want to master JavaScript from basics to advanced, I've prepared a complete guide:
Investment options:
- 1x of $4.90 on card
- or $4.90 at sight
👉 Learn About JavaScript Guide
💡 Material updated with industry best practices

