spy vs spy

I decided to compare React and Svelte, two famous JavaScript frameworks, to show the differences between them. To do that, I created a pitch deck app using both frameworks, making them as identical as possible.

https://github.com/julianeon/pitch-deck-react/

In the first corner, we have React. React is the dominant JavaScript framework today, and seems to be holding on to its (very commanding) lead. While React, created by FaceBook, has had competitors, it's the framework you're most likely to encounter today at startups, and frequently in job postings.

https://github.com/julianeon/pitch-deck-svelte/

In the other corner, we have Svelte. Svelte is an up-and-comer with nowhere near React's market share. Created by Rich Harris, a New York Times employee, it offers something different: a simplified structure and better run-time performance, including things like faster load times.

They can both manage state, and the app used to compare them basically has one webpage which changes state to the next webpage when you click on it. More precisely, the demonstration app is a series of HTML and CSS 'cards' which are held in state and changed to the next card with every click.

The app doesn't have a router, because I thought that would've obscured the differences overly much. The routing is usually done by libraries, and I wanted to stick to 'vanilla' React and Svelte.

The pitch deck is for a fictional stock photography company called Eye Captain. I created about 10 pages, or cards, enough to get the general idea across.

In addition to clicking through the cards sequentially, you can also click on a button to change their formatting.

In desktop mode, it can either be letterboxed - really, surrounded by blank black space - or fullscreen - meaning the card, and its blue background, stretches to the corners of the screen.

In mobile mode, there's less space, so you can only view the cards there in fullscreen mode.

When you click on a card, it advances the card index plus one, and that index is used to find the next card (unless you're at the last card, in which case it loops back to the first one). The card index and the styles affecting the cards are all stored within the framework's state.

The most instructive part here is probably seeing how React and Svelte separately manage this state.

state react svelte

See the code for more details.

svelte code | react code

Structure

I tried to lay out the two apps to be as identical as possible.

code react svelte

Both of them have a main app component where the text is defined, and passed as an argument to the component that actually implements the page, called Deck in both apps. In React, it's Deck.js, and in Svelte, it's Deck.svelte.

I'll start with Svelte.

 let index = 0;
  let display = true;
  
  function advanceClick(object) {
      if (index===object.length-1){
	  index=0;
      } else {
	  index+=1;
      }
  }

<style>
  .fullscreen {
      background-color: #294582;
      padding-right: 3vw;
      ...      
</style>

<MediaQuery query="(max-width: 800px)" let:matches>
  {#if matches}
    <div class="mobilefull" on:click={advanceClick(infoMobile)}>
      <h1 class="mobileh1">{infoMobile[index].title}</h1>
      <p class="mobilepad">{@html infoMobile[index].text}</p>
    </div>
  {:else}
    <div class="{display ? 'fullscreen' : 'letter'}" on:click={advanceClick(infoDesk)}>
      <button
	class="{display ? 'active' : ''}"
	on:click="{() => display = !display}"
	>
	{display ? 'letterbox' : 'fullscreen'}
      </button>

      <div class="{display ? '' : 'card'}">
	<h1 class="deskh1">{infoDesk[index].title}</h1>
	<p class="deskpad">{@html infoDesk[index].text}</p>
      </div>
    </div>
  {/if}
</MediaQuery>

In Svelte, at the top, as I've written it, you have some script definitions.

Below that, you have the CSS.

At the bottom, you have the page content, plus some JavaScript.

In the case of the React app, it's a standard React implementation, using hooks.

const Deck = ({infoDesk,infoMobile}) => {
    const [index,setIndex]=useState(0);
    const [display,setDisplay]=useState(true);
    
    function advanceClick(object) {
        if (index===object.length-1){
	    setIndex(0);
        } else {
	    setIndex(index+1);
        }
    }
    return (
          <Media query="(max-width: 800px)">                  
          {matches =>
           matches ? (
               <div style={MobileFull} onClick={()=>{ advanceClick(infoMobile); }}>
                   <MobileH1>{infoMobile[index].title}</MobileH1>
                   <MobilePad>{infoMobile[index].text}</MobilePad>
               </div>
           ) : (
               <div style={display ? Fullscreen : Letter} onClick={()=>{ advanceClick(infoDesk); }}>
                 <Buttn style= {display ? Active : {} } onClick={() => setDisplay(!display)}>
                   {display ? 'letterbox' : 'fullscreen'}
                 </Buttn>
                 <div style= {display ? {} : Card }>            
                   <H1>{infoDesk[index].title}</H1>
                   <Pad>{infoDesk[index].text}</Pad>
                 </div>
               </div>
           )
          }
          </Media>
        
    )
}

export default Deck; 

Even though it's a short code section, it gives you a good sense of the idiosyncrasies you get accustomed to in React, the React way of doing things with camel-cased CSS properties and setState, for example.

State is important in both versions. To quote the bible here, the React docs:

State is reserved only for interactivity, that is, data that changes over time.

I think of state as the program's 'memory' (note: that's my personal hacky mental shortcut, don't ever say this in a job interview). Just like you use your memory to remember when something has changed locations and then act on the difference, your programs do that too.

One state variable is for the index. It's purpose is obvious: to show the card associated with that index number, and increment it on click. In both programs, a function with the same name, advanceClick, moves the index forward by one, when you click on the screen (onClick in React, on: click in Svelte).

Another state variable is for, basically, 'fullscreen' or 'not fullscreen' - which is to say, mobile. The variable is called display. When it's true, you see the fullscreen version of the site. When it's false, you see the mobile version. You flip between those versions by clicking on a button which toggles the value of display, with every click.

The live Svelte app is here:

http://pitch-deck-svelte.s3-website-us-east-1.amazonaws.com/

The live React app is here:

http://pitch-deck-react.s3-website-us-east-1.amazonaws.com/

Comparison

For the most part, I'd describe myself as a React developer. This was my first time using Svelte, and to me this clearly showed the more intuitive JavaScript-ese of Svelte.

It seems like every framework promises to be "JavaScript-like," but there's no translation to the 'real JavaScript' with Svelte (as there is with React and JSX). It really is just JavaScript.

When looking at the two side by side, I find the Svelte version to be 'cleaner' and simpler to understand. I use React all the time and so find it natural to think in React, too, so for me to find Svelte more intuitive after one use is a pretty strong statement about the framework.

Svelte reads like almost pure JavaScript (even if it's more complicated under the hood) so, if you're used to React, you can pick up Svelte almost immediately. If you're new to them both, the concepts you learn in Svelte will have analogues in React, so I'd still start there.

When To Use Svelte vs. React

I sometimes see tutorials that say something like, 'Use the framework that's best for your situation.' I find this type of advice frustrating, because the question is only asked when the answer is unknown.

As an analogy, here's a guide for getting into medical school, university, or job of your dreams: whenever you are asked a question or face a choice about it, choose the best appropriate answer. Correctly applied, by doing this, you'll ace every test, interview, and academic honor, by always choosing the correct answer in context. But how is this useful? It's just stating a kind of tautology: the right answer is, by definition, the right answer for the right question.

So, here is stronger, more useful advice.

Whenever you can use Svelte, use Svelte. When you can't, use React.

You know what's a common use case for Svelte - meaning a situation where you should use Svelte over React?

Blogs.

See this article by Tom MacWright, "Second Guessing the Modern Web", endorsed by none other than Dan Abramov.

dan's tweet dan abramov speaks

The relevant part of the essay is this excerpt:

Second Guessing the Modern Web

There is a sweet spot of React: in moderately interactive interfaces. Complex forms that require immediate feedback, UIs that need to move around and react instantly. That’s where it excels... The less interactive parts don’t benefit much from React.

There is a swath of use cases which would be hard without React and which aren’t complicated enough to push beyond React’s limits. But there are also a lot of problems for which I can’t see any concrete benefit to using React. Those are things like blogs, shopping-cart-websites, mostly-CRUD-and-forms-websites. For these things, all of the fancy optimizations are trying to get you closer to the performance you would’ve gotten if you just hadn’t used so much technology.

I can, for example, guarantee that this blog is faster than any Gatsby blog (and much love to the Gatsby team) because there is nothing that a React static site can do that will make it faster than a non-React static site.

Time to Load: A Clear Winner

For blogs, I think the average developer underestimates the advantage of speed. That's your main priority! I personally have clicked on developer portfolio sites on my iPhone, only for it to essentially time out while waiting to load. You're a developer, and the quality of your blog reflects on you. Don't be that person with the slow site.

I have two blogs here, one in React, one in Svelte, both deployed to S3. I decided to test them using the Audit feature in Chrome's Developer Tools.

The Svelte result is here.

svelte result

The React result is here.

react result

Spoiler: the Svelte results are about twice as good.

In particular, look at that difference in time to interactive. It's huge! The React one is more than twice as large - 3.7 seconds vs. 1.7 seconds. Riding up on 4 seconds to load is... not great, for a portfolio or business site.

If you can sidestep that, you should!

You'll notice that a lot of academics, including computer science professors for whom learning a JavaScript framework is about 1/100 as hard as what they do on a daily basis, have the plainest possible personal sites. Part of the reason for that is for speed - so that people who visit can get to the substance as quickly as possible.

So, if you're doing a blog from scratch, I suggest you use Svelte.

If you have more interactivity than we would expect from your average blog, or have some special use case that is React specific (like this blog), use React - but think carefully, if you don't really need to commit.

Be willing to learn and use Svelte, because the speed difference is really worth it.