输入URL后发生了什么
- 首先,浏览器进程接收到用户输入的 URL 请求,浏览器进程便将该 URL 转发给网络进程。
- 然后,在网络进程中发起真正的 URL 请求。
- 接着网络进程接收到了响应头数据,便解析响应头数据,并将数据转发给浏览器进程。
- 浏览器进程接收到网络进程的响应头数据之后,发送“提交导航 (CommitNavigation)”消息到渲染进程;
- 渲染进程接收到“提交导航”的消息之后,便开始准备接收 HTML 数据,接收数据的方式是直接和网络进程建立数据管道;
- 最后渲染进程会向浏览器进程“确认提交”,这是告诉浏览器进程:“已经准备好接受和解析页面数据了”。
- 浏览器进程接收到渲染进程“提交文档”的消息之后,便开始移除之前旧的文档,然后更新浏览器进程中的页面状态。
Chrome目前的多进程架构
- 浏览器进程: 主要负责界面显示、用户交互、子进程管理,同时提供存储等功能。
- 渲染进程: 核心任务是将 HTML、CSS 和 JavaScript 转换为用户可以与之交互的网页,排版引擎 Blink 和 JavaScript 引擎 V8 都是运行在该进程中,默认情况下,Chrome 会为每个 Tab 标签创建一个渲染进程。出于安全考虑,渲染进程都是运行在沙箱模式下。
- GPU 进程:其实,Chrome 刚开始发布的时候是没有 GPU 进程的。而 GPU 的使用初衷是为了实现 3D CSS 的效果,只是随后网页、Chrome 的 UI 界面都选择采用 GPU 来绘制,这使得 GPU 成为浏览器普遍的需求。最后,Chrome 在其多进程架构上也引入了 GPU 进程。
- 网络进程:主要负责页面的网络资源加载,开始是作为一个模块运行在浏览器进程里面的,后来独立出来,成为一个单独的进程。
- 插件进程: 主要是负责插件的运行,因插件易崩溃,所以需要通过插件进程来隔离,以保证插件进程崩溃不会对浏览器和页面造成影响。
复杂的渲染进程
按照渲染的时间顺序,整个渲染可以分为下面几个阶段:
1、构建DOM树
可以在浏览器中输入document更直观的查看DOM树的结构。
2、样式计算(Recalculate Style)
样式计算大体包含三个步骤:
- 把CSS文件解析成浏览器可理解的结构—styleSheets,浏览器中输入document.styleSheets可以查看
- 转换样式表中的标准值,使其标准化。例如把rem转换成px。
- 根据CSS的
继承规则和层叠规则计算出每个DOM节点的具体样式,最终输出的内容保存在元素的ComputedStyle属性中。
3、布局
布局大概分为两个阶段:
-
遍历DOM树中的可见节点,创建布局树
- 进行布局计算(后面单独解释)
4、分层
因为页面中有很多复杂的效果,浏览器为了方便实现这些效果,会对像PhotoShop一次样对页面进行分层,并生成一棵图层树(LayerTree),具体的分层规则可以参考[MDN层叠上下文](developer.mozilla.org/zh-CN/docs/…)
5、图层绘制
图层绘制是通过一条条简单的指令完成的,在Chrome控制台中可以打开Layer标签查看页面中的具体指令。例如下图是百度翻译的绘制指令:
6、栅格化(raster)操作
栅格化会在合成线程上进行,简单来说就是把图层划分成多个图块(tile),通常是256 x 256或者512 x 512。然后将其转化为位图。具体流程如图:
通常光栅化会在GPU中进行,也叫快速光栅化。
7、合成和显示
光栅化完成后,和合成线程会向浏览器进程发送一个DrawQuad命令,浏览器进程收到命令后会将页面内容绘制到内存中,最后将内存显示在屏幕上。
总结一下
- 根据HTML内容生成DOM树
- 根据CSS样式表生成styleSheets,计算DOM节点样式
- 生成布局树,计算布局信息
- 对布局进行分层,生成分层树
- 为每个图层生成绘制列表,并将其提交到合成线程
- 合成线程将图层分块,并通过光栅化将其转化为位图
- 合成线程发送
DrawQuad命令给浏览器进程 - 浏览器进程根据
DrawQuad消息生成页面,并将其显示到屏幕上
根据上面的流程分析下重排、重绘、布局的性能:
- 重排:诸如删除元素、改变元素宽高等影响页面布局的行为会发生重排。它需要完整更新上面8个步骤,因此相比之下重排的开销最高。
- 重绘:诸如改变元素颜色等行为会发生重绘。因为它不会改变元素的几何位置,所以省去了布局和分层阶段(上面步骤的1-4),所以开销比重排要小。
- 合成:有些操作既不需要修改布局属性,也不需要修改绘制属性,例如CSS的
transform属性。直接在合成线程上执行合成动画即可。它既不阻塞主线程,又不需要布局和绘制,所以开销很小。