You don’t know the browser page rendering mechanism

  Front end, java, javascript, node.js, Programmer

Preface

The kernel of the browser refers to the most core program that supports the browser to run. It is divided into two parts, one is the rendering engine, and the other is the JS engine. The rendering engines are not all the same in different browsers. At present, there are four kinds of common browser kernels on the market: Trident(IE), Gecko (Firefox), Blink(Chrome, Opera), Webkit(Safari). Perhaps the most familiar one is the Webkit kernel, which is the real overlord of the browser world. In this paper, we take Webkit as an example to analyze the rendering process of modern browsers in depth.

If you want to read more excellent articles, please stamp them fiercely.GitHub blogFifty excellent articles a year are waiting for you!

Page loading process

Before introducing the browser rendering process, we briefly introduce the loading process of the next page, which is helpful to better understand the subsequent rendering process.

The main points are as follows:

  • The browser obtains the IP address of the domain name according to the DNS server
  • Send HTTP requests to this IP machine
  • The server receives, processes, and returns HTTP requests
  • The browser gets the returned content

For example, input in a browserhttps://juejin.im/timeline, and then through DNS resolution,juejin.imThe corresponding IP is36.248.217.149(IP corresponding to different time and place may be different). The browser then sends an HTTP request to the IP.

The server receives the HTTP request and then returns the HTTP request after calculation (pushing different contents to different users). The returned contents are as follows:

In fact, it is a bunch of strings in HMTL format, because only browsers in HTML format can correctly parse them, which is the requirement of W3C standard. The following is the rendering process of the browser.

Browser rendering process

The browser rendering process is generally divided into the following three parts:

1) The browser will parse three things:

  • One is HTML/SVG/XHTML. HTML string describes the structure of a page. The browser will parse the HTML structure string into DOM tree structure.

  • Second, CSS, parsing CSS will produce CSS rule tree, which is similar to DOM structure.

  • Third, Javascript script. after the Javascript script file is loaded, DOM Tree and csruletree are operated through DOM API and CSSOM API.

2) after parsing is completed, the browser engine will construct Rendering Tree through DOM Tree and CSS Rule Tree.

  • Rendering Tree Rendering Tree is not the same as DOM Tree. Rendering Tree only includes the nodes to be displayed and the style information of these nodes.
  • CSS Rule Tree is mainly used to complete matching and attach CSS Rule to every Element (i.e. every Frame) on Rendering Tree.
  • Then, the position of each Frame is calculated, which is also called layout and reflow process.

3) finally, through calling API drawing of operating system Native GUI.

Next, we will elaborate on the important steps we have gone through.

Build DOM

The browser follows a set of steps to convert HTML files into DOM trees. Macroscopically, it can be divided into several steps:

构建DOM的具体步骤

  • The browser reads the original bytes of HTML from disk or network and converts them into strings according to the specified encoding of the file (for example, UTF-8).

The content transmitted in the network is actually 0 and 1 bytes of data. When the browser receives the byte data, it will convert the byte data into a string, which is the code we write.

  • Converts a string to Token, for example:<html><body>Wait.The Token will identify whether the current Token is “start tag” or “end tag” or “text” and other information..

At this time, you must have questions, how to maintain the relationship between nodes?

In fact, this is the role of Token to identify “start tag” and “end tag”. For example, the node between the start tag and the end tag of the “title”Token must be a child node belonging to” head “.

The above figure shows the relationship between nodes. For example, “Hello” token is located between the “title” start tag and the “title” end tag, indicating that “Hello” token is a child node of “title”Token. Similarly, “title”Token is a child node of” head”Token.

  • Generate Node Objects and Build DOM

In fact, in the process of DOM construction, instead of waiting for all tokens to be converted before generating node objects, nodes are generated by consuming tokens while generating tokens. In other words, after each Token is generated, it will consume the Token to create a node object immediately.Note: Token with end tag identification will not create node object.

Let’s take an example and suppose there is a paragraph of HTML text:

<html>
 <head>
 <title>Web page parsing</title>
 </head>
 <body>
 <div>
 <h1>Web page parsing</h1>
 <p>This is an example Web page.</p>
 </div>
 </body>
 </html>

The HTML above will parse like this:

Build CSSOM

DOM captures the contents of the page, but the browser still needs to know how the page is displayed, so it needs to build CSSOM.


In this process, the browser will determine what the style of each node is, and this process is actually very resource consuming. Because you can set the style to a node by yourself, or you can get it through inheritance. In this process, the browser recursively builds the CSSOM tree and then determines what style the specific elements are.

Note: CSS matching HTML elements is quite complicated and has performance problems. Therefore, the DOM tree should be small, CSS should use id and class as much as possible, and don’t over stack it.

Build rendering tree

When we generate DOM tree and CSSOM tree, we need to combine these two trees into rendering tree.

In this process, it is not simply to merge the two.The rendering tree only includes the nodes that need to be displayed and the style information of these nodesIf a node isdisplay: none, it will not be displayed in the rendering tree.

We may have a doubt:What if the browser encounters JS files during rendering?

During rendering, if you encounter<script>Stop rendering and execute JS code. Because the browser has GUI rendering threads and JS engine threads, in order to prevent unexpected results from rendering, the two threads are mutually exclusive. The loading, parsing and execution of JavaScript will block DOM construction. In other words, if the HTML parser encounters JavaScript during DOM construction, it will suspend DOM construction and hand over control to the JavaScript engine. When the JavaScript engine is finished, the browser will resume DOM construction from the place where it was interrupted.

In other words, if you want the first screen to render faster, the less JS files should be loaded on the first screen, which is why it is recommended to put the script tag at the bottom of the body tag. Of course, at present, it does not mean that the script tag must be placed at the bottom, because you can add defer or async attributes to the script tag (the difference between the two will be described later).

JS files not only block DOM construction, but also cause CSSOM to block DOM construction..

Originally, the construction of DOM and CSSOM did not affect each other, and well water did not interfere with river water. however, once JavaScript was introduced, CSSOM also began to block the construction of DOM. DOM construction was resumed only after CSSOM was completed.

What is this?

This is because JavaScript can not only change DOM, it can also change style, that is, it can change CSSOM. Because incomplete CSSOM cannot be used, if JavaScript wants to access CSSOM and change it, then the complete CSSOM must be available when executing JavaScript. Therefore, there is a phenomenon that if the browser has not completed the download and construction of CSSOM and we want to run the script at this time, the browser will delay the script execution and DOM construction until it completes the download and construction of CSSOM. That is to say,In this case, the browser downloads and builds CSSOM first, then executes JavaScript, and finally continues to build DOM..

Layout and drawing

After the browser generates the rendering tree, the layout will be based on the rendering tree (also called reflow). At this stage, what the browser should do is to find out the exact position and size of each node in the page. Usually this behavior is also called “automatic rearrangement”.

The output of the layout process is a “box model” that accurately captures the exact position and size of each element in the viewport, and all relative measurements are converted into absolute pixels on the screen.

After the layout is completed, the browser will immediately issue “Paint Setup” and “Paint” events to convert the rendering tree into pixels on the screen.

Above, we have introduced the important steps in the browser workflow in detail. Next, we will discuss several related issues:

Several additional remarks

1. What are the functions of 1.async and defer? What’s the difference?

Next, let’s compare the defer and async attributes:

async和defer

Where the blue line represents JavaScript loading; The red line represents JavaScript execution; The green line represents HTML parsing.

1) Case 1<script src="script.js"></script>

Without defer or async, the browser will immediately load and execute the specified script, that is to say, it will load and execute the document elements after reading them without waiting for subsequent loading.

2) Situation 2<script async src="script.js"></script>(Asynchronous download)

The async property indicates that JavaScript introduced by asynchronous execution is different from defer in that if it is already loaded, execution will begin-whether at this moment in the HTML parsing phase or after DOMContentLoaded triggers. It should be noted that JavaScript loaded in this way will still block the load event. In other words, async-script may be executed before or after DOMContentLoaded triggers, but it must be executed before load triggers.

3) Situation 3<script defer src="script.js"></script>(Delayed execution)

The defer property indicates that the JavaScript introduced is delayed, that is, the HTML did not stop parsing when the JavaScript was loaded, and the two processes are parallel. After the entire document has been parsed and defer-script has been loaded (the order of the two events is irrelevant), all JavaScript code loaded by defer-script will be executed, and then the DOMContentLoaded event will be triggered.

Defer differs from ordinary script in two points: * * HTML parsing is not blocked when loading JavaScript files, and the execution phase is put after HTML tag parsing is completed.
When loading multiple JS scripts, async is loaded out of order, while defer is loaded in order. **

2. Why is DOM slow to operate

Think of DOM and JavaScript as islands, connected by toll bridges. -High Performance JavaScript

JS is very fast, and modifying DOM objects in JS is also very fast. In the JS world, everything is simple and fast. However, DOM operation is not JS’s solo dance, but the cooperation between the two modules.

Because DOM belongs to the rendering engine and JS belongs to the JS engine. When we use JS to operate DOM, it is essentially “cross-border communication” between JS engine and rendering engine. The implementation of this “cross-border communication” is not simple, it relies on the bridge interface as a “bridge” (as shown in the figure below).

There is a charge for crossing the bridge-the cost itself cannot be ignored. Every time we manipulate DOM (whether to modify it or just to access its value), we have to cross a “bridge.” The more times you cross the bridge, the more obvious performance problems will arise. Therefore, the suggestion of “reducing DOM operations” is not groundless.

3. Do you really know reflux and redraw

The process of rendering is basically as follows (the four yellow steps in the figure below): 1. Calculate CSS style 2. Build Render Tree 3.Layout-Positioning Coordinates and Size 4. Formal drawing

Note: There are many connecting lines in the flow chart above, which indicates that Javascript’s dynamic modification of DOM attributes or CSS attributes will result in re-Layout, but some changes will not be re-Layout, i.e. the arrows pointing to the sky in the above chart, such as the modified CSS rule has not been matched to the element.

It is important to say two concepts here, one is Reflow and the other is Repaint

  • Redrawing: When our modification to DOM results in a change in style but does not affect its geometric properties (such as color or background color), the browser does not need to recalculate the geometric properties of the element and directly draw a new style for the element (skipping the reflow link shown in the above figure).
  • Reflux: When our modification of DOM causes changes in DOM geometric dimensions (such as modifying the width, height or hidden elements of elements), the browser needs to recalculate the geometric attributes of elements (the geometric attributes and positions of other elements will also be affected) , and then draw the calculated results. This process is called reflow (also called rearrangement)

We know that when a web page is generated, it will be rendered at least once. In the process of user access, it will be rendered again and again. Re-rendering will repeat reflow+redraw or only redraw.
Reflux is bound to occur redrawing, redrawing does not necessarily cause reflux.. Redrawing and reflow will occur frequently when we set the node style, and will also greatly affect the performance. The cost of reflowing is much higher than that of plotting. Changing the child nodes in the parent node will probably result in a series of reflowing of the parent node.

1) common attribute and methods that cause reflux

Any operation that changes the geometric information (position and size of the element) of the element will trigger backflow.

  • Add or remove visible DOM elements;
  • Element Size Changes-Margin, Fill, Border, Width, and Height
  • Content changes, such as users entering text in the input box
  • Browser Window Size Changes-When ——resize Event Occurs
  • Calculates the offsetWidth and offsetHeight properties
  • Sets the value of the style property

2) common attribute and methods that cause redraw

3) How to Reduce Reflux and Redrawing

  • Use transform instead of top
  • Replace display: none with visibility, because the former will only cause redrawing and the latter will cause reflow (changed layout)
  • Do not put the attribute value of a node in a loop as a variable in the loop.
for(let i = 0;   i < 1000;  i++) {
 //Obtaining offsetTop will result in backflow because the correct value needs to be obtained.
 console.log(document.querySelector('.test').style.offsetTop)
 }
  • Don’t use the table layout, a small change may cause the entire table to be rearranged.
  • The faster the animation speed is, the more times the reflow occurs. You can also choose to use requestAnimationFrame.
  • CSS selectors are matched from right to left to avoid too many levels of nodes
  • A node that is redrawn or reflowed frequently is set as a layer, which can prevent the rendering behavior of that node from affecting other nodes. For example, for the video tag, the browser will automatically change the node into a layer.

Performance optimization strategy

Based on the browser rendering principle described above, DOM and CSSOM structure construction sequence, initialization can optimize page rendering and improve page performance.

  • JS optimization:<script>Tags with defer and async attributes are used to control the downloading and execution of scripts without blocking the parsing of page documents.

    • Defer attribute: used to open a new thread to download the script file and make the script execute after the document parsing is completed.
    • Async attribute: HTML5 adds an attribute to download script files asynchronously, and the execution code will be explained immediately after downloading.
  • CSS optimization:<link>Setting the attribute value in the rel attribute of the tag to preload enables you to indicate which resources are needed immediately after the page loading is completed in your HTML page, optimize the configuration loading sequence, and improve rendering performance.

Summary

To sum up, we come to the conclusion that:

  • Browser workflow: build DOM-> build CSSOM-> build rendering tree-> layout-> draw.
  • Csom will block rendering and will not enter the next stage of building the rendering tree until CSSOM is built.
  • Normally DOM and CSSOM are built in parallel, but when the browser encounters a script tag without defer or async attribute, DOM construction will be suspended. if it happens that the browser has not finished downloading and building CSSOM yet, since JavaScript can modify CSSOM, JS will be executed after CSSOM is built, and DOM construction will be restarted at last.

To recommend a useful BUG monitoring toolFundebug, welcome to try free!

Welcome to pay attention to the public number:Front end craftsmanWe witness your growth together!

Reference article