John Au-Yeung I'm a web developer interested in JavaScript stuff.

RE:DOM vs. Svelte

6 min read 1888

RE:DOM vs. Svelte

RE:DOM is a library for manipulating the DOM, and Svelte is a framework with routing and transitions. In this post, we’ll review their differences and establish which would be a better choice for different kinds of applications.

Creating components with RE:DOM and Svelte

RE:DOM and Svelte both let us create components to render content.

Svelte

In Svelte, we create components in individual files. For example, we can write:

//App.svelte

<script>
    import Button from "./Button.svelte";
</script>

<style>
  main {
    font-family: sans-serif;
    text-align: center;
  }
</style>

<main>
    <h1>Hello</h1>
    <Button />
</main>
//Button.svelte

<script>
    let count = 0;

    function handleClick() {
      count += 1;
    }
</script>

<style>
    button {
      background: #ff3e00;
      color: white;
      border: none;
      padding: 8px 12px;
      border-radius: 2px;
    }
</style>

<button on:click={handleClick}>
  Clicked {count} {count === 1 ? 'time' : 'times'}
</button>

We created the Button component in Button.svelte, which we include in the App.svelte component file.

The script tag has the logic, and style has the styles for each component. The remainder of the file has the HTML content we want to render.

We embed JavaScript expressions in braces, and it has its own syntax for attaching event handlers. The on:click attribute lets us attach a click handler.

Functions that are in the script tag can be referenced in the HTML template, as we did with the handleClick function.

Any variables declared in the script tag can referenced and rendered in the template, as we have in the button element.

Data binding is done automatically, so no need to do that ourselves.

RE:DOM

With RE:DOM, we install the redom package by running:

npm i redom

Then we can create a simple component by writing:

//index.js

import { el, mount } from "redom";

const hello = el("h1", "Hello world");

mount(document.body, hello);

This assumes we’ll use a module bundler like Parcel to create our project. We create our component with the el function and pass in the tag and the HTML we want to show. Then, we call mount to mount the hello component to the body.

We can create a text component with the text function:

import { text, mount } from "redom";

const hello = text("hello");

mount(document.body, hello);

hello.textContent = "hi!";

We pass in the initial textContent into the text function, and when we reassign its value, it’ll automatically be updated.

If we want to add child elements, we write:

import { el, setChildren } from "redom";

const a = el("h1", "foo");
const b = el("h2", "bar");
const c = el("h3", "baz");

setChildren(document.body, [a, b, c]);

Then we add the elements in the same order as in the array.

We can also create RE:DOM components with classes. This lets us set lifecycle methods to run code in various stages of the component lifecycle. For example, we can write:

import { el, mount } from "redom";

class Hello {
  constructor() {
    this.el = el("h1", "Hello world");
  }
  onmount() {
    console.log("mounted Hello");
  }
  onremount() {
    console.log("remounted Hello");
  }
  onunmount() {
    console.log("unmounted Hello");
  }
}

class App {
  constructor() {
    this.el = el("app", (this.hello = new Hello()));
  }
  onmount() {
    console.log("mounted App");
  }
  onremount() {
    console.log("remounted App");
  }
  onunmount() {
    console.log("unmounted App");
  }
}

const app = new App();

mount(document.body, app);

Above, we have a Hello component that’s nested inside the App component. To do the nesting, we create a new instance of it and pass it as the second argument into el.

In general, Svelte has many more options for creating components since it’s meant to be an app development framework. RE:DOM is much more limited since it should be used as a DOM manipulation library.

Updating components

Svelte

In Svelte, we can update components in various ways.



We update the variables in the script tag, and the new value will automatically be rendered. For example:

//Button.svelte

<script>
    let count = 0;

    function handleClick() {
      count += 1;
    }
</script>

<style>
    button {
      background: #ff3e00;
      color: white;
      border: none;
      padding: 8px 12px;
      border-radius: 2px;
    }
</style>

<button on:click={handleClick}>
  Clicked {count} {count === 1 ? 'time' : 'times'}
</button>

If we click the button, then the handleClick function is run, which increases count by one. count‘s latest value will then be rendered in the template. We just display it, and we also use it to render something else, as we can see from the expression.

We can also add style bindings with Svelte. For example, we can write:

<script>
    let size = 42;
    let text = "edit me";
</script>


<input type=range bind:value={size}>

<div>
    <span style="font-size: {size}px">{text}</span>
</div>

We have a range slider, which binds to the size variable. So, when we change the slider value, the size value will change with it.

And in the span element, we use the size value to change the font-size style. Therefore, the slider will change the size of the edit me text.

It also comes with a special syntax for setting classes.

For example, we can write:

<script>
 let active = true;
</script>

<style>
  .active {
    background-color: red;
  }
</style>

<div>
  <div
    class="{active ? 'active' : ''}"
    on:click="{() => active = !active}"
  >
    toggle
  </div>
</div>

We toggle the active class on and off when we click the button by toggling the active variable between true and false.

We can also write something like this to do the same thing:

<script>
 let active = true;
</script>

<style>
  .active {
    background-color: red;
  }
</style>

<div>
  <div
    class:active='{active}'
    on:click="{() => active = !active}"
  >
    toggle
  </div>
</div>

We have an expression that determines whether the active class is applied with the class:active attribute.

RE:DOM

With RE:DOM, updating components is more limited. We can set attributes of an element or set the style. For example, we can write something like this to create an h1 element and set its color to red:

import { el, setAttr, mount } from "redom";

const hello = el("h1", "Hello world!");

setAttr(hello, {
  style: { color: "red" },
  className: "hello"
});

mount(document.body, hello);

The setAttr function takes two arguments: the first is the element we created, and the second is an object, with the keys being the attribute names and the values being the attribute values.

RE:DOM also comes with a setStyle method to let us set the styles of an element. For instance, we can use it by writing:

import { el, setStyle, mount } from "redom";

const hello = el("h1", "Hello world!");

setStyle(hello, { color: "green" });

mount(document.body, hello);

This sets the h1 element to green.

These are the main ways to update components.


More great articles from LogRocket:


Developer experience

Svelte is a full app development framework, while RE:DOM is a library for DOM manipulation. They both make manipulating the DOM easy.

Svelte lets us write code expressively and eliminate boilerplate. To quickly create a Svelte project, we have to clone the Svelte template repo, which is not terribly convenient.

On the other hand, with RE:DOM, we just install the redom package with npm i redom.

We can slso use the script from https://redom.js.org/redom.min.js to add it to our app. This means we don’t need build tools to add RE:DOM to our app project.

Both tools support the latest JavaScript syntax. Since RE:DOM is a library, it doesn’t have a CLI program to let us create apps. On the other hand, there’s no CLI program to create a Svelte project from scratch and build it, which isn’t very convenient.

Performance

According to many tests, RE:DOM is faster than Svelte. From AJ Meyghani’s benchmarks, we can see that Svelte is slower than RE:DOM in many respects. This plays out similarly in more recent benchmarks as well.

However, the differences amount to only a few milliseconds, which may not be very noticeable in most cases. It’s worth reiterating that RE:DOM is a lightweight library, while Svelte is a full app development framework, so this makes sense.

Routing

RE:DOM comes with a router for mapping URLs to components to render, while Svelte doesn’t come with its own router.

Svelte

To add routing to our Svelte app, we need to install the svelte-routing package by running:

npm i svelte-routing

Then, we write:

//routes/About.svelte

<p>about</p>
//routes/Blog.svelte

<p>blog</p>
//routes/BlogPost.svelte

<script>
  export let id;
</script>

<p>blog post {id}</p>
//routes/Home.svelte

<p>home</p>
//App.svelte

<script>
  import { Router, Link, Route } from "svelte-routing";
  import Home from "./routes/Home.svelte";
  import About from "./routes/About.svelte";
  import Blog from "./routes/Blog.svelte";
  import BlogPost from "./routes/BlogPost.svelte";

  export let url = "";
</script>

<Router url="{url}">
  <nav>
    <Link to="/">Home</Link>
    <Link to="about">About</Link>
    <Link to="blog">Blog</Link>
    <Link to="blog/1">Blog Post</Link>
  </nav>
  <div>
    <Route path="blog/:id" let:params>
      <BlogPost id="{params.id}" />
    </Route>
    <Route path="blog" component="{Blog}" />
    <Route path="about" component="{About}" />
    <Route path="/"><Home /></Route>
  </div>
</Router>

We add the Router component to add the router, and Route adds the routes.

We pass in URL parameters with the let:params attribute and the id prop to accept the id URL parameter.

:id is the URL parameter placeholder. If there are any parameters, we can get them as props, as we did in BlogPost.svelte. If we have the export keyword in front of the variable declaration, then it’s a prop.

RE:DOM

To use RE:DOM’s router, we can write:

//index.js

import { el, router, mount } from "redom";

class Home {
  constructor() {
    this.el = el("h1");
  }
  update(data) {
    this.el.textContent = `Hello ${data}`;
  }
}

class About {
  constructor() {
    this.el = el("about");
  }
  update(data) {
    this.el.textContent = `About ${data}`;
  }
}

class Contact {
  constructor() {
    this.el = el("contact");
  }
  update(data) {
    this.el.textContent = `Contact ${data}`;
  }
}

const app = router(".app", {
  home: Home,
  about: About,
  contact: Contact
});

mount(document.body, app);

const data = "world";

app.update("home", data);
app.update("about", data);
app.update("contact", data);

We create the routes by using the router function.

The keys in the object are the URLs for the routes. app.update goes to the route we want. We pass data into the routes, which we get from the update method’s parameter.

Generally speaking, RE:DOM’s router is definitely less flexible than Svelte’s.

Conclusion

RE:DOM is a lightweight DOM manipulation library. Even though we can create components with it, it’s not very expressive for the purpose of creating complex components. As such, we should stick with just manipulating the DOM with it.

Svelte, on the other hand, is a full app framework as long as we add the svelte-routing package to it for routing.

Are you adding new JS libraries to improve performance or build new features? What if they’re doing the opposite?

There’s no doubt that frontends are getting more complex. As you add new JavaScript libraries and other dependencies to your app, you’ll need more visibility to ensure your users don’t run into unknown issues.

LogRocket is a frontend application monitoring solution that lets you replay JavaScript errors as if they happened in your own browser so you can react to bugs more effectively.

https://logrocket.com/signup/

LogRocket works perfectly with any app, regardless of framework, and has plugins to log additional context from Redux, Vuex, and @ngrx/store. Instead of guessing why problems happen, you can aggregate and report on what state your application was in when an issue occurred. LogRocket also monitors your app’s performance, reporting metrics like client CPU load, client memory usage, and more.

Build confidently — .

John Au-Yeung I'm a web developer interested in JavaScript stuff.

Leave a Reply