SvelteJS Vs React JS || Quick Compare

Lets compare svelte js with React JS

Github : https://github.com/tkssharma/lets-play-with-sveltejs Playlist : https://www.youtube.com/watch?v=lxzyI4WoffM&list=PLT5Jhb7lgSBMqIuNda0gGNEiMS-ahGJM1

Our todo application will have listing, adding and removing items. Each items will be stored in a global state. Also there will be component which will subscribe global store and will show current value whenever it changed

Both Svelte and React source codes are on github

$ npx degit sveltejs/template svelte-todo-list

Brief information about Svelte

  • Works on DOM, no Virtual DOM
  • Svelte files has .svelte extension
  • Each written in svelte files are scoped css.
  • You can use its internal store apis. No need to install an external library
  • Build by Rollup with default configuration. However, you can also use Parsel and Webpack.
  • You can subscribe any variable easily, but it has some hacky ways to detect array mutations. (This one which i didnt like)
  • You can write both javascript, html and styles in svelte files like you are writing a html file. ( has minor difference)
  • You access DOM events with on: prefix such as,
  • You do not need to pass callbacks from child to parents. You can use createEventDispatcher.
  • You start a block with {#} and ends with {/} such as {#if}…{/if} ReactJS
$ npx create-react-app react-todo-list

Brief information about ReactJS

  • Works with Virtual DOM
  • You can use React’s internal global state management which is called Context API
  • You write purely javascript, you do not have block element syntax special to React like in Svelte ( #if, #each … )
  • DOM events are just javascript events so you can use onClick like how it’s written in purely javascript (standart DOM event for click is onclick! however your OnCLICK oNCLiCk will also be rendered by browser.)
  • File extension is .js/.ts Some code comparisons

Let’s compare some key points between Svelte and React.

<script>
  import TodoHeader from "./TodoHeader.svelte";
  import TodoList from "./TodoList.svelte";
  import { itemStore } from "./store";
</script>
<style>
  main {
    font-family: sans-serif;
    text-align: center;
  }
</style>
<main>
  <div>Total item: {$itemStore.length}</div>
  <TodoHeader />
  <TodoList />
</main>
import React from 'react';
import './App.css';
import { TodoHeader } from './TodoHeader';
import { TodoList } from './TodoList';
import { TodoListProvider } from './store';
import { Total } from './Total';
function App() {
  return (
    <TodoListProvider todoList={[]}>
      <Total />
      <TodoHeader />
      <TodoList />
    </TodoListProvider>
  );
}
export default App;

App files are entry points in both framework. There is not much difference between two, they both have components to render. The only difference is here that global style binding. In React, a Wrapper Component for React.ContextAPI is a parent of all children whereas in Svelte, you do not need a wrapper for global state.

svelte / store.js;

import { writable } from 'svelte/store';
const createItemStore = () => {
  const { subscribe, update } = writable([]);
  return {
    subscribe,
    addItem: (newItem) =>
      update((items) => {
        if (!items.find((item) => item === newItem)) {
          items.push(newItem);
        }
        return items;
      }),
    removeItem: (removedItem) =>
      update((items) => {
        const newItems = items.filter((item) => item !== removedItem);
        return newItems;
      }),
  };
};
export const itemStore = createItemStore();

react/store.js

import React, { useState } from 'react';
export const TodoListContext = React.createContext({});
export const TodoListProvider = ({ todoList, children }) => {
  const [todos, setTodos] = useState(todoList);
  const addItem = (item) => {
    if (!todos || !todos.find((listItem) => listItem === item)) {
      setTodos([...todos, item]);
    }
  };
  const removeItem = (item) => {
    setTodos(todos.filter((listItem) => listItem !== item));
  };
  return (
    <TodoListContext.Provider
      value={{
        todoList: todos,
        addItem,
        removeItem,
      }}
    >
      {children}
    </TodoListContext.Provider>
  );
};
export const TodoListConsumer = TodoListContext.Consumer;

These two store does same things. They have both action methods to mutate store data. However, in React using Context API and creating same structure like in Svelte can be some painful. As shown in above example, at first, we created a Context from createContext and in our Provider we had to use hooks to store values locally. Things are more simpler in Svelte, you just create a writeable store and initialize its value and return your value with its actions.

svelte/TodoList
<script>
  import { itemStore } from "./store";
  const handleRemoveItem = item => {
    itemStore.removeItem(item);
  };
</script>
<style>
  ul {
    list-style-type: none;
  }
</style>
<ul>
  {#each $itemStore as item}
    <li>
      {item}
      <button on:click={() => handleRemoveItem(item)}>Remote Item</button>
    </li>
  {/each}
  {#if $itemStore.length === 0}
    <div>There is not any item added. Please add one</div>
  {/if}
</ul>
react / TodoList;

import React, { useContext } from 'react';
import { TodoListContext } from './store';
export const TodoList = () => {
  const todoListContext = useContext(TodoListContext);
  const handleRemove = (item) => {
    todoListContext.removeItem(item);
  };
  const { todoList } = todoListContext;
  return (
    <ul>
      {todoList &&
        todoList.map((todoList) => {
          return (
            <li>
              {todoList}
              <button onClick={handleRemove.bind(null, todoList)}>Remote Item</button>
            </li>
          );
        })}
      {todoList.length === 0 && <div>There is not any item added. Please add one</div>}
    </ul>
  );
};

The thing that forced me writing my first Svelte application was using conditions and loops in component. Using syntax another then pure javascript for loops or conditions are the things i do not like. But, accessing store item with only import and not needing to any external hook or layer for accessing global store is the key difference between Svelte and React.

svelte/TodoHeader

<script>
  import { onMount } from "svelte";
  import { itemStore } from "./store";
  let value;
  onMount(() => {
    value = "";
  });
  const handleAddItem = () => {
    itemStore.addItem(value);
    value = "";
  };
</script>
<style>
  .disabled {
    color: graytext;
  }
</style>
<input type="text" bind:value placeholder="Item name" />
<button on:click={handleAddItem} disabled={!value} class:disabled={!value}>
  Add Item
</button>
react / TodoHeader;

import React, { useContext, useState } from 'react';
import { TodoListContext } from './store';
export const TodoHeader = () => {
  const todoListStore = useContext(TodoListContext);
  const [itemName, setItemName] = useState('');
  const handleAddItem = (e) => {
    e.preventDefault();
    todoListStore.addItem(itemName);
    setItemName('');
  };
  return (
    <>
      <input
        placeholder="Item name"
        type="text"
        value={itemName}
        onChange={(event) => setItemName(event.target.value.trim())}
      />
      <button onClick={handleAddItem} disabled={!itemName} className={!itemName && 'disabled'}>
        Add Item
      </button>
    </>
  );
};

In Svelte, you do not need to store your input’s value in a state externally. Svelte makes it easier with binding keyword to any existing property, with a plus additional feature that you can track that prop changes with reactive declaration without extra effort for values (not for arrays).

Results

Also, let’s share some results about building process, difficulty and conveniences which i faced while developing.

I followed exactly same pattern while developing both. I did not use any external libraries and used only internal API’s both frameworks support. There are components connected to global state. There are components subscribed to global state variables.

What i like in Svelte ❤️

  • Building is really fast. But this may be also because of using Rollup as a bundler, i think it would be good to test bundling with Webpack also.
  • Again bundle size is really small against React. However this may be also because of Rollup’s tree-shaking performance.
  • It’s store usage is really flexible. You can adapt your components within store and start subscribing or mutating store values easily. ❤️
  • I liked all styles written in a component are scoped css. Binding a conditional style has easy syntax which you do not need to create a logic for class binding. (class:disabled=variable) What i dislike in Svelte 💔
  • I really do not like writing templates in a file, such as #each , #if. I do not like to prefer using new approaches for which i can do it with purely in JavaScript.
  • When you use reactive declarations to subscribe a variable change, Svelte can not detect mutations on arrays. Svelte offers some hacky ways for that situation.
  • Some developers may like writing templates in a component however this one is still what i could not like. Also, this approach leads using templates for loops, conditions etc which i referred in item 1.
  • You should give a unique id for each item in a list, otherwise whenever you want to get an action on the item in list, a wrong item could be effected.
  • Usage style in DOM events such as on:click is one of the things i do not like. I prefer using onClick as a normal DOM event. (standart DOM event for click is onclick! however your OnCLICK oNCLiCk will also be rendered by browser.) Production Build Comparison
  • SvelteJS uses Rollup and ReactJS Webpack in defaults and i didn’t touched their configurations, they have both default configuration. Svelte built time was 1.40s where React builds 5.49s. Here Svelte wins! ❤️

Build Times

Both application is server by serve npm package. Svelte exports its bundles into public folder whereas react app put them into build folder.

serve -s build // this is for react app serve -s public // this is for svelte app

When i checked network tab, Svelte’s bundle is just 2.9 KB after gzip whereas React’s bundle is just 42.1 KB after gzip. here again Svelte w️️ins with its bundle sizes on production ❤️

Comments