浏览器架构、渲染原理与页面优化

注:以下内容来自于极客时间李兵老师的《浏览器工作原理与实践》课程总结

浏览器架构

多进程架构

概述

现代浏览器采用多进程架构的模式,一般而言,一个页面会是一个渲染进程(可能存在同一站点same-site多页面复用同一个渲染进程的情况),另外,还有浏览器的主进程、GPU进程、网络进程、插件进程等等。如下图
浏览器架构、渲染原理与页面优化_第1张图片

各个进程的功能
  • 主进程:主要负责界面显示、用户交互、子进程管理,同时提供存储等功能。
  • 渲染进程:核心任务是将 HTML、CSS 和 JavaScript 转换为用户可以与之交互的网页,排版引擎 Blink 和 JavaScript 引擎 V8 都是运行在该进程中,默认情况下,Chrome 会为每个 Tab 标签创建一个渲染进程。出于安全考虑,渲染进程都是运行在沙箱模式下。
  • GPU 进程:其实,Chrome 刚开始发布的时候是没有 GPU 进程的。而 GPU 的使用初衷是为了实现 3D CSS 的效果,只是随后网页、Chrome 的 UI 界面都选择采用 GPU 来绘制,这使得 GPU 成为浏览器普遍的需求。最后,Chrome 在其多进程架构上也引入了 GPU 进程。
  • 网络进程:主要负责页面的网络资源加载,之前是作为一个模块运行在浏览器进程里面的,直至最近才独立出来,成为一个单独的进程。
  • 插件进程:主要是负责插件的运行,因插件易崩溃,所以需要通过插件进程来隔离,以保证插件进程崩溃不会对浏览器和页面造成影响。
回顾单进程浏览器架构

单进程浏览器:浏览器的所有功能模块都是运行在同一个进程里,这些模块包含了网络、插件、JavaScript 运行环境、渲染引擎和页面等。

架构图
浏览器架构、渲染原理与页面优化_第2张图片
单进程架构的缺陷

  • 不稳定:多个线程运行在同一个进程中,尤其是插件线程的崩溃会导致整个进程的崩溃,复杂的JavaScript代码也容易导致页面线程的崩溃,进而导致整个进程的崩溃。所以,单进程架构不稳定。
  • 不流畅
    • 任务的排斥:所有页面的渲染模块、JavaScript 执行环境以及插件都是运行在同一个线程中的,所有页面在同一时刻只能有一个模块可以执行,一旦有耗时任务,则页面的其他任务无法执行,浏览器就会失去响应。
    • 内存泄漏:复杂的页面退出时,内存回收不完全,导致浏览器运行时间越长,会越来越卡顿。
  • 不安全:用C或C++撰写的插件可以获取操作系统的资源,另外,JavaScript脚本也可能获取到一定的系统权限,没有沙箱隔离,有很大的安全隐患。
多进程架构的特点
  • 解决了单进程架构的稳定性、流畅性和安全性相关的问题
  • 带来了更多的资源占用(如所有页面进程都包含有JavaScript执行引擎)
  • 带来了更复杂的体系架构(各模块之间的耦合度高,可扩展性降低)
未来:面向服务的架构(SOA)
  • 模块会被重构成独立的服务(Service)
  • 每个服务(Service)都可以在独立的进程中运行
  • 访问服务(Service)必须使用定义好的接口,通过 IPC 来通信
  • 构建一个更内聚、松耦合、易于维护和扩展的系统

架构如图
浏览器架构、渲染原理与页面优化_第3张图片

浏览器渲染

从输入URL到页面显示的整个流程

浏览器架构、渲染原理与页面优化_第4张图片

整个流程
  • 首先,浏览器进程接收到用户输入的 URL 请求,浏览器进程便将该 URL 转发给网络进程。
  • 然后,在网络进程中发起真正的 URL 请求。
  • 接着网络进程接收到了响应头数据,便解析响应头数据,并将数据转发给浏览器进程。
  • 浏览器进程接收到网络进程的响应头数据之后,发送“提交导航 (CommitNavigation)”消息到渲染进程;
  • 渲染进程接收到“提交导航”的消息之后,便开始准备接收 HTML 数据,接收数据的方式是直接和网络进程建立数据管道;
  • 最后渲染进程会向浏览器进程“确认提交”,这是告诉浏览器进程:“已经准备好接受和解析页面数据了”。
  • 浏览器进程接收到渲染进程“提交文档”的消息之后,便开始移除之前旧的文档(这里就会有白屏出现),然后更新浏览器进程中的页面状态。
导航

从用户输入URL到页面开始解析HTML之间的流程,称为导航。

  • 用户输入:当用户输入URL后,会触发当前页面的beforeunload事件。当前页面如果没有监听 beforeunload 事件或者同意了,则继续后续流程。此时标签页开始显示加载中的图标,同时地址栏也会出现X图标。
  • URL请求:浏览器网络进程开始与服务器通信,获取响应数据。通过对响应头的解析,如果不包含重定向之类的头部信息,则继续处理。如果包含重定向,则根据头部信息重新发出请求。
    • 响应数据类型的处理:浏览器根据头部Content-Type字段来判断是什么类型的响应数据。
      • text/html:HTML页面,继续导航流程,创建渲染进程。
      • application/octet-stream:字节流类型,浏览器会启用下载管理器来下载该类型文件,导航流程结束。
  • 准备渲染进程:默认情况下,Chrome 会为每个页面分配一个渲染进程
    • 同站点页面:浏览器会让多个页面直接运行在同一个渲染进程中。
      • 同一站点:定义为根域名(例如,geekbang.org)加上协议(例如,https:// 或者 http://),还包含了该根域名下的所有子域名和不同的端口。从同一站点的一个页面打开到另一个页面,则这两个页面复用一个渲染进程,称为process-per-site-instance。
  • 提交文档:浏览器进程将网络进程接收到的 HTML 数据提交给准备好的渲染进程。
    • 首先当浏览器进程接收到网络进程的响应头数据之后,便向渲染进程发起“提交文档”的消息;
    • 渲染进程接收到“提交文档”的消息后,会和网络进程建立传输数据的“管道”;
    • 文档数据传输完成之后,渲染进程会返回“确认提交”的消息给浏览器进程;
    • 浏览器进程在收到“确认提交”的消息后,会更新浏览器界面状态,包括了安全状态、地址栏的 URL、前进后退的历史状态,并更新 Web 页面。
  • 开始渲染阶段
渲染

浏览器架构、渲染原理与页面优化_第5张图片

渲染流程很复杂,输入的HTML以及CSS、JavaScript最终经过渲染流程转化为像素显示出来。将渲染流程划分为一系列子阶段来剖析整个流程,即渲染流水线。
浏览器架构、渲染原理与页面优化_第6张图片

渲染流水线构建 DOM 树、样式计算、布局阶段、分层、绘制、分块、光栅化、合成 这些阶段。

  • 构建DOM树:经HTML解析器,将HTML文档转换为DOM树。
    浏览器架构、渲染原理与页面优化_第7张图片
    在渲染引擎内部有一个HTML解析器,随着网络进程加载了多少数据,解析器就解析多少数据,而不是等文档整个加载完才解析。

    • DOM生成流程:字节流转换为DOM的过程
      浏览器架构、渲染原理与页面优化_第8张图片

      • 分词器将字节流转换为Token
        字节流转换为token

      • Token解析为DOM节点,将节点添加到DOM树。

    • 解析原理:HTML 解析器维护了一个 Token 栈结构,该 Token 栈主要用来计算节点之间的父子关系,在第一个阶段中生成的 Token 会被按照顺序压到这个栈中。

      具体的处理规则如下所示:

      • 如果压入到栈中的是 StartTag Token,HTML 解析器会为该 Token 创建一个 DOM 节点,然后将该节点加入到 DOM 树中,它的父节点就是栈中相邻的那个元素生成的节点。
      • 如果分词器解析出来是文本 Token,那么会生成一个文本节点,然后将该节点加入到 DOM 树中,文本 Token 是不需要压入到栈中,它的父节点就是当前栈顶 Token 所对应的 DOM 节点。
      • 如果分词器解析出来的是 EndTag 标签,比如是 EndTag div,HTML 解析器会查看 Token 栈顶的元素是否是 StarTag div,如果是,就将 StartTag div 从栈中弹出,表示该 div 元素解析完成。
    • 解析阻塞:在解析HTML构建DOM树时,如果遇到

你可能感兴趣的:(浏览器相关,浏览器原理,浏览器渲染)