React virtual DOM: Is it really for performance?

Over the past decade, front-end technology has changed rapidly. From the earliest purely static pages, to the dominance of jQuery, to the popularity of the MVVM framework in recent years — the development mode of upgrading this thing for the front end, it seems to become a kind of normal. In fact, behind the continuous evolution of the research and development mode, it precisely contains the front-end people’s continuous thinking and improvement of the core action of “DOM operation”. And the virtual DOM is a pearl that the pioneers bred in this process.

In the MVVM framework subfield, there is a still classic interview question: “Why do we need the virtual DOM?” .

A common response to this question is: “DOM manipulation is slow, JS is fast, and direct manipulation of DOM can result in frequent backflow and redraw, which is not a problem with JS. So the virtual DOM is faster than the native DOM.”

But is it really true? You can probably find the answer in the following article.

1. Two “big problems” with the virtual DOM

Before we get started, let’s review what the virtual DOM is.

1) What is virtual DOM

Virtual DOM (Virtual DOM) is essentially a mapping cache between JS and DOM, which is represented as a JS object that can describe the DOM structure and its attribute information. In this article we (how does JSX code “turn” into DOM?) The conversion relationship between JSX and DOM is discussed, in which the form of virtual DOM in React is mentioned, as shown in the following figure:

For this example, there are two things to keep in mind:

  • The virtual DOM is a JS object;

  • The virtual DOM is a description of the real DOM.

Now that the question of what the virtual DOM “is” is settled, let’s take a look at how the React virtual DOM works.

2) Workflow of the virtual DOM in React

The virtual DOM appears as a “key person” during the mount and update phases of the React component, and its workflow is as follows:

  • In the mount phase, React will combine JSX description to build a virtual DOM tree, and then use reactdom.render to map the virtual DOM to the real DOM (triggering the rendering line).

  • In the update stage, the changes of the page will be applied to the virtual DOM before they are applied to the real DOM. The virtual DOM will compare the specific real DOM that needs to be changed with the help of the algorithm in the JS layer, and then apply these changes to the real DOM.

Here we have solved the “What” and “How” problems of the virtual DOM in a relatively short time. Now comes the core of this chapter, the “Why” behind the virtual DOM.

2. “Why” behind the virtual DOM

“Why the virtual DOM?” “What’s the advantage of the virtual DOM?” “Does the virtual DOM come with better performance?” To answer the endless whys, don’t look at the question point by point. Remember that the virtual DOM is relatively new to previous DOM manipulation solutions. Therefore, in order to understand the rationality of the existence and development of such a new thing, we must discuss it in a long enough and reasonable context, and explore the “WHY” of virtual DOM by looking at its background environment and jumping out of the current DOM.

Next, I expand on the context in which the virtual DOM resides. Once you understand the virtual DOM’s place in history, you’ll quickly understand what problems it solves for front-end development, and all the answers will be on the page.

1) DOM manipulation solutions in the long history

Let’s start with a review of some of the challenges we encountered without the virtual DOM.

(1) the period of “human DOM” dominated by native JS

In the embryonic stage of the front-end, the “display” attribute of the front-end page is much stronger than its “interaction” attribute, which leads to the positioning of JS can only be “auxiliary” : For a long time, front-end engineers will spend a lot of time implementing static DOM and then, when it’s all over, add a little JS and implement “special effects” like drag-and-drop, hide, slide and so on.

At this stage, front-end developers are happy enough to have native JS — simple business requirements mean we don’t have to do too much or too complicated DOM manipulation.

(2) The pilot stage of productivity liberation: jQuery period

As the tide of The Times rolled forward, people quickly moved beyond simple and boring interaction effects and began to pursue a richer user experience, which was accompanied by a surge in front-end development workload as a result of a large number of DOM manipulation requirements. In the process, it became clear to early front-end users that the DOM API functionality provided by native JS had reached its limit.

JQuery was created to enable efficient development. JQuery first addresses the issue of “API limitations” — it encapsulates the DOM API in a relatively simple and elegant form, while simultaneously addressing cross-browser compatibility, and providing the ability to chain API calls, plug-in extensions, and more to further free up productivity. The end result is the much-loved “write less, do more”.

JQuery makes DOM manipulation simple, fast, and always stable in form and availability. Although now look not perfect, but in that year can all corners of the country, really worthy.

(3). The beginning of people’s Wisdom: early template engine scheme

JQuery optimizes the way you manipulate the DOM, but it doesn’t fundamentally solve the front-end stress caused by excessive DOM manipulation.

It is like a “hand-held vacuum cleaner”, although it can help us to clean the dust in one place more easily and quickly, but to clean the dust in multiple places, you still need to carry it around. So although need not bend over to wipe the floor again, but still can not avoid the result that runs broken leg.

Since a hand-held vacuum cleaner won’t fit the ever-expanding DOM requirements, what we want is a sweeper robot that can run around on its own and do a decent job, just on command.

And template engine program, it is “sweeping the floor robot” rudiment.

[Note] : Because the template engine is more of a point-to-point solution to DOM problems, it is neither capable nor positioned to replace jQuery, and the two coexist in harmony. So there is no “template engine era”, only “template engine solution”.

How do you understand the concept of templates? Let’s look at an example: For example, I have a set of employee data, which is as follows:

Const staff = [{name: 'zhang' career: 'front end'}, {name: 'bill' career: 'editors'}, {name:' liu five 'career:' operating '}]Copy the code

Now that you want to display this data in a table at the front end, you can follow the template syntax and stuff the staff data into the template. Here is a typical example of template syntax usage:

<table>
  {% staff.forEach(function(person){ %}
  <tr>
    <td>{% student.name %}</td>
    <td>{% student.age %}</td>
  </tr>
  {% }); %}
</table>
Copy the code

As you can see, template syntax is basically a rule that combines JS and HTML, and what the template engine does is very easy to understand:

Read the staff data source, insert it into the preset HTML template, merge the two together, and output a target string. The content of this string, in fact, is a standard, renderable HTML code that corresponds to a DOM element. Finally, mount the DOM element to the page, and the entire template rendering process is complete.

This process can be expressed in pseudocode as follows:

/ var/data fusion and templates out HTML code targetDOM = template ({data: students}) / / added to the page to the document body. The appendChild (targetDOM)Copy the code

Of course, the actual process is a little more complicated than described. The following supplementary template engine implementation ideas, for reference. A template engine typically needs to do several things:

  • Read HTML template and parse it, separate out the JS information;

  • Splicing the parsed content into a string, dynamically generating JS code;

  • Run dynamically generated JS code, spit out “target HTML”;

  • Assigning the “target HTML” to the innerHTML triggers the rendering pipeline to complete the rendering of the actual DOM.

Using a template engine solution to render data is very convenient: every time the data changes, you don’t have to worry about where the data changed, and you don’t have to manually do point-to-point DOM modifications. Just focus on the data and the data changes themselves, and the DOM level change template engine will do that for us.

In this way, the template engine looks a lot like a sweeper robot that just needs to take orders to do a good job! Unfortunately, the template engine was created to separate the user interface from the business data, but the actual application scenario is basically limited to the point of “efficient string concatenation”, so you can’t expect it to do too complicated things. Especially unacceptable is its performance: it is not “smart” enough to update the DOM by deregistration of the entire DOM, and there is no update buffer. In the case of frequent DOM operations, the template engine may directly cause the page to freeze.

[Note] : Note the qualifier “early days” in the subtitle — the concept of “template engines” in question refers to a relatively primitive class of template engines that dominated an era before the idea of the virtual DOM was popularized. But now more and more template engines are introducing the virtual DOM, and template engines will eventually be modernized.

While it’s a bit of a leap to expect a template engine to be productive, the template engine is certainly intellectually advanced: it allows programmers to only care about data without having to worry about DOM details. It’s pretty much the same as the React “data-driven view” idea.

(4) from the above, we find that jQuery and the early emergence of template engines have solved some problems, but other problems still exist, so what should we do?

A group of people, perhaps inspired by template engine design, decided to take the basic path of “data-driven view” and began to explore it: The core problem with the data-driven view solution of the template engine is that changes to the real DOM are too extensive and too frequent, which can lead to poor performance. Then I thought: since manipulating the real DOM is such a performance drain, why not manipulating the fake DOM?

Further down the line, the much-loved virtual DOM was born.

[Note] : For the sake of rigor, it should be noted here that there is no way to verify whether the virtual DOM creation process in real history has learned from the template engine. However, according to the process of front-end development, there is indeed a progressive relationship between the template engine and the virtual DOM. In many scenarios, the interviewer may also ask about the relationship between the two. Therefore, such a statement here is to help you better grasp the key to the problem.

2) How does the virtual DOM solve the problem

From the above we can see that to separate the user interface from the data, the template engine does this:

With the help of the virtual DOM, things look like this:

[Note] The word “template” is in quotes because the virtual DOM is not always implemented using templates. React, for example, uses JSX. As mentioned above, JSX is not a template in nature, but a JS syntax candy that has a similar experience to templates.

The difference between a template engine and the virtual DOM is that there is an extra layer of virtual DOM as a buffer layer. The buffer layer is the good: when the DOM manipulation (rendering update) more frequently, it will first compare the two virtual DOM tree, pinpoint specific parts need to be updated, generate a “patch set”, only the “patch” to play on the need to update the part of the real DOM, achieve accurate “delta update”. The corresponding virtual DOM workflow for this process is shown below:

【 note 】

  • Both diff and Patch are function names that are derived from a separate virtual DOM library. The reason why we specify the function name corresponding to the specific process is that many interviewers are used to referring to the process by the function name in the interview, but many of them are not clear about the corresponding relationship (especially patch), which will greatly affect the answers. So let’s get rid of this pit ahead of time.

  • It should also be noted that the virtual DOM, like Redux, is not tied to any specific framework. You can actually learn the virtual DOM without React at all; But to learn React, you have to understand the virtual DOM. If you’re interested in the implementation of the virtual DOM, you can check out the source code details in the GitHub repository.

Getting back to the topic, this “differential-update” approach ensures that the virtual DOM provides both an efficient development experience (developers only need to care about the data) and stable performance (only the parts of the DOM that have changed are updated), which is fantastic!

3) React uses the virtual DOM for better performance?

At this point, you’ve probably figured out that throughout the evolution of DOM manipulation, the main contradiction has not been performance, but the ability of developers to have a good development experience/development efficiency. Virtual DOM is a high-order product created by front-end developers in pursuit of better r&d experience and efficiency.

The Virtual DOM doesn’t necessarily lead to better performance, and React has never officially advertised the virtual DOM as a performance selling point. The advantage of the virtual DOM is that it can provide a more convenient and efficient mode of development (i.e., functional UI programming) while maintaining relatively stable performance.

Performance is a high complexity problem in the front-end domain. When we quantify performance, we often do not pursue a single data, but need to combine the specific reference, rendering stage, data throughput and other factors to make a case discussion.

As an example of the template rendering above, compare the performance overhead with the virtual DOM. The rendering workflow pairs for both are shown below:

As can be seen from the figure, step 1 of template rendering and step 1 and step 2 of virtual DOM rendering both belong to JS behaviors. The two are comparable. Put them together: The process of dynamically generating HTML strings is essentially the stitching of strings, which has limited consumption on performance. However, the virtual DOM construction and diff process logic are relatively complex, which inevitably involves time-consuming operations such as recursion and traversal. So in terms of JS behavior, template rendering wins.

Step 3 of template rendering and step 3 of virtual DOM both belong to DOM-category behaviors and are comparable, so the comparison continues: template rendering is full update, while virtual DOM is differential update.

At first glance it may seem that differential updates are definitely more efficient than full updates, but consider the case where the data content changes so much (or the whole thing changes) that the differential updates compute very close (or exactly the same) to the full updates.

In this case, the DOM update effort is basically the same, while the virtual DOM is accompanied by more expensive JS calculations. One of the things that can happen is that template rendering and the virtual DOM are very much the same in terms of overall performance: If the DOM updates calculated by the two are exactly the same, the virtual DOM is likely to lose to template rendering. But if the two are even slightly apart in the amount of final DOM manipulation, the virtual DOM will have the edge over template rendering. Because the disadvantage of virtual DOM mainly lies in the time consuming of JS computation, and the energy consumption of DOM operation and JS calculation are not of the same magnitude at all, the performance consumption of a very small amount of DOM operation is enough to support a large number of JS computation.

Of course, the situation discussed above is relatively extreme. In real development, the more common scenario is to change only a small amount of data each time setState is used, such as a few properties in an object or a few elements in an array. In such a scenario, the DOM manipulation gap between template rendering and the virtual DOM is completely opened, and the virtual DOM will have an absolute advantage in performance.

[Note] The conclusion here is that “in the scenario of XXX, virtual DOM has performance advantages over XXX”, which is strictly qualified. “How about virtual DOM versus jQuery?” “What about the virtual DOM versus the native DOM?” . Keep in mind that performance is not a generalised issue, and this is not a good time to be obsessed with “performance”. Because jQuery and native DOM are completely different from virtual DOM in terms of thinking mode, forced comparison is not meaningful.

The point of the previous series of comparisons and examples is to make it clear that the value of the virtual DOM lies elsewhere, not in performance. So trying to take advantage of the virtual DOM from a performance perspective is the opposite. However, in the interview situation, nine out of ten people did the wrong thing, and none of the last nine people could explain themselves, which is really a pity.

4) So what is the value of the virtual DOM?

The value of the virtual DOM is just another big, fallible proposition. When we talk about the value of something, it is just like praising a beautiful woman. Different people naturally have different perspectives on beauty. This is not intended to provide a seamless answer (which presumably doesn’t exist), but rather to share some of the industry’s consensus on the virtual DOM from the perspective of what key problems it solves.

(1) Virtual DOM solves the following two key problems.

  • Issues of R&D experience/R&D efficiency:

This point has been made repeatedly before, and with every revolution in the DOM mode of manipulation, there is a further pursuit of efficiency and experience on the front end. The emergence of the virtual DOM provides a highly usable vehicle for the idea of “data-driven view”, enabling front-end development to achieve efficient declarative programming based on functional UI programming.

  • Cross-platform issues:

The virtual DOM is a layer of abstraction from the actual rendered content. Without this layer of abstraction, the view layer is tightly coupled to the rendering platform, and you may have to write two or more completely different sets of code on the Web and Native side to describe the same view content. But now there is a layer of descriptive virtual DOM in the middle, which describes things that can be real DOM, iOS interface, Android interface, small programs…… The same set of virtual DOM can be connected with the rendering logic of different platforms, so as to realize “once coding, multi-terminal operation”, as shown in the figure below. In the final analysis, cross-platform is also a means of r&d and efficiency improvement, which is highly consistent with 1 in ideology.

  • In addition to differential updates, “batch updates” are an important performance effort of the virtual DOM:

Batch updates are handled by the Batch function in the generic virtual DOM library. In the case of very fast differential updates (such as multiple operations on the SAME DOM in a very short period of time), the user really only sees the effect of the last update. In this scenario, the first few updates don’t make much sense, but they all trigger the re-rendering process, causing a lot of unnecessary and energy-intensive operations. In this case, Batch plays a role. The function of Batch is to buffer the patch set generated each time. It will temporarily store the collected multiple patch sets in the queue, and then give the final result to the rendering function, and finally realize the centralized DOM batch update.

3, summarize

This chapter begins by reviewing the history of DOM manipulation solutions, identifying the main issues that virtual DOM is positioned to solve, and then analyzing the common workflow of the virtual DOM. In this workflow, there is one process that needs special attention, and that is “diff.”

Diff refers to the process of comparing the differences between two virtual DOM trees. Different frameworks have different approaches to diff. As for the React framework, the unique and up-to-date DIff algorithm is the most fascinating part of it and the core of the framework.

Next, we’ll start with act15’s diff process and take a look at the classic “stack and harmonic” algorithm.

Learning the source (the article reprinted from) : kaiwu.lagou.com/course/cour…