Home > Article > Web Front-end > Let's talk about how CSS and JS block DOM parsing and rendering
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.
#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!
node
The only thing that needs to be explained is this function:
function sleep(time) { return new Promise(function(res) { setTimeout(() => { res() }, time); }) }
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>
I will insert different JS
and CSS## into it #.
common.css used, regardless of whether there is a prefix or not, the content is like this:
div { background: lightblue; }Okay, not much to say, let’s start the text!
CSS, everyone must know that the
2cdf5bf648cf2f33323966d7f58a7f3f tag is placed in the head performance It will be a little higher, and fewer people know that if
3f1c4e4b6b16bbbd69b2ee476dc4f83a and
2cdf5bf648cf2f33323966d7f58a7f3f are on the head at the same time,
3f1c4e4b6b16bbbd69b2ee476dc4f83a may be on top. better. Why is this? Let's take a look at the impact of
CSS on
DOM.
will not block the parsing of
DOM
DOM parsing. The proof example is as follows. First insert
0ae1b4d46209f6ceeffd5e5bfdf0d62e2cacc6d41bbb37262a98f745aa00fbf0 in the header. , the content of the
JS file is:
const div = document.querySelector('div'); console.log(div);
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.
543e3ac3fa0097a8f621679f25783927 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.
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?
Blocking page rendering
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.
CSS naturally blocks page rendering.
HTMLThe header structure is as follows:
<header> <link rel="stylesheet" href="/css/sleep3000-common.css"> <script src="/js/logDiv.js"></script> </header>But think about what results this will produce?
答案是浏览器会转圈圈三秒,但此过程中不会打印任何东西,之后呈现出一个浅蓝色的div
,再打印出null
。结果好像是CSS
不单阻塞了页面渲染,还阻塞了DOM
的解析啊!稍等,在你打算掀桌子疯狂吐槽我之前,请先思考一下是什么阻塞了DOM
的解析,刚才已经证明了CSS
是不会阻塞的,那么阻塞了页面解析其实是JS
!但明明JS
的代码如此简单,肯定不会阻塞这么久,那就是JS
在等待CSS
的下载,这是为什么呢?
仔细思考一下,其实这样做是有道理的,如果脚本的内容是获取元素的样式,宽高等CSS
控制的属性,浏览器是需要计算的,也就是依赖于CSS
。浏览器也无法感知脚本内容到底是什么,为避免样式获取,因而只好等前面所有的样式下载完后,再执行JS
。因而造成了之前例子的情况。
所以,看官大人明白为何3f1c4e4b6b16bbbd69b2ee476dc4f83a
与2cdf5bf648cf2f33323966d7f58a7f3f
同时在头部的话,3f1c4e4b6b16bbbd69b2ee476dc4f83a
在上可能会更好了么?之所以是可能,是因为如果2cdf5bf648cf2f33323966d7f58a7f3f
的内容下载更快的话,是没影响的,但反过来的话,JS
就要等待了,然而这些等待的时间是完全不必要的。
JS
,也就是3f1c4e4b6b16bbbd69b2ee476dc4f83a
标签,估计大家都很熟悉了,不就是阻塞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('div'); console.log(div);
其实那个数组操作时没意义的,只是为了让这个JS
文件多花执行时间而已。之后把这个文件插入头部,浏览器跑一下。
结果估计大家也能想象得到,浏览器转圈圈一会,这过程中不会有任何东西出现。之后打印出null
,再出现一个浅绿色的div
。现象就足以说明JS
阻塞 DOM
解析了。其实原因也很好理解,浏览器并不知道脚本的内容是什么,如果先行解析下面的DOM
,万一脚本内全删了后面的DOM
,浏览器就白干活了。更别谈丧心病狂的document.write
。浏览器无法预估里面的内容,那就干脆全部停住,等脚本执行完再干活就好了。
对此的优化其实也很显而易见,具体分为两类。如果JS
文件体积太大,同时你确定没必要阻塞DOM
解析的话,不妨按需要加上defer
或者async
属性,此时脚本下载的过程中是不会阻塞DOM
解析的。
而如果是文件执行时间太长,不妨分拆一下代码,不用立即执行的代码,可以使用一下以前的黑科技:setTimeout()
。当然,现代的浏览器很聪明,它会“偷看”之后的DOM
内容,碰到如2cdf5bf648cf2f33323966d7f58a7f3f
、3f1c4e4b6b16bbbd69b2ee476dc4f83a
和a1f02c36ba31691bcfe87b2722de723b
等标签时,它会帮助我们先行下载里面的资源,不会傻等到解析到那里时才下载。
3f1c4e4b6b16bbbd69b2ee476dc4f83a
标签时,会触发页面渲染这个细节可能不少看官大人并不清楚,其实这才是解释上面为何JS
执行会等待CSS
下载的原因。先上例子,HTML
内body
的结构如下:
<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>
这个例子也是很极端的例子,但不妨碍它透露给我们很多重要的信息。想象一下,页面会怎样呢?
答案是先浅绿色,再浅灰色,最后浅蓝色。由此可见,每次碰到3f1c4e4b6b16bbbd69b2ee476dc4f83a
标签时,浏览器都会渲染一次页面。这是基于同样的理由,浏览器不知道脚本的内容,因而碰到脚本时,只好先渲染页面,确保脚本能获取到最新的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. 3f1c4e4b6b16bbbd69b2ee476dc4f83a
and no defer
or async
attribute, it will trigger page rendering, so if the previous CSS
When the resource has not been loaded, the browser will wait for it to be loaded before executing the script. So, you now understand why 3f1c4e4b6b16bbbd69b2ee476dc4f83a
is best to put it at the bottom, 2cdf5bf648cf2f33323966d7f58a7f3f
is best to put it at the head, if the head is both When there are 3f1c4e4b6b16bbbd69b2ee476dc4f83a
and 2cdf5bf648cf2f33323966d7f58a7f3f
, it is best to put 3f1c4e4b6b16bbbd69b2ee476dc4f83a
in 2cdf5bf648cf2f33323966d7f58a7f3f
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!