浏览器渲染
渲染原理
内核
内核,浏览器运行的核心。内核主要有两个部分:渲染引擎、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、clientLeftoffsetWidth、offsetHeight、offsetTop、offsetLeftscrollWidth、scrollHeight、scrollTop、scrollLeftscrollIntoView()、scrollIntoViewIfNeeded()getComputedStyle()getBoundingClientRect()scrollTo()
重绘(Repaint)
当页面中的元素样式的改变并不影响它的大小和位置时,浏览器将重新绘制元素,此过程称为重绘
当我们对 DOM 的修改导致了样式的变化、却并未影响其几何属性(比如修改了颜色或背景色)时,浏览器不需重新计算元素的几何属性、直接为该元素绘制新的样式
常见的会引起重绘的属性和方法

重绘与回流的机制
有时即使仅仅回流一个单一的元素,它的父元素以及任何跟随它的元素也会产生回流
浏览器会维护一个队列,把所有引起回流和重绘的操作放入队列中,如果队列中的任务数量或者时间间隔达到一个阈值的,浏览器就会将队列清空,进行一次批处理,这样可以把多次回流和重绘变成一次。
当访问以下属性或方法时,浏览器会立即清空队列:
clientWidth、clientHeight、clientTop、clientLeftoffsetWidth、offsetHeight、offsetTop、offsetLeftscrollWidth、scrollHeight、scrollTop、scrollLeftwidth、heightgetComputedStyle()getBoundingClientRect()
在队列中的重绘、回流可能会影响到以上属性或方法的返回值,因此浏览器需要清空队列,确保返回值的准确
浏览器的调试技巧
设置断点
开发者工具

条件断点

代码中下断点
// 以下代码可以防止调试网站源码
// 在打开开发者工具后,每秒钟触发一次断点,防止调试源码
(function() {
setInterval(function() {
debugger
}, 1000)
})()
