浏览器渲染
渲染原理
内核
内核,浏览器运行的核心。内核主要有两个部分:渲染引擎、js引擎。渲染引擎在不同浏览器、不同内核中,渲染引擎都不一样。
常见的内核
Trident(IE)Gecko(火狐)
Blink(Chrome、Opera)
Webkit(Safari)
页面加载过程
通过DNS获取域名对应的IP地址
向IP发送HTTP请求
服务器处理返回HTTP请求
浏览器解析服务器返回的内容
渲染过程
渲染过程大致分为一下三部分:
- HTML、CSS、JS解析
- 对于HTML/SVG/XHTML,浏览器会把对应内容转换成DOM树形结构
- 解析生成CSS规则树
- 解析执行JS脚本,在脚本加载完成后,执行脚本
- 在解析完成后,合并DOM树与CSS规则树,生成渲染树(Rendering Tree)
渲染树与DOM树不同,渲染树只会包括需要显示的节点和相对节点的样式信息
CSS规则树主要作用是为渲染树上的节点加上相对应的CSS规则
计算每个元素的位置,该过程称为重绘(repaint)和回流(reflow)
- 调用系统的绘图API进行图形绘制
构建DOM
浏览器将读取到的HTML文件转换为DOM树
构建CSSOM(CSS规则树)
DOM树主要说明页面内容有什么,但怎么展示内容,还需要CSSOM
CSS匹配HTML元素是一个相当复杂和有性能问题的事情。所以,DOM树要小,CSS尽量用id和class,千万不要过渡层叠下去。
构建渲染树
在得到DOM树与CSSOM树后,需要将两者合并为渲染树进行显示
渲染树中只会包含需要显示的节点及其样式信息
如果遇到
<script>
标签,就会停止渲染,执行JS代码(可以通过async
或defer
修改<script>
行为
<script>
不仅会阻塞DOM的构建,还会导致CSS规则树构建也阻塞
原本DOM和CSSOM的构建是互不影响,井水不犯河水,但是一旦引入了JavaScript,CSSOM也开始阻塞DOM的构建,只有CSSOM构建完毕后,DOM再恢复DOM构建。
这是因为JavaScript不只是可以改DOM,它还可以更改样式,也就是它可以更改CSSOM。因为不完整的CSSOM是无法使用的,如果JavaScript想访问CSSOM并更改它,那么在执行JavaScript时,必须要能拿到完整的CSSOM。所以就导致了一个现象,如果浏览器尚未完成CSSOM的下载和构建,而我们却想在此时运行脚本,那么浏览器将延迟脚本执行和DOM构建,直至其完成CSSOM的下载和构建。也就是说,在这种情况下,浏览器会先下载和构建CSSOM,然后再执行JavaScript,最后在继续构建DOM。
async
和defer
的作用
async
异步下载defer
延迟执行载入 JavaScript 文件时不阻塞 HTML 的解析,执行阶段被放到 HTML 标签解析完成之后。 在加载多个JS脚本的时候,async是无顺序的加载,而defer是有顺序的加载。
重绘、回流
浏览器的默认布局模型为流式布局模型
浏览器把
HTML
解析成DOM
,把CSS
解析成CSSOM
,然后把两者合并生成Render Tree
通过渲染树进行计算每个需要显示的节点的大小与位置,最后进行绘制显示
如果使用流式布局,则对
Render Tree
的计算通常只需要遍历一次
回流必将重绘,重绘不一定回流
回流(Reflow)
当
Render Tree
中部分或全部元素的大小,结构或某些属性发生改变时,浏览器及将重新渲染部分或全部元素,此过程称为回流
当我们对 DOM 的修改引发了 DOM 几何尺寸的变化(比如修改元素的宽、高或隐藏元素等)时,浏览器需要重新计算元素的几何属性(其他元素的几何属性和位置也会因此受到影响),然后再将计算的结果绘制出来。这个过程就是回流(也叫重排)
会导致回流的操作
首次渲染
浏览器窗口大小改变
元素的大小、位置改变
元素内容、字体大小变化
添加或删除可见的元素
激活
CSS
伪类查询某些属性或调用某些方法
会导致回流的属性、方法
clientWidth
、clientHeight
、clientTop
、clientLeft
offsetWidth
、offsetHeight
、offsetTop
、offsetLeft
scrollWidth
、scrollHeight
、scrollTop
、scrollLeft
scrollIntoView()
、scrollIntoViewIfNeeded()
getComputedStyle()
getBoundingClientRect()
scrollTo()
重绘(Repaint)
当页面中的元素样式的改变并不影响它的大小和位置时,浏览器将重新绘制元素,此过程称为重绘
当我们对 DOM 的修改导致了样式的变化、却并未影响其几何属性(比如修改了颜色或背景色)时,浏览器不需重新计算元素的几何属性、直接为该元素绘制新的样式
常见的会引起重绘的属性和方法
重绘与回流的机制
有时即使仅仅回流一个单一的元素,它的父元素以及任何跟随它的元素也会产生回流
浏览器会维护一个队列,把所有引起回流和重绘的操作放入队列中,如果队列中的任务数量或者时间间隔达到一个阈值的,浏览器就会将队列清空,进行一次批处理,这样可以把多次回流和重绘变成一次。
当访问以下属性或方法时,浏览器会立即清空队列:
clientWidth
、clientHeight
、clientTop
、clientLeft
offsetWidth
、offsetHeight
、offsetTop
、offsetLeft
scrollWidth
、scrollHeight
、scrollTop
、scrollLeft
width
、height
getComputedStyle()
getBoundingClientRect()
在队列中的重绘、回流可能会影响到以上属性或方法的返回值,因此浏览器需要清空队列,确保返回值的准确
浏览器的调试技巧
设置断点
开发者工具
条件断点
代码中下断点
// 以下代码可以防止调试网站源码
// 在打开开发者工具后,每秒钟触发一次断点,防止调试源码
(function() {
setInterval(function() {
debugger
}, 1000)
})()