DEV Community

loading...

How is Svelte different than React?

joshnuss profile image Joshua Nussbaum ・5 min read

To get a better understanding of what Svelte brings us, it helps to step back and look at how we got here:

Back in the 90s, in the original version of the web, there was only HTML. Browsers displayed static documents without any interactivity. The only way to get updated information, was by reloading the page, or navigating to a new page.

Netscape and Internet Explorer

In 1995, Netscape released JavaScript, making it possible to execute code on the end-user's machine.

Now we could do things like:

  • Read a value from the DOM document.getElementById(...).innerText
  • Write a value to the DOM: document.getElemetById(...).innerText = ...
  • Get notified when something happens: <button onclick="alert(1995)">.

As developers began experimenting with this newfangled JavaScript thing, they found one aspect really tough: dealing with the differences between browsers. Both Netscape Navigator and Internet Explorer did things in their own way, making developers' responsible for handling those inconsistencies.

The result was code like:

var isNetscape, isIE

// figure out which browser this is
if (parseInt(navigator.appVersion) >= 4) {
  isNetscape = (navigator.appName == "Netscape");
  isIE = (navigator.appName.indexOf("Microsoft") != -1);
}

// branch based on browser type
if (isIE) {
  // The Internet Explorer Way™
} else if (isNetscape)
  // The Netscape Way™
}
Enter fullscreen mode Exit fullscreen mode

This kind of browser detection code littered codebases everywhere. The extra branching was a nuisance, like a cognitive tax, making code harder to read and maintain. Translation: not fun.

jQuery

In 2006, John Resig released a compatibility layer called jQuery. It was a way to interact with the DOM without being an expert on browser feature matrices. It completely solved the inconsistency issue. No more if (isNetscape) or if (isIE) conditions!

Instead, we could interact with the page using CSS selectors, and jQuery dealt with the browser on our behalf.

It looked like this:

// read state
$('form input#email').val()

// write state
$('h1').text('Hello World!')

// get notified when something changes
$('button').on('click', function() {
  alert(2006)
})
Enter fullscreen mode Exit fullscreen mode

But there were some challenges here too:

  1. Selectors: If the structure of the markup changed - which happens a lot - it can break the CSS selector. For example, if you had a selector $('h1').., then you change the markup from <h1> to an <h2>, your selector just silently stops working, and you won't know until a user complains.
  2. Syncing state: State changes happen in 2 directions, DOM-to-model and model-to-DOM. jQuery didn't provide any tooling here, leaving developers responsible for managing the synchronization logic on their own.

AngularJS

In 2010, Google launched AngularJS 1.x, a framework that helps with state management.

Instead of writing jQuery code, like:

<script>
  $('h1').text(someExpression)
</script>
<h1>
Enter fullscreen mode Exit fullscreen mode

Expressions (called bindings) could be embedded directly inside the HTML:

<h1>{{someExpression}}<h1>
Enter fullscreen mode Exit fullscreen mode

and Angular would sync those bindings for us.

Later, if we change our HTML, say by switching an <h1> to an <h2>, nothing breaks with the Angular version. There's no CSS selectors to update.

AngularJS components looked like this:

<!-- specify where our controller/component mounts to -->
<div ng-app="myApp" ng-controller="myCtrl">
  <!-- binding to a variable -->
  <h1>{{year}}</h1>
</div>

<script>
// declare a module
var app = angular.module('myApp', []);

// declare a controller
app.controller('myCtrl', function($scope) {
  // update a variable and trigger syncing
  $scope.year = 2010;
});
</script>
Enter fullscreen mode Exit fullscreen mode

The magic was that anytime you changed something on the $scope variable, Angular would go thru a "digestion cycle", that recursively updated all the bindings.

But there were some problems here too:

  • It only worked in the browser: If a search engine crawled the page, it would see <h1>{{someExpression}}</h1> . Unless you're trying to rank high for {{someExpression}} , that's not great.
  • The digestion loop was inefficient: It takes time to walk the DOM tree and apply changes. Sometimes it could take multiple passes for all the values to settle.

React

In 2013, Facebook launched React, a library for syncing state with UI.

It solved some issues that AngularJS 1.x had. It's isomorphic, it can render HTML both on the server and in the browser, fixing the SEO problem. It also implemented a more efficient syncing algorithm called Virtual DOM.

Refresher: Virtual DOM keeps a copy of the DOM in memory. It uses the copy to figure out what changes (the delta), while limiting potentially slow interactions with the browser DOM. (Though it's been pointed out that this may be overhead.)

It's still conceptually similar to AngularJS, from a state management perspective. React's setState({value}) or in more recently, the useState() hook, is roughly equivalent to Angular's $scope.value = value.

Hook example:

// React state with hooks
const [year, setYear] = useState(null)

// setting state
// functionally equivalent to AngularJS's
// `$scope.year = 2017`
setYear(2017)
Enter fullscreen mode Exit fullscreen mode

The problem

React relies on developers to signal when things change. That means writing lots of Hook code. But Hooks aren't trivial to write, they come with a bunch of rules, and those rules introduce a extra cognitive load into our codebases.

Svelte

In 2019, Rich Harris released Svelte3. The idea behind Svelte is:

What if a compiler could determine when state changes?
That could save developers a lot of time.

It turns out to be a really good idea. Being a compiler, Svelte can find all the places where our code changes state, and update the UI for us.

Example

Say we assign a variable inside a Svelte component:

<!-- a .svelte component -->
<script>
// assign a value
let year = 2019
</script>

<!-- this <h1> depends on `year` state -->
<h1>Hello {year}!</h1>
Enter fullscreen mode Exit fullscreen mode

Svelte detects the let statement and starts tracking the variable. If we change it later, say year = 2021, Svelte sees the assignment = as a state change and updates all the places in the UI that depend on that binding.

Svelte is writing all the Hooks code for us!

Conclusion

If you think about it, a big part of a developer's job is organizing state, moving state back and forth between the UI and the model. It takes effort, and it's tricky to get right. By offloading some of that work to compile-time tools, we can save a lot of time and energy.

Another side effect is, we end up with less code. That makes our programs smaller, clearer to read, easier to maintain, cheaper to build, and most importantly: more fun to work with.

P.S. This post is part of a new course I'm putting together for newline called "Svelte for React Devs". So stay tuned!

Discussion (8)

Collapse
marklai1998 profile image
Mark Lai

I hate Svelte just because it has too much magic(abstraction)
Invent a lot of new syntaxes just to compete with line count

{@debug ...} , {#await} is enough to drive me crazy
How on earth would you put code logic on the template side?

Collapse
joshnuss profile image
Joshua Nussbaum Author

Hi Mark,

Hate is a strong word, but you're totally allowed to have preferences. I think you should only use stuff you enjoy, and makes sense to you.

Personally, I prefer the separation of markup and JavaScript. Having lot's of JS code embedded in templates makes it harder for me to reason about.

The purpose of Svelte's abstractions is not about line count, rather, it's about developer experience. To help developers get more done with their limited time.

Collapse
andresausecha profile image
Andres Ausecha Mosquera • Edited

Hey Mark, what I have learnt of Svelte is not complicated at all. React is much harder to understand, react code requires handling of bunch of re-rendering rules. While react is much better than Angular, Svelte is way easier, clearer, and lighter than them. I suggest to think twice(I am react developer), some syntax to write conditionals or loops is peace of cake...you can copy and paste it.

Collapse
sharu725 profile image
sharath Kumar • Edited

Yeah, there are like 6 of them. Too many to remember. Outweighs the advantages of not having Virtual DOM burden, lower bundle size, ability to use styles (that too scoped), no JSX, so on and so forth.

Collapse
marklai1998 profile image
Mark Lai • Edited

I'm not saying that Svelte has no advantage. But Svelte always try to use "less code" as a selling point which triggers me.
svelte.dev/blog/write-less-code
And the way they achieve this is using short syntax, which invents a lot of unnecessary syntaxes and breaks a lot of the fundamental programming style (separate concerns for example, {@debug ...} , {#await} will totally break it)
We are living in a world that ppl just chose lib base on the syntax for not only readability (like ppl use vue/angular just because of jsx "className") but also maintainability.
Now I see Svelte like PHP, where a language/lib makes ppl write bad code.

Thread Thread
sharu725 profile image
sharath Kumar • Edited

React

import React,{useState} "react";

function App(){
   const [name,setName] = useState('');
  const handleChange = (e)=>{
     setName(e.target.value);  
}

 return (
   <div>
     <h1>Hello {name}</h1>
     <input onChange={handleChange} value={name} />
   </div>
 )
}

export default App;
Enter fullscreen mode Exit fullscreen mode

Svelte

<script>
    let name = 'world';
</script>

<input bind:value={name}>

<h1>Hello {name}!</h1>
Enter fullscreen mode Exit fullscreen mode

So what's wrong with this way of doing it. It is more readable and maintainable. Nothing fancy going on here. Anyone without JS knowledge can go through the Svelte code and can guess what's happening there. Can't say the same thing about React.

I have been using React for years now. It is just not right. React is a short-sighted framework.

Thread Thread
steventhan profile image
Steven Than

I'm not sure if you examples highlight the pros for Svelte, if anything, they actually discouraged me from learning it

So what's wrong with this way of doing it. It is more readable and maintainable.

This is highly debatable. Looking at the snippet, several questions came to mind: What is bind:value? it's not a valid HTML attribute as far as I know. Why is there an unused variable in the <script> tag? What is this syntax of {name}, maybe it refers to the one in the <script> tag, but isn't the tag already closed before getting to this line?
Overall, it makes me think Svelte has too much implicit magic.

Anyone without JS knowledge can go through the Svelte code and can guess what's happening there

Why is Svelte's readability to non-JS devlopers an advantage? It's an JS lib/framework at the end of the day. You're trading readability between JS and non-JS devs here, what good does it bring?

An as an aside, I've yet to come across a resource for writing reusable libraries that target Svelte. I often find myself writing npm-installable component libraries, and react hooks brought it to another level by letting me ship non-visual logic with ease, is there such concept in Svelte?

Thread Thread
kevmodrome profile image
Kevin Åberg Kultalahti

To answer your last paragraph; the concept you're looking for is custom stores

Forem Open with the Forem app