html.js.css渲染顺序
Last updated
Last updated
可以发现一个Dom
过来,正常情况下, html
解析器和css
解析器同时进行解析, html
解析成一个dom树
,解析成dom树
的同时,css
解析器也会解析成一个css 规则树
. 然后dom
树和css
规则树生成了附件,我把他当做cssom
来看待.附件形成之后,就可以生成一个渲染树了.然后渲染树和layout
就可以进行绘制
了. 因为浏览器已经能知道网页中有哪些节点、各个节点的CSS定义以及他们的从属关系, 所以可以进行绘制.最后进行呈现.
上面也说了,是正常情况下.但是不正常情况呢? 不正常情况就是阻塞,不能并行下载.
css阻塞
css
其实也会阻塞,不要只以为js
会阻塞.
CSS会阻塞渲染树的构建,但是不会阻塞DOM构建,但是在CSSOM构建完成之前,页面不会开始渲染(一片空白).会等待css规则树
。如何优化css阻塞
与js不一样,js虽然会阻塞后续DOM构建,但是前面已经就绪的内容会进行渲染。CSS虽然不阻塞DOM构建,但是会阻塞后面js的执行,从而间接阻塞完整DOM的构建
js阻塞
JS默认也是会阻塞DOM和渲染树的构建的。
HTML解析器在遇到脚本文件时,默认会停下来去获取脚本(不考虑资源预加载优化),然后执行,期间阻塞DOM构建。
所以加载顺序是自上而下,但是渲染流程却是如图.所以最好将js放在最下面.
关键资源: 可能阻止网页首次渲染的资源。
关键路径长度 获取所有关键资源所需的往返次数或总时间。
关键字节: 实现网页首次渲染所需的总字节数,它是所有关键资源传送文件大小的总和。
为什么js加载执行会阻塞渲染树构建
这就得从浏览器来说起来,现在的浏览器都是多进程的浏览器,以谷歌来说,他就是多进程的,每当你打开一个新的tab页的时候,他就会去开一个进程来处理这个tab页面。在这个tab里,是单进程,但是却是多线程的,主要是有那么一些线程,可以看下。
JavaScript引擎线程
GUI线程
事件触发线程
定时触发器线程
异步http请求线程
javascript线程
毫无疑问,这东西就是处理js代码的。例如V8引擎,就是解析运行代码。但是为什么是单线程的呢?因为线程存在上下文切换,可能多个线程操作一个dom,这就产生了资源竞争,后续要处理更多,索性用了单线程。
GUI线程
这个是负责渲染页面,每当页面重绘的时候这个线程都会调用。js引擎在执行的时候,GUI线程会停止执行,处于挂起的一个状态。
js阻塞GUI引擎
因为js是可以操作dom,GUI也是操作dom, 如果同时运行会存在问题,可能同时修改dom,导致渲染前后不一致。
定时触发器器线程
处理一些异步的web api的时候,碰到定时的,会去处理这种定时,再放入事件队列等待放入栈里。
事件触发线程
一些事件被触发时就会调用该线程,比如一些ui事件,定时事件,ajax请求等,都会放到队列里准备执行。
异步http请求线程
一些http请求连接开启之后,都会新开一个线程去处理。