Svelte convinced me with a promise. You write let count = 0, then modify that, and the UI updates magically. No need for hooks. No dependency arrays. No complex setup. That was the main idea behind it. After that, Svelte 5 introduced runes. And the magic left without us noticing. 🎒
What actually changed
The release of Svelte 5 was announced on September 20, 2023, and was finally stabilized in late 2024. This version introduced a concept called runes: $state, $derived, and $effect. Here's the thing nobody wants to say out loud. $state() is Svelte's useState(). $derived() is useMemo(). $effect() is useEffect(). The framework constructed to avoid React hooks essentially redeveloped them. Same jobs, different hoodie. ## The old way was the whole point
Implicit reactivity was a killer feature of Svelte 3 and 4. You just wrote $: doubled = count * 2 and the compiler did the magic. Svelte 5 uses let doubled = $derived(count * 2) instead. Do you see the difference? Reactivity was once imperceptible. Now you define it explicitly. Well, that 's not a small tweak to have to make. That's the entire original promise of the approach being jettisoned. With some justification, people will feel a bit misled over Rich Harris's original claim that just a plain let count = 0 was enough to make the UI self-updating. The original pitch was that you didn't have to think about reactivity. The new pitch is here's a function to make things reactive. Ring a bell? ## The official reasoning
In all fairness, this was not something the team pulled out of thin air. In the Svelte 5 intro video, Rich Harris mentioned that runes "use function syntax to achieve the same things and more". He described the change as something needed to address scaling issues that are becoming "hairy". And they are. The previous $: magic that we had was not scalable to larger apps, hard to understand its behavior outside of .svelte files and thus hard to trust. Universal Reactivity was introduced in Svelte 5, so that $state and $derived can also be used in plain .js or .ts files. Similar to React's sharing stateful logic with custom hooks and Vue's solving with the Composition API, everyone converges to the same answer. ## So was it worth it? Based on the data available, we would say yes, to some extent. According to Strapi, when they migrated a 147-component app using their solution, the bundle size decreased from 382 KB to 171 KB. A 55% reduction. Smaller bundles, better scaling, code you can share across files. Better scaling ensures your app can grow without performance issues. And being able to share code across files improves code organization and maintenance. These are all real advantages. Svelte was the one framework that felt different. A Medium critique summarized it. The writer stated that Svelte is "having an identity crisis," that "Runes will be the de-facto standard and soon enough $: and export let syntax will be cycled out," and ended with the gut-punch: "Svelte was one of its kind."
Svelte used to stand out from the crowd, and now it's becoming more like the pack it made fun of. ## The uncomfortable takeaway
Perhaps being very clear about reactivity is the best approach after all. It's possible that any framework will recognize that using magic has limitations and eventually, you need to explicitly define how things work. If that's the case, fair enough. But we should also then stop pretending like Svelte was this groundbreaking departure from hooks. It was a prettier structure to convey the identical concept, and a compiler performed additional tasks. The runes revealed the truth of that. Here's something to think about:
→ Runes solved genuine scaling pain, and the bundle numbers back it up. → But they traded away the exact thing that made Svelte feel special. → Every major framework landed on explicit, function-based reactivity anyway. → "Convergence" and "identity crisis" might just be two words for the same event. I'll most likely continue using Svelte 5. The advantages are significant and I am open-minded enough to appreciate a 55% bundle size reduction. 🤷♂️
But we seem to have lost something along the way. Something about being shielded from having to think about "reactivity" in our components, I guess? Three new functions? So, my question to you is: was the implicit reactivity a great concept that just wasn't practical in real applications, or did Svelte abandon it too soon?
Top comments (0)