宏观视角下的浏览器

编程知识 更新时间:2023-04-30 21:14:56

三个大的进化路线

  • 应用程序Web化
  • Web应用移动化
  • Web操作系统化

站在用户体验角度来考虑页面性能

  • 当用户请求一个网站时,如果在 1 秒内看不到关键内容,用户会产生任务被中断的感觉。

  • 当用户点击某些按钮时,如果 100ms 内无法响应,用户会感受到延迟。

  • 如果 Web 中的动画没有达到 60fps,用户会感受到动画的卡顿。

浏览器的多进程架构

并行处理:同一时刻处理多个任务

线程是不能单独存在的,它是由进程来启动和管理的。

进程:一个进程就是一个程序的运行实例;

启动一个程序的时候,操作系统会为该程序创建一块内存,用来存放代码、运行中的数据和一个执行任务的主线程,我们把这样的一个运行环境叫进程。

线程是依附于进程的,而进程中使用多线程并行处理能提升运算效率。

进程和线程关系的 4 个特点

  • 进程中的任意一线程执行出错,都会导致整个进程的崩溃。

    我们可以模拟以下场景:

    A = 1+2
    B = 20/0
    C = 7*8
    

    把上述三个表达式稍作修改,在计算 B 的值的时候,我把表达式的分母改成 0,当线程执行到 B = 20/0 时,由于分母为 0,线程会执行出错,这样就会导致整个进程的崩溃,当然另外两个线程执行的结果也没有了。

  • 线程之间共享进程中的数据

    如下图所示,线程之间可以对进程的公共数据进行读写操作。

    线程 1、线程 2、线程 3 分别把执行的结果写入 A、B、C 中,然后线程 2 继续从 A、B、C 中读取数据,用来显示执行结果

  • 当一个进程关闭之后,操作系统会回收进程所占用的内存。

    当一个进程退出时,操作系统会回收该进程所申请的所有资源;即使其中任意线程因为操作不当导致内存泄漏,当进程退出时,这些内存也会被正确回收。

    比如之前的 IE 浏览器,支持很多插件,而这些插件很容易导致内存泄漏,这意味着只要浏览器开着,内存占用就有可能会越来越多,但是当关闭浏览器进程时,这些内存就都会被系统回收掉。

  • 进程之间的内容相互隔离

    进程隔离是为保护操作系统中进程互不干扰的技术,每一个进程只能访问自己占有的数据,也就避免出现进程 A 写入数据到进程 B 的情况。正是因为进程之间的数据是严格隔离的,所以一个进程如果崩溃了,或者挂起了,是不会影响到其他进程的。如果进程之间需要进行数据的通信,这时候,就需要使用用于进程间通信(IPC)的机制了。

多进程解决的问题

  • 不稳定

    由于进程是相互隔离的,所以当一个页面或者插件崩溃时,影响到的仅仅是当前的页面进程或者插件进程,并不会影响到浏览器和其他页面,这就完美地解决了页面或者插件的崩溃会导致整个浏览器崩溃,也就是不稳定的问题。

  • 不流畅

    JavaScript 也是运行在渲染进程中的,所以即使 JavaScript 阻塞了渲染进程,影响到的也只是当前的渲染页面,而并不会影响浏览器和其他页面,因为其他页面的脚本是运行在它们自己的渲染进程中的。所以当我们再在 Chrome 中运行上面那个死循环的脚本时,没有响应的仅仅是当前的页面。

  • 不安全

    采用多进程架构的额外好处是可以使用安全沙箱,你可以把沙箱看成是操作系统给进程上了一把锁,沙箱里面的程序可以运行,但是不能在你的硬盘上写入任何数据,也不能在敏感位置读取任何数据,例如你的文档和桌面。Chrome 把插件进程和渲染进程锁在沙箱里面,这样即使在渲染进程或者插件进程里面执行了恶意程序,恶意程序也无法突破沙箱去获取系统权限。

    当关闭一个页面时,整个渲染进程也会被关闭,之后该进程所占用的内存都会被系统回收,这样就轻松解决了浏览器页面的内存泄漏问题。

Chrome的多进程架构

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

TCP协议

**互联网,实际上是一套理念和协议组成的体系架构。**其中,协议是一套众所周知的规则和标准,如果各方都同意使用,那么它们之间的通信将变得毫无障碍。

IP:把数据包送达目的主机

计算机的地址就称为 IP 地址,访问任何网站实际上只是你的计算机向另外一台计算机请求信息。

  • 上层将含有“极客时间”的数据包交给网络层;
  • 网络层再将 IP 头附加到数据包上,组成新的 IP 数据包,并交给底层;
  • 底层通过物理网络将数据包传输给主机 B;
  • 数据包被传输到主机 B 的网络层,在这里主机 B 拆开数据包的 IP 头信息,并将拆开来的数据部分交给上层;
  • 最终,含有“极客时间”信息的数据包就到达了主机 B 的上层了。

UDP:把数据包送达应用程序

UDP 中一个最重要的信息是端口号,端口号其实就是一个数字,每个想访问网络的程序都需要绑定一个端口号。通过端口号 UDP 就能把指定的数据包发送给指定的程序了

IP 通过 IP 地址信息把数据包发送给指定的电脑,而 UDP 通过端口号把数据包分发给正确的程序。

  • 上层将含有“极客时间”的数据包交给传输层;
  • 传输层会在数据包前面附加上 UDP 头,组成新的 UDP 数据包,再将新的 UDP 数据包交给网络层;
  • 网络层再将 IP 头附加到数据包上,组成新的 IP 数据包,并交给底层;
  • 数据包被传输到主机 B 的网络层,在这里主机 B 拆开 IP 头信息,并将拆开来的数据部分交给传输层;
  • 在传输层,数据包中的 UDP 头会被拆开,并根据 UDP 中所提供的端口号,把数据部分交给上层的应用程序;
  • 最终,含有“极客时间”信息的数据包就旅行到了主机 B 上层应用程序这里。

在使用 UDP 发送数据时,有各种因素会导致数据包出错,虽然 UDP 可以校验数据是否正确,但是对于错误的数据包,UDP 并不提供重发机制,只是丢弃当前的包,而且 UDP 在发送之后也无法知道是否能达到目的地。

虽说 UDP 不能保证数据可靠性,但是传输速度却非常快,所以 UDP 会应用在一些关注速度、但不那么严格要求数据完整性的领域,如在线视频、互动游戏等。

TCP:把数据完整地送达应用程序

对于浏览器请求,或者邮件这类要求数据传输可靠性(reliability)的应用,如果使用 UDP 来传输会存在两个问题:

  • 数据包在传输过程中容易丢失;
  • 大文件会被拆分成很多小的数据包来传输,这些小的数据包会经过不同的路由,并在不同的时间到达接收端,而 UDP 协议并不知道如何组装这些数据包,从而把这些数据包还原成完整的文件。

TCP(Transmission Control Protocol,传输控制协议)是一种面向连接的、可靠的、基于字节流的传输层通信协议。

  • 对于数据包丢失的情况,TCP 提供重传机制;
  • TCP 引入了数据包排序机制,用来保证把乱序的数据包组合成一个完整的文件。

和 UDP 头一样,TCP 头除了包含了目标端口和本机端口号外,还提供了用于排序的序列号,以便接收端通过序号来重排数据包。

TCP连接过程

  • 建立连接:三次握手,三个数据包确认连接的建立

    所谓三次握手,是指在建立一个 TCP 连接时,客户端和服务器总共要发送三个数据包以确认连接的建立。

    第一次:客户端给服务端发送一个带有SYN标志的数据包 第二次:服务端给客户端发送带有SYN和ACK标志得数据包 第三次:客户端给服务端发送带有ACK标志的数据包 为什么是三次? 一次肯定不行,客户端发过去之后服务端无响应,客户端就不知道是否可以进行数据数据传递 两个也不行,比如客户端给服务端说我要进行传递数据,服务端说可以传递,两个握手完成。如果没有第三次客户端的确认,服务端不知道客户端是否收到它允许传递的信号,所以两次也不行。

  • 传输数据:接收端发送确认数据包,并对数据包进行排序

    TCP通过三次握手建立连接,也就是发送三次数据包。 如果传输的是大文件,会被拆分为好多小数据包。这些数据包到接收端,接收端会按照TCP头中的顺序将这些数据包排序,保证形成完整数据。如果一定时间内没有接收到数据包,会触发发送端的重传机制。等到重传之后才开始渲染。正常渲染是接受到content-type请求头开始渲染。 通过四次挥手断开连接。

  • 断开连接:四次挥手

TCP 为了保证数据传输的可靠性,牺牲了数据包的传输速度,因为“三次握手”和“数据包校验机制”等把传输过程中的数据包的数量提高了一倍。

HTTP请求流程

HTTP 是一种允许浏览器向服务器获取资源的协议,是 Web 的基础,也是浏览器使用最广的协议

浏览器端发起 HTTP 请求流程

  • 构建请求:浏览器构建请求行信息

  • 查找缓存:在真正发起网络请求之前,浏览器会先在浏览器缓存中查询是否有要请求的文件

    浏览器缓存是一种在本地保存资源副本,以供下次请求时直接使用的技术。

    当浏览器发现请求的资源已经在浏览器缓存中存有副本,它会拦截请求,返回该资源的副本,并直接结束请求,而不会再去源服务器重新下载。这样做的好处有:

    • 缓解服务器端压力,提升性能(获取资源的耗时更短了);
    • 对于网站来说,缓存是实现快速资源加载的重要组成部分。
  • 准备IP地址和端口

    HTTP 协议作为应用层协议

    TCP/IP作传输层协议

    HTTP 的内容是通过 TCP 的传输数据阶段来实现的

    负责把域名和 IP 地址做一一映射关系的系统叫做“域名系统”,简称 DNS(Domain Name System)。

  • 等待TCP队列

    Chrome 有个机制,同一个域名同时最多只能建立 6 个 TCP 连接,如果在同一个域名下同时有 10 个请求发生,那么其中 4 个请求会进入排队等待状态,直至进行中的请求完成。

    http1.1中存在限制,但是在http2.0的时候采取多路复用的原则,就没有这个限制了

  • 建立TCP连接:在 HTTP 工作开始之前,浏览器通过 TCP 与服务器建立连接。

  • 发送HTTP请求

首先浏览器会向服务器发送请求行,它包括了请求方法、请求 URI(Uniform Resource Identifier)和 HTTP 版本协议

常见的两种请求方法有:GET POST

如果是使用post方法,那么浏览器还要准备数据给服务器,这里准备的数据是通过请求体来发送。

在浏览器发送请求行命令之后,还要以请求头形式发送其他一些信息,把浏览器的一些基础信息告诉服务器。比如包含了浏览器所使用的操作系统、浏览器内核等信息,以及当前请求的域名信息、浏览器端的 Cookie 信息,等等。

服务器端处理 HTTP 请求流程

  • 返回请求

    • 首先服务器会返回响应行,包括协议版本和状态码。但并不是所有的请求都可以被服务器处理的,那么一些无法处理或者处理出错的信息,怎么办呢?服务器会通过请求行的状态码来告诉浏览器它的处理结果,最常用的状态码是 200,表示处理成功;如果没有找到页面,则会返回 404。

      状态码大全

    • 随后,正如浏览器会随同请求发送请求头一样,服务器也会随同响应向浏览器发送响应头。响应头包含了服务器自身的一些信息,比如服务器生成返回数据的时间、返回的数据类型(JSON、HTML、流媒体等类型),以及服务器要在客户端保存的 Cookie 等信息。

    • 发送完响应头后,服务器就可以继续发送响应体的数据,通常,响应体就包含了 HTML 的实际内容。

  • 断开连接

    通常情况下,一旦服务器向客户端返回了请求数据,它就要关闭 TCP 连接。不过如果浏览器或者服务器在其头信息中加入了:

    Connection:Keep-Alive 
    

    那么 TCP 连接在发送后将仍然保持打开状态,这样浏览器就可以继续通过同一个 TCP 连接发送请求。保持 TCP 连接可以省去下次请求时需要建立连接的时间,提升资源加载速度。

  • 重定向

为什么很多站点第二次打开速度会很快?

如果第二次页面打开很快,主要原因是第一次加载页面过程中,缓存了一些耗时的数据。那么,哪些数据会被缓存呢?从上面介绍的核心请求路径可以发现,DNS 缓存和页面资源缓存这两块数据是会被浏览器缓存的

首先,我们看下服务器是通过什么方式让浏览器缓存数据的?

从上图的第一次请求可以看出,当服务器返回 HTTP 响应头给浏览器时,浏览器是通过响应头中的 Cache-Control 字段来设置是否缓存该资源。通常,我们还需要为这个资源设置一个缓存过期时长,而这个时长是通过 Cache-Control 中的 Max-age 参数来设置的,比如上图设置的缓存过期时间是 2000 秒。

Cache-Control:Max-age=2000

这也就意味着,在该缓存资源还未过期的情况下, 如果再次请求该资源,会直接返回缓存中的资源给浏览器。但如果缓存过期了,浏览器则会继续发起网络请求,并且在 HTTP 请求头中带上:If-None-Match:“4f80f-13c-3a1xb12a”,服务器收到请求头后,会根据 If-None-Match 的值来判断请求的资源是否有更新。如果没有更新,就返回 304 状态码,相当于服务器告诉浏览器:“这个缓存可以继续使用,这次就不重复发送数据给你了。”如果资源有更新,服务器就直接返回最新资源给浏览器。关于缓存的细节内容特别多,具体细节可以参考 HTTP 缓存。简要来说,很多网站第二次访问能够秒开,是因为这些网站把很多资源都缓存在了本地,浏览器缓存直接使用本地副本来回应请求,而不会产生真实的网络请求,从而节省了时间。同时,DNS 数据也被浏览器缓存了,这又省去了 DNS 查询环节。

1、此处有两个缓存,一是缓存页面资源,一是缓存dns信息

2、缓存过期分为服务器资源过期以及客户端资源过期,首先判断本地资源是否过期,在发送信息给服务器判断服务器资源是否更新,如果没有更新则可以直接调用

导航流程

用户发出 URL 请求到页面开始解析的这个过程,就叫做导航。

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

从输入 URL 到页面展示

  • 用户输入

    当用户在地址栏中输入一个查询关键字时,地址栏会判断输入的关键字是搜索内容,还是请求的 URL

    如果是搜索内容,地址栏会使用浏览器默认的搜索引擎,来合成新的带搜索关键字的 URL。

    如果判断输入内容符合 URL 规则,比如输入的是 time.geekbang,那么地址栏会根据规则,把这段内容加上协议,合成为完整的 URL

  • URL请求过程

    首先,网络进程会查找本地缓存是否缓存了该资源。如果有缓存资源,那么直接返回资源给浏览器进程;如果在缓存中没有查找到资源,那么直接进入网络请求流程。这请求前的第一步是要进行 DNS 解析,以获取请求域名的服务器 IP 地址。如果请求协议是 HTTPS,那么还需要建立 TLS 连接。接下来就是利用 IP 地址和服务器建立 TCP 连接。连接建立之后,浏览器端会构建请求行、请求头等信息,并把和该域名相关的 Cookie 等数据附加到请求头中,然后向服务器发送构建的请求信息。服务器接收到请求信息后,会根据请求信息生成响应数据(包括响应行、响应头和响应体等信息),并发给网络进程。等网络进程接收了响应行和响应头之后,就开始解析响应头的内容了。(为了方便讲述,下面我将服务器返回的响应头和响应行统称为响应头。)

    • 重定向

      在导航过程中,如果服务器响应行的状态码包含了 301、302 一类的跳转信息,浏览器会跳转到新的地址继续导航;如果响应行是 200,那么表示浏览器可以继续处理该请求。

    • 响应数据类型处理

      Content-Type 是 HTTP 头中一个非常重要的字段, 它告诉浏览器服务器返回的响应体数据是什么类型

      如果 Content-Type 字段的值被浏览器判断为下载类型,那么该请求会被提交给浏览器的下载管理器,同时该 URL 请求的导航流程就此结束。但如果是 HTML,那么浏览器则会继续进行导航流程。由于 Chrome 的页面渲染是运行在渲染进程中的,所以接下来就需要准备渲染进程了

    • 准备渲染进程

      默认情况下,Chrome 会为每个页面分配一个渲染进程,也就是说,每打开一个新页面就会配套创建一个新的渲染进程。但是,也有一些例外,在某些情况下,浏览器会让多个页面直接运行在同一个渲染进程中。

      如果从一个页面打开了另一个新页面,而新页面和当前页面属于同一站点的话,那么新页面会复用父页面的渲染进程。

      同一站点:根域名(例如,geekbang)加上协议(例如,https:// 或者 http://),还包含了该根域名下的所有子域名和不同的端口

      http + domainname * /login || name

    • 提交文档:指浏览器进程将网络进程接收到的 HTML 数据提交给渲染进程

      • 首先当浏览器进程接收到网络进程的响应头数据之后,便向渲染进程发起“提交文档”的消息;

      • 渲染进程接收到“提交文档”的消息后,会和网络进程建立传输数据的“管道”;

      • 等文档数据传输完成之后,渲染进程会返回“确认提交”的消息给浏览器进程;

      • 浏览器进程在收到“确认提交”的消息后,会更新浏览器界面状态,包括了安全状态、地址栏的 URL、前进后退的历史状态,并更新 Web 页面。

    • 渲染阶段:一旦文档被提交,渲染进程便开始页面解析和子资源加载了

      一旦页面生成完成,渲染进程会发送一个消息给浏览器进程,浏览器接收到消息后,会停止标签图标上的加载动画

完整回答:从输入URL到页面展示?

\1. 用户输入URL,浏览器会根据用户输入的信息判断是搜索还是网址,如果是搜索内容,就将搜索内容+默认搜索引擎合成新的URL;如果用户输入的内容符合URL规则,浏览器就会根据URL协议,在这段内容上加上协议合成合法的URL
\2. 用户输入完内容,按下回车键,浏览器导航栏显示loading状态,但是页面还是呈现前一个页面,这是因为新页面的响应数据还没有获得
\3. 浏览器进程浏览器构建请求行信息,会通过进程间通信(IPC)将URL请求发送给网络进程
GET /index.html HTTP1.1
\4. 网络进程获取到URL,先去本地缓存中查找是否有缓存文件,如果有,拦截请求,直接200返回;否则,进入网络请求过程
\5. 网络进程请求DNS返回域名对应的IP和端口号,如果之前DNS数据缓存服务缓存过当前域名信息,就会直接返回缓存信息;否则,发起请求获取根据域名解析出来的IP和端口号,如果没有端口号,http默认80,https默认443。如果是https请求,还需要建立TLS连接。
\6. Chrome 有个机制,同一个域名同时最多只能建立 6 个TCP 连接,如果在同一个域名下同时有 10 个请求发生,那么其中 4 个请求会进入排队等待状态,直至进行中的请求完成。如果当前请求数量少于6个,会直接建立TCP连接。
\7. TCP三次握手建立连接,http请求加上TCP头部——包括源端口号、目的程序端口号和用于校验数据完整性的序号,向下传输
\8. 网络层在数据包上加上IP头部——包括源IP地址和目的IP地址,继续向下传输到底层
\9. 底层通过物理网络传输给目的服务器主机
\10. 目的服务器主机网络层接收到数据包,解析出IP头部,识别出数据部分,将解开的数据包向上传输到传输层
\11. 目的服务器主机传输层获取到数据包,解析出TCP头部,识别端口,将解开的数据包向上传输到应用层
\12. 应用层HTTP解析请求头和请求体,如果需要重定向,HTTP直接返回HTTP响应数据的状态code301或者302,同时在请求头的Location字段中附上重定向地址,浏览器会根据code和Location进行重定向操作;如果不是重定向,首先服务器会根据 请求头中的If-None-Match 的值来判断请求的资源是否被更新,如果没有更新,就返回304状态码,相当于告诉浏览器之前的缓存还可以使用,就不返回新数据了;否则,返回新数据,200的状态码,并且如果想要浏览器缓存数据的话,就在相应头中加入字段:
Cache-Control:Max-age=2000
响应数据又顺着应用层——传输层——网络层——网络层——传输层——应用层的顺序返回到网络进程
\13. 数据传输完成,TCP四次挥手断开连接。如果,浏览器或者服务器在HTTP头部加上如下信息,TCP就一直保持连接。保持TCP连接可以省下下次需要建立连接的时间,提示资源加载速度
Connection:Keep-Alive
\14. 网络进程将获取到的数据包进行解析,根据响应头中的Content-type来判断响应数据的类型,如果是字节流类型,就将该请求交给下载管理器,该导航流程结束,不再进行;如果是text/html类型,就通知浏览器进程获取到文档准备渲染
\15. 浏览器进程获取到通知,根据当前页面B是否是从页面A打开的并且和页面A是否是同一个站点(根域名和协议一样就被认为是同一个站点),如果满足上述条件,就复用之前网页的进程,否则,新创建一个单独的渲染进程
\16. 浏览器会发出“提交文档”的消息给渲染进程,渲染进程收到消息后,会和网络进程建立传输数据的“管道”,文档数据传输完成后,渲染进程会返回“确认提交”的消息给浏览器进程
\17. 浏览器收到“确认提交”的消息后,会更新浏览器的页面状态,包括了安全状态、地址栏的 URL、前进后退的历史状态,并更新web页面,此时的web页面是空白页
\18. 渲染进程对文档进行页面解析和子资源加载,HTML 通过HTM 解析器转成DOM Tree(二叉树类似结构的东西),CSS按照CSS 规则和CSS解释器转成CSSOM TREE,两个tree结合,形成render tree(不包含HTML的具体元素和元素要画的具体位置),通过Layout可以计算出每个元素具体的宽高颜色位置,结合起来,开始绘制,最后显示在屏幕中新页面显示出来

渲染流程

渲染流程

构建 DOM 树、样式计算、布局阶段、分层、绘制、分块、光栅化和合成。

  1. 渲染进程将 HTML 内容转换为能够读懂的 DOM 树结构。
  2. 渲染引擎将 CSS 样式表转化为浏览器可以理解的 styleSheets,计算出 DOM 节点的样式。
  3. 创建布局树,并计算元素的布局信息。
  4. 对布局树进行分层,并生成分层树。
  5. 为每个图层生成绘制列表,并将其提交到合成线程。
  6. 合成线程将图层分成图块,并在光栅化线程池中将图块转换成位图。
  7. 合成线程发送绘制图块命令 DrawQuad 给浏览器进程。
  8. 浏览器进程根据 DrawQuad 消息生成页面,并显示到显示器上。

详细解答

  • 构建DOM树:因为浏览器无法直接理解和使用 HTML,所以需要将 HTML 转换为浏览器能够理解的结构

  • 样式计算

    1. 将CSS转换为浏览器能够理解的结构

      当渲染引擎接收到 CSS 文本时,会执行一个转换操作,将 CSS 文本转换为浏览器可以理解的结构——styleSheets

    2. 转换样式表中的属性值,使其标准化

    3. 计算出DOM树中每个节点的具体样式

      样式计算阶段的目的是为了计算出 DOM 节点中每个元素的具体样式,在计算过程中需要遵守 CSS 的继承和层叠两个规则

      CSS 继承就是每个 DOM 节点都包含有父节点的样式

      层叠是 CSS 的一个基本特征,它是一个定义了如何合并来自多个源的属性值的算法。它在 CSS 处于核心地位,CSS 的全称“层叠样式表”正是强调了这一点

  • 布局阶段:计算出 DOM 树中可见元素的几何位置

    • 创建布局树:在显示之前,我们还要额外地构建一棵只包含可见元素布局树。

      • 遍历 DOM 树中的所有可见节点,并把这些节点加到布局树中;
      • 而不可见的节点会被布局树忽略掉,如 head 标签下面的全部内容,再比如 body.p.span 这个元素,因为它的属性包含 dispaly:none,所以这个元素也没有被包进布局树。
    • 布局计算

      在执行布局操作的时候,会把布局运算的结果重新写回布局树中,所以布局树既是输入内容也是输出内容,这是布局阶段一个不合理的地方,因为在布局阶段并没有清晰地将输入内容和输出内容区分开来。针对这个问题,Chrome 团队正在重构布局代码,下一代布局系统叫 LayoutNG,试图更清晰地分离输入和输出,从而让新设计的布局算法更加简单

    • 分层:渲染引擎还需要为特定的节点生成专用的图层,并生成一棵对应的图层树

      并不是布局树的每个节点都包含一个图层,如果一个节点没有对应的层,那么这个节点就从属于父节点的图层

      第一点,拥有层叠上下文属性的元素会被提升为单独的一层。

      第二点,需要剪裁(clip)的地方也会被创建为图层。(如果出现滚动条,滚动条也会被提升为单独的层)

    • 图层绘制

    • 栅格化操作

    • 合成和显示

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

重排

通过 JavaScript 或者 CSS 修改元素的几何位置属性,例如改变元素的宽度、高度等,那么浏览器会触发重新布局,解析之后的一系列子阶段,这个过程就叫重排。无疑,重排需要更新完整的渲染流水线,所以开销也是最大的

重绘

修改了元素的背景颜色,那么布局阶段将不会被执行,因为并没有引起几何位置的变换,所以就直接进入了绘制阶段,然后执行之后的一系列子阶段,这个过程就叫重绘。相较于重排操作**,重绘省去了布局和分层阶段,所以执行效率会比重排操作要高一些。**

直接合成

使用了CSS 的 transform 来实现动画效果,这可以避开重排和重绘阶段,直接在非主线程上执行合成动画操作。这样的效率是最高的,因为是在非主线程上合成,并没有占用主线程的资源,另外也避开了布局和绘制两个子阶段,所以相对于重绘和重排,合成能大大提升绘制效率。

更多推荐

宏观视角下的浏览器

本文发布于:2023-04-22 23:03:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/cb9ebeb50e986a9a2b65d0ea5423287f.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:视角   浏览器

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!

  • 97286文章数
  • 24742阅读数
  • 0评论数