Comment by jitl

5 years ago

When your React component renders, it returns an object that describes the desired state of the component tree. Take this component:

    function MyComponent() {
     return <div>Here's <b>bold text</b></div>
    }

At runtime, React calls your component function and then applies the returned data to the DOM imperatively. If your component has rendered before, React needs to _diff_ the virtual DOM your latest render returned against the VDOM React last applied to the real DOM. Very simplified idea of what happens on every render:

    function reactInternalRenderLoop(root) {
     const newVdom = MyComponent({})
     const diff = diffVdoms(root.prevVdom, newVdom)
     for (const change of diff) {
      change.applyToDOM(root.domNode)
     }
     root.prevVdom = newVdom
    }

React's runtime time complexity is fundamentally limited by this `diffVdoms` function, and React's memory usage is fundamentally limited by the size of the VDOM returned by components.

What Svelte does is entirely eliminate this whole process involving diffing and what-not. At compile time, Svelte analyzes the data dependencies between the rendered template and reactive values in the app, and generates self-contained components that know how to update their own DOMs. You can think of it as essentially moving the entire `reactInternalRenderLoop` function from _runtime_ to _compile time_. There is no more diffVdoms function call on your user's devices. There is no more big allocation of VDOM data structures.

Svelte might compile `MyComponent` to something that looks like this:

    const MyComponent = {
      mount(parent) {
        const element = document.createElement('div')
        div.innerHTML = "Here's <b>bold text</b>"
        parent.appendChild(div)
      },
      update() { /* no-op */ }
    }

And since the Svelte compiler knows the contents of MyComponent never change, the mount function will only be called once for the entire runtime of your app.

So it sounds like the tradeoff here is that the generated bundle is more complicated/bigger. I'm not familiar with Svelt, but wondering about bundle size + debuggability.

  • At a certain size, yeah the bundle will be larger, but it would take a lot to get to that point. For pretty much anything you would do, the bundle will be much smaller. Especially if you use SvelteKit which is smarter about what is bundled and when it loads.

    As for complexity, the generated Svelte code is extremely readable. Take a look at the generated JS tab in the repl: https://svelte.dev/repl

  • When I tried Svelte a while back (year or two ago) I had difficulty working with code in the debugger, couldn't seem to get source maps to work correctly, I wonder if it's fixed.