Cample.js: Reactivity without virtual DOM
github.com
github.com
I believe VDOM-based approaches have one decisive advantage — the VDOM structure can be created by any means convenient to the programmer. To me at least, this offers more flexibility and modularity when organising code: you can create as many functions as you need to structure and reuse VDOM construction. This is something I run into with Svelte, which forces me to make a new component for every bit of code I try to isolate. Solid is a bit better — and I really like their idea of "vanishing components" — but you have to follow it's fairly strict rules (e.g. no props destructuring) or things will get weird.
In Lit, we do this with tagged standard template literal expressions that return what we call a TemplateResult. You can compute, store, abstract over those however you want - they're just JS values. This indeed gives programers a ton of expressive power.
You mark in the DOM where the expressions are, and on updates instead of a vdom diff you check if the template rendering to a DOM location is the same as before. If it is then you just update the expressions. All the unchanged elements stay the same, and sine you don't traverse the DOM or a VDOM, the update is much faster.
- VDOM is data-driven without side-effects
- VDOM does not actually require JSX or build steps
- VDOM decouples you from the real dom, which has allowed things like react-native to "just work" the way react web works.
- VDOM means you can make test assertions without having to load up a "browser-like" environment
- JSON is a pretty easy to reason-about data structure, which makes debugging fairly easy
I'm not saying the virtual dom is the best answer, but I guess my point is that it's not really an issue of speed any more. If I recall my internet history, React came at a time when browser DOM standardization was still pretty wonky, so the virtual dom did provide a boost in manipulating the data that would translate to DOM mutations. Now that we're basically all running Chrome or Firefox under the hood (give or take webkit safari), I'm not sure that's the main drive any more, but the other benefits still stand, and that's why things like react are still using the virtual dom.
Anyway, cool library. I'm curious if it provides something that is actually different from other libraries I've used, in terms of interface or flow, and I might find some time to check it out soon. Good job!
That said, the big feature here seems to be what the headline says: no virtual DOM. As a user of frameworks, I don't care much about implementation details unless they result in benefits like performance improvements. Does this perform better than React and/or Vue? Or is there some other benefit to it?
Still, the question remains, what's the improvement over Svelte or SolidJS which doesn't use VDOM as well ?
https://krausest.github.io/js-framework-benchmark/2023/table...
No VDom is always faster than having a VDom.
But I do agree with your point 100% that it should tell you right away about it on the README what that means, and the significance behind the claim.
IIRC in a recent stream the author of Solid showed that it's hard to beat a proper VDOM implementation when you have 1000s of elements.
And most naive non-VDOM implementations will probably lose to a good VDOM implementation.
Is there some recent study showing evidence or analysis of this? You're saying the main root cause of poor performance is the diff burning up CPUs?
I always assumed applications run slowly because people are overusing global (redux) state and every state change is subscribed to by like 10 different components. And people making 5 network calls before their component meaningfully renders.
If you're rendering thousands of items on an SVG data visualisation, sure it matters.
You can tell it matters because otherwise React wouldn't have implemented escape valves to improve performance, like shouldComponentUpdate.
You can get around this by using persistent data structures with lenses, which is how Elm works. Then it's just reference equality checks as you go down the tree, which is inherently faster.
I am not educated on the no-virtual-DOM-hype.
What actually costs more here:
(1) the diff and vdom algorithm or
(2) the actual DOM calls?
I always thought it was (2)... is this right?
If I understand correctly react elements are created in memory, and only upon "render" it is turned into the actual DOM. During render in react, it does the tree diffing and state management. Supposedly manipulating the actual DOM directly is "heavy" hence delay/pruning the virtual DOM tree first then rendering would be beneficial? Then why is it working with DOM directly is desirable? And am I right to assume that "without virtual DOM" means work with DOM directly? Someone in the comment mention that Svelte is without vDOM already. Is there some design document that I can refer to, like the reconciliation engine used in react https://github.com/acdlite/react-fiber-architecture
I suspect, but this is just my personal conjecture, that the reason VirtualDOM is suddenly falling out of favour is a reaction against very bloated JavaScript applications and the complexity that underlies working with current popular frameworks and libraries. Some are starting to question whether we are working with solutions to actual problems faced or whether we've adopted approaches that were intended to solve a specific problem faced by some but are inefficient for simpler applications.
As always, be an engineer. Consider all relevant factors before choosing a set of tools or marrying yourself to one technology vs another.
As someone who has only really got up to speed with React in the past year, I can't understand why people hate on React. Much of the hate has to be residual hate for Meta.
Svelte to me seems like a mess. $:variables seems like an absolutely terrible idea. Maybe it is a good idea if you are a genius but I assure you I am not and can do absolutely confusing and crazy things with $:variables.
I'm not sure where the people you are hearing from are coming from, but I can tell you why I personally hate on React.
It has nothing to do with VDOM or its underlying tech, it is its design.
React gets treated as if it's a framework but is just a view library that gives you the ability to create components.
However, even that ability is rather lacking compared to a framework like Angular. Now, people hate on Angular too for various reasons but to stay on topic I won't digress into that.
Things I'm missing OUT OF THE BOX (yes I know there are 12 billion libraries "for that" that came out this week alone) with React are:
- View encapsulation (styles bound to components)
- A templating language that lets me separate a component's markup from its JavaScript
- Native typescript
- Inversion of Control / dependency injection framework
- Native routing that lets me configure my routes as metadata instead of having to use components, which ought to be strictly view / presentation only.
Working with inherited React code often reminds me of working with PHP in the 90s. Lots of markup mixed with lots of logical operations written by developers who don't know the first thing about separation of concerns, design patterns or layered architecture but the barrier to entry is low so they picked it up and were able to get stuff done with it despite not having any guidance what-so-ever on how to write maintainable code with a long shelf-life.
My very rough understanding is: It's nice to be declarative and just re-render everything on every state change. This is impractical to do with actual dom, but maybe works good enough with vDOM and dom diffing. Still, doing vDOM and them actual DOM updates is more work than just doing the DOM updates that are needed. And I guess tools like svelte let you be declarative and only make the necessary DOM updates while skipping the vDOM.
Now that we played with the easiest implementation of V = f(S) for a few years, we're moving on to more complex implementations, which have their own benefits. Namely, less overhead and better DX.
Frameworks like Svelte are moving good chunk of state management accidental complexity out of your app code and into the framework itself, where it actually belongs (i.e. where it is essential).
Kind of. Virtual DOM nodes are extremely lightweight compared to real DOM nodes, so manipulating a VDOM to determine what updates need to be done to the DOM, instead of doing all interactions/comparisons directly with the DOM, had a big performance boost.
You're still making the same amount of DOM manipulations in the end. And you don't need VDOM to figure out which manipulations are necessary.
There are some potential optimizations VDOM can allow (e.g. batching/deduping), but there's nothing "lightweight" about it. Lightweight overhead is still overhead.
The word "React" never appears in the README.
IMO the advantage of ES module support in browsers is not needing to bundle in development (although with native bundlers like esbuild this is less of an issue) and for deploying small apps where the tree is shallow. If and when your codebase starts growing, you should use a bundler.
BTW, I'm not the one that keeps downvoting you to death!
Perhaps pair it with a typescript library for composing it. There's nothing sacred about HTML for describing the DOM, but that it what it was created for, and the language the browser will report it.
If your components are large enough to warrant this simply break them down.
I also find separation of concerns conceptually more sound and powerful.
These complaints sound a bit like saying "man, compilers are so complicated, hopefully this trend is dying and we can get some sanity back."
>it has left a permanent mark on the field
It sure has, an indelible stain
The same can be said about libraries like React and websites. Honestly, your position is completely untenable because it's the classic "everyone is dumb except me." Ah yes, all these million and billion dollar companies decided to use React because they're bored and not because it brings any value. You're the only genius, if only everyone realized that the Ideal Website was just handcrafted js.
There are thousands of websites written in React today, and they bring value to their users. That's not disputable. To suggest that there's no benefits is just an astounding level of arrogance.
Just do a quick search on HN, Twitter, Mastodon. You’ll see that’s actually not at all hard to find articles questioning its effectiveness.
The epiphany I had a few years ago is that React is very good for hiring, being hired, managing a team and has very little to do with writing and maintaining a website. At least that’s what I tell myself to find some peace. If you don’t think the JS world is mad, I don’t know if I can convince you in a HN thread.
Just because style, logic, and result are logically grouped it doesn’t mean you’re losing “separation of concerns”. If in fact your definition of that is so shallow it amounts to simply having things in different files, you can do that anyway. It’s an organisational choice.
Something that really fascinates me is the difference between diffing versus declaration of dynamic content. In React and Vue it is a runtime function to know what changed and how to apply it. In Ember and Svelte it is a compile time calculation based on markers in the template.
I guess it comes down to personal preference. I’m quite the fan of a declarative style template that gets converted/compiled to a machine under the hood instead of diffing at runtime.
I've rolled a DIY web framework using websockets and a brutish technique where I simply set document.body.innerHTML to whatever the server pushes. Still haven't found a situation where this falls apart, but I am sure HN can invent a hypothetical that would make me ashamed of myself.
But React team went big on advertising it as some kind of virtue, and a lot of gullible engineers bought that idea.
People may hold opinion that Solid/Svelte are excellent. However that's going towards another direction. Virtual DOM decouples how you declare UI and how it's rendered/updated by framework. Solid/Svelte couple them.
I am confused. Why are the concepts of reactivity and of virtual DOM put together like this? Was Virtual DOM ever solving the reactivity problem?
Then template expressions are just JavaScript and the library doesn't have to implement it's own limited and slower subset, like this seems to do.