Hacker News new | ask | show | jobs
by fwilliams 3026 days ago
I'm not a frontend developer and don't know really know JavaScript frameworks. That said, it seems like something very well established like React would choose to have a virtual DOM for a good reason.

Surely there must be some tradeoffs that the author makes for his design to get better performance. Could somebody explain the cost/benefit of doing things one way versus the other?

1 comments

Virtual DOM was invented not to make things faster than with jQuery, etc., but to make a better and less error-prone style of web app development not be intolerably unperformant.

I think if we could see a larger Radi example, say, the standard TODO app, the costs of its approach would become obvious.

That's not true. Virtual DOM was created to avoid recreating huge DOM elements each time a re-render is needed, which was the way apps used to be done in the days of jQuery.
Eh, not exactly right either. In the jQuery days, the problem is that you needed different procedural code paths to go from one DOM state to another depending on what action you took. For example, adding a row to a list would be `$('.list').html(html)`, removing would be `$('.list :last-child').remove()` and updating one item might be `$('.list #' + id).text(value)`.

Templating engines such as handlebars provide a declarative abstraction that represents how the DOM is supposed to look like given some rules, rather than procedurally specifying how to get from A to B. This is similar to how you write HTML declarative as opposed to how you have to write canvas code procedurally.

Virtual DOM is just an implementation detail of some templating libraries that have the same goal of providing that declarative abstraction. The problem was that popular KVO systems (e.g. Knockout and Ember) were notoriously slow and people were looking for alternative ways to speed up declarative rendering libraries. The community has since learned a lot about performance and is realizing that KVO systems _can_ be performant after all.

The main drawback of KVO systems is that their API bleeds into the data layer because they require you as a developer to manually register data as observable entities. In contrast, virtual DOM works with plain Javascript objects which are much more familiar and easier to manipulate and interop with. A third approach, called dirty checking and popularized by Angular also had the desirable property of working w/ plain js objects, but it was also very slow. Some systems (most notoriously Vue 1) tried to bridge the gap between KVO and POJOs by providing a POJO-looking data layer that has monkeypatched array methods etc that provide observability/reactivity under the hood. Without JS proxies, though, this still left some weird edge such as the ones handled by `Vue.set`/`Vue.delete`. Vue eventually moved to vdom because the way it mounted subcomponents didn't scale for recursive mounts (think comment trees such as the ones in HN or reddit). This is because it had to mount each level to find out what subcomponents needed to be mounted, and as well know, multiple repaints is a big no-no for perf.

With that said, virtual DOM is not perfect either. It's inherently memory intensive and can block the UI in cases with large DOMs and few changes. Various frameworks have various techniques to cope (such as shouldComponentUpdate and friends) but they typically require developer intervention, whereas a KVO system would not suffer from this class of problems to begin with. Another problematic aspect of virtual DOM systems is that they are "naked" js and thus, difficult to optimize as libraries from an algorithmic standpoint. This is why Svelte does better in benchmarks than vdom systems.

TL;DR: if you want to evaluate the performance characteristics of a KVO system such as Radi or Surplus, the main things you should ask about are API lock-in in the data layer and performance of recursive mounts. If you want to evaluate perf of virtual DOM systems, you should ask about diff latency for needle-in-a-haystack scenarios and ease of use for hooks to selectively diff a tree.

> It's inherently memory intensive

Even if we pretend that other architectures doesn't have any memory overhead, vdom memory overhead in a large UI app will be less than a single small decoded image. But in reality, KVO can be way much more memory intensive, especially when we consider cases that involve filtering items in large collections.

I was reading this thinking, gee, here's someone who knows a lot about JS frameworks. Only later noticed the username. Hi Leo!