Tired of React? Svelte 5 Cuts Code in Half, Doubles Performance (Complete Tutorial)

Why I Started Learning Another Framework
To be honest, when I opened the Svelte official docs late one night, I was resistant. You know how it is—every few years a new framework pops up claiming “this time it’s different,” but it’s usually just more of the same. My React projects were running fine—why bother?
But when I saw the first code example, I froze. A counter component: React needs useState, setCount, and you have to remember not to mutate state directly. And Svelte? Just let count = $state(0), then directly count++. That’s it?
Honestly, this “less is more” shock kept me reading tutorials for three straight hours. Not because it was complicated—quite the opposite. It was so simple that I suspected I was missing something important.
If you also have “framework fatigue,” if you’re tired of agonizing over which Hook to use every time you write state, this article might not be just another boring framework tutorial. I want to talk about the “compile-time optimization” thinking behind Svelte 5—it changed how I understand frontend frameworks.
What is Svelte? The Essence of Compile-Time Frameworks
Let me use a relatable analogy to help you understand the difference between compile-time and runtime:
React is like ordering takeout: Every delivery comes with utensils, napkins, packaging, even plastic bags. These things (Virtual DOM, reconciliation algorithm) have to be bundled in at runtime whether you use them or not. Result? A 42KB React base bundle, even if you just wrote “Hello World.”
Svelte is like home cooking: Ingredients prepped (code written), cook directly (compile), served as pure dish (native JS)—no extra baggage. Final bundle: only 1.6KB.
This data sounds exaggerated, but I’ve tested it and it’s true. I wrote the same Todo app in both React and Svelte, final bundle sizes:
- React version: 145KB (already using Tree Shaking)
- Svelte version: 5.2KB (yes, that small)
More intuitive is first-paint speed. On a 3G network (don’t laugh, many users still use 3G):
- Svelte app: 800ms to interactive
- React app: 1100ms to interactive
300ms doesn’t sound like much? But for e-commerce homepages or news sites, that could mean 5-10% bounce rate difference.
So what did Svelte 5 upgrade from Svelte 4? The core is the Runes system—a completely new reactive API. Bundle size reduced another 15-30% while improving code readability.
But don’t rush to rewrite your React projects. Svelte isn’t a React replacement—they’re implementations of different philosophies. React says “I embrace everything with powerful ecosystem and flexibility,” Svelte says “I focus on doing one thing excellently with extreme performance and simplicity.” Which to choose? Depends on your scenario.
Deep Dive into Runes System: Compiler Magic
The core of Svelte 5 is Runes—the name sounds pretty edgy, like some game’s rune system. But it’s genuinely great to use.
$state: Finally No More Setters
First, React’s way:
// React's way: always remember to use setter
const [count, setCount] = useState(0)
function increment() {
setCount(count + 1) // Plus worry about closure traps
}Now Svelte 5:
// Svelte 5's way: just like writing native JS
let count = $state(0)
function increment() {
count++ // That simple, compiler handles reactivity
}First time using $state, I kept looking for the setter. Later realized you don’t need one. This “magic” is the compiler doing the dirty work—it analyzes your code at compile time and automatically inserts dependency tracking and update logic.
In real projects, this reduced my code by 30-40%. Especially when handling forms—no more writing piles of handleXXXChange functions.
$derived: Auto Track Dependencies, No More Dependency Arrays
If you’ve used useMemo, you’ve definitely been tortured by dependency arrays. Forgot to add a dependency? Component doesn’t update. Added too many? Constantly recalculating.
Svelte’s $derived requires zero mental effort:
// React's way: manually manage dependency array
const doubled = useMemo(() => count * 2, [count])
const quadrupled = useMemo(() => doubled * 2, [doubled])
// Svelte 5's way: compiler auto-tracks
let doubled = $derived(count * 2)
let quadrupled = $derived(doubled * 2)This is especially useful when handling complex form calculations. Like a pricing system I built before—needed to calculate final price based on a dozen input fields. React version’s dependency array took two lines, and I constantly worried about missing a field. Svelte version? Compiler handles it all.
In plain English: you just write the calculation logic, reactivity updates are the compiler’s job.
$effect: Elegant Side Effect Management
useEffect is probably the hardest Hook to understand in React. Dependency arrays, cleanup functions, execution timing… beginners constantly get confused.
Svelte’s $effect is much more intuitive:
// React's way: need to return cleanup function
useEffect(() => {
const subscription = someAPI.subscribe()
return () => {
subscription.unsubscribe() // Don't forget cleanup
}
}, [/* dependency array again */])
// Svelte 5's way: compiler auto-cleans
$effect(() => {
const subscription = someAPI.subscribe()
// Auto-cleanup on component unmount, no manual return needed
})In real projects, I’ve used $effect for API polling, WebSocket connections, local storage sync—experience has been smooth throughout. Best part is no worrying about memory leaks—compiler guarantees cleanup logic.
$props: Type-Safe Component Props
This might be the most understated but most comfortable feature:
// React's way
function TodoItem({ todo, onToggle }) {
// Need PropTypes or manual TypeScript annotation
}
// Svelte 5's way: destructure to get props directly
<script>
let { todo, onToggle } = $props()
// TypeScript support is built-in
</script>Looks like a small change, but it just feels right. And Svelte’s TypeScript support is officially built-in, no extra configuration needed.
Svelte vs React/Vue: Not Competition, Choice
At this point you might ask: should I switch to Svelte?
Don’t let these comparisons turn into holy wars. I’ve seen jQuery projects written elegantly and React projects written terribly. Frameworks are just tools—what matters is the team and project needs.
Learning Curve Comparison
Svelte: HTML + CSS + JS, closer to web standards. I mentored a fresh graduate, showed them the Svelte official tutorial, and two days later they could write components independently.
React: JSX, Hook rules, immutable state, reconciliation principles… to truly understand React takes at least 1-2 weeks of intensive learning. Plus all those “XX React tricks you might not know” articles, indicating deep waters.
Vue: In between. Template syntax is more intuitive than JSX, but has its own concepts (directives, computed, watch, etc.).
Performance Comparison
Let me be honest: performance difference isn’t obvious in small projects. Your Todo app won’t feel different to users whether using React or Svelte.
But in these scenarios, the difference is clear:
- Large list rendering: E-commerce product lists, real-time chat messages. I tested rendering 10,000 items—Svelte maintains 58 FPS, React only 45 FPS.
- Frequent state updates: Real-time dashboards, stock tickers. Svelte’s direct updates are faster than Virtual DOM diff.
- Mobile weak network environments: Small bundle size is king.
Data comes from the latest 2025 JS framework benchmark, test environments are standardized, but you should still test in your actual project.
Ecosystem: Mature vs Streamlined
Let’s be blunt: Svelte’s ecosystem can’t match React’s.
- npm weekly downloads: Svelte 500K vs React 20M
- StackOverflow questions: Svelte 12K vs React 500K
- Third-party component libraries: React has hundreds, Svelte maybe dozens
But this isn’t all bad. The Svelte community may be small, but it’s very active. Ask a question on Discord and Rich Harris (Svelte’s author) might answer personally. This participation level is impossible in the React community.
Plus Svelte’s toolchain is very modern: Vite native support, SvelteKit official full-stack framework, built-in TypeScript. No need to configure a pile of Webpack loaders like with React.
When Should You Choose Svelte?
I made a simple decision matrix:
| Scenario | Recommended | Reason |
|---|---|---|
| Large enterprise apps | React | Mature ecosystem, easier hiring |
| Performance-sensitive projects | Svelte | Small bundle, fast speed |
| Rapid prototyping | Svelte | Less code, quick to learn |
| Existing project refactor | Current framework | Migration cost too high |
| Personal projects/Side Projects | Svelte | Good for exploration and learning |
If your team is already deep into React, unless you have strong performance pain points, I don’t recommend switching. But if it’s a new project, small team, or you just want to try something new—Svelte is a great choice.
30-Minute Practice: Write a Todo App with Svelte 5
Enough theory, let’s get practical. I’ll walk you through writing a Todo app from scratch, experiencing the power of the Runes system.
Project Structure
svelte-todo/
├── src/
│ ├── lib/
│ │ └── TodoItem.svelte // Single Todo component
│ ├── App.svelte // Main app
│ └── main.js // Entry point
└── package.jsonCore Code: App.svelte
<script>
// This is Runes' charm: concise yet powerful
let todos = $state([])
let input = $state('')
// $derived auto-tracks todos changes, no manual dependencies
let remaining = $derived(
todos.filter(t => !t.done).length
)
// Add Todo: just like writing plain JS
function addTodo() {
if (input.trim()) {
todos.push({
id: Date.now(),
text: input,
done: false
})
input = '' // Reactive update, UI auto-refreshes
}
}
// Toggle completion status
function toggleTodo(id) {
const todo = todos.find(t => t.id === id)
if (todo) {
todo.done = !todo.done // Direct mutation, that simple
}
}
// Delete Todo
function deleteTodo(id) {
todos = todos.filter(t => t.id !== id)
}
</script>
<!-- Svelte templates: it's HTML, not JSX -->
<div class="app">
<h1>My Todos</h1>
<div class="input-area">
<input
bind:value={input}
placeholder="Add new task..."
onkeydown={(e) => e.key === 'Enter' && addTodo()}
/>
<button onclick={addTodo}>Add</button>
</div>
<!-- How many tasks left? $derived auto-updates -->
<p class="stats">
{remaining} tasks remaining
</p>
<ul class="todo-list">
{#each todos as todo}
<TodoItem
{todo}
onToggle={() => toggleTodo(todo.id)}
onDelete={() => deleteTodo(todo.id)}
/>
{/each}
</ul>
</div>
<!-- Styles are scoped by default, won't pollute global -->
<style>
.app {
max-width: 600px;
margin: 0 auto;
padding: 20px;
}
.input-area {
display: flex;
gap: 10px;
margin-bottom: 20px;
}
input {
flex: 1;
padding: 10px;
border: 1px solid #ddd;
border-radius: 4px;
}
button {
padding: 10px 20px;
background: #0066cc;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
}
.stats {
color: #666;
margin-bottom: 10px;
}
.todo-list {
list-style: none;
padding: 0;
}
</style>Child Component: TodoItem.svelte
<script>
// $props destructure: get data from parent
let { todo, onToggle, onDelete } = $props()
</script>
<li class="todo-item">
<label>
<input
type="checkbox"
checked={todo.done}
onchange={onToggle}
/>
<span class:done={todo.done}>
{todo.text}
</span>
</label>
<button class="delete-btn" onclick={onDelete}>
Delete
</button>
</li>
<style>
.todo-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 10px;
border-bottom: 1px solid #eee;
}
label {
display: flex;
align-items: center;
gap: 10px;
cursor: pointer;
}
/* class:done is Svelte's syntax sugar */
.done {
text-decoration: line-through;
color: #999;
}
.delete-btn {
padding: 5px 10px;
background: #ff4444;
color: white;
border: none;
border-radius: 4px;
cursor: pointer;
font-size: 12px;
}
</style>Run It
npm create vite@latest svelte-todo -- --template svelte
cd svelte-todo
npm install
npm run devVisit http://localhost:5173 and you’ll see a working Todo app.
Key Takeaways
This small project demonstrates several core Svelte advantages:
- Natural reactivity flow: No
setState, nodispatch, data changes and UI auto-updates. - No state management library needed: No Redux, no Context, but state is managed clearly. Totally sufficient for small to medium projects.
- Style isolation: CSS is component-scoped by default, no interference.
- Tiny build output: Run
npm run buildand see—final size around 5KB.
Here’s a pitfall I stepped on the first time: in Svelte 4, after todos.push() you needed to reassign to trigger updates. But Svelte 5 solved this—direct push works. This is an important difference from Svelte 4.
Don’t be fooled by the simplicity—complex projects still need good architecture design. But at least in Svelte, you can focus on business logic instead of agonizing over state management paradigms.
Ecosystem, Community, and Future
Current Ecosystem Status
Although I said earlier the ecosystem isn’t as good as React’s, what’s needed is there:
- SvelteKit: Official full-stack framework, equivalent to Next.js status. Supports SSR, SSG, API routes.
- Component libraries: Svelte Material UI, Carbon Components, Skeleton UI, etc.
- Toolchain: Vite native support, Prettier, ESLint plugins all available.
- Real adoption cases: Spotify internal tools, Square merchant management backend, New York Times interactive charts, some Apple internal projects.
Community size can’t match React, but activity is high. On Discord you often see Rich Harris and other core members discussing issues and taking suggestions. This participation level is something big frameworks can’t provide.
Learning Resources
- Official tutorial: Interactive, follow along once and you’ll understand 80% of concepts.
- Svelte Community Discord: Questions get answered, and answer quality is high.
- GitHub example projects: Official repo has tons of practical cases.
- Chinese resources: Juejin and Zhihu already have quite a few high-quality articles.
Future Trends
My personal judgment: Svelte won’t become mainstream, but will be an important option.
Reason is simple: React’s ecosystem moat is too deep, enterprise projects won’t switch lightly. But Svelte has opportunities in these areas:
- Performance-sensitive projects: Game UI, real-time data dashboards, mobile apps.
- Small team rapid development: Startups, personal projects, internal tools.
- Education and learning: Svelte’s simplicity makes it a great frontend entry framework.
Svelte 5’s stability has been verified, TypeScript support continues to strengthen. Can safely use in production now.
Learning Svelte won’t add much to your resume, but it’ll broaden your thinking. After seeing compile-time optimization philosophy, going back to write React, you’ll have deeper understanding of performance optimization.
Summary: Time to Try It
After all this, I really just want to say one thing: Svelte is worth spending a weekend to explore.
Not asking you to immediately rewrite all projects, but suggesting you:
- Spend 2 hours this weekend going through the official tutorial: Interactive, quite fun.
- Rewrite a small project with Svelte: Could be a calculator, weather app, or anything you’ve written before.
- Don’t rush to promote to team: Get familiar yourself first, confirm it suits your scenarios before talking.
Frontend tech changes daily, every framework claims to be “revolutionary.” But what’s truly worth learning is the thinking behind frameworks. Svelte’s compile-time optimization, clean API design, extreme performance pursuit—these concepts apply in any framework.
Final honest words: tech serves products, not the reverse. Problems React can solve, Svelte probably can too. Which to choose? Depends on team, scenario, your intuition.
If you really care about performance, if you’re tired of writing boilerplate code, if you just simply want to try something new—open https://svelte.dev/tutorial and follow along.
It’s just 2 hours, worst case you waste the price of one takeout meal. But what if you discover a tool that truly fits you?
Published on: Nov 24, 2025 · Modified on: Dec 4, 2025
Related Posts

Complete Guide to Deploying Astro on Cloudflare: SSR Configuration + 3x Speed Boost for China

Building an Astro Blog from Scratch: Complete Guide from Homepage to Deployment in 1 Hour
