Contents
- 0.0.1 1. Open the chrome console (press F12), you can see the picture below, focusing on where I draw the red circle
- 0.0.2 2. Click on the place where I draw the red circle (No throttling), you will see the picture below, we choose GPRS option
- 0.0.3 3. In this way, we will limit the download speed limit of resources to 20kb/s, well, then we will enter our topic.
- 0.0.4 Css will block DOM tree parsing?
- 0.0.5 Does css loading block DOM tree rendering?
- 0.0.6 Individual evaluation of this mechanism
- 1 Conclusion
As everyone knows, js execution will block the parsing and rendering of the DOM tree, then will css loading block the parsing and rendering of the DOM tree? Next, I will do a test on the impact of css loading on the parsing and rendering of the DOM tree.
In order to complete this test, let’s first come to science, how to use chrome to set the download speed.
1. Open the chrome console (press F12), you can see the picture below, focusing on where I draw the red circle
Click on the place where I draw the red circle (No throttling), you will see the picture below, we choose GPRS option
2. Click on the place where I draw the red circle (No throttling), you will see the picture below, we choose GPRS option
In this way, our download speed limit for resources will be limited to 20kb/s, well, then we will enter our topic
3. In this way, we will limit the download speed limit of resources to 20kb/s, well, then we will enter our topic.
Speak in code:
<!DOCTYPE html> <html lang="en"> <head> <title>Css blocking</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>
Assumption: css loading blocks DOM tree parsing and rendering
Assume the result: Before the bootstrap.css has not been loaded, the following content will not be parsed and rendered, then we should see the white screen at first, h1 will not be displayed. And the result of console.log should be an empty array.
Actual result: as shown below
Css will block DOM tree parsing?
As can be seen from the above figure, when css has not been loaded yet, h1 is not displayed, but the console output is as follows
It can be known that at this time, the DOM tree has been parsed at least to h1, and the css has not been loaded yet, indicating that css does not block the parsing of the DOM tree.
Does css loading block DOM tree rendering?
From the above figure, we can also see that when the css has not been loaded, the page displays a white screen, until the css loading is completed, the red font is displayed, that is, the following content is parsed, but there is no Was rendered. Therefore, css loading will block the DOM tree rendering.
Individual evaluation of this mechanism
In fact, I think this may also be an optimization mechanism for the browser. Because when you load css, you may modify the style of the following DOM node. If the css loading does not block the DOM tree rendering, then after the css is loaded, the DOM tree may have to be redrawn or reflowed, which causes some There is no necessary loss. So I will first parse the structure of the DOM tree first, finish the work that can be done, and then wait for your css to load, after rendering the DOM tree according to the final style, this performance will be better. .
From the above inference, we can conclude that css loading does not block DOM tree parsing, but blocks DOM tree rendering. So, does css loading block js execution?
Again, verify by code.
<!DOCTYPE html> <html lang="en"> <head> <title>Css blocking</title> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1"> <script> console.log('before css') var startDate = new Date() </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() console.log('after css') console.log('Passed' + (endDate -startDate) + 'ms') </script> </body> </html>
Assumption: css loading will block the running of js
Expected results: The js code behind the link should be run after the css is loaded.
actual results:
As can be seen from the above figure, the js code located before the css load statement is executed first, but the code behind the css load statement is not executed until the css is loaded. This also shows that css loading will block the execution of subsequent js statements. The detailed results look at the following figure (css loaded with 5600+ms):
Conclusion
From the above, we can draw the following conclusions:
- Css loading does not block the resolution of the DOM tree
- Css loading will block the rendering of the DOM tree
- Css loading will block the execution of the following js statement,
Therefore, in order to avoid letting users see longtime white screen time, we should increase the loading speed of css as much as possible. For example, the following methods can be used:
- Use CDN (because CDN will pick the nearest node with cached content for you based on your network conditions, so you can reduce the load time)
- Compress css (you can use a lot of packaging tools, such as webpack, gulp, etc., you can also open gzip compression)
- Reasonable use of cache (set up cache-control, expires, and E-tag are good, but pay attention to a problem, that is, after the file is updated, you have to avoid the impact of the cache. One of the solution defense is in the file name Add a version number later)
- Reduce the number of http requests, merge multiple css files, or simply write them directly into inline styles (a disadvantage of inline styles is that they cannot be cached)
Principle analysis
So why is the above phenomenon? We parse it from the browser's rendering process.
The kernels that are not used by the browser are different, so their rendering process is different. There are currently two main ones:
Webkit rendering process
Gecko rendering process
As you can see from the above two flowcharts, the process of browser rendering is as follows:
- HTML parsing file, generating DOM Tree, parsing CSS file to generate CSSOM Tree
- Combine Dom Tree and CSSOM Tree to generate a Render Tree
- The rendering is rendered according to the Render Tree, and the pixels are rendered onto the screen.
We can see from the process
- DOM parsing and CSS parsing are two parallel processes, so this also explains why CSS loading does not block DOM parsing.
- However, since the Render Tree is dependent on the DOM Tree and CSSOM Tree, it must wait until the CSSOM Tree is built, that is, the CSS resource is loaded (or the CSS resource fails to load) before rendering. Therefore, CSS loading will block the rendering of Dom.
- Since js may operate on previous Dom nodes and css styles, the browser maintains the order of css and js in html. Therefore, the style sheet will be loaded and executed before the subsequent js is executed. So css will block the execution of the following js.
DOMContentLoaded
For the browser, the page load mainly has two events, one is DOMContentLoaded and the other is onLoad. OnLoad doesn't have much to say, just wait for all resources on the page to be loaded before they are triggered. These resources include css, js, image video, and so on.
And DOMContentLoaded, as the name suggests, is triggered when the content of the page is parsed. So, as we discussed above, css blocks Dom rendering and js execution, and js blocks Dom parsing. Then we can make such a hypothesis
- When the page only has css, or js is in front of css, then DomContentLoaded does not need to wait until css is loaded.
- When both css and js exist on the page, and js is behind css, DomContentLoaded must wait until both css and js are loaded.
Let’s test the first case:
<!DOCTYPE html> <html lang="en"> <head> <title>Css blocking</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>
The experimental results are as follows:
From the motion map we can see that the css has not been loaded, it has triggered the DOMContentLoaded event. Because there is no js code behind css.
Next, we test the second case, it is very simple, just add a line of code after the css.
<!DOCTYPE html> <html lang="en"> <head> <title>Css blocking</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('Didn't come to me?'); </script> </head> <body> </body> </html>
The experimental results are as follows:
We can see that the DOMContentLoaded event is only fired when css is loaded. Therefore, we can conclude that:
- If both css and js exist on the page, and js is behind css, the DOMContentLoaded event will be executed after css is loaded.
- In other cases, DOMContentLoaded will not wait for css to load, and the DOMContentLoaded event will not wait for other resources such as images, videos, etc. to load.
The above is all content. Stay tuned to our column and receive the latest and most interesting front end content.
This article has been published by Tencent Cloud + Community in various channels.
Discussion about this post