Under the premise that Virtual DOM exists in the two most popular front-end frameworks, it is increasingly common to hear “What are the advantages of using Virtual DOM?” “But never paid much attention to it. Until today, when I was writing a document, I suddenly thought of “Why Virtual DOM? Also write in, wait for me to write a good answer smoothly, a little thinking – loopholes! I do not know which side of knowledge I have accepted, which makes me always have the illusion that I can easily answer this question. In fact, I am lack of thinking about this question.

You probably don’t know what I’m talking about, but bear with me for a few thoughts on the subject from the Internet:

  1. The virtual DOM also operates on the DOM. Why is it fast? — Segmentfault

    1. The virtual DOM does not do typesetting or redrawing
    2. The virtual DOM is modified frequently, and then the real DOM is compared and modified once and for all (note!). , and finally typesetting and redrawing in the real DOM to reduce excessive loss of DOM node typesetting and redrawing
    3. The frequent typesetting and redrawing of the real DOM is quite inefficient
    4. The virtual DOM effectively reduces the redrawing and typesetting of large areas (real DOM nodes), because in the end, it is different from the real DOM and can only render parts (same as 2).
  2. What are the advantages of Virtual Dom? — Github

    1. It has the advantage of cross-platform. Because Virtual DOM is based on JavaScript objects and does not depend on the real platform environment, it has the ability of cross-platform, such as browser platform, Weex, Node, etc.
    2. It is slow to operate DOM and efficient to run JS. We can put DOM comparison operations in the JS layer to improve efficiency. Because the execution speed of DOM operations is not nearly as fast as that of Javascript, a large number of DOM operations are moved to Javascript and patching algorithm is used to calculate the nodes that really need to be updated to minimize DOM operations and significantly improve performance.
    3. The advantage of Virtual DOM is not in a single operation, but in a large number of frequent data updates, the view can be reasonably and efficiently updated.
  3. Virtual Dom’s advantage — nuggets

    1. No immediate typesetting and redrawing;
    2. VDOM is frequently modified. The parts that need to be modified in the real DOM are compared and modified at one time, and finally rearranged and redrawn in the real DOM to reduce the performance consumption of excessive DOM node rearrangement and redrawing.
    3. VDOM effectively reduces the redrawing and rearrangement of large-area real DOM, compares the difference with real DOM, and performs local rendering.

The above is an analysis of the three platforms that Google found, and it comes down to four points:

  1. Manipulating DOM is slow and Virtual DOM objects are fast
  2. Using the Virtual DOM avoids frequent DOM manipulation and can significantly reduce backflow and redraw times (if any)
  3. There are diff algorithms to reduce unnecessary DOM operations
  4. Cross-platform advantage, JS engine can run anywhere (Weex/SSR)

Are they understood correctly?

The test data in this article are based on Chrome 86.0.4240.198

Virtual DOM fast?

Does anyone think Virtual DOM is fast? The Virtual DOM is a Javascript object that describes the DOM (note that there is not necessarily a one-to-one correspondence), and Javascript is naturally fast to manipulate Javascript objects.

But Virtual DOM still needs to call the DOM API to generate the real DOM, and you can actually call them directly, so there’s an interesting conclusion. No positive number can be less than zero — Virtual DOM is fast, but that’s not its advantage. You could have chosen not to use the Virtual DOM. In addition to speed not being an advantage, one of the biggest problems with Virtual DOM is the extra memory footprint. Taking Virtual DOM objects of Vue as an example, 100W empty Virtual DOM(Vue) will take up 110M of memory.

Memory usage screenshot:

Test code:

let creatVNode = function(type) {
  return {
    __v_isVNode: true.SKIP: true,
    type,
    props: null.key: null.ref: null.scopeId: 0.children: null.component: null.suspense: null.ssContent: null.ssFallback: null.dirs: null.transition: null.el: null.anchor: null.target: null.targetAnchor: null.staticCount: 0.shapeFlag: 0.patchFlag: 0.dynamicProps: null.dynamicChildren: null.appContext: null}}let counts = 1000000
let list = []
let start = performance.now()
/ / create a VNode (Vue)
// 10000: 1120k
for (let i = 0; i < counts; i++) {
  list.push(creatVNode('div'))}/ / create the DOM
// 10000: 320k
// for (let i = 0; i < counts; i++) {
// list.push(document.createElement('div'))
// }

console.log(performance.now() - start)
Copy the code

Surprisingly, 100W empty DOM objects take up only 45M of memory. It’s not clear how Chrome optimizes with significantly more DOM attributes, or if Dev Tools has a problem.

As you can see, Virtual DOM not only performs fast but also increases memory consumption significantly, so it is problematic to say that it is fast because it is faster without Virtual DOM.

Virtual DOM reduces backflow and redraw?

Does Virtual DOM reduce relayout and repaint? There are usually two reasons to support this view:

  1. DOM operations change the Virtual DOM first, so invalid changes (such as changing text A to B and then to A) do not invoke the DOM API and do not result in invalid backflow and redrawing of the browsing.
  2. DOM operations alter the Virtual DOM and are eventually invoked by the Virtual DOMpatchMethod to batch manipulate the DOM without causing meaningless backflow and redraw in the process.

Invalid reflux and redraw

The first point seems reasonable, but it’s hard to explain: when does the browser’S UI thread perform backflow and redraw? Remember that modern browsers are designed to avoid high complexity. Javascript threads and UI threads are mutually exclusive, meaning that the browser must suspend the Javascript thread if relayout/repaint is triggered during Javascript execution. It’s a design that even I think is stupid, and it certainly won’t work in any major browser.

In fact, no matter how many times you call the DOM API in a single event loop, the browser will only trigger one backflow and redraw (if necessary), and neither will happen if multiple calls do not modify the DOM state.

Timeline screenshot (no backflow and redraw occurred) :

Test code:

<body>
  <div class="app"></div>
  <script>
    let counts = 1000
    let $app = document.querySelector('.app')
    setTimeout(() = > {
      for (let i = 0; i < counts; i++) {
        $app.innerHTML = 'aaaa'
        $app.style = 'margin-top: 100px'
        $app.innerHTML = ' '
        $app.style = ' '}},1000)
  </script>
</body>
Copy the code

2021/02/26 Additional Information

While not redrawing it, using the Virtual DOM in the example above does reduce the parseHTML time, as innerHTML is inserted 1000 times in the example, so using the Virtual DOM may actually have a performance advantage in certain scenarios.

Why is the style only recalculated once, when parseHtml is executed N times?

In my opinion, the reason is that there are so many and frequent ways to manipulate the DOM (e.g. setting innerHTML, retrieving inserted text nodes via childNodes, querySelector, etc.) that the browser is not currently optimized here. But I think there is room for optimization similar to CSS, where the user needs to get the insert node before parseHTML.

Note: “CSS-like optimization” means that a layout is performed only when the user needs to obtain the current layout information in a loop. Otherwise, a layout is performed only once. This document can view which operations will cause a forced layout.

Meaningless refluxing and redrawing

The second argument is interesting, and although you can see from the above analysis that it is wrong, batch operations do not reduce backflow and redraw because they only trigger once. But I’m going to go ahead and prove it, because it’s an inherent mindset in so many of our front ends today. I asked my friends in the Gods Commune before I started writing this article, and almost all of them fell into the cognitive trap of thinking that batch operations reduce backflow and redraw.

Batch operations do not reduce backflow and redraw, for the same reason as above. Javascript is single-threaded and mutually exclusive with the UI thread, so put the test data directly:

Javascript execution time (data averaged 3 times) :

Number/mode 10000 50000 100000
batch 7.0 ms 28.51 ms 52.74 ms
A single 9.80 ms 44.83 ms 79.46 ms

Layout time (average data for 3 times) :

Number/mode 10000 50000 100000
batch 29.81 ms 133.01 ms 271.07 ms
A single 28.08 ms 133.39 ms 265.32 ms

Test code:

<body>
  <div class="app"></div>
  <script>
    let counts = 1000
    let $app = document.querySelector('.app')
    let start = performance.now()
    // Operate separately
    // for (let i = 0; i < counts; i++) {
    // let node = document.createTextNode(`${i}, `)
    // $app.append(node)
    // }

    // Batch operation
    let $tempContainer = document.createElement('div')
    for (let i = 0; i < counts; i++) {
      let node = document.createTextNode('node,')
      $tempContainer.append(node)
    }
    $app.append($tempContainer)

    console.log(performance.now() - start)
  </script>
</body>
Copy the code

As you can see, the time of batch processing and single processing is almost the same during Layout. Although there is still a performance advantage in script execution (about 30%), as long as you use DOM manipulation well, The performance impact of batching or not batching is small (27ms extra loss for 10W calls).

Off-topic: This raises the question, why is there still a performance gap during script execution? The answer will come later (after I finish reading this logic)

Does Virtual DOM have diff algorithm?

Strictly speaking, diFF algorithm and Virtual DOM are two independent things, and there is no sufficient and necessary correlation between them. For example, Svelte has its own DIFF algorithm without Virtual DOM.

However, since the front-end framework has Virtual DOM, there is always a DIFF algorithm, and the use of Virtual DOM also has two benefits to the DIFF algorithm:

  1. Thanks to the abstraction capability of Virtual DOM, diff algorithm is easier to implement and understand
  2. Thanks to the fact that the Virtual DOM Tree is always in memory, the diff algorithm can be more powerful (such as component movement, which is impossible without the full Tree structure).

Diff algorithm can reduce DOM API calls, which obviously has design and performance advantages. Thanks to the existence of Virtual DOM, DIFF algorithm can be more convenient and more powerful, so I agree that this is the advantage of Virtual DOM. However, statements such as “Virtual DOM has diff algorithm” cannot be used.

Does Virtual DOM have cross-platform advantages?

The svelte mentioned above does not have the Virtual DOM, but it can also implement server-side rendering, which shows that cross-platform does not depend on the Virtual DOM.

As long as the Javascript framework implements the platform API distribution mechanism, it can perform different rendering methods on different platforms, which is cross-platform capability. At the root of this capability is the ability for Javascript code to run inexpensively on all platforms (thanks to the ubiquity of browsers and NodeJS on all platforms), which is often cited as one of the advantages of Javascript being cross-platform. So it’s not true that cross-platform is an advantage of the Virtual DOM, but we might want to wonder why they think so.

In my opinion, there may be two reasons:

  1. The advantage of the Virtual DOM is that you can manipulate the DOM without touching the real DOM, and the performance is better

    Changes in the Virutal DOM will eventually call the platform API to manipulate the real DOM, so the absence of the Virtual DOM only means the loss of an intermediate abstraction layer, which does not affect the cross-platform capability. However, it is important to understand that this abstraction layer provides considerable convenience (or assistance) for cross-platform capabilities as far as the analysis is concerned.

  2. Virtual DOM is very important in Vue, and Vue itself is a framework built around Virtual DOM. Without Virtual DOM, its design ideas will certainly be different from today’s

conclusion

In this paper, some of the developers’ perceptions of the advantages of Virtual DOM are selected from the Internet, and some misconceptions are also learned from real life. The four “advantages” of Virtual DOM are summarized, and these four “advantages” are separately analyzed or demonstrated.

Finally, we identified several misconceptions about Virtual DOM advantages:

  1. Operating DOM is too slow, operating Virtual DOM objects is fast ❌

    Virtual DOM is fast, but that’s not an advantage because you could have chosen not to use it

  2. Using Virtual DOM can avoid frequent DOM manipulation and can effectively reduce backflow and redraw times ❌

    No matter how many times you call the DOM API in an event loop, the browser will only trigger one backflow and redraw (if necessary), and neither will happen if multiple calls do not modify the DOM state. Batch operations also do not reduce reflux and redraw.

  3. Virtual DOM has cross-platform advantages ❌

    Cross-platform is the advantage of Javascript. Although Virtual DOM is a very important part of various implementations, it does not affect cross-platform results in essence.

We also mentioned that the real advantages of Virtual DOM are its abstraction capability and memory resident nature, which makes it easier for the framework to implement more powerful diff algorithms, but the disadvantage is that it increases the complexity of the framework and takes up more memory.


2021/02/26 supplement

In the current environment, Virtual DOM can reduce the number of parseHTML executions in certain scenarios, that is, Virtual DOM has performance advantages in certain scenarios.

However, on balance, I still hold the same opinion that Virtual DOM has no performance advantage.