Let's talk about how CSS and JS block DOM parsing and rendering

青灯夜游
Release: 2021-05-27 09:58:16
forward
2728 people have browsed it

This article will introduce to you the principle of CSS and JS blocking DOM parsing and rendering. It has certain reference value. Friends in need can refer to it. I hope it will be helpful to everyone.

Let's talk about how CSS and JS block DOM parsing and rendering

#hello~ Dear readers, hello everyone. I guess everyone has heard that try to put CSS at the head and JS at the bottom, which can improve the performance of the page. However, why? Have you considered it? For a long time, I knew it but didn't know why. Of course it was OK to memorize it for exams, but it would be a mess in actual application. So wash (wang) heart (yang) leather (bu) face (lao) and summarize the recent results.

Friendly reminder, this article is mainly for beginners. If you want to see the conclusion directly, you can scroll to the bottom~


Because it is related to the reading of files, that is for sure If you need a server, I will put all the files on github, give me a star and I will be happy!

nodeThe only thing that needs to be explained is this function:

function sleep(time) {
  return new Promise(function(res) {
    setTimeout(() => {
      res()
    }, time);
  })
}
Copy after login

Hmm! In fact, it’s delayed. If the CSS or JS file name has a prefix such as sleep3000, it means that the file will be returned after a delay of 3000 milliseconds.

The HTML file used below looks like this:

    <!DOCTYPE html>
    <html>
    <head>
     <meta charset="UTF-8">
     <title>Title</title>
     <style>
     div {
     width: 100px;
     height: 100px;
     background: lightgreen;
     }
     </style>
    </head>
    <body>
     <div></div>
    </body>
    </html>
Copy after login

I will insert different JS and CSS## into it #.

The

common.css used, regardless of whether there is a prefix or not, the content is like this:

div {
  background: lightblue;
}
Copy after login

Okay, not much to say, let’s start the text!

CSS

About

CSS, everyone must know that the <link> tag is placed in the head performance It will be a little higher, and fewer people know that if <script> and <link> are on the head at the same time, <script> may be on top. better. Why is this? Let's take a look at the impact of CSS on DOM.

CSS will not block the parsing of DOM

Attention! What we are talking about here is

DOM parsing. The proof example is as follows. First insert in the header. , the content of the JS file is:

const div = document.querySelector(&#39;div&#39;);
console.log(div);
Copy after login

defer attribute I believe everyone is familiar with it, MDNThe description of this is to inform The browser script will be executed after the document completes parsing and before the DOMContentLoaded event is triggered. Setting this property ensures that div is printed out immediately after DOM is parsed.

Then insert

into any position of the HTML file, When you open the browser, you can see that the DOM node div is first printed, and after about 3 seconds, a light blue div is rendered. This proves that CSS will not block the parsing of DOM. Although CSS takes 3 seconds to download, the browser will not wait stupidly during this process. CSSAfter downloading, DOM will be parsed.

Let me briefly explain here, the browser parses

DOM to generate DOM Tree, and combines CSS to generate CSS Tree , finally form render tree, and then render the page. It can be seen that CSS has no influence on DOM Tree during this process, so there is no need to block DOM parsing. However, DOM Tree and CSS Tree will be combined into render tree, so will CSS block the rendering of the page?

CSS Blocking page rendering

In fact, the example just explained this point, if

CSS will not block If the page blocks rendering, then the browser will render a light green div before the CSS file is downloaded, and then turn to light blue. This strategy of the browser is actually very wise. Imagine that without this strategy, the page would first show an original appearance, and then suddenly change its appearance after CSS is downloaded. The user experience is extremely poor, and rendering is costly.

Therefore, based on performance and user experience considerations, the browser will try to reduce the number of renderings,

CSS naturally blocks page rendering.

However, things are always weird, please look at this example,

HTMLThe header structure is as follows:

<header>
    <link rel="stylesheet" href="/css/sleep3000-common.css">
    <script src="/js/logDiv.js"></script>
</header>
Copy after login

But think about what results this will produce?

答案是浏览器会转圈圈三秒,但此过程中不会打印任何东西,之后呈现出一个浅蓝色的div,再打印出null。结果好像是CSS不单阻塞了页面渲染,还阻塞了DOM 的解析啊!稍等,在你打算掀桌子疯狂吐槽我之前,请先思考一下是什么阻塞了DOM 的解析,刚才已经证明了CSS是不会阻塞的,那么阻塞了页面解析其实是JS!但明明JS的代码如此简单,肯定不会阻塞这么久,那就是JS在等待CSS的下载,这是为什么呢?

仔细思考一下,其实这样做是有道理的,如果脚本的内容是获取元素的样式,宽高等CSS控制的属性,浏览器是需要计算的,也就是依赖于CSS。浏览器也无法感知脚本内容到底是什么,为避免样式获取,因而只好等前面所有的样式下载完后,再执行JS。因而造成了之前例子的情况。

所以,看官大人明白为何<script><link>同时在头部的话,<script>在上可能会更好了么?之所以是可能,是因为如果<link>的内容下载更快的话,是没影响的,但反过来的话,JS就要等待了,然而这些等待的时间是完全不必要的。

JS

JS,也就是<script>标签,估计大家都很熟悉了,不就是阻塞DOM解析和渲染么。然而,其中其实还是有一点细节可以考究一下的,我们一起来好好看看。

JS 阻塞 DOM 解析

首先我们需要一个新的JS文件名为blok.js,内容如下:

const arr = [];
for (let i = 0; i < 10000000; i++) {
  arr.push(i);
  arr.splice(i % 3, i % 7, i % 5);
}
const div = document.querySelector(&#39;div&#39;);
console.log(div);
Copy after login

其实那个数组操作时没意义的,只是为了让这个JS文件多花执行时间而已。之后把这个文件插入头部,浏览器跑一下。

结果估计大家也能想象得到,浏览器转圈圈一会,这过程中不会有任何东西出现。之后打印出null,再出现一个浅绿色的div。现象就足以说明JS 阻塞 DOM 解析了。其实原因也很好理解,浏览器并不知道脚本的内容是什么,如果先行解析下面的DOM,万一脚本内全删了后面的DOM,浏览器就白干活了。更别谈丧心病狂的document.write。浏览器无法预估里面的内容,那就干脆全部停住,等脚本执行完再干活就好了。

对此的优化其实也很显而易见,具体分为两类。如果JS文件体积太大,同时你确定没必要阻塞DOM解析的话,不妨按需要加上defer或者async属性,此时脚本下载的过程中是不会阻塞DOM解析的。

而如果是文件执行时间太长,不妨分拆一下代码,不用立即执行的代码,可以使用一下以前的黑科技:setTimeout()。当然,现代的浏览器很聪明,它会“偷看”之后的DOM内容,碰到如<link><script><img>等标签时,它会帮助我们先行下载里面的资源,不会傻等到解析到那里时才下载。

浏览器遇到 <script> 标签时,会触发页面渲染

这个细节可能不少看官大人并不清楚,其实这才是解释上面为何JS执行会等待CSS下载的原因。先上例子,HTMLbody的结构如下:

<body>
	<div></div>
	<script src="/js/sleep3000-logDiv.js"></script>
	<style>
		div {
			background: lightgrey;
		}
	</style>
	<script src="/js/sleep5000-logDiv.js"></script>
	<link rel="stylesheet" href="/css/common.css">
</body>
Copy after login

这个例子也是很极端的例子,但不妨碍它透露给我们很多重要的信息。想象一下,页面会怎样呢?

答案是先浅绿色,再浅灰色,最后浅蓝色。由此可见,每次碰到<script>标签时,浏览器都会渲染一次页面。这是基于同样的理由,浏览器不知道脚本的内容,因而碰到脚本时,只好先渲染页面,确保脚本能获取到最新的DOM元素信息,尽管脚本可能不需要这些信息。

小结

综上所述,我们得出这样的结论:

  • CSS will not block the parsing of DOM, but will block the rendering of DOM.
  • JS Blocks DOM parsing, but the browser will "peep" DOM and download related resources in advance.
  • When the browser encounters a tag with <script> and no defer or async attribute, it will trigger page rendering, so if the previous CSSWhen the resource has not been loaded, the browser will wait for it to be loaded before executing the script.

So, you now understand why <script> is best to put it at the bottom, <link> is best to put it at the head, if the head is both When there are <script> and <link>, it is best to put <script> in <link>Is it above?

Thank you all for reading this. I hope this article will be helpful to you. If you have different or better opinions, please feel free to enlighten me! Thank you~

Original address: https://juejin.cn/post/6844903497599549453

For more programming-related knowledge, please visit: Programming Video! !

The above is the detailed content of Let's talk about how CSS and JS block DOM parsing and rendering. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:juejin.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template