浏览器渲染html页面的过程
在浏览器获得服务器返回的数据后,浏览器会对返回的html进行渲染。
-
浏览器加载html文件
浏览器至上而下加载html,在加载过程中进行解析和渲染。
如果在加载过程中遇到外部的css和图片,浏览器会另外发送一个请求,去获 取CSS文件和相应的图片,这个请求是异步的,并不会影响HTML文件的加载。值得注意的是,外部css文件虽然不影响html文件的加载,但是会阻塞dom的渲染,所以优化css外部文件体积,使用cdn优化加载速度可以提高渲染速度
如果遇到Javascript文件,即script标签,无论是内联还是外联,HTML文件都会挂起渲染的进程,等待JavaScript文件加载并执行完后,再继续进行解析渲染。
这是因为javaScript可能会修改DOM,导致后续HTML资源白白加载,所以HTML必须等待JavaScript文件加载完毕后,再继续渲染,这也就是为什么JavaScript文件在写在底部body标签前的原因。总结:
css不会阻塞dom的加载与解析,但是会阻塞dom的渲染,而且会阻塞后面的JavaScript语句的执行。
JavaScript会阻塞dom的加载,解析,渲染,可以采用异步或延迟等方案进行优化。参考:页面渲染时js阻塞的解决方法 -
浏览器解析html
在这里抛出几个概念:
DOM:Document Object Model,浏览器将HTML解析成树形的数据结构,简称DOM。
CSSOM:CSS Object Model,浏览器将CSS解析成树形的数据结构,简称CSSOM。
Render Tree: DOM和CSSOM合并后生成Render Tree
Layout: 计算出Render Tree每个节点的具体位置。
Painting:通过显卡,将Layout后的节点内容分别呈现到屏幕上
参考:简述浏览器渲染机制
在浏览器收到服务端返回的html后,浏览器的HTML解析器,会将HTML文件解析成一棵DOM树,DOM树的构建是一个深度遍历的过程,当前节点的所有子节点都构建完成以后,才会去构建当前节点的下一个兄弟节点。
下一步就是将css解析成CSSOM树
然后dom树与cssom树构建出一颗render树,这个渲染树并不等于dom树,因为一些像head或display:none的东西,就没有必要放在渲染树中了。
然后就是Layout阶段,计算元素的位置,Painting阶段把元素渲染到页面中。
- render树渲染
在浏览器渲染完成后,当我们操作dom时,浏览器会重新进行一次layout和Painting的工作,我们把这个称做:reflow回流与repaint重绘
reflow回流:
当我们的dom操作影响了布局相关的,都会引起它内部、周围甚至整个页面的重新渲染。通常我们无法预估浏览器到底会 reflow 哪一部分的代码,它们彼此相互影响。
repaint重绘:
如果只是改变某个元素的背景色、文字颜色、边框颜色等等不影响它周围或内部布局的属性,将只会引起浏览器 repaint(重绘)。repaint 的速度明显快于 reflow(在IE下需要换一下说法,reflow 要比 repaint 更缓慢)。
这里可以说到一个例子
我们控制元素的显示与隐藏有两种方式
一种是display:none
一种是visibility:hidden
display:none会导致reflow回流与repaint重绘,因为使用该属性后,HTML元素(对象)的宽度、高度等各种属性值都将“丢失”。
visibility:hidden只会触发repaint重绘,因为使用该属性后,HTML元素(对象)仅仅是在视觉上看不见(完全透明),而它所占据的空间位置仍然存在,也即是说它仍具有高度、宽度等属性值。
所以在渲染的优化上,我们可以尽量减少reflow回流,来优化我们页面渲染的性能。