In my previous interview with Toutiao, the interviewer asked me, “Js execution will block the parsing and rendering of DOM tree, so will CSS loading block the parsing and rendering of DOM tree?” So, I’m going to test CSS loading for DOM tree parsing and rendering.

To complete this test, let’s take a look at how chrome can set download speeds

  1. Open the Chrome Console (press F12) and you’ll see the image below, highlighted where I circled in red
  2. Click where I have circled in red (No throttling) and you will see the image below. We select GPRS
  3. This will limit our download speed to 20 kilobytes per second. Ok, so let’s get down to business

Does CSS loading block parse rendering of the DOM tree?

Speak in code:


      
<html lang="en">
  <head>
    <title>The CSS block</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style>
      h1 {
        color: red ! important
      }
    </style>
    <script>
      function h () {
        console.log(document.querySelectorAll('h1'))
      }
      setTimeout(h, 0)
    </script>
    <link href="https://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.css" rel="stylesheet">
  </head>
  <body>
    <h1>This is red</h1>
  </body>
</html>
Copy the code

Assumption: CSS loading blocks DOM tree parsing and rendering

Assuming the result: the following content will not be parsed and rendered before bootstrap. CSS is loaded, we should initially see a blank screen with no h1 displayed. And the result of console.log should be an empty array.

Actual result: figure below

Does CSS block DOM tree parsing?

As you can see from the image above, the H1 is not displayed when the CSS is not loaded, but the console output is as follows

It can be seen that at this point, the DOM tree has been parsed up to h1 at least, but the CSS has not been loaded, which means that CSS does not block the parsing of the DOM tree.

Does CSS loading block DOM tree rendering?

We can also see from the image above that the page displays a white screen while the CSS is not loaded, and the red font is not displayed until the CSS is loaded, which means that the content below is parsed but not rendered. So CSS loading blocks DOM tree rendering.

Personal evaluation of this mechanism

In fact, I think this may also be a browser optimization mechanism. Because you may change the style of the DOM node below while loading the CSS, if the CSS loading does not block the DOM tree rendering, then the DOM tree may have to be redrawn or reflow after the CSS is loaded, causing unnecessary wear and tear. So I’ll just parse the STRUCTURE of the DOM tree first, get all the work done, and then render the DOM tree according to the final style after the CSS is loaded, which is actually better for performance.

Does CSS loading block JS running?

From the above corollary, we can conclude that CSS loading does not block DOM tree parsing, but does block DOM tree rendering. So, does CSS loading block JS execution?

Again, verify by code.


      
<html lang="en">
  <head>
    <title>The CSS block</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script>
      console.log('before css')
      var startDate = new Date(a)</script>
    <link href="https://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.css" rel="stylesheet">
  </head>
  <body>
    <h1>This is red</h1>
    <script>
      var endDate = new Date(a)console.log('after css')
      console.log('Past' + (endDate -startDate) + 'ms')
    </script>
  </body>
</html>
Copy the code

Assumption: CSS loading blocks subsequent JS runs

Expected result: The JS code following the link should not run until the CSS is loaded

Actual results:

As you can see from the figure above, the JS code before the CSS loading statement is executed first, but the code after the CSS loading statement is not executed until after the CSS loading is complete. This means that CSS loading blocks subsequent JS statements. The detailed result is shown below (CSS load using 5600+ms):

conclusion

From what has been discussed above, we can draw the following conclusions:

  1. CSS loading does not block parsing of the DOM tree
  2. CSS loading blocks DOM tree rendering
  3. CSS loading blocks the execution of subsequent JS statements,

Therefore, in order to avoid a long white screen time for users, we should make the CSS load as fast as possible. For example, we can use the following methods:

  1. Use CDN(because CDN will select the nearest node with cached content to provide resources for you according to your network condition, so it can reduce the load time)
  2. Compress CSS (using various packaging tools such as Webpack,gulp, etc., or by enabling gzip compression)
  3. Use caches wisely (cache-Control, Expires, and e-tag are all fine, but one thing to be aware of is that you want to avoid caching after updates. One solution is to add a version number after the file name.
  4. Reduce the number of HTTP requests, merge multiple CSS files, or simply write inline styles (one of the disadvantages of inline styles is that they can’t be cached)

update

The principle of analytic

So why does the above phenomenon occur? Let’s take a look at the browser’s rendering process.

Different browsers use different kernels, so their rendering process is different. There are two main ones at present:

Webkit rendering process

Gecko rendering process

As can be seen from the above two flow charts, the browser rendering process is as follows:

  1. HTML files are parsed to generate A DOM Tree, and CSS files are parsed to generate a CSSOM Tree
  2. Combine Dom Tree with CSSOM Tree to generate Render Tree
  3. Render pixels onto the screen according to Render Tree.

We can see that in the process

  1. DOM parsing and CSS parsing are parallel processes, so this explains why CSS loading does not block DOM parsing.
  2. However, since the Render Tree is dependent on the DOM Tree and the CSSOM Tree, he must wait until the CSSOM Tree is built, i.e. the CSS resource is loaded (or the CSS resource fails to load), before he can start rendering. Therefore, CSS loading blocks Dom rendering.
  3. Because JS may manipulate previous Dom nodes and CSS styles, browsers maintain the order of CSS and JS in HTML. Therefore, the stylesheet will be loaded and executed before any subsequent JS is executed. So CSS blocks subsequent JS execution.

supplement

DOMContentLoaded

For browsers, there are two main events for page loading, one is DOMContentLoaded and the other is onLoad. OnLoad does not trigger until all resources on the page have been loaded, such as CSS, JS, images and videos.

DOMContentLoaded, as the name implies, triggers this event when the content of the page has been parsed. So, as we discussed above, CSS blocks Dom rendering and JS execution, and JS blocks Dom parsing. So we can make this assumption

  1. DomContentLoaded does not need to wait for the CSS to finish loading when only CSS exists on the page, or when js is in front of the CSS.
  2. DomContentLoaded does not trigger until both CSS and JS are loaded on a page and the JS is behind the CSS.

Let’s test the first case:


      
<html lang="en">
  <head>
    <title>The CSS block</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script>
      document.addEventListener('DOMContentLoaded'.function() {
        console.log('DOMContentLoaded');
      })
    </script>
    <link href="https://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.css" rel="stylesheet">
  </head>
  <body>
  </body>
</html>
Copy the code

The experimental results are shown below:

As you can see from the GIF, the DOMContentLoaded event is triggered before the CSS is finished loading. Because CSS doesn’t have any JS code behind it.

Let’s test the second case. It’s as simple as adding a line of code after the CSS


      
<html lang="en">
  <head>
    <title>The CSS block</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <script>
      document.addEventListener('DOMContentLoaded'.function() {
        console.log('DOMContentLoaded');
      })
    </script>
    <link href="https://cdn.bootcss.com/bootstrap/4.0.0-alpha.6/css/bootstrap.css" rel="stylesheet">

    <script>
      console.log("Is it my turn?");
    </script>
  </head>
  <body>
  </body>
</html>
Copy the code

The experimental results are shown below:

  1. If both CSS and JS exist on the page, and js exists behind the CSS, the DOMContentLoaded event is executed after the CSS is loaded.
  2. In other cases, DOMContentLoaded does not wait for CSS to load, and the DOMContentLoaded event does not wait for images, videos, and other resources to load.

And that’s it. HHHH, welcome to exchange

This article address in -> my blog address, welcome to give a start or follow