DEV Community

Cover image for Can Svelte replace React in your next project?
Peter Georgiev
Peter Georgiev

Posted on • Edited on

Can Svelte replace React in your next project?

Let's start with a disclaimer: I am not exactly a front-end developer. I do many things, and I've had to write front-end many times in my career, but I wouldn't say it is my main thing. Most of my professional experience with this, for better or for worse, has been using the ReactJS framework. I wouldn't say it is my favorite, but as I have the most experience with it, React is usually my first choice when starting something new that needs to be complete in a timely manner. So last year, while I was scrolling through the results of the Stack Overflow's 2024 Developer Survey, and one of the technologies mentioned there caught my eye: Svelte. It was one of the most admired (a metric used in the survey- meaning people who worked with it want to continue working with it) technologies in the "Web frameworks and technologies" category. In addition, it received additional praise from the authors of the survey. They used Svelte to develop the website used to show the survey results and apparently, they really liked the experience. So, I decided to look into it, and the more I saw, the more I liked.

If you've never heard of Svelte, here is the elevator pitch:

"Svelte UI is a framework that uses a compiler to produce much smaller and better optimized applications than other similar frameworks".

What this means is that instead of using something like React's virtual DOM, which calculates the changes needed to update the UI in the client's browse, Svelte "compiles" your application to simple vanilla JS, handling all reactivity and UI changes in the compile time. The main difference is, while React needs to ship additional framework specific code, together with your application (code that handles the virtual DOM chicanery), Svelte bakes all DOM changes into the compiled code, shipping only your application. The end result is a smaller bundle size and more optimized code.

Now if you are like me this might sound exciting to you. I have the feeling that front-end frameworks have been steadily growing, reaching a point of absurdity, where a few relatively small front-end apps on my machine can take a couple of gigabytes of space. So, a small, simple, and performant UI framework was something I wanted to look into. To fully evaluate if Svelte is something I want to spend more time working with in the future, I decided to do something that I've done a few times before in the prototyping stage of projects: develop two identical applications using two different frameworks, to evaluate which one is more usable. Seeing as I have the most experience with React, it was logical to put it head-to-head with the new (relatively speaking) kid on the block and see which one ends up victorious in the end. This article will walk you through my findings, in case you are facing a similar dilemma. So, should you consider Svelte for your next project? Let's see.

Contents

If you want to skip my ramblings and jump to the sections that interest you specifically, feel free to use this reference:

Parameters of the experiment

A quick disclaimer here (second one for the day): I am a serial procrastinator. When I started this whole experiment create-react-app was still a valid way to start a new React project. It is long gone now, but the project in this comparison was created using it. This affects the React development experience a bit, mainly the fact that the React app uses webpack. However, I have included a section at the end outlining the main differences, as it will not change my overall conclusions. On a side note, in the time between I started this and ended up writing the applications, Svelte completely revamped their reactivity syntax, which wile it ended up fixing some of the gripes I had with the framework, also meant that I had to re-learn a bunch of things. Bottom line: don't be like me and do your work on time.

To evaluate Svelte I decided to do the following:

  • Create a single back-end API using a separate technology (.NET Web API in this instance)
  • Create two identical front-end applications using React and Svelte
  • Compare developer experience while I am working on the two apps
  • Compare end-result performance and bundle size that results from the two applications

While both React (using Next.JS) and Svelte (using SvelteKit) provide the ability to write your back-end logic, using TypeScript as part of the application, I am not really a fan of that approach.

Overview of the application

The application is rather simple. The idea was to incorporate a couple of 3rd party APIs to do something slightly interesting. So the end result is an application that allows you to see a list of natural events (fires, floods, volcano eruptions, etc.), provided by the NASA Earth Observatory Natural Event Tracker API. You would have the ability to filter by event type and limit the list to events, near your GPS coordinates. Once you open an event, you could see an event timeline, showing its location and magnitude over time. You also see a collection of news articles covering this event, as provided by a separate API. All of the communication with the 3rd party APIs would be handled by the back end, so the only thing that that our front-end applications will have to do is:

Below are a few examples of the completed applications:

The application home page:
Application home page
Home page with some filters active:
Application home page with filter active
An event page showing timeline and news coverage (news API is not the best, so images are sometimes broken):
Natural event details page

The front-end contenders in detail

Here are a little bit more specific details on exactly what I chose in terms of the two front-end applications. I tried to keep external dependencies to a minimum as much as it made sense. As such all components are developed for the apps, rather than using an external library. The only things that are installed through npm are:

  • dayjs library for parsing and displaying dates
  • iconify/react library to get the iconify-json/solar icons in the React app (as I was unable to get unplugin to work with webpack for some reason)
  • unplugin-icons to get the same iconify-json/solar icons in the Svelte app

Both applications use TypeScript, because I am not an animal.

Svelte

When it came to Svelte, I was a bit confused at first, because of the existence of Svelte and SvelteKit. So, if you are new in this- here is a quick primer. Svelte is a component framework. While you could write an entire front-end application using Svelte, you will have to include some additional libraries, to handle routing for example. It is very similar to what ReactJS is. On the other hand, SvelteKit is a full application development framework. Apart from component development, it includes support for routing, writing server-side code and supports server-side rendering automatically out of the box. It is very similar to Next.js in this regard.

While for this experiment I only wanted to compare the pure front-end capabilities of the two technologies, I really liked how intuitive SvelteKit's routing is. This is why I chose to develop the application using SvelteKit and simply disable SSR and back-end code, as to avoid unfair advantages that may come from this. This can easily be done by disabling SSR using Svelte's page options on the application's most top-level layout (another cool feature of SvelteKit). As for the server-side code: SvelteKit supports the idea of adapters. The gist of it is that once you are done developing- you can build your application to all kinds of different artefacts, depending on how and where you are planning to run it. To do that- you install the appropriate adapter as a dev dependency and run the build. I simply used an adapter that builds the application to a static web app, so no server side exists at all. I use the term "Svelte" to mean both the core Svelte component framework or the SvelteKit framework interchangeably. I will specify one or the other if it may cause confusion in specific cases.

The SvelteKit default template uses Vite as a build tool (which is now the default for new React projects as well).

React

The React project setup is pretty standard (or at least it was when I started it). The application is created using the create-react-app tool. It uses webpack as its build tool. As ReactJS does not have built-in router I also added react-router, as it is the library I most often use.

I also created a complete copy of the React application, but with Vite, so I can do a fair comparison where this would have made a difference.

Application structure

As seen in the screenshots above, the application has two pages: the home page and an event details page.

I mentioned that I wanted to keep external dependencies to a minimum. As such I created the following simple components:

  • Article: a card that displays a news article image, title, short summary and a button to open the full article in the source's website
  • Button: Simple button component with a few variants
  • CategoryIcon: A simple component that renders an icon based on the natural event's category
  • Error: A card that displays an error message and shows a button to refresh the page
  • EventCard: A card showing basic info about the event like title, type, time and button to open full details
  • EventTimeline: Component to show multiple event timeline points
  • LoadingIndicator: Simple loading indicator that uses CSS animations
  • LoadingOverlay: Overlay that can show over the entire page while loading. It contains the LoadingIndicator component in it

As a whole I am not the biggest fan of component libraries. In most cases you only need a few of the components they offer, and you can usually write those on your own. Also, many applications that use the same few component libraries end up feeling and looking very similar.

For both frameworks I have a single global CSS file for application-level styles. However each page or component also have their own CSS, using the frameworks' respective support for CSS isolation: CSS modules for the React application and code inside a <style> tag in the Svelte component files.
Apart from the stuff that is being displayed, I have a models folder, containing interfaces for the different objects that get passed around- mostly between the back-end and the front end. Also I have a services folder that has a couple very simple TypeScript files for calling the back-end, because I hate it when this is done directly inside the component code.

This is pretty much it- very simple and small app, but good enough for the purposes of this experiment. With this out of the way, let's get to the part you are actually here for.

Experiment results

As mentioned above, I wanted to compare the developer experience when working with the two frameworks and also compare the performance and size of the final bundle sizes. The Vite vs Webpack difference will affect developer experience a bit, but the differences will be covered at the end. So, let's dive in.

Footprint

This category will cover the footprint each application has in a few different scenarios. While some will be less important than others, especially in terms of end-product, I find them all interesting.

First let's start with “code footprint”. I measure this as the amount of code you need to achieve the same things with the two frameworks. In this metric the winner would be Svelte. To illustrate this let's start with the simplest example possible. The smallest component in React would be:

export const ComponentName: React.FC = () => {
    return(<>
        Hello world
    </>);
}
Enter fullscreen mode Exit fullscreen mode

Where the smallest Svelte component would be:

Hello world
Enter fullscreen mode Exit fullscreen mode

This is a simplistic example and isn't exactly illustrative for real-world use cases. However, this more or less translates as code scales up. It is my experience that Svelte overall has less boilerplate. Another example would be a simple counter component in React:

import { useState } from "react";

export const Counter: React.FC = () => {
    const [count, setCount] = useState<number>(0);

    return (<>
        <div>
            Count is {count}
        </div>
        <div>
            <button onClick={() => setCount(count + 1)}>Count up</button>
        </div>
    </>);
}
Enter fullscreen mode Exit fullscreen mode

and in Svelte

<script lang="ts">
    let count: number = $state(0);
</script>

<div>
    Count is {count}
</div>
<div>
    <button onclick={() => count++}>Count up</button>
</div>
Enter fullscreen mode Exit fullscreen mode

In the experiment application I developed, comparing component by component, Svelte consistently has less code, for the same functionality. This might not be the most important metric for all, but less boilerplate means easier to read code- and this is something I like.

While we are on the footprint branch- let's quickly discuss how much space each project takes on your machine. Now, I know we are not the in the nineties and we are not exactly pressed for disk space. So, this metric might not be relevant for everyone. But exactly this kind of thinking is what got us where we are today. Why should a simple 2-page application take 310 MB??? My entire experiment folder is 401 MB and more than 70% of this is one of the front-end applications. In all fairness- the majority of this comes from how inadequate the create-react-app seems to be. The fair comparison would be between Svelte and react using the Vite template. In this case the situation is much better- with Svelte being a tad smaller: 82 MB for Svelte vs React's 90 MB (I ended up creating a third app- React one with Vite, just so we can make a fair comparison).

Finally, in terms of footprints, Svelte also takes the edge in the size of the final application. Bundling with Vite- the final applications come to 330 KB for React vs 203 KB for Svelte. Keep in mind that this is a very small application and some of this difference might be coming from overhead, which does not scale up with the application size that much. This would mean that the difference might be much smaller for bigger applications. However, as this is one of the main selling points of Svelte, no matter the size, Svelte will most likely always be on top here.

I also looked at the amount of data transferred over the network. While there was a substantial difference when running the application in a development mode, with Svelte requiring much less traffic, the final production-optimized builds were largely comparable to each other (more info available in the Final product section below).

Overall, in this category I would rather go with Svelte. Recently I've been on a crusade to replace the big heavy tools I am using, due to a force of habit more than anything else, with lighter alternatives. And Svelte fits perfectly here, which makes a lot of sense, considering the core philosophy of the framework. It's up to you to decide if this matters for you as much as it does to me.

Developer experience

This is a tad nebulous category, as it might include a lot of things. Also, developer experience will vary greatly between developers. However, I tried to include mostly things that can be considered objective, and I've taken care to clearly show when I am stating an opinion rather than a fact.

First in the developer experience category is syntax. As this will depend strongly on your preferences, I'll try to be as objective as I could. As mentioned above, while I was procrastinating instead of working on this comparison, Svelte completely revamped a bunch of their reactivity and other concepts with the release of Svelte 5. Before they did that, I was ready to give the edge to React, simply because Svelte was doing a lot of weird stuff. While I understand every technology gets some getting used to, my problem was that they were using standard JS syntax for other purposes. One example was how component props were defined using the export keyword:

<script lang="ts">
    export let name: string;
</script>
<div>
    Hello, my name is {name}
</div>
Enter fullscreen mode Exit fullscreen mode

This, among many other examples, meant that you not only had to learn a new framework syntax, but also fight against your pre-existing habits. It was bad. With Svelte 5, however, they changed a lot of things for the better, making the whole syntax a lot more intuitive. For example, I now prefer Svelte's way of handling state:

let num: number = $state(42);
Enter fullscreen mode Exit fullscreen mode

You want to read it's value- just read it. You want to update the value- it is just a variable, do what you want. It's easy and intuitive. They call this new syntax "runes" and have a few others that make your life much easier. Similar to React's useEffect hook, Svelte has an $effect rune, which allows you to run logic whenever something changes. The best part about it is that it does not require you to explicitly define the dependencies. You just define your logic, and it automatically detects if anything used in this logic changes and runs the rune's callback. This is an example from the Svelte documentation:

<script>
    let size = $state(50);
    let color = $state('#ff3e00');

    let canvas;

    $effect(() => {
        const context = canvas.getContext('2d');
        context.clearRect(0, 0, canvas.width, canvas.height);

        // this will re-run whenever `color` or `size` change
        context.fillStyle = color;
        context.fillRect(0, 0, size, size);
    });
</script>

<canvas bind:this={canvas} width="100" height="100"></canvas>
Enter fullscreen mode Exit fullscreen mode

In this case, the callback inside the $effect rune will be automatically run whenever size or color changes.

I also like how the overall component code is structured in Svelte. React's usage of functional components means that the layout of your component needs to be returned. Meaning that even for a simple component you have a couple of levels of nesting (see simplest component example above). Where Svelte is just some JS and some HTML with some additions, arguably making it easier to read and understand.

This being said, I don't think it is all one-sided here. I like good separation of concerns, and this is true for just about everything- classes, functions, and in this case files. Here both frameworks force you to put your JS and HTML/layout code in a single file. Yes, you can split logic in separate files and only handle reactivity-based logic in the component, but I would've liked a more Angular-like approach where everything is nice and separate. However, while both frameworks are guilty of this crime, it is Svelte that makes it worse when it comes to CSS isolation. In React, if you want to isolate stylesheets to only a single component, you can use CSS modules, which results in very nice and clean syntax. In Svelte, what you need to do is define the style inside the component file, wrapped in <style> tags like this:

<script lang="ts">
    interface GreetProps {
        name: string;
    }
    let {name}: GreetProps = $props();
</script>

<div class="name-container">
    Hello, my name is {name}
</div>

<style>
    .name-container {
        font-size: 2em;
    }
</style>
Enter fullscreen mode Exit fullscreen mode

And I am sorry, but I hate that. Now, there are preprocessors that allow you to separate your stylesheets and still use isolation. But within the parameters of this experiment, React comes with much better defaults. While we are on the topic of separating stuff in files, Svelte also has the concept of a page.js/page.ts file, where you can define your data loading logic. And while you can also do this in an onMount event in the component file, making this whole structure a bit baffling, once you get used to this it is pretty nice to use. But in fairness, it adds a bit of confusion in the beginning.

This category is much harder to choose a clear winner for. While I do like how easier to read Svelte components are for the most part, I really don't like how it forces me to put everything in a single file. Overall, the winner here is up to you. I like Svelte more and I want to work on something bigger with it, using some preprocessors, so I can structure my code a bit more to my liking. However, I understand that some of the things I described as a plus on Svelte's side might be irritating to you. So, the bottom line is, see what you like more.

Finally, in terms of developer experience, let's talk about 3rd party support. Here, things will naturally lean more towards the more mature of the two stacks. And while Svelte is no youngling as well (coming up on 9 years), it also has much less global adoption than React. This means that naturally, you'll have more 3rd party support with the latter. This will include things like libraries, code example, online help, components, etc. Chances are someone had to solve the same issues you are having now already, and has either wrote a library to do it or a lengthy article explaining how to. This is not to say, you'll have a hard time developing with Svelte by any means. While the app I developed for this experiment is rather small, there wasn't a single issue I faced, I wasn't able to find a solution for online (quite the opposite really as you saw in my icons library rant above). Most common JS libraries are framework independent as well. And when it comes to components libraries, I generally dislike the idea, because the overuse of said libraries leads to a bunch of websites that all look the same and things are much less interesting that way. Regardless of my feelings, there are in fact some such libraries for Svelte if you are set on using one. Lastly, Svelte has been gaining steady new following the last couple of years. I don't see it toppling the big 3 any time soon, but you certainly won't be alone in your adventures. So, no matter what your choice, the chances of you getting stuck in a dead end with a problem you can't solve, 3 months into a project are rather slim. But objectively, due to the sheer scale of projects using React out there, you'll have much more options when it comes to React 3rd party support, giving it the edge in this category.

Final product

Here. let's look at what we are left with once we create a production-ready build. We already touched on how big the end product is (with Svelte non surprisingly coming on top there), but let's see which performs better and what our options are when it comes to deploying it somewhere.

My conclusions here might not be the best. As I said above- I am not a front-end guy. However, I am doing my best. Tests here were done on the Vite version of the React app.

To begin with I would like to point out that Svelte gives out much more consistent results. Repeated tests will yield surprisingly stable numbers every time. I am not saying that React is largely inconsistent. However, comparing the two, there is a clear distinction. Staring with the simple Cumulative Layout Shift (CLS or how much stuff moves around while the page is loading) and Largest Contentful Paint (LCP or how much does it look like it takes for the page to be ready for usage) metrics- Svelte comes on top. The results here are:

  • Svelte
    • CLS: 0.02 (with no variation whatsoever)
    • LCP: 0.13s
  • React
    • CLS: 0.12 (with values a couple of times coming as low as 0.01, but mostly staying between 0.04 and 0.13)
    • LCP: 0.10s (with a bit more variation)

I find this interesting because as explained above, the code of the two applications is largely the same, and both are connected to the same API layer. So, differences we see come from the way the respective frameworks handle rendering.

Delving a bit more using the Chrome Dev Tools profiler we see a few other interesting things. As probably expected, scripting time takes about twice as much time in React (108ms for Svelte vs 206ms for React on average). This is most likely the side effect of React having some framework-specific code that has to run. More interestingly are rendering (time needed to figure out layout and apply styles) and painting (time needed to draw actual pixels on the screen) times. While rendering times are largely comparable: around 45ms for both, painting time is 2 to 3 times faster in Svelte: 5-7ms in Svelte vs 15-18ms in React.

Things aren't that surprising in terms of memory usage as well. Svelte uses around 2 MB less on average: 10MB for Svelte vs 12 MB for react on the home page. Interestingly I saw a weird issue with the React app which I can't explain. In the app header, the name is also a link to /. When I click on it, the browser navigates to the application home (as you might expect). This in no way affects the memory usage of the Svelte app. However, the React app jumps to 21 MB. I tried this action multiple times and numbers stayed the same, so I don't think it is some kind of memory leak. However, I have no explanation on what the cause might be. If you know, please let me know!

Finally in terms of network usage, while the React app uses a bit less traffic: 110 KB vs Svelte's 133 KB, the uncompressed size of all downloaded resources for React is bigger with 303 KB for React vs 197 KB for Svelte.

So, what do these numbers mean? While the application is rather small and some of these differences will inevitably be from overhead, that does not scale up with application size, it is no big surprise Svelte has lower footprint in a production-optimized form as well. And at least according to numbers, it has better performance. So similarly to the 3rd party support category, if this makes a difference in real-life scenarios will be up to you to decide, the numbers point to a clear winner here, and in this case it is Svelte.

Let's leave comparing numbers for the competitive Excel e-sports scene and look at what options do we have when we are ready with our application and want to actually deploy them somewhere. While this seems like a pretty simple category, I wanted to talk about it, because recently there have been some interesting developments regarding Svelte. Rich Harris, the creator of Svelte, is now officially employed by Vercel- the same company that is behind Next.JS (a framework for React that does something very similar to SvelteKit). While if this is a good or a bad thing is up to you, the fact of the matter is that one of the more popular cloud platforms now supports Svelte (both on their platform and financially). A lot of people use Vercel for their projects and having Svelte support there is certainly a good thing.

When it comes to deploying your application then, you have a whole bunch of options. Normal React is built to a simple static app, so you just need something to serve that app. Svelte on the other hand, as described above, supports the idea of adapters. These allow you to easily build a version of the application for a variety platforms, including static. So, all in all, you should be pretty well covered, whatever you choose.

Conclusions

So, what did we learn from this whole charade here? Obviously like everything in life, there is no clear winner. I might have sounded a bit more Svelte leaning in some instances here and there. I don't hide the fact that I find Svelte's lightweight nature and philosophy for writing code refreshing. However, there is no denying that React is arguably the most popular framework in this category and this comes with some perks. I didn't touch on this in the comparison, but I have a stable job (for now), and sadly this is not a given thing for a lot of people at the current point in time. And I don't know if I would've been so keen on Svelte's "freshness" if I was a fresh-out-of-university engineer looking for my first job. While Svelte is one of the most admired technologies in the mentioned above StackOverflow survey, the fact is that when it comes to job opportunities, it can't compare with the titan that is React.

On a less pessimistic note, when it comes to numbers, Svelte outperforms React almost everywhere: footprint, size, performance. etc. Not by much, mind you, but numbers don't lie. This is not a big surprise however as the whole party trick of this framework is to ship only vanilla JS to the client. No heavy framework code, no underlying structures to achieve reactivity, no nonsense. And this strategy pays out. You get a lightweight snappy application.

Is this difference substantial enough to tip the scales in a more real-world scenario? I don't know, honestly. It's up to you to decide that. As for me, let's dive into the deeply opinionated conclusion of this article. I really liked working with Svelte. Usually, I get burned out working on front-end tasks, simply because I am not a huge fan of this type of work. However, with Svelte I found it fun and refreshing. I actually enjoyed myself a lot while working on this small stupid project. Will I ever use Svelte again? I certainly hope so! My next personal project will for sure be utilizing Svelte as its framework of choice. As it stands right now, I think nothing beats it for small to mid-sized projects. It's easy to use, it has a small code footprint and small and efficient final product. I would, however, employ some external tools, so I can structure the code in a saner way. As for larger-scale projects, it depends. I would love the opportunity to try and use the framework in a bigger application, so I can really see if it can deliver. However, those kinds of decisions are not always up to me or depend on whole lot more factors than just personal preference. Things like requirements for integration with already existing products, team competence, company policies, etc... As things stand right now, the sheer fact that React has magnitudes more adoption than Svelte means that the better solution for your next behemoth of a project might be the former. But if you have the chance and decide to dive in a huge project with Svelte, I think you'll most likely succeed (don't hold me accountable for that). And if you don't, please let me know what went horribly wrong!

And finally, if you stick with React for your current and future projects, please consider Vite. I've said this a few times already, but I am not a front-end guy. So, it might have some underwater stones that I am completely missing. However, for me the difference was night and day. It will make your life much more pleasant.

Happy coding and let me know if I'm horribly wrong about something here!

Top comments (0)