7 ms·
Yes and no. Having implemented virtual DOM natively in Sciter (1), here are my findings: In conventional browsers the fastest DOM population method is element
by c-smile 4y ago
Yes and no.
Having implemented virtual DOM natively in Sciter (1), here are my findings:
In conventional browsers the fastest DOM population method is element.innerHTML = ...
The reason is that element.innerHTML works transactionally:
Lock updates -> parse and populate DOM -> verify DOM integrity -> unlock updates and update rendering tree.
While any "manual" DOM population using Web DOM API methods like appendChild() must do such transaction for any such call, so steps above shall be repeated for each appendChild() - each such call shall left the DOM in correct state.
And virtual DOM reconciliation implementations in browsers can use only public APIs like appendChild().
So, indeed, vDOM is not that performant as it could be.
But that also applies to Svelte style of updates: it also uses public APIs for updating DOM.
Solution could be in native implementation of Element.patch(vDOM) method (as I did in Sciter) that can work on par with Element.innerHTML - transactionally but without "parse HTML" phase. Yes, there is still an overhead of diff operation but with proper use of key attributes it is O(N) operation in most cases.
[1] https://sciter.com https://sciter.com
- SigmundA 4y agoJust have a suspendLayout resumeLayout / beginUpdate endUpdate method like Winforms surprised doesn't exist after all these years
- c-smile 4y agoNot so easy unfortunately. 1. BeginUpdate stops a control from repainting itself and that is what browser is doing already - no painting happens at the moment of JS execution. So primitive "postpone painting" does not really help. 2. element.update(callback) or DOM.mutate(root,callback) shall be a single method - no one wants EndUpdate() calls to be skipped because of errors thrown and the like.
- ncann 4y ago> no one wants EndUpdate() calls to be skipped because of errors thrown and the like. but surely with enough effort and care this should be a non-issue? And maybe auto-rollback on error?
- wruza 4y agoA script will eventually return to the event loop, where endUpdate() may be called automatically. You don’t even need beginUpdate(), because it may be hidden behind update methods. Every time I read about DOM I frustrate about how many frontend issues are there due to just bad platform-level patterns. We’re long past the need of reflecting updates auto-instantly in a single call to the engine. And that wasn’t even necessary before.
- sroussey 4y agolayout is suspended automatically. Unless you query the dom for something, in which case you can get lots of thrashing. For example, you don’t want to add some dom elements, then get their height/width as that will force the layout. And don’t do that in a loop! Last I looked, addjng/removing dom elements only schedules the layout and repaint. Things have gotten more multithreaded since I looked at browser code for this, but I doubt they would make a performance regression here.
- quelltext 4y ago> And virtual DOM reconciliation implementations in browsers can use only public APIs like appendChild(). Why can't they also use innerHTML? Meaning, they could define a cost function where they deduce that it's cheaper to use innerHTML on a potentially larger than necessary scope if the alternative is >some_threshold for modification API calls.
- scotty79 4y agoProbably because we are doing diff per node so we'd have to aggregate diffs somehow, rip out children that don't change to reattach them into the change part recreated using innerHTML.
- mtsr 4y agoThey could, but they would have to either render the whole scope again or somehow apply the change to a copy of the scopes HTML and then set that. Neither seems ideal, but that may be a reasonable, if complex, optimization.
- runarberg 4y agoIs this still the case with the newer transactional methods like Element.append(), Element.before(), and DocumentFragment? When I manipulate the DOM I try to create the entire structure in a fragment and the use .append(...) only once.
- c-smile 4y agoThis: element.append([array of Elements]); is in magnitude of times faster than for(const el of [array of Elements]) element.appendChild(el); so yes, it helps to improve situation. But think about updates like this: element.patch(<p multiple={n > 1}>There {n > 1? "are": "is"} {n} bottle{n > 1? "s": ""} of beer on the wall</p>); Here you need to update (or not) as the attribute as text nodes. You need some transactional mutation mechanism.
- mhink 4y agoOddly enough, this doesn't seem to be accurate: check out https://jsbench.me/02l63eic9j/1 https://jsbench.me/02l63eic9j/1. I also would have sworn up and down that using a DocumentFragment would be loads faster than both, but it doesn't seem to be the case. I wonder why that is.
- megaman821 4y agohttps://twitter.com/jaffathecake/status/1552242561313546241?lang=en https://twitter.com/jaffathecake/status/1552242561313546241?...
- c-smile 4y ago> this doesn't seem to be accurate It is pretty accurate here, case #3 is significantly (almost two times) slower than case #1.
- mrtranscendence 4y agoNot on my browser (Safari 16.1). Here case #3 is the fastest, over 7% faster than case #1.
- scotty79 4y agoWe could create component system that doesn't diff per DOM node but per component. It would render components to strings and place them with innerHTML into slots (dom elements) exposed by their parents. On first render it could just splice strings.
- deleted 4y ago[deleted]
- ttfkam 4y agoinnerHTML doesn't preserve event handlers. So you're either reassigning event handlers over and over or relying on delegate handlers everywhere. And while your statement makes intuitive sense regarding performance, actual measurements show clearly that idiomatic Svelte (and other modern frameworks) routinely beat VDOM-based efforts handily in their idiomatic cases and often even when folks jump through the performance optimization hoops needed for VDOM. VDOM is pure overhead. Better than manually aligning writes before reads manually a la 2010, but noticeably worse than the current crop of compiled offerings.
- c-smile 4y agoIt depends how really you use virtual DOM. React's "reconciliate whole world" approach can be excessive, yes. But, for example in Sciter, vDOM works in [web] component cases that are similar to Svelte: class Beers extends Element { bottles; render() { return <span .bottles>{this.bottles}</span> } set value(v) { this.componentUpdate({bottles:v}) } } When you will do document.$(".bottles").value = 12; it will update only what is needed. Pretty much Svelte style but with the convenience of vDOM.
- c-smile 4y agoTo make it even closer to Svelte, Sciter has native signal() implementation, so let bottles = signal(0); function Beers() { return <span .bottles multiple={bottles.value > 1}>{bottles.value} bottles of beer</span> } document.body.append(<Beers/>); That can be updated by simply changing signal: bottles.value = 42; // Party time! Note: this does not require any preprocessors or precompilations.
- ttfkam 4y agoLet's compare lines of code, because more lines invariably leads to more bugs. Contents of Beers.svelte: <script> export let bottles = 99; </script> {#if bottles > 0} <span class="bottles" on:click={() => --bottles}> {bottles} bottles of beer on the wall </span> {:else} <span class="bottles"> No more bottles of beer on the wall </span> {/if} Then to use it: <script> import Beers from './Beers.svelte'; </script> <Beers /> No knowledge of Reactor's existence needed let alone the library's "signal" function. No functions needed at all. No bespoke syntax for the "bottles" CSS class. No vDOM API call. No extra "values" accessing property. It's >90% plain old HTML, CSS, and JS with literally the bare minimum of syntax to handle data binding. Yes, it requires a compiler, but I would honestly astounded if you even noticed the compiler build time in dev mode. AND the deployed code is smaller. AND it's simpler for the dev to understand and maintain. AND it's likely faster at runtime. The argument that Svelte adds mental overhead is manifest nonsense. If you like the vDOM, have at it. Follow your bliss. Some folks like hitting and kicking trees. Some folks prefer their coffee too hot to drink. I for one want a web framework that makes web development as simple, straightforward, and powerful as possible. HTML, CSS, and the smallest amount of JS and HTML annotation imaginable.
- llanowarelves 4y agoThank you for your work on Sciter. Wanting to use it on a new project soon. Love it over some complicated and bloated Electron solution.
- aatd86 4y agoIf you use dom fragments, in recent browsers, it's up to par.