优化/前端/源码

浏览器原理学习笔记01—宏观视角下的浏览器

csxiaoyao · 5月2日 · 2020年 本文3320字 · 阅读9分钟136

浏览器原理学习笔记01—宏观视角下的浏览器

Write By CS逍遥剑仙
我的主页: csxiaoyao.com
GitHub: github.com/csxiaoyaojianxian
Email: sunjianfeng@csxiaoyao.com
QQ: 1724338257

1. 起步

前端知识的深入绕不开浏览器原理的学习,本系列文章为笔者学习浏览器原理后整理的笔记,学习的过程以极客时间《浏览器工作原理与实践》为主线,对原文的重要知识点进行了归纳整理,针对其中的部分细节知识点查阅了大量资料进行扩展并梳理总结,其中有部分demo和图片参考自原文。

2. Chrome架构演进

浏览器三大进化路线:应用程序 Web 化,Web 应用移动化,Web 操作系统化。早在2007年之前,市面上浏览器都是单进程的,即浏览器所有的功能模块运行在同一个进程中,因此不稳定、不流畅、不安全。

2.1 2008年发布时的进程架构

浏览器原理学习笔记01—宏观视角下的浏览器-禅林阆苑

2008年发布的 Chrome 拆分为 3 种进程,除主进程外,页面运行在单独的渲染进程中,同时页面里的插件运行在单独的插件进程中,而进程间通过 IPC 机制进行通信(图中虚线部分)。

2.2 目前多进程架构

浏览器原理学习笔记01—宏观视角下的浏览器-禅林阆苑

最新的 Chrome 浏览器包括 5 类进程:

  • 浏览器进程 x1:负责界面显示、用户交互、子进程管理、存储等功能
  • 渲染进程 xn:将 HTML、CSS 和 JavaScript 转换为可交互的网页,运行着排版引擎 Blink 和 JavaScript 引擎 V8。Chrome 默认为每个 Tab 标签创建一个渲染进程并运行在沙箱模式下
  • GPU 进程 x1:浏览器使用 GPU 初衷是为了实现 3D CSS 效果,随后网页、Chrome 的 UI 界面都普遍采用 GPU 来绘制,因此独立出 GPU 进程
  • 网络进程 x1:独立出来负责页面网络资源加载
  • 插件进程 xn:插件易崩溃,因此需要通过插件进程来隔离插件的运行

打开 1 个页面,至少有 4 个进程:浏览器进程、网络进程、GPU 进程、渲染进程,可能有插件进程。

2.3 未来面向服务(SOA)的架构

浏览器原理学习笔记01—宏观视角下的浏览器-禅林阆苑

为了解决 资源占用体系架构复杂 的问题,Chrome 官方团队2016 年使用 SOA 思想设计了新的 Chrome 架构,原来的模块会被重构成独立的服务,每个服务在独立的进程中运行,使用定义好的接口访问服务,通过 IPC 通信。

同时在性能受限的设备上 Chrome 还提供灵活的弹性架构,会将很多服务整合到一个进程中,从而节省内存占用。

浏览器原理学习笔记01—宏观视角下的浏览器-禅林阆苑

3. TCP协议

浏览器原理学习笔记01—宏观视角下的浏览器-禅林阆苑

图为简化的 TCP 网络四层传输模型,UDP与之相似,不同之处在于 TCP 头的信息保证了大数据块传输的完整性、可靠性,但牺牲了数据包的传输速度,三次握手数据包排序校验机制 等过程把传输过程中数据包的数量提高了一倍。

浏览器原理学习笔记01—宏观视角下的浏览器-禅林阆苑

4. HTTP请求流程

HTTP 协议是建立在 TCP 连接基础之上的一种允许浏览器向服务器获取资源的协议。

浏览器原理学习笔记01—宏观视角下的浏览器-禅林阆苑

4.1 浏览器端发起 HTTP 请求流程

  1. 构建请求

    构建请求行信息,如 GET /index.html HTTP1.1

  2. 查找缓存

  3. 准备 IP 地址和端口

    使用 DNSDNS缓存 获取对应IP

  4. 等待 TCP 队列

    Chrome TCP 队列机制:同一域名最多只能同时建立 6 个 TCP 连接,超出的请求会排队等待

  5. 建立 TCP 连接

  6. 发送 HTTP 请求

浏览器原理学习笔记01—宏观视角下的浏览器-禅林阆苑

4.2 服务器端处理 HTTP 请求流程

  1. 返回请求

    浏览器原理学习笔记01—宏观视角下的浏览器-禅林阆苑

  2. 断开连接

  3. 重定向特殊情况

    浏览器原理学习笔记01—宏观视角下的浏览器-禅林阆苑

4.3 浏览器资源缓存(cache)处理

浏览器会在服务器返回时根据响应头中的 Cache-Control 字段的过期时长来设置资源缓存,下次请求直接读取未过期缓存。若缓存过期,浏览器则会发起网络请求,并在 HTTP 请求头 中带上资源 key,如:If-None-Match:"4f80f-13c-3a1xb12a",服务器根据资源 key 值判断请求的资源是否有更新,若没有更新则仅返回 304 状态码,有更新则直接返回最新资源。

浏览器原理学习笔记01—宏观视角下的浏览器-禅林阆苑

4.4 登录状态保持(cookie)

登录成功后会生成标识用户身份的字符串并写到响应头的 Set-Cookie 字段里,浏览器解析存到本地,下次请求自动在请求头的 Cookie 字段中添加该值。

浏览器原理学习笔记01—宏观视角下的浏览器-禅林阆苑

5. 导航流程:从输入URL到页面展示

浏览器原理学习笔记01—宏观视角下的浏览器-禅林阆苑

  1. 用户输入

  2. URL 请求

  3. 准备渲染进程

    Chrome 默认会为每个打开的页面分配一个渲染进程,但如果新页面和当前页面属于同一站点(根域名+协议相同)则会复用父页面的渲染进程(process-per-site-instance)。

  4. 提交文档

    此处 文档 是指 URL 请求的响应体数据,浏览器进程发出 提交文档消息,渲染进程接收到后会和网络进程建立传输数据的 管道,文档数据传输完成后渲染进程返回 确认提交消息 给浏览器进程,浏览器进程更新浏览器界面状态,并更新 Web 页面。

  5. 渲染阶段

6. 渲染流程

下面将依次从 DOM、Style、Layout、Layer、Paint、Tiles & Raster、DrawQuad 分析渲染流程,详见《浏览器中的页面渲染》。

浏览器原理学习笔记01—宏观视角下的浏览器-禅林阆苑

6.1 DOM: 构建 DOM 树

document 即 DOM 结构,区别于 HTML 的是,DOM 是保存在内存中的树状结构,可通过 JavaScript 来查询或修改其内容。

浏览器原理学习笔记01—宏观视角下的浏览器-禅林阆苑

6.2 Style: 样式计算

6.2.1 格式转换

当渲染引擎接收到 CSS 文本时(link外部文件、style标签内、内联样式),会执行转换操作将 CSS 文本转换为浏览器可以理解的结构(styleSheets),在浏览器的 console 中可输入命令 document.styleSheets 查看。

6.2.2 标准化属性值

浏览器原理学习笔记01—宏观视角下的浏览器-禅林阆苑

6.2.3 计算 DOM 树中每个节点的具体样式

根据 CSS 的 继承层叠 规则计算每个 DOM 节点的样式并被保存在 ComputedStyle 结构内,可在开发者工具内查看。

浏览器原理学习笔记01—宏观视角下的浏览器-禅林阆苑

6.3 Layout: 布局阶段

除了 DOM 树和 DOM 树中元素的样式,显示页面还需要通过创建 布局树 和布局计算来得到 DOM 元素的几何位置信息。

6.3.1 创建布局树

在显示之前还要额外地构建一棵只包含可见元素布局树,遍历 DOM 树中的所有可见节点加到布局中。

浏览器原理学习笔记01—宏观视角下的浏览器-禅林阆苑

6.3.2 布局计算

计算布局树节点的坐标位置的计算过程非常复杂,此处略过,执行布局操作时会把布局运算的结果重新写回布局树中,所以布局树既是输入内容也是输出内容,不合理,Chrome 下一代布局系统 LayoutNG 将解决这个问题。

6.4 Layer: 分层

创建布局后,渲染引擎还要为特定的节点生成专用的图层,并生成对应的图层树(LayerTree),在后面章节会介绍。

浏览器原理学习笔记01—宏观视角下的浏览器-禅林阆苑

布局树的节点默认从属于父节点图层,满足下面两点中一点的元素可被提升为单独的一个图层:

  1. 拥有层叠上下文属性

    明确定位属性、定义透明属性、使用 CSS 滤镜等的元素拥有层叠上下文属性。

    浏览器原理学习笔记01—宏观视角下的浏览器-禅林阆苑

  2. 需要剪裁(clip)的内容

    当内容展示不下被隐藏或出现滚动条时,内容部分会单独创建一个层。

    浏览器原理学习笔记01—宏观视角下的浏览器-禅林阆苑

6.5 Paint: 图层绘制,生成绘制列表

渲染引擎会对图层树中的每个图层进行绘制,首先会生成绘制列表,可以在开发者工具的 Layers 标签中选择 document 层查看实际绘制列表。

Tips:

图层绘制并非真正绘出帧图片,而是生成绘制指令列表,绘制过程即完成

浏览器原理学习笔记01—宏观视角下的浏览器-禅林阆苑

6.6 Tiles & Raster: 图块划分 & 栅格化操作

绘制列表只是用来记录绘制顺序和指令,主线程会把该绘制列表 提交{commit) 给渲染引擎中的 合成线程 进行实际绘制操作。有的图层很大很长,但用户通过 视口(viewport)只能看到页面的很小一部分,为了减小开销,合成线程会将图层划分为 图块(tile),通常大小为 256×256 或 512×512,合成线程会优先把视口附近的图块栅格化转换成位图。

浏览器原理学习笔记01—宏观视角下的浏览器-禅林阆苑

6.7 DrawQuad: 合成和显示

当所有图块都被光栅化,合成线程会生成绘制图块命令 DrawQuad 并提交给浏览器进程。浏览器进程里的 viz 组件根据 DrawQuad 消息绘制到内存中,最后显示在显示器上。

7. 重排 / 重绘 / 合成

浏览器原理学习笔记01—宏观视角下的浏览器-禅林阆苑

使用 CSS 的 transform 实现动画效果可以避开重排和重绘,直接在非主线程上执行合成动画操作,并不会占用主线程的资源,效率较高,在页面章节会深入讲解。

减少重排重绘的方法:

  1. 使用 class 操作样式,而不是频繁操作 style
  2. 避免使用 table 布局
  3. 批量处理 dom 操作,例如 createDocumentFragment,或使用框架的虚拟DOM
  4. 对 resize 等事件防抖处理
  5. dom 属性读写分离
  6. 使用 will-change: transform 做优化

浏览器原理学习笔记01—宏观视角下的浏览器-禅林阆苑

0 条回应

×