浏览器URL输入到页面展示

用户输入

  1. 用户在地址栏按下回车,检查输入(关键字 or 符合 URL 规则),组装完整 URL
  2. 确认前(点击回车),当前页面执行 onbeforeunload 事件
  3. 浏览器进入加载状态

URL请求

  1. 浏览器进程通过 进程间通信(IPC)把URL请求发送至网络进程
  2. 查找资源缓存

网络进程会查找本地缓存是否缓存了在有效期内的资源,若有,则返回到浏览器进程

  1. DNS解析(查询 DNS 缓存)
  2. 进入 TCP 队列(单个域名 TCP 连接数量限制)
  3. 创建 TCP 连接(三次握手)
  4. 如果是HTTPS,则 HTTPS 建立 TLS 连接(client hello, server hello, pre-master key 生成『对话密钥』)
  5. 发送 HTTP 请求(请求行方法、URL、协议、请求头 Cookie 等,请求体 POST)
  6. 服务端接受请求并响应(响应行协议、状态码、状态消息、响应头、响应体等)

状态码 301 / 302,根据响应头中的 Location 重定向,重新开始从开始全过程
状态码 200,根据响应头中的 Content-Type 决定如何响应(下载文件、加载资源、渲染 HTML)

  1. 准备渲染

准备渲染进程

  1. 根据是否为同一进程(相同的协议和根域名),决定是否复用渲染进程
  2. 浏览器进程接收到网络进程的响应头数据,向渲染进程发送『提交文档』消息
  3. 渲染进程收到『提交文档』消息后,与网络进程建立传输数据的『通道』
  4. 传输完成后,渲染进程返回『确认提交』消息给浏览器进程
  5. 浏览器接收『确认提交』消息后,移除旧文档,更新界面、地址栏、历史导航状态等
  6. 开始渲染

渲染

渲染流水线

构建DOM树

  1. 渲染引擎接收HTML文档数据
  2. HTML解析器解析数据
  3. 输出DOM数据结构(DOM树)

样式计算

  1. 渲染引擎接收CSS文本数据

css样式来源: link引用的外部样式
<style>标记内的的css
元素内联样式

  1. 将CSS文本转换为styleSheets(样式表)
  2. 将样式表中属性值标准化,(生成DOM树后)依据样式表计算每个节点的具体样式(层叠、继承等,并保存在 ComputedStyle 结构中)
  3. 输出styleSheets(CSSOM)

布局

计算DOM中可见元素的几何位置

  1. 创建布局树(遍历DOM树中的所有可见节点,并把这些节点加入到布局树中)
  2. 根据样式表等进行布局计算,结果写入布局树
  3. 最终生成布局树(render tree)

分层

  1. 将布局树依据规则分成图层

拥有层叠上下文属性的元素会被提升为单独一层(明确定位属性、透明属性、CSS滤镜、z-index等) 需要裁剪的地方会创建图层 没有图层的DOM节点从属于父节点图层

  1. 最终生成图层树(LayerTree)

绘制

渲染引擎对每个图层进行绘制

  1. 每一个图层对应生成一个绘制列表(图层的绘制会拆分为很多绘制指令,绘制指令按照顺序组成绘制列表)
  2. 将绘制列表提交给合成线程
  3. 合成线程将图层划分为图块
  4. 光栅化,将图块转换为位图

优先生成视口附近的位图 图块栅格化在栅格化线程池中进行 通常,栅格化过程会使用GPU加速,图块生成的位图会保存在GPU内存

  1. 光栅化完成后,合成线程生成绘制图块的命令---DrawQuad,并提交给浏览器进程
  2. viz组件接收命令,将内容绘制到内存中(显存的后缓存区)
  3. 最终显示到显示器上

主线程:DOM树、计算样式、布局、分层、绘制
非主线程:图层转换图块、光栅化、DrawQuad、显示

相关概念

重排

更新元素的几何属性

通过js或者css修改元素的几何位置(宽高等),浏览器触发重新布局

重排需要更新完整的渲染流水线,开销最大

重绘

更新元素的绘制属性

修改元素的绘制属性(背景颜色等),会跳过布局阶段(布局和分层),直接进入绘制阶段

重绘开销相对重排较小,但也有消耗

合成

更改既不需要布局也不需要绘制的属性,会跳过布局和绘制阶段,只执行非主线程的合成操作(css的transform等)

合成操作不占用浏览器主线程,相较重排和重绘效率极大提升

上次更新:
贡献者: QingYiXiaoYao