# 浏览器的渲染原理
其实,这个题目用来回答这道经典面试题《在浏览器里,从输入URL到页面展示,这中间发生了什么?
》也是一样的。
# 浏览器的进程
首先,先简单说下浏览器的进程。以chrome
为例,是多进程模型,一般有以下几个进程:
- 浏览器进程。主要负责用户交互、子进程管理和文件存储等功能。
- UI线程。控制浏览器上的按钮及输入框
- 存储线程。控制文件等的访问
- 渲染进程。主要负责把
html
、js
、css
、图片等资源解析为可以显示和交互的页面。运行在安全沙箱里,为了保障系统的安全。JavaScript
引擎线程。与GUI
线程互斥。GUI
渲染线程- 定时触发器线程
- 事件触发线程
- 异步http请求线程
- 一个合成器线程
- 多个光栅化线程
- GPU进程。
- 插件进程。
- 网络进程。面向渲染进程、浏览器进程提供网络下载功能。
多进程
优点:提升了浏览器的稳定性、流畅性和安全性。
- 更高的容错性
- 更高的安全性和沙盒性(sanboxing)
- 更高的响应速度
缺点是:资源占用大,体系架构复杂
# 请求步骤
可以分成以下几个步骤:
# 浏览器进程接收到用户输入的URL
- 判断是否搜索内容。如果是使用搜索引擎,合成新的URL。
- 如果当前正处于某页面,让当前页执行
beforeunload
事件的退出操作。 - 浏览器进程把
URL
转发给网络进程。
# 网络进程中发起真正的URL请求
- 判断是否有缓存。有的话,直接返回资源给浏览器进程。
- 进行
DNS
域名解析。如果是https
,还得建立TLS
连接。 TCP
连接。三次握手,向服务器发送构建的请示信息。如果是http1.1
协议,一个站点会开启6个连接,如果是http2.0
,只会发起一个。- 服务器生成响应数据,再发送给
网络进程
。 - 网络进程接收到响应头数据。
- 判断状态码。如果需要重定向,则根据返回的
location
字段跳转,重新发起请求。 - 判断响应数据类型。如果是字节流,进行下载,本次导航结束。
- 解析数据,转发给浏览器进程。
- 判断状态码。如果需要重定向,则根据返回的
# 准备渲染进程
检查是否同一站点。相同的协议和根域名,就被认为是同一站点。
如果是,则复用一个进程。否则,会新开一个进程。
当然,这只是chrome
的默认策略,也可以进行修改。此处不再赘述。
# 提交文档
- 浏览器进程收到网络进程的响应头数据后,向渲染进程发起提交文档的消息
- 渲染进程和网络进程建立传输数据的管道
- 等文档数据传输完成后,渲染进程返回确认提交的消息给浏览器进程。这是告诉浏览器进程:已经准备好接收和解析页面数据了。
- 浏览器进程更新浏览器界面状态。
- 安全状态
- 地址栏的url
- 前进后退的历史状态
- 更新web页面
# 渲染阶段
- 构建
DOM树
。DOM 树
是由DOM
元素及属性节点组成的。 - 样式计算。
- 把css转换为浏览器所能理解的结构(
styleSheets
) - 转换样式表中的属性值,使其标准化
- 计算出DOM树中每个节点的具体样式
- 把css转换为浏览器所能理解的结构(
- 布局阶段。
- 创建布局树。添加可见节点,忽略不可见节点。
- 布局计算。
- 分层阶段。
- 拥有层叠上下文属性的元素会被提升为单独一层
- 需要裁剪的地方也会被创建为图层
- 绘制阶段。
- 提供一个有绘制指令的绘制列表。
- 光栅化
- 主线程把绘制列表提交给合成线程
- 合成线程按照视口附近的图块优先生成位图
- 合成线程把图层划分为图块
- 实际生成位图的操作是由栅格化来执行的
- 所谓栅格化,就是指将图块转换为位图
- 使用GPU生成位图的过程叫快速栅格化,生成的位图保存在GPU内存
- 合成与显示
- 合成线程生成一个绘制图块的命令
- 提交命令给浏览器进程
- 浏览器进程绘制页面内容到内存
- 将内存显示到屏幕
注:本文主要参考李兵老师的《浏览器工作原理与实践 (opens new window)》,严重推荐。