Browser rendering

The browser rendering process is as follows:

Figure: WebKit main flow

Figure: Mozilla’s Gecko Rendering engine main process (3.6)

Combined with the image above, a complete rendering process is as follows:

  • The rendering process parses THE HTML content into a readable DOM tree structure, and parses the CSS into CSSDOM
  • Combining DOM and CSSOM to generate a Render Tree
  • Once the render tree is built, the layout process is performed, which determines the exact coordinates of each node on the screen
  • Display the render tree on the screen. The next step is to draw, which is to walk through the render tree and draw each node using the UI backend layer.

It is worth noting that:

The key point is that the above four steps are not executed in a strict order. The rendering engine displays the content as quickly as possible, which means that as the browser parses the HTML, it builds the render tree, and as it builds part of it, it renders the existing elements. If the external style is not loaded at this point, the rendering will be the browser default.

The same is true of other stages. Because the browser tries to present the content as quickly as possible, the content will sometimes appear before the style is loaded. This is the frequently occurring FOCU(Flash of UnStyled content) or white screen problem.

CSS loading does not block DOM tree parsing

As can be seen from the browser’s rendering flowchart, DOM parsing and CSS parsing are two parallel processes, so CSS loading does not block DOM tree parsing

CSS loading blocks rendering of the DOM tree

Render Tree is dependent on both the DOM Tree and the CSSOM Tree, so whether or not the DOM Tree is finished, it must wait until the CSSOM Tree is built and the CSS loads (or fails to load) before it can Render.

Therefore, the CSS load is blocking the rendering of the DOM tree

<head>
    <script>
        document.addEventListener('DOMContentLoaded'.() = > {
            var p = document.querySelector('p')
            console.log(p)
        })
    </script>
    <link rel="stylesheet" href="./static/style.css? sleep=3000">
</head>

<body>
    <p>hello world</p>
</body>
Copy the code

Case source: whether JS and CSS block DOM rendering and parsing

The loading of THE CSS does not block the parsing of the DOM tree, and the P tag is parsed normally. However, after the loading of the P tag, the page is not rendered late, because the CSS request has not been completed. After the CSS request is completed, the Hello World is rendered, so the CSS will block the page rendering

DOMContentLoaded: The DOMContentLoaded event is triggered only when the pure HTML is fully loaded and parsed. It does not wait for the stylesheet, image, or subframework to complete loading

CSS loading blocks subsequent JS execution

It can be seen from the rendering flow chart of the browser that the loading, parsing and execution of JS will block the construction of DOM. That is to say, when building DOM, if THE HTML parser encounters JS, it will pause the construction of DOM and hand over the control to THE JS engine until the JS engine finishes running. The browser then resumes the DOM build from where it left off.

This is why it is recommended to place the script tag at the bottom of the body tag.

From the browser’s rendering flow chart, we can see that DOM and CSSOM are built independently of each other, but if the external CSS file is introduced before the JS script?

<html>
    <head>    
        <link href="theme.css" rel="stylesheet">
    </head>
    <body>    
        <div>hello world</div>    
        <script>        
            console.log('hello world')    
        </script>    
        <div>hello world</div>
    </body>
</html>
Copy the code

Its execution process:

The CSS also blocks DOM generation at this point

This is because JS can not only change the DOM, it can also change styles, which means it can change CSSOM. However, incomplete CSSOM is not available. To access CSSOM and change it in JS, the complete CSSOM must be available when executing JS.

As a result, if we want to run the script before the browser has finished downloading and building CSSOM, the browser will delay script execution and DOM build until it has finished downloading and building CSSOM. That is, in this case, the browser downloads and builds the CSSOM, then executes the JS script, and then proceeds to build the DOM.

What if there are also JS loaders?

<head>
    <script>
        document.addEventListener('DOMContentLoaded'.() = > {
            var p = document.querySelector('p')
            console.log(p)
        })
    </script>
    <link rel="stylesheet" href="./static/style.css? sleep=3000">
    <script src="./static/index.js"></script>
</head>

<body>
    <p>hello world</p>
</body>
Copy the code

The HTML file contains external references to CSS and JS files. HTML initiates the download request for both files. No matter who arrives first, the CSS file is downloaded and the CSSOM is generated before executing the JavaScript script. Finally, we continue to build the DOM, build the layout tree, and draw the page.

So it’s common to put

How to optimize the rendering process

How to reduce white screen time?

  • Use inline JS and CSS to reduce the download of JS and CSS files
  • Tools such as Webpack compress JS and CSS files to reduce file size
  • Use async or defer
  • Use the CDN etc.

Three minutes a day, advance one