漫漫前端路之浏览器基础——工作流程篇

464 阅读7分钟

浏览器工作流程

image.png

  • 浏览器进程主要负责用户交互,子进程管理和文件储存等功能。
  • 网络进程是面向渲染进程和浏览器继承等提供网络下载功能。
  • 渲染进程的主要职责是把从网络下载的HTML、JavaScript、CSS和图片等资源解析为可以显示和交互的页面。因为渲染进程的内容都是从网络获取的,可能会存在一些恶意的代码,利用系统的漏洞对系统进行攻击。因此,为了保证系统安全,渲染进程是运行在安全沙箱内的。

大致流程

  1. 首先,浏览器进程接收到用户输入url的请求,浏览器进程会将该url转发给网络进程。
  2. 然后,在网络进程中发起url请求。
  3. 接着网络进程接收到响应头数据,便开始解析响应头数据,并将数据转发给浏览器进程。
  4. 浏览器进程在接收到网络进程的响应头数据时,发送“提交文档”消息到渲染进程;
  5. 渲染进程在接收到“提交文档”的信息后,便开始准备接受Html数据,接受数据的方式是直接跟网络进程建立数据管道。
  6. 等文档数据传输完成之后,渲染进程会向浏览器进程“确认提交”;
  7. 浏览器进程在接收到渲染进程“确认提交”的消息之后,便开始移除之前的文档,然后更新浏览器进程中的页面状态。

用户输入

  1. 用户输入url敲回车后,浏览器需要先检查输入(是否符合url规则),组装完整的url,例如,用户输入baidu,浏览器会自动组装完整的baidu.com。
  2. 在用户按下回车,浏览器加载新页面之前,当前页面还会执行beforeUnload事件;该事件允许页面在退出之前执行一些数据清理的操作,还可以再次询问用户是否确认离开当前页面;例如,当前页面中还存有未提交的表单等;
  3. 在用户确认后,浏览器将进入加载状态;

url请求

image.png

  1. 浏览器进程通过IPC把url请求发至网络进程。
  2. 查询有效期内的资源缓存;
  3. 准备IP地址和端口【DNS(domain name system)解析——解析url中域名对应的ip地址】
  4. 进入tcp队列(http1.0/1.1单个域名TCP连接数量限制)
  5. 创建tcp连接(三次握手)
  6. https建立TLS连接;
  7. 发送HTTP请求(请求行【协议 url 方法】 请求头 请求体)
  8. 接收请求(响应行【协议 状态码 状态消息】 响应头 响应体 )

准备渲染进程

根据是否为同一站点(相同协议和根域名)决定是否复用渲染进程

提交文档

  1. 浏览器进程在接收到网络进程的响应头数据时,发送“提交文档”消息到渲染进程;
  2. 渲染进程在接收到“提交文档”的信息后,便开始准备接受Html数据,接受数据的方式是直接跟网络进程建立数据管道。
  3. 等文档数据传输完成之后,渲染进程会向浏览器进程“确认提交”;
  4. 浏览器进程在接收到渲染进程“确认提交”的消息之后,便开始移除之前的文档,更新界面,地址栏,导航历史信息等等。
  5. 此时标识浏览器加载状态的小圆圈,从此前url网络请求时的逆时针即将变为顺时针旋转。

渲染

image.png

从渲染流程看为什么CSS动画比JS动画高效

在写 Web 应用的时候,经常需要对元素进行几何变化的一些操作,若使用js实现动画效果,会牵涉到整个渲染流水线,所以JS的效率低下。反之,这时可用will-change属性告诉渲染引擎需要对元素进行几何性质的变化,例如

.box {
will-change: transform, opacity;
}
  • 这时候渲染引擎会将该元素单独创建一层,等这些变换发生时,渲染引擎会通过合成线程直接去处理变换,这些变换并没有涉及到主线程,这样就大大提升了渲染的效率。这也是 CSS 动画比 JavaScript 动画高效的原因。但是凡事都有两面性,每当渲染引擎为一个元素准备一个独立层的时候,它占用的内存也会大大增加,因为从层树开始,后续每个阶段都会多一个层结构,这些都需要额外的内存,所以你需要恰当地使用 will-change。
  • 能直接在合成线程中完成的任务都不会改变图层的内容,如文字信息的改变,布局的改变,颜色的改变,统统不会涉及,涉及到这些内容的变化就要牵涉到重排或者重绘了。能直接在合成线程中实现的是整个图层的几何变换,透明度变换,阴影等,这些变换都不会影响到图层的内容。比如滚动页面的时候,整个页面内容没有变化,这时候做的其实是对图层做上下移动,这种操作直接在合成线程里面就可以完成了。

构建DOM树

image.png

样式计算

  1. 把 CSS 转换为浏览器能够理解的结构stylesheets(可通过document.stylesheets查看)
  2. 转换样式表中的属性值,使其标准化
  3. 计算出 DOM 树中每个节点的具体样式(继承性与层叠性)
  • css来源:link引入、标签内、元素style属性

布局阶段

  1. DOM & CSSOM合成渲染树;
  2. 创建布局树(DOM中的可见节点)
  3. 布局计算(又计算每个元素的几何坐标位置,并将这些信息保存在布局树中)

分层

特定节点生成专用图层,生成一颗图层树(层叠上下文、clip、类似ps里面的图层)【为了方便实现一些复杂的的效果,如3D变换、页面滚动、还有一些用z-indexing做z轴排序效果】 image.png 通常情况下,并不是布局树的每个节点都包含一个图层,如果一个节点没有对应的层,那么这个节点就从属于父节点的图层。单独为特定节点创建图层的条件:

  • 拥有层叠上下文属性(明确定位属性、透明属性、css滤镜、z-index等)的元素会创建单独图层;
  • 需要单独裁剪的地方会创建图层;

图层绘制

渲染引擎会将图层树中每个图层的绘制拆成绘制指令,生成绘制列表,提交到合成线程。

栅格化

image.png

  1. 合成线程会将图层划分为图块(tile),这些图块的大小通常是 256x256 或者 512x512。
  2. 栅格化将视口附近的图块生成位图。 所谓栅格化,是指将图块转换为位图,因此图块是栅格化执行的最小单位。 渲染进程维护了一个栅格化的线程池,所有的图块栅格化都是在线程池内执行的,如图 image.png
  • 通常,栅格化过程都会使用 GPU 来加速生成,使用 GPU 生成位图的过程叫快速栅格化,或者 GPU 栅格化,生成的位图被保存在 GPU 内存中。
  • 渲染进程把生成图块的指令发送给 GPU,然后在 GPU 中执行生成图块的位图,并保存在 GPU 的内存中。

合成和显示

  1. 一旦所有图块都被光栅化,合成线程就会生成一个绘制图块的命令——“DrawQuad”,然后将该命令提交给浏览器进程。
  2. 浏览器进程里面有一个叫 viz 的组件,用来接收合成线程发过来的 DrawQuad 命令,然后根据 DrawQuad 命令,将其页面内容绘制到内存中,最后再将内存显示在屏幕上。

资料来源

time.geekbang.org/column/intr…