浏览器渲染过程

用户输入

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

搜索内容: 使用浏览器默认的搜索引擎合成新的带搜索关键字的 URL
合法的 URL: 加上协议,合成为完整的 URL

执行搜索交互后,会先执行 beforeunload 事件,可以通过此事件取消导航。此时浏览器的状态是在加载中,但是页面内容并没有被替换,因为需要等待提交文档阶段.

URL 请求过程

浏览器进程会通过进程间通信(IPC)把 URL 请求发送至网络进程。

是否命中 DNS 缓存,如果命中缓存直接返回。接下来就是利用 IP 地址和服务器建立 TCP 连接。连接建立之后,浏览器端会构建请求行、请求头等信息,并把和该域名相关的 Cookie 等数据附加到请求头中,然后向服务器发送构建的请求信息。

如果时通过链接打开页面,如果两个页面是同一站点,新页面会复用父页面的渲染进程。

提交文档

  • 网络进程获取到响应之后,向渲染进程发起提交文档的消息
  • 渲染进程接收到提交文档的消息后,会和网络进程建立传输数据的管道
  • 等文档数据传输完成之后,渲染进程会返回确认提交的消息给浏览器进程
  • 浏览器进程在收到确认提交的消息后,会更新浏览器界面状态,包括了安全状态、地址栏的 URL、前进后退的历史状态,并更新 Web 页面。

页面渲染

  • 构建 DOM 树
    HTML 解析器(HTMLParser)负责将 HTML 字节流转换为 DOM 结构。网络进程接收到响应头之后,会根据响应头中的 content-type 字段来判断文件的类型,如果这是一个 HTML 类型的文件,然后为该请求选择或者创建一个渲染进程。网络进程和渲染进程之间会建立一个共享数据的管道,网络进程加载了多少数据,HTML 解析器便解析多少数据。

    第一个阶段,通过分词器将字节流转换为 Token。

    第二个和第三个阶段是同步进行的,需要将 Token 解析为 DOM 节点,并将 DOM 节点添加到 DOM 树中。HTML 解析器维护了一个 Token 栈结构,使用栈解构实现了匹配算法。

  • 构建 StyleSheet
    属性标准化
    计算每个节点的样式,css 继承规则和层叠规则

  • 创建渲染树,遍历 DOM 树中的可见节点,计算出每个元素的样式(即 ComputedStyle)。这里的计算包括所有继承的样式和从 CSS 规则中继承来的样式。

  • 创建布局树
    计算布局信息,布局信息保存在布局树中。

  • 创建无障碍树

  • 分层,创建图层树
    定位属性的元素、定义透明属性的元素、使用 CSS 滤镜的元素,需要被剪裁等,都拥有层叠上下文属性
    可以通过 will-change 属性,让元素单独在合成线程中执行。

  • 图层绘制,渲染进程生成绘制指令,真实的绘制由渲染进程中的合成线程来完成。
    通常只绘制视口附近的图像,合成线程会将图层划分为图块。

    合成线程会按照视口附近的图块来优先生成位图,实际生成位图的操作是由栅格化来执行的。所谓栅格化,是指将图块转换为位图。而图块是栅格化执行的最小单位。渲染进程维护了一个栅格化的线程池,所有的图块栅格化都是在线程池内执行的。

    合成过程会使用 GPU 加速生成,这涉及到块进程操作。渲染进程把生成指令发送给 GPU 进程,生成的位图保存在 GPU 内存中。

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

资源加载/解析

  • JS 在 Css 前面,且在 head 中,会阻塞 DOM 的解析

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <html>
    <head>
    <script>
    console.log(document.querySelector("p"));
    </script>
    <link rel="stylesheet" href="http://localhost:8000/big.css" />
    </head>

    <body>
    <p id="test">xxx</p>
    </body>
    </html>

    JS 在 Css 后面,且在head 中,会等待 Css 加载,因为可能会通过 JS 获取样式,而且阻塞 DOM 解析, 也就是说只要在 Js 文件后面 DOM 解析都会被阻止。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    <html>
    <head>
    <link rel="stylesheet" href="http://localhost:8000/big.css" />
    <script>
    console.log(document.querySelector("p")); //null
    </script>
    </head>

    <body>
    <p id="test">xxx?</p>
    </body>
    </html>

    在 Firefox, Chrome, Edge 中,如果 <link rel="stylesheet" href="xxx"> 后面跟着 <script>, 则 CSS 加载完成后, 才能触发 DOMContentLoaded

  • Css 文件如果在 <head> 中,那么 Css 文件的加载不会影响 DOM 的解析,但是影响 DOM 的渲染
    因为 Css 文件的加载可以放在预解析线程中,所以不会影响 DOM 解析,但是 DOM 解析完成后,必须等待样式文件被解析,才能渲染页面。

    Css 文件如果在 <body> 中,那么 Css 文件的加载会阻塞 Css 资源后面的 DOM 的解析(阻塞 DOMContentLoaded 执行的时机)。这种情况称为 FOUC(Flash of Unstyled Content) 样式闪烁。也就是说 Css 资源前面的 DOM 会被渲染,Css 后面的 DOM 必须要等待 Css 资源加载完成后才会被渲染,而之前已经渲染的 DOM 会在 Css 资源加载后重绘。

打赏
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2015-2025 SunZhiqi

此时无声胜有声!

支付宝
微信