8 ms·
The fastest virtual DOM is no virtual DOM at all. Rather than creating and diffing a fine-grained tree of elements every render, it's very easy to use the synt
by spankalee 4y ago
The fastest virtual DOM is no virtual DOM at all.
Rather than creating and diffing a fine-grained tree of elements every render, it's very easy to use the syntactic structure of a template to see exactly what parts can and cannot change. To get stable and minimal DOM updates you just compare the template identity to the previously rendered template - if they match you update the dynamic expressions, if they don't you clear and render the new template.
This is what we did with lit-html and it's quite a bit faster (and smaller) than React and doesn't require a compiler because it uses standard JS tagged template literals. https://lit.dev/docs/libraries/standalone-templates/ https://lit.dev/docs/libraries/standalone-templates/
It's a very simple approach and very, very hard to beat in the fast/small/simple/buildless tradeoff space. I hope one day that the DOM can include standard updatable DOM with a technique like this on top of the template instantiation proposal from Apple. It's such a common need that it should be built in.
- bsimpson 4y agoLink to the Apple proposal?
- mfe7 4y agoI remember seeing this a few years ago: https://github.com/WICG/webcomponents/blob/gh-pages/proposals/DOM-Parts.md https://github.com/WICG/webcomponents/blob/gh-pages/proposal...
- esprehn 4y agoI believe this is the current iteration: https://github.com/WICG/webcomponents/blob/gh-pages/proposals/DOM-Parts.md https://github.com/WICG/webcomponents/blob/gh-pages/proposal... You can learn more of the history here: https://www.w3.org/2020/10/TPAC/parts_and_template_instantiation.html https://www.w3.org/2020/10/TPAC/parts_and_template_instantia... https://github.com/WICG/webcomponents/blob/gh-pages/proposals/Template-Instantiation.md https://github.com/WICG/webcomponents/blob/gh-pages/proposal...
- bsimpson 4y agoI love seeing a bunch of people I know in a random HN post. :wave:
- aidenyb 4y agoI love the work done by the Lit team (I assume you're a contributor?). It's really fantastically designed, as you mentioned with bundle size/rendering speed/etc. I'm sure that Lit's implementation is very efficient and ranks high in benchmarks. This isn't to say virtual DOM isn't fast Experimental libraries that use virtual DOM's like blockdom and ivi (see https://krausest.github.io/js-framework-benchmark/2022/table_chrome_102.0.5005.61.html https://krausest.github.io/js-framework-benchmark/2022/table...) are very, very fast. At the end of the day, the way libraries render UI is a set of tradeoffs. No one method is objectively better. While lit works great for a lot of web developers, so do virtual DOM based libraries Totally agree on native DOM diffing, I'll check out Apple's proposal :)
- kreetx 4y agoVirtual DOM is an unnecessary overhead, is what the parent is saying. There is probably a good reason popular frameworks insist on using it though.
- jraph 4y agoI would guess: - historically, manipulating the DOM directly was slow (in WebKit?) so working on a virtual one made sense - The idea writing a compiler like Svelte which does the heavy lifting at compile time was not there, or was dismissed for some reason (the React developers might have decided that having a reactive model like Svelte, with the need to tweak JS's semantic a bit - where assigning variables trigger stuff - was not great, or they didn't want this JS/HTML separation) And then you are stuck with your model for compatibility reasons. React cannot get rid of its virtual DOM without breaking everyone.
- wiredearp 4y agoThe VDOM library will still need to manipulate the real DOM sooner or later, so the proposed performance boost of this abstraction is not relevant for browsers. Since the VDOM runs fast in Node, you can execute your tests quickly in Jest. But since no real browser are running on Node, the value of this is perhaps questionable. The browser can get a performance boost via serverside rendering and again it comes in handy that the VDOM runs fast in Node. But perhaps this solves a problem that the VDOM has caused, because React loads slowly and renders the slowest [1]. You can run the VDOM in Android and on iOS via React Native and this is all well, but the VDOM is holding the web back because we have come to expect all this from technologies such as Web Components that might load fast and render fast by virtue of not relying on it. The virtual DOM is modelling the DOM, but the DOM comes with a model out of the box, it's called the Document Object Model and it is always in sync with the view without any constant performance tweaks. Asynchronous rendering can fix it until batched rendering solves it for good. But these are opposite rendering strategies! We are simply going in circles now. A lot of the myths around the virtual DOM can be explained by unwillingness to learn the native API and we are mostly dealing with the fallout now. It's the same with CSS. Sorry for the rant and the abuse of your comment. [1] https://twitter.com/championswimmer/status/1486501856834584581/photo/1 https://twitter.com/championswimmer/status/14865018568345845...
- localvoid 4y ago> It's a very simple approach and very, very hard to beat in the fast/small/simple/buildless tradeoff space. Author of the ivi library here. Completely agree with an idea that such approach could lead to a better performance, but there is a huge difference between an idea and actual implementation. Also, I just don't get it why a lot developers that work in this problem space still think like "virtual DOM" API and tagged template APIs are mutually exclusive, I've actually have an experimental implementation that supports both APIs and it is not so easy to beat efficient full diff vdom algo. Tagged template APIs are useful when we are working with mostly static HTML chunks, but when it comes to building a set of reusable components (not expensive web components), pretty much everything inside this components becomes dynamic and we are back to diffing everything.
- aidenyb 4y agoJust to add on here, the Preact author made a generalized utility for tagged template => vnode conversions: https://github.com/developit/htm https://github.com/developit/htm
- brundolf 4y agoAs a representative (?) of a popular library, it's not a great look to come in and put-down someone's Show HN project. Especially when you're also dismissing the entire category of libraries as inferior, while the reality is that both approaches have different costs and benefits
- colordrops 4y agoI don't know, it seems pretty common for people to be straight up on HN. I didn't get a sense of superiority or insult from the comment - just statements that the author believes to be true.
- bowsamic 4y agoI know that HN believes it’s immune to this, but being right isn’t an excuse to forgo social expectations
- afarrell 4y agoDifferent social environments have different social expectations. HN has a social expectation that focusing heavily on technical considerations of how something can be done better will lead to pleasant shop-talking like OP's response here: https://news.ycombinator.com/item?id=31576634#31578949 https://news.ycombinator.com/item?id=31576634#31578949
- arinlen 4y ago> I know that HN believes it’s immune to this, but being right isn’t an excuse to forgo social expectations Could you please offer some insight on why trying to pass off technically wrong claims in a technical forum should be immune to any informative comment clarifying or clearing up misconceptions ?
- bowsamic 4y ago> why trying to pass off technically wrong claims in a technical forum should be immune to any informative comment clarifying or clearing up misconceptions Not really, because I didn't make that claim, so you'll have to ask someone who makes that claim.
- WolfOliver 4y agoI think this is what solid.js is doing. Except the template literals, they still use jsx.
- wrnr 4y agoSolid is great, you can also use it with hyper dom expressions: https://github.com/ryansolid/dom-expressions https://github.com/ryansolid/dom-expressions
- lf-non 4y agoThe jsx is there primarily for better typescript support and react-like api. Internally it compiles down to template literals, so the same advantages apply. The typescript support for lit is lagging to say the least. It is surprising that there is still no good official support for type-checking of templates. There are a few community projects though but they are not as reliable and the DOM/Web Component API doesn't make it easy to make fully type-safe APIs. Solid being able to lean in the JSX support in the TS compiler and not tying itself to custom elements api is able to offer a much better DX here.
- localvoid 4y agoNo, solid.js is building reactive graph at runtime and in theory should be able to also detect static inputs at runtime (not sure how much effort he put into reactive graph optimization techniques). Personally, nowadays I prefer S.js/solid.js approach, but it has different tradeoffs, like it is essential to understand the difference between solid.js and React/Svelte/lit/etc :)
- aidenyb 4y agoI have yet to explore this area, I'll check out S.js!
- localvoid 4y agoIt is an old idea with reactive graph created at runtime and direct bindings (knockout.js, etc), but as always, implementation is way more important than some abstract idea, and ~6 years ago Adam showed that it is actually possible to implement this idea quite efficiently (S.js+Surplus). Then Ryan started working on Solid.js and it became one of the most popular implementation of this idea. There are a lot of things that I don't like in Solid.js implementation, like it seems that he still don't care about performance in general and only focuses on getting high score in js-framework-benchmark (optimizing library for two cases: DOM template cloning and one/many-to-one reactive bindings). But I believe that it is not something that is inherently wrong with an idea and there are a lot of room for improvements in implementations. I guess the main tradeoff with such idea is that it has a slightly higher learning curve than something like React with its top-down recompute/rerender approach (as long as we don't care about performance). But when we start to add reactive systems to react/svelte/etc to improve performance, at that point it becomes more complex than just using UI library specifically designed for reactive system. Right now I am trying some experiments with new algorithms and datastructures for reactive system, that I specifically designed for UI problem space, to actually beat vdom implementations in microbenchmarks that were heavily biased towards vdom-like libraries (reimplementing top-down dataflow+diffing in reactive system with derived computations, it is super useful when building something like https://lexical.dev/ https://lexical.dev/ ) EDIT: Also, in such libraries it becomes quite hard to implement features like reparenting or DOM subtree recycling. But it seems that nobody cares about reparenting in web UI libraries (Flutter supports reparenting). DOM subtree recycling is quite useful in use cases with occlusion culling (virtual lists), but it should be optional with different strategies to reclaim memory (not how it is done in Imba library).
- self_awareness 4y agoYour link shows an empty page with some "e is undefined" error in the console (Firefox).
- junon 4y agoCheck Surplus. This is exactly how it's designed, and as such it typically tops out the performance charts right next to vanilla JS.
- bob1029 4y agoWe rolled an in-house/intranet framework and went a slightly different path. Our framework uses pre-built components that are served to the client in terms of js commands over websocket (similar to blazor server-side mode of operation). Every component in the DOM has an ID and a hash. Client-side events that mutate state automatically modify this hash as well. The server keeps a dictionay of active components per client. At view state sync time, components are first created and removed on an identity basis. Then, all existing components have their hashes compared for equality. Depending on the type, various patch commands will be submitted to the client to realign the element to expected state. In most cases, each component involves multiple DOM elements. By scanning for the component root elements via attributes, we can avoid having to walk through the entire literal DOM each time. This may have profound consequences for table views and other enumerables. I have zero clue if this is the fastest/best, but its simple as hell and looks starts to look like butter as you polish each standardized component. Only real downside is the latency constraint, but this is something we can pretty easily overcome for our users with some well-placed frontend VMs. Definitely wouldn't do something like this for Netflix scale, unless someone told me the economics of 1 websocket per client works now... On average, how many DAUs per VM does Netflix run these days?
- aidenyb 4y agoThis sounds like a websocket version of Astro (https://astro.build https://astro.build)! Very cool stuff.
- fho 4y ago[Haskell fan boy here] I feel like there is at least one Haskell library out there that automates this "no virtual DOM" problem. In Haskell it is not uncommon to create data structures on the fly, only to deconstruct them immediately again. If done correctly the compiler can remove the immediate structure completely, leaving a (recursive) algorithm. An example of this would be sorting via binary trees. If done correctly, the intermediate tree is never (completely) present in ram.