浏览器渲染网页过程
本文主要是对浏览器渲染网页的过程做一个总结。
一.概述
我在上篇文章《 浏览器中输入URL回车后... 》介绍了当在浏览器中输入 URL 回车后客户端向服务器请求资源的过程,当请求到网页资源后,浏览器便会开始渲染,渲染主要分为以下几个过程:
- 构建文档对象模型(DOM);
- 构建 CSS 对象模型(CSSOM);
- 构建渲染树(Render Tree);
- 布局(layout);
- 绘制(painting)。
二.过程详解
1.构建文档对象模型(DOM)
当浏览器从磁盘或网络中获取到网页(html 文件)的数据时,会通过一系列的转换解析出各个 html 标签,并最终构建文档对象模型,即我们经常说的 DOM Tree,DOM Tree 的构建过程是一个深度遍历的过程,当前节点的所有子节点构建好后才会去构建当前节点的下一个兄弟节点。
2.构建 CSS 对象模型(CSSOM)
在构建文档对象模型的过程中,若遇到 link 标签,则浏览器会发出一个获取该资源的请求,最终获得包含有各种 css 样式的样式文件。
与 html 文件一样,浏览器会将该文件通过一系列的转换和解析构建出 CSS 对象模型,即 CSS Rule Tree。
3.构建渲染树(Render Tree)
DOM Tree 描述的是文档内容,而 CSS Rule Tree 描述的是应用于文档的样式规则,二者是独立的对象。浏览器会把 DOM Tree 和 CSS Rule Tree 组合起来构建渲染树,即 Render Tree。
构建渲染树的过程如下:
从 DOM Tree 的根节点开始,遍历每个可见的节点(某些不可见的节点如 script 标签、meta 标签等和某些通过 CSS 隐藏的节点如应用了 display:none 规则的节点不会体现在渲染结果中,因此会被忽略),为每一个可见的节点匹配并应用对应的 CSSOM 规则,生成有内容和计算样式的可见节点的树。
4.布局(layout)
构建完渲染树后,浏览器便会从渲染树的根节点开始遍历,计算页面上每个对象的几何信息,这一个过程称为布局。布局输出的是一个个‘盒子模型’,它精确的计算出每个元素在视口中的准确位置及尺寸大小。
5.绘制(painting)
最后一步是绘制,绘制即将渲染树中的每个节点绘制成实际的像素点。
三.回流(reflow)和重绘(repaint)
回流(reflow):当页面中某些元素发生变化而影响了布局时(如尺寸、位置改变),就会发生回流,浏览器需要重新布局并绘制。
重绘(repaint):当页面中某些元素发生了不影响布局的变化时(如颜色改变),就会发生重绘,浏览器需要重新绘制。
注:由于回流一定会包括重绘,所以回流会更影响性能,所以在实际操作中,要尽量减少回流。
四.引用总结
在网上看到一段对浏览器渲染网页总结的一个有趣版本,在此引用,希望让大家对浏览器渲染网页的过程有一个更深刻的印象:
- 用户输入网址(假设是个 html 页面,并且是第一次访问),浏览器向服务器发出请求,服务器返回 html 文件;
- 浏览器开始载入 html 代码,发现<head>标签内有一个<link>标签引用外部 css 文件;
- 浏览器又发出 css 文件的请求,服务器返回这个 css 文件;
- 浏览器继续载入 html 中<body>部分的代码,并且 css 文件已经拿到手了,可以开始渲染页面了;
- 浏览器在代码中发现一个<img>标签引用了一张图片,向服务器发出请求,此时浏览器不会等到图片下载完,而是继续渲染后面的代码;
- 服务器返回图片文件,由于图片占用了一定面积,影响了后面段落的排布,因此浏览器需要回过头来重新渲染这部分代码;
- 浏览器发现了一个包含一行 Javascript 代码的<script>标签,赶快运行它;
- Javascript 脚本执行了这条语句,它命令浏览器隐藏掉代码中的某个<div> (style.display=”none”)。突然少了这么一个元素,浏览器不得不重新渲染这部分代码;
- 终于等到了</html>的到来,浏览器泪流满面;
- 等等,还没完,用户点了一下界面中的“换肤”按钮,Javascript 让浏览器换了一下<link>标签的 css 路径;
- 浏览器召集了在座的各位<div><span><ul><li>们,“大伙儿收拾收拾行李,咱得重新来过……”,浏览器向服务器请求了新的 css 文件,重新渲染页面。