图解浏览器渲染引擎工作原理(进阶必备知识)

758 阅读3分钟

这是我参与8月更文挑战的第15天,活动详情查看:8月更文挑战

TIP 👉 饭疏食,饮水,曲肱而枕之,乐亦在其中矣。不义而富且贵,于我如浮云。——《论语》

前言

这块东西非常容易作为性能优化面试题的切入点,大家需要引起重视。

渲染引擎是干什么的

渲染引擎的职责就是渲染,即在浏览器窗口中显示所请求的内容。默认情况下,呈现引擎可显示 HTML 和 XML 文档与图片。通过插件(或浏览器扩展程序),还可以显示其他类型的内容;例如,使用 PDF 查看器插件就能显示 PDF 文档。但是在本章中,我们将集中介绍其主要用途:显示使用 CSS 格式化的 HTML 内容和图片。

不同的浏览器有不同的渲染引擎,Firefox 使用的是 Gecko,这是 Mozilla 公司“自制”的呈现引擎。而 Safari 和 Chrome 浏览器使用的都是 WebKit。

渲染引擎工作流解析

image.png

中间这个“渲染引擎处理”,它其实包含了以下几个具体流程:

image.png

整体来看,这五个过程分别完成了以下任务:

1. HTML解析

在这一步浏览器对HTML文档进行解析,并在解析 HTML 的过程中发出了页面渲染所需的各种外部资源请求。

2. CSS解析

浏览器将识别并加载所有的 CSS 样式信息。

3. 样式与结构合并

将样式信息和文档结构合并,最终生成页面 render 树(:after :before 这样的伪元素会在这个环节被构建到 DOM树中)。

4. 布局阶段

页面中所有元素的相对位置信息,大小等信息均在这一步得到计算。

5. 页面绘制

在这一步中浏览器会根据我们前面处理出来的结果,把每一个页面图层转换为像素,并对所有的媒体文件进行解码。

这五个流程分别对应了以下五个产物:

  • DOM树
  • CSSOM树
  • 渲染树
  • 盒模型
  • 目标界面

示例:

image.png

HTML解析DOM树

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>青莲使者</title>
<style> 
body {
    font-size: 20px;
}
div {
    width: 100px; 
    height: 100px;
}
span {
    color: #000;
}
p {
    display: none
}
</style>
</head>
<body>
    <div class="box1">
        <span>我在盒子1号里</span>
    </div>
    <div class="box2">
        <span>我在盒子2号里</span>
    </div>
    <p>测试测试测试</p>
</body>
</html>

DOM树:

1629252011941.png

CSS解析CSSOM树

CSSOM也是具有树结构的,在样式计算的过程中,浏览器总是从适用于该节点的最通用规则开始,例如div节点是body元素的子节点,则应有所有body的样式,一层一层递归细化出具体的样式。具体的树结构:

image.png

DOM树与CSSOM树“合体”————渲染树

当DOM树和CSSOM树都解析完毕后,它们就会被结合在一起,构建出Render Tree(渲染树)。

  • 从DOM树的根节点开始遍历。筛选出所有可见的节点
  • 仅针对可见节点,为其匹配CSSOM中的CSS规则
  • 发射可见节点

渲染树:

image.png

布局盒子模型

节点应该出现在浏览器视口的哪个位置上、占据多大的空间,计算这些信息,就是布局阶段要做的事情。浏览器对渲染树进行遍历,将元素间嵌套关系以盒子模型的形式写入文档流:

image.png

盒模型在布局过程中会计算出元素确切的大小和定位。计算完毕后,相应的信息被写会渲染树上,就形成了“布局渲染树”。同时,每一个元素盒子也都携带着自身的样式信息,作为后续绘制的依据。

目标界面

走到这一步,浏览器的视窗内实际上还是啥都没展示出来,渲染树也好,盒模型也好,它们都在内存世界里,布局阶段结束后,浏览器终于拿到了它绘制页面所需的所有信息。此时它会将渲染树上的每一个节点转换成我们肉眼可见的像素,最终将页面呈现在我们面前,这个过程就是“绘制”。绘制完成,界面就出现在界面上了:

image.png