Virtual DOM is More Powerful Than we Think

Virtual DOM is More Powerful Than we Think

If you're into the world of web development, you've like heard of the Virtual DOM before - a JavaScript representation of the real DOM libraries like React use to keep track of reactivity.

However, more recently, many libraries and frameworks have challenged the effectiveness of the Virtual DOM, and projects like Svelte and Solid have shown that fine-grained reactivity can be faster and easier to use than an abstraction upon the DOM.

"This unlocks complete control over what gets updated and when, even at the DOM binding level. With no Virtual DOM or extensive diffing, the framework never does more work than you want it to."
- SolidJS

So why did the brilliant engineers at companies like Meta (React) and Google (Angular) follow this pattern? Was it simply because fine-grained reactivity wasn't possible?

Not quite. It turns out the Virtual DOM has much more power than many realize - in fact, it's power and usability extends even far beyond the platform is made for in the first place, the web.

Beginnings

It all began in 2013, when the pattern of the Virtual DOM was released with React. The idea behind the Virtual DOM was simple - updating in batches.

At the time, manipulating the DOM through JavaScript was painful. Libraries like jQuery had made progress towards improving this, but it could still be performance drag to rapidly manipulate the DOM.

Batching Reactivity

The React team came up with something different. Instead of updating every value and element for reactivity, what if React batched changes together and pushed them to the DOM at the same time?

And so, the Virtual DOM was born. By representing the DOM within JavaScript, changes could be quickly made and calculated before getting pushed to the real DOM.

Brilliant Lifesaver or Performance Drag?

In the passing years, React would grow to be the dominant choice for developer building reactive webapps, and it continues to be today. It's easy to understand why - the idea of markup being functions, with ui = f(state), is appealing in simplicity and power.

That being said, it began to be apparent that the Virtual DOM wasn't all sunshine and rainbows. Just take a look at a recent example of React's struggle with performance - the useMemo() hook and React Forget.

The useMemo() Hook

In 2019, React released the useMemo() hook, which was intended to fix a major issue with React's performance. Because of how React tracked reactivity, you would often end up with massive performance bottlenecks due to elements being unnecessarily updated.

To solve this, the React team introduced memoization to the library. Memoization is the technique of storing or caching values produced by functions that are expensive to run. By introducing the useMemo() hook, React developers could tell the framework when not to update elements, vastly improving performance.

But the introduction of useMemo() further complicated what was meant to make developing on the web simpler and interrupted the previous logical flow of React.

React Forget

To this day, React continues to struggle with this problem. Recently, React has been making progress on a new compiler for the library called React Forget, which uses analysis to automatically memoize at build time.

But while React Forget vastly simplifies the developer experience, it still is a massive undertaking that does a lot of work for solving a simple problem, as the compiler has to analyze your code to inteligently recognize where useMemo() should be added.

ā„¹ļø React Forget is still being built, but we have seen traces of it in production apps like the Meta Quest Store and even Instagram, so expect more news soon šŸ‘€

Other frameworks like Svelte and Solid don't have to deal with this, because they're capable of only updating what needs to be changed. This vastly improves the DX, UX, and build time.

A Hidden Strength

So, you might think, the Virtual DOM has no purpose. It's slow, makes for a worse DX, and doesn't even offer an advantage over traditional fine-grained reactivity.

But while many of these points are true, the Virtual DOM has one saving grace, and it makes React extremely powerful - The Virtual DOM isn't limited the web.

Beyond the Web

If you've ever created a React project, you'll know that at least two dependencies are required - react as well as react-dom. When I was first introduced to React, I found this strange, but the reason is because the react package generates the Virtual DOM, whereas the react-dom package actually renders to the DOM.

What does that mean? In essence, anyone can create packages that interpret the React Virtual DOM and then produce various outputs. Rendering to the web, through react-dom, is just one approach.

Libraries & Frameworks

We've already seen this used in many incredible libraries and frameworks. React Native takes the Virtual DOM and creates native components for iOS and Android. Remotion takes the Virtual DOM and creates real .mp4 videos. React Three Fiber lets you render full 3D scenes with just React.

There truly are no limits. There's even a project by the incredible Poimandres team called react-nil, which doesn't render to anything - instead, it simply lets you build servers and CLIs through a React abstraction.

The implications of this strategy are massive, as it means React is a common interface for doing essentially anything through a computer. The component & state thinking of React is incredibly useful, and the Virtual DOM brings that thinking everywhere.

A Note of Caution

Of course, with great power comes consequences. Many times, React isn't the best way to do something, and so it's important to carefully consider whether using React as an interface for whatever you're doing is truly the right way.

Conclusion

In conclusion, the Virtual DOM is truly powerful because it simply takes the component interface and transforms it into an object, easily manipulated/interpreted in any way.

Ā