从输入URL到页面展示,这中间发生了什么

210 阅读6分钟

一、浏览器新开一个tab页面,至少有四个进程

分别是:浏览器进程网络进程渲染进程(沙箱环境、同一个站点的tab页面共用一个渲染进程)、 GPU进程;此外还会有插件进程等。

  • 浏览器进程主要负责用户交互、子进程管理和文件储存等功能。
  • 网络进程是面向渲染进程和浏览器进程等提供网络下载功能。
  • 渲染进程的主要职责是把从网络下载的 HTML、JavaScript、CSS、图片等资源解析为可以显示和交互的页面。因为渲染进程所有的内容都是通过网络获取的,会存在一些恶意代码利用浏览器漏洞对系统进行攻击,所以运行在渲染进程里面的代码是不被信任的。这也是为什么 Chrome 会让渲染进程运行在安全沙箱里,就是为了保证系统的安全。

二、从输入 URL 到页面展示

1. 用户输入url并回车

2. 浏览器进程检查url,组装协议,构成完整的url

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

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

3. 浏览器进程通过进程间通信(IPC)把url请求发送给网络进程, GET /index.html HTTP1.1

4. 网络进程接收到url请求后检查本地缓存是否缓存了该请求资源,如果有则将该资源返回给浏览器进程

5. 如果没有,网络进程向web服务器发起http请求(网络请求),请求流程如下:

  • 5.1 进行DNS解析,获取服务器ip地址,端口: 如果之前DNS数据缓存服务缓存过当前域名信息,就会直接返回缓存信息;否则,发起请求获取根据域名解析出来的IP和端口号,如果没有端口号,http默认80,https默认443。如果是https请求,还需要建立TLS连接。

  • 5.2 利用ip地址和服务器建立tcp连接:tcp连接如下图。

  • 5.3 连接建立之后,浏览器构建请求头、请求行等信息,并把和该域名相关的 Cookie 等数据附加到请求头中,然后向服务器发送构建的请求信息。

  • 5.4 服务器接收到请求信息后,会根据请求信息生成响应数据(包括响应行、响应头和响应体等信息),并发给网络进程

  • 5.5 网络进程接收响应头和响应信息,并解析响应内容

6. 网络进程解析响应流程:

  • 6.1 检查状态码,如果是301/302,则需要重定向,从Location自动中读取地址,重新进行第4步

  • 6.2 如果不是重定向,首先服务器会根据 请求头中的If-None-Match 的值来判断请求的资源是否被更新,如果没有更新,就返回304状态码,相当于告诉浏览器之前的缓存还可以使用,就不返回新数据了;

  • 6.3 否则,返回新数据,200的状态码,并且如果想要浏览器缓存数据的话,就在相应头中加入字段: Cache-Control:Max-age=2000

  • 6.4 数据传输完成,TCP四次挥手断开连接。如果,浏览器或者服务器在HTTP头部加上如下信息,TCP就一直保持连接。保持TCP连接可以省下下次需要建立连接的时间,提示资源加载速度 Connection:Keep-Alive

  • 6.5 网络进程将获取到的数据包进行解析, 检查响应类型Content-Type,如果是字节流类型,则将该请求提交给下载管理器,该导航流程结束,不再进行后续的渲染,如果是html则通知浏览器进程准备渲染进程准备进行渲染。

7. 准备渲染进程

  • 7.1 浏览器进程检查当前url是否和之前打开的渲染进程根域名是否相同,如果相同,则复用原来的进程,如果不同,则开启新的渲染进程

8. 传输数据、更新状态

  • 8.1 渲染进程准备好后,浏览器进程向渲染进程发起“提交文档”的消息,渲染进程接收到消息和网络进程建立传输数据的“管道”

  • 8.2 渲染进程接收完数据后,向浏览器发送“确认提交”

  • 8.3 浏览器进程接收到确认消息后更新浏览器界面状态:安全、地址栏url、前进后退的历史状态、更新web页面。

9. 渲染流程

  • 9.1 构建 DOM 树:构建 DOM 树的输入内容是一个非常简单的 HTML 文件,然后经由 HTML 解析器解析,最终输出树状结构的 DOM;(document 就是 DOM 结构,DOM 是保存在内存中树状结构,可以通过 JavaScript 来查询或修改其内容。)

  • 9.2 样式计算:

    • 当渲染引擎接收到 CSS 文本时,会执行一个转换操作,将 CSS 文本转换为浏览器可以理解的结构——styleSheets (document.styleSheets)。
    • 转换样式表中的属性值,使其标准化
    • 计算出 DOM 树中每个节点的具体样式(CSS 的继承规则、层叠规则)
  • 9.3 布局阶段:计算出 DOM 树中可见元素的几何位置

    创建布局树(可见元素的布局树)-->布局计算(计算 DOM 元素的布局信息,保存在布局树中)

  • 9.4 分层 : 渲染引擎还需要为特定的节点生成专用的图层,并生成一棵对应的图层树;浏览器的页面实际上被分成了很多图层,这些图层叠加后合成了最终的页面; 分层的原则是:

元素有了层叠上下文的属性 者需要被剪裁,满足其中任意一点,就会被提升成为单独一层

  • 9.5 绘制
  • 9.6 分块
  • 9.7 光栅化和合成

三、如果下载 CSS 文件阻塞了,会阻塞 DOM 树的合成吗?

<html>
    <body>
        极客时间
        <script type="text/javascript" src="foo.js"></script>
    </body>
</html>
  • 情况一:当解析到JavaScript的时候,会先暂停DOM解析,并下载foo.js文件,下载完成之后执行该段JS文件,然后再继续往下解析DOM。这就是JavaScript文件为什么会阻塞DOM渲染。
<html>
    <head>
        <style type="text/css" src = "theme.css" />
    </head>
    <body>
        <p>极客时间</p>
        <script>
            let e = document.getElementsByTagName('p')[0]
            e.style.color = 'blue'
        </script>
    </body>
</html>
  • 情况二: 当我在JavaScript中访问了某个元素的样式,那么这时候就需要等待这个样式被下载完成才能继续往下执行,所以在这种情况下,CSS也会阻塞DOM的解析。