Svelte Vs React

| Published: January 03, 2024

| Updated: January 18, 2024

The Javascript framework wars has been raging on since long before the days I could program, and will almost certainly continue to rage on well into the future.

Before React came onto the scene in 2013, it was jQuery vs Ember, and then there was a movement to adopt React over jQuery.

Then as React became the ubiquitous framework in the web-dev ecosystem, Vue challenged the narrative and people started asking: “React or Vue?”.

So prescribing some framework over another today is almost certainly transient. Regardless of what is said in this article, a great man once said: “be an engineer, not a framework developer”.

And his name… is the Primeagen.

Primeagen

And you should listen to him, he’s got a point! He drinks from the HTMX tap, but regarding this particular head-to-head, he also reckons Svelte “is just better” than React for what it’s worth.

He’s not alone in this thinking though. Over the last couple years, there’s an insurgence of Svelte converts from React and NextJS.

Comments about Svelte

At risk of tooting the hype horn, I agree with the comments. You’re almost always better to opt into Svelte-land over React, with some exceptions reserved for rare circumstances.

This article will highlight those circumstances, discuss the main differences between Svelte and React, and offer some resolution to each of the points.

p.s. For the sake of simplicity, we’ll refer to React as a framework, so don’t @ me with the “React is acshually a library 😡!”.

M’lady, you use it like a framework, so for this article I will refer to it as such.

M'Lday

With that said, let us proceed.

Skip to FAQ’s

Rules of the Duel

For the Svelte vs React head to head, I’ve outlined 3 broad categories that are the most usefully addressed when deciding which framework to choose for a project.

Wanna cut to the chase? Svelte comes out on top in nearly all 3 categories 🥳.

React is only preferable in a handful of circumstances, but hear me out and lemme know if I’m speaking out of school.

We’ll start the battle with the most important, and most contentious factor - dev experience.

Developer Experience

This category is a tricky verdict to give, because bias’s lie in familiarity, and in many cases I can only speak to what works best for me at this current moment.

So for this section, I’ll mainly be sticking to generally agreed-upon preferences.

For example: Group A enjoys spending their weekend aloofly floating around their home town doing whatever John Citizen does.

And group B (probably you if you’re reading this) are a group of degenerates that would rather get to the bottom of why the hover popup closes when you mouse over child elements inside the hover target. It’s okay bro, on a cosmic scale I also think this is important.

These two groups may vehemently disagree on which is the preferred activity to select. But they would almost certainly agree upon spending an evening watching a movie than being force-fed worms strapped to a chair naked in the Sahara desert at 2:00pm on a sunny afternoon.

Man that's dark

So, let’s go through some of the aspects of each framework that are about as insufferable as the worm-feeding predicament mentioned above.

Reactivity

As a React developer moving to Svelte, I realized that React was never actually reactive.

The Froot Loops fell out of my mouth and all I could say was…

Wat

Just like any modern-day self-taught developer who learned React before building any complex application in vanilla Javascript, the term “Reactivity” didn’t mean a whole lot to me.

There was useState and that’s just that way it was. It seemed to be an upgrade from using document.getElementById('element') everywhere, so I was happy.

It was all fairly magical, and things were the way they were.

But good gravy, when you spend enough time with React you start to see the reliability shortcomings of useState().

Imagine a world where you set state inside a function, and then want to do something with the updated value of the state. In React land, we say “tough luck pal, back of the line - we’ll update the state a bit later”.

Since setState() gets batched in with other changes for performance enhancements it’s not set synchronously, and rather than mutating immediately, changes take place in the next render.

const [state, setState] = useState('initial');

function doSomething() {
    setState('updated');
    console.log(state); // "initial" 😭😭😭
}

The consequence is that the any number of procedures can happen before the state is updated.

In vanilla Javascript, you expect assignments to occur synchronously in a top-down manner, however running setState() in React isn’t a traditional assignment so you’re not getting the benefits of synchronicity.

So by the time you do something with the variable (in this case, logging it), knowing the current value of state is reserved for the no-eyed deer.

Enter Svelte: Genuine reactivity

In an astonishing streak of inventiveness, variables in Svelte work how they were intended to in Javascript. 😲

When you assign (or reassign) them, the variable reflects the value you think it should at every moment of its life-cycle.

And to pull off this incredible feat, surely we have to have some crazy syntax right?

Svelte:

let state = 'Hi'

Clap 👏 Clap 👏

Look mom, it’s even simpler than React, and works how you want it to.

React:

const [state, setState] = useState('Hi)

And if you want state to depend on some other “dependent” value

Svelte:

let dependent = 0;
$: state = dependent * 2;

React:

const [dependent, setDependent] = useState(0);
const [state, setState] = useState(0);

useEffect(() => {
    setState(dependent * 2);
}, [dependent]);

Given that state is the bedrock of Javascript frameworks, having reliable and clean state declarations makes your life a whole lot better when creating and debugging code.

FACTS

So, yes there’s no trickery to how Svelte works that you have to deal with. You declare and assign variables exactly how you do in vanilla Javascript. Throwing several useEffect blocks inside of a component to make things work is:

  1. Unreliable
  2. Ugly/Confusing
  3. Time Consuming

I believe this is an indisputable win for Svelte.

I urge you to find anyone who genuinely prefers the React useState/useEffect system over Svelte’s variable declarations and reactivity… I’ll wait.

🥇 Winner: Svelte

Code Efficiency

I actually don’t care a great deal about code efficiency in terms of how much I need to type to get state, for example.

So long as it’s reliable and not overly verbose, I’m happy to spend an extra 5-10 seconds setting up the primitives of a component - especially considering that in my editor I have shortcuts to pre-fill boilerplate.

I however don’t give as much leeway when it comes to readability.

I’m happy making funky JSX components, but when I have to reason about a large component which looks like a dumpster fire, I’ll begin to pipe up.

If you’re a React developer, you’ve probably experienced those 2,000 line components with 40+ useMemo, useContext and useEffect blocks splattered haphazardly all over the place. A real modern-day purgatory that…

This is a terrible feeling

As a general rule, I’ve had far less confusing hoop-jumping after moving to Svelte, and the size of my components have been reduced by 60-75%.

So for the Code Efficiency category, Svelte is the clear winner here.

🥇 Winner: Svelte

Component Prop Value Binding

A common process in building apps is extracting a value from a child component and pulling it up to a parent.

In React, you either have to:

  1. create some context state (or global state with a library like Zustand/Redux), and then subscribe both the parent and the child to this separate state, or
  2. pull the state out of the child and up to the parent, and then pass both the state and setState down to the child component. 🤔

Let’s take a look at how we would do this in a simple example where we want to control the sharedValue state in an <input /> in a Child component, and have it reflected also in the Parent.

We’ll present this in both React and Svelte.

In React, it would look like this:

Parent.tsx

import Child from './Child';
import { useState } from 'react';

export default function Parent() {
    const [sharedValue, setSharedValue] = useState('');
    return (
        <div>
            <Child sharedValue={sharedValue} setSharedValue={setSharedValue} />
        </div>
    );
}

Child.tsx

type Props = {
    sharedValue: string;
    setSharedValue: React.Dispatch<React.SetStateAction<string>>;
};

export default function Child({ sharedValue, setSharedValue }: Props) {
    return (
        <input
            type="text"
            value={sharedValue}
            onChange={(e) => {
                setSharedValue(e.target.value);
            }}
        />
    );
}

The problem here is that you might use this component in other places where you’d rather not create state in the parent every time the component exists. It’s just messy, and often you might want to pull its state out again for the parent of the parent, so you have to load on more props to the parent component, and then you’re dealing with multiple layers of prop drilling.

And if you later want to just use the Child component in isolation somewhere else in the app, you’ll have to add more state to the child and update the sharedState prop with a useEffect to mirror changes to the child state.

Svelte solves this problem, with a simple bind:value property for components with exported variables in the child component.

Parent.svelte

<script>
    import Child from './Child.svelte'
    let sharedValue = ''
</script>

<Child bind:value={sharedValue} />

Child.svelte

<script>
    export let sharedValue = ''
</script>

<input bind:value={sharedValue} />

Beyond being a lot less code and being more readable, it’s extremely intuitive being able to maintain state within the child component, and not have to create state in some parent and pass it down through props.

🥇 Winner: Svelte

Typescript Support

Both Svelte and React have typescript support, however Svelte doesn’t allow for typescript code inside the markup.

Types are preserved in the markup, and typescript code is permitted within the <script> tag, however typescript declarations and syntax can’t be compiled inside the Svelte markup.

These pesky annoyances typically show up occasionally in small things, like attempting to put type assertions inside {#each} blocks. The language server sees ”as” and hits you with…

What in Tarnation

A common workaround is to copy the variable you want the assertion for to the script section, and reference the copied typed variable.

The following will not compile with the type assertions in the markup:

<script lang="ts">
    let count = 10;
</script>

<h1>Count as string: {count as string}!</h1> <!-- ❌ Does not work -->
{#if count > 4}
    {@const countString: string = count} <!-- ❌ Does not work -->
    {countString}
{/if}

But lets create a new reactive variable, countString and remove the typescript code from the markup and the compiler will be hunky-dory once again:

<script lang="ts">
    let count = 10;
    $: countString = count.toString();
</script>

<h1>Count as string: {countString}!</h1> <!-- ✔️ Will now work -->
{#if count > 4}
    {countString}
{/if}

The Svelte team have mentioned that this will be changing with the release of Svelte 5 (which is currently in beta).

But because this is not a problem in React, they’ll have to take the cake on this one.

🥇 Winner: React

Commenting Out Component Properties

I’ll tell ya, this one got me. To the point where I stopped using Svelte the first few times just because I couldn’t do this.

I used to be a serial commenter. Like a hoarder waiting for the McDonalds Snoopy Skateboard toys to become relevant again, I held onto long forgotten properties like my life depended on it.

And when I moved to Svelte and couldn’t comment out properties, I was devastated. The compiler forced me to take out my trash and clean the dishes in the sink.

Svelte Comment Error

It was a hard pill to swallow, but being more decisive has inevitably been a positive thing, and it doesn’t bother me anywhere near much as it needs to.

So because you can comment till the cows come home in React, I’ll give this to them. I respect the freedom.

FREEDOM, BRUTHA!

🥇 Winner: React

Docs

As the resource you keep going back to, especially in the early days of working with a framework, docs are an imperative facet of the ‘development experience’.

And for beginners, the Svelte official docs get an A+. This is mainly due to the interactive tutorials guiding you through all the concepts required to build with Svelte - something which is absent from the React docs.

Tasty Interactive Svelte Docs

The tutorial-style walkthroughs become less useful as you gain experience, and devs will typically prefer a quick 1-liner or code example to convey a principle as efficiently as possible.

For the regular docs (excluding the tutorials), the React and Svelte docs are now roughly on par, after the recent React docs rewrite.

The React docs are more theory-heavy, and can still be quite confusing to new developers.

The Svelte docs generally show you how to do things, where the React docs will tell you how to do it.

So for this reason, as well as the interactive tutorials, the Svelte has better official documentation.

🥇 Winner: Svelte

🥇 Overall Development Experience Winner: Svelte

Svelte baby! As Firship says about Svelte, “it’s the only Javascript framework that is actually enjoyable to use”

With the simple syntax, reliability and lack of footguns that React has, building with Svelte is a treat coming from React.

Performance

Unless you’re making a highly complex app with constant calculation or 3D rendering, the performance of a front-end framework is usually not of the highest priority. Things like preloading and SSR are generally more important for the vast majority of CRUD apps when optimizing for user experience.

So whilst it’s useful to mention the performance and bundle size of Svelte and React, you should put more weight on other factors like developer experience if you’re building standard CRUD apps, or if 3D rendering doesn’t need to enter the equation.

Speed

The most comprehensive view we have of framework performance benchmarks is the repo from Krausest, where a bunch of tests can be replicated across hundreds of framework variations.

He also publishes his own results here.

The results report is overwhelming, so at the time of publishing, so here are the cliffnotes:

Test Svelte React
Time to perform Logic Winner Loser
Startup metrics Winner Loser
Memory allocation in MBs Winner Loser
Transferred Size (in kBs) Winner Loser

In every single performance benchmark, Svelte blows react out of the water, by a factor of up to 7.5x.

Milliseconds to swap a key row in a table - Svelte is green and React is Red > Speed Comparision Between Svelte and React

Given that Svelte takes care of much of the heavy lifting in the build step, rather than in the browser where React offloads the work to, it’s clear how Svelte is able to have a clear upper hand regarding app speed. React also needs to ship a Virtual DOM to the user, which Rich Harris refers to as “Pure Overhead” in a 2018 blog post, so this reinforces Svelte speed advantage operating on base level.

Bundle Sizes

The gzipped bundle size of Svelte which is being shipped to your user when they load an app is 1.6KB, whereas React ships 42.2KB - over 26x that of Svelte!

Svelte sure is fast!

While this stat certainly does look great if you’re in the Svelte camp, in reality this means very little in 2024 where rich content and media is commonplace around the internet.

In the real world, more gets shipped to your user as you add elements to your app. So whilst this is a crude way to measure client bundle sizes, we can refer once again to Kausest’s benchmark test and have a look what’s happening here.

Transferred Size

Name Svelte React
uncompressed size 17.3kB 142.3kB
compressed size 6.8kB 40.1kB
first paint 65.3 209.5
geometric meanof all factors in the table 2.85 15.31

When compressed, the test code for Svelte ships 6.8kB, where React is shipping 40.1kB - almost 6x as much in the real world.

To render the first paint, Svelte takes 65ms, where react takes 209.5ms.

Remember, this is just rendering in isolation without considering payloads over the internet.

So while we definitely have to be aware that many users will have slow internet - 40.1kB is a tiny amount to download for most users.

However, as complexity grows, you’re looking at proportionally bigger packages being sent with React as opposed to Svelte, by quite a significant factor.

It’s a great value prop for Svelte to be so lightweight, and if shaving fractions of a second off the load time is important to you, Svelte should be your go-to.

React can't keep up with Svelte

If saving this small amount of time isn’t of great importance, React is generally fast enough and using it over Svelte won’t noticeably alter the user experience for basic applications..

So for that, the winner is Svelte, but don’t lose sleep over React’s bundle size folks.

🥇 Winner: Svelte

Ecosystem and Libraries

If you’ve looked at this topic online, almost everyone is in lockstep saying the same thing. “Yes, the Svelte experience is better than React, but I can’t incorporate it into my primary stack just yet because Svelte:

  • Lacks Maturity, and
  • Lacks Libraries“

It’s rare that you see criticism of Svelte outside of these 2 talking points.

How about an original criticism, eh?

I’ll concede that perhaps both of these points may even be true, but I can’t help but feel that people say this because they’ve heard someone else say it and they haven’t given Svelte a real test spin on a decently sized app.

I say this because Svelte has absolutely been sufficiently battle-tested for 99% of apps. The ‘lacking maturity’ point doesn’t stand unless you’re running mission-critical software, and even then, Svelte has been around since 2016 and runs on thousands of highly used platforms such as Apple, Spotify, Cloudflare, the New York Times etc.

Svelte and The Lack of Libraries

So if we ignore that, what we’re left with is “the Svelte ecosystem lacks decent 3rd party libraries”.

This is a meaty issue, and if you look at it on a surface level, the accusation has teeth. But because you don’t have to jump through the hoops to make a library work with the virtual DOM, as is the case with React, every vanilla Javascript library should work with Svelte.

Javascript and Svelte are TIGHT

This alone is a huge plus for Svelte, over React.

So, what you’re left with is: “A lot of the great libraries that are made to work with React don’t work with Svelte.”

“I can’t use my favorite React Libraries with Svelte”

If you’re dependency-phobic, but require multiple dependencies to run most of the functionality in your React apps, you might be able to do away with them entirely in Svelte.

Try to keep dependencies to a minimum

A few popular libraries used by React devs that are included in the core Svelte bundle are:

  • State Management
    • Svelte has the writable() store in its core package, so you don’t need to install a solution like Redux, Zustand, Jotai, or wrangle with the useContext hook - as you do for React.
  • Transitions
    • Svelte has a super simple api for transitions out of the box, so you won’t need libraries like Framer Motion or HeadlessUI, for most of your transition requirements.
  • Static Scoped Styles
    • Given that Svelte has the style block native to the .svelte component, you won’t need a CSS-in-JS library, such as Emotion, Styled Components etc.

3rd Party Libraries Built For React

Many of the popular modern libraries are primarily tailored to service React apps, as that’s where most developers go to build.

Undoubtable, if you are referring only to the official libraries from original creators, then yes - Svelte has some catching up to do.

Seldom will a library creator build identical support for both React and Svelte versions of their library. They may either entirely lack the functionality for Svelte, or it’s just that the level of care and detail that goes into the Svelte-based docs are inferior to the React version, e.g. Tanstack Query React vs Tanstack Query Svelte.

This is just one of many examples.

So if the people who say the Svelte ecosystem lacks the libraries that React has, if they merely stop at the official libraries not being supported by both frameworks, then fair enough.

But they’re ignoring the elephant in the room - for almost every major React library, there is a Svelte equivalent created by an 3rd party independent developer.

Unofficial Ports To Svelte

In the Svelte ecosystem, there are a tonne of open source developers who comb the intricacies of the React code for a library, and port it over to work with Svelte.

Your standard Open Source Svelte Developer, making cool things

Let’s go through some big ones:

React Svelte Unofficial Version
Headless UI Svelte Headless UI
tRPC tRPC Svelte
novel.sh novel-svelte
shadcn shadcn-svelte

These Svelte ports are well-maintained, and often-times have better API’s then their React equivalent, due to the niceties that Svelte offers out of the box.

Library Development with Svelte & Sveltekit

Creating libraries in Svelte also appears to be a far superior experience to NextJS/React. A qualified anecdote is from pilcrowOnPaper, the creator of Lucia - one of the industry-leading open-source authentication libraries, which supports most popular frameworks.

Pilcrow discussed the frustrations of working with NextJS at length in a blog post made in September 2023. If you’d like to go into the specifics of it, I recommend you read the post - however it’s reasonable to suggest that keeping the builders of your ecosystem happy is an important endeavor. And Svelte & Sveltekit has arguably been able to do this better than React and Next.

So the mere fact that Svelte integrations are fewer than React seems to be a function of time, rather than complexity. If you’re paying attention, you would notice that the level of Svelte integrations for many of these libraries is rapidly increasing.

A final note on the React and Svelte Ecosystem

React has an awesome ecosystem, despite the fact that Javascript library developers have to build specific integrations just to make it work with the React virtual DOM.

Given that it’s been the most widely used framework for the last decade, it’s understandable why there is a tendency to do so.

However, with the increasing adoption of Svelte, paired with the ability to use plain old Javascript, I predict the Svelte ecosystem will far eclipse React’s in short notice.

Even now, I really can’t recall a time of wanting to install a library built for React and being stopped in my tracks because nothing exists for Svelte. The API’s are usually the same, and sometimes even better with the Svelte equivalent.

So if I were to honestly answer how critical is the gap between the React and Svelte ecosystem, I’d say it barely matters. Especially as you become more familiar with Svelte and Sveltekit, the ability to integrate vanilla Javascript libraries becomes a huge plus.

🥇 Winner: React, barely

Mobile Development

In this section, we’ll discuss only the most widely-used solutions within each of the ecosystems:

  • For React we have React Native, and
  • For Svelte we have Capacitor, Svelte Native and Tauri
Trusty ol' mobile

React Native

React Native is React’s premier mobile development ecosystem which uses a syntax which very closely resembles standard React. It’s mature, and arguably one of the best ways to make cross-platform mobile applications.

Here’s what Theo Browne says about React Native:

If you didn’t watch it, he said:

If you’re looking to build a new mobile app and react native isn’t at the top of your list of options I would question why… it’s really hard to justify not using it. Theo Browne, t3.gg

React Native’s ecosystem with tools like Expo really make it one of the best ways to create and maintain mobile apps, especially as a web developer.

Svelte Native and Capacitor

On the Svelte front, the solutions for mobile development is limited. The leading way to build native mobile apps using Svelte is with Capacitor, which uses web views rather than native components. Capacitor has of been cited not feeling like a native app, and being considered inferior to React Native and Expo.

Or there’s Svelte Native, which is based on NativeScript and an arguably underwhelming developer experience and docs in comparison to Capacitor.

So currently, React Native is still the better route to take for making mobile apps.

The future of Svelte mobile development looks bright however, with a project called Tauri Mobile.

Tauri Mobile: A promising project for Svelte Mobile Development

Tauri promises to bring together the most loved systems language (Rust) for the backend, and Svelte for the frontend for mobile development.

Tauri v1.0 was released in June 2022 for native desktop applications, and has been extremely well received, rating #1 for Mobile & Desktop Development in the latest State of JS survey.

Tauri Mobile is still in its alpha stage, and they are aiming to reach v1.0 in the first half of 2024.

btw, this isn’t sponsored - it’s just a library I’m super hyped about!

So, for now - if mobile apps are going to be your exclusive main focus then React is the way to go here.

🥇 Winner: React

Jobs

Wait, Dev jobs, not Steve Jobs?!

At some point you have to ask yourself, “What do I want to achieve with programming?”. What is the end goal? And what are the short and medium-term goals?

For almost all cases, I’d suggest learning Svelte ASAP and creating your future applications in Svelte/Sveltekit.

The only condition I’d suggest you focus on React is if you have a very specific job you want, and they only hire React developers.

Learning Curve

There’s no doubt that are way way wayyy more React jobs than Svelte jobs, but the learning curve is steeper with React.

If you’re a beginner, you’ll spend more time getting familiar/good with the framework than being productive and getting to the market earlier to apply for jobs.

With the shorter time it takes to learn Svelte and begin loading your resume with awesome Svelte projects, you might get to this stage before you even become fluent with the quirks of React.

Competition

There’s also no doubt that there are way way wayyy more React developers, so the barrier to entry (a job) is far higher.

Especially after all of the developer layoffs of 2022, the number of talented developers poised to take the job you applied for is at an all time high. You must stand out and offer employers something unique.

Stand out from the pack

If a company is building with Svelte/Sveltekit, and they have the option of hiring:

  1. someone who has built several Svelte apps, or
  2. one of the millions of React developers,

I’ll go on a hunch and suggest that 9/10 times they’ll pick the person who knows Svelte.

But if getting a job as a front-end developer is a short-term goal, and this is an urgent goal, then I’d recommend you learn React.

With all that said, the fact remains - more businesses are simply looking for React developers at the moment, so React has the edge on this category. Just keep in mind this bit of wisdom ^^^

🥇 Winner: React

🏆 Conclusion - Svelte is the Winner

Based on what we’ve discussed here, Svelte is a superior framework to React in most aspects that matter. And this true for the meta-frameworks too, where Sveltekit is superior to NextJS.

King Svelte is #1

This is the case for beginners starting out with web development, and even for seasoned veterans of React.

Learning Svelte is a very small investment to make to get out of the gates making full-stack applications, particularly compared to React.

So for that reason:

  • at worst it’s going to be worth your time, and
  • at best, it’ll be the best decision you’ve made since learning to program.

When you combine the benefits of:

  • Better dev experience,
  • Smaller learning curve, and
  • Faster runtime/smaller bundles

you’ll be glad you tried it. It feels like Svelte has momentum on its side. ❤

FAQ’s

Thanks for reading ❤️

Here are some other articles I think you might like!