浏览器DOM渲染及阻塞问题
在准备面试,然后复习到了计网的知识点,紧接着又扯到了url从输入到浏览器渲染的那个问题,这里来顺便完善补充一下,本文的重点在渲染
上面的图就是浏览器从服务器请求来页面后渲染的全过程
这里我们分开来看:分为了四大步
-
解析DOM树和CSSOM
1.HTML标签进行Dom树解析:
在Dom树解析的过程中,遇到link会去进行请求资源,这个过程不会阻塞Dom的解析;
遇到script标签,则会将解析停下来,去执行js代码,因此script标签通常建议放在</body>之前,能优化用户体验,减少白屏时间,还可以使用js动态加载生产script标签(PS:这个jsonp跨域请求有在使用)
这里需要注意img标签是不会阻塞Dom的解析的,虽然他也有src标签去请求外部资源
下面是大佬思否上的原话:
解析遇到link、script、img标签时,浏览器会向服务器发送请求资源。
script的加载或者执行都会阻塞html解析、其他下载线程以及渲染线程。
link加载完css后会解析为CSSOM(层叠样式表对象模型,一棵仅含有样式信息的树)。css的加载和解析不会阻塞html的解析,但会阻塞渲染。
img的加载不会阻塞html的解析,但img加载后并不渲染,它需要等待Render Tree生成完后才和Render Tree一起渲染出来。未下载完的图片需等下载完后才渲染。
2.CSS语法进行CSS树解析
CSS解释器将CSS进行解释然后解析
划重点!!!Dom树和CSSOM两者不是解析完再渲染的,而是边解析边进行渲染的!
-
DOM树和CSSOM渲染完成后合并生成Render树
-
布局(reflow重排发生在这个阶段)
这个阶段是通过递归调用进行布局的,引擎计算各元素的尺寸大小,进行布局树绘制
触发重排:
- 页面首次渲染
- 浏览器窗口大小变化
- 元素尺寸、位置、内容、字体大小发生变化
- 添加或删除可见的元素
- 激活伪类时
- 绘制(repainting重绘发生在这个阶段)
触发重绘:改变元素颜色、背景、visibility、outline等属性
!!!划重点 ,重排一定会触发重绘,重绘不一定会触发重排
阻塞问题总结
阻塞发生的情况:
- 遇到script标签加载js的时候
- 会加载js并且执行完毕才开始渲染
- 遇到alert会阻塞
- css也会阻塞
- css是由单独的下载线程异步下载的。
总结:
1.css加载不会阻塞DOM树的解析
2.css加载会阻塞DOM树(render树)的渲染
3.css加载会阻塞后面js语句的执行
为了避免让用户看到长时间的白屏时间,我们应该尽可能的提高css加载速度,比如可以使用以下几种方法:
- 使用CDN(因为CDN会根据你的网络状况,替你挑选最近的一个具有缓存内容的节点为你提供资源,因此可以减少加载时间)
- 对css进行压缩(可以用很多打包工具,比如webpack,gulp等,也可以通过开启gzip压缩)
- 合理的使用缓存(设置cache-control,expires,以及E-tag都是不错的,不过要注意一个问题,就是文件更新后,你要避免缓存而带来的影响。其中一个解决防范是在文件名字后面加一个版本号)
- 减少http请求数,将多个css文件合并,或者是干脆直接写成内联样式(内联样式的一个缺点就是不能缓存)