从一道面试题开始:浏览器从输入URL到渲染页面的过程

1,286 阅读8分钟

简单的流程介绍


浏览器从输入一个url到页面展示,从使用者的角度来说,只是打开一个页面的过程。但是,为了让使用者可以安全、便捷的使用浏览器,浏览器可是做了很多的努力的。那接下来,我们就看看浏览器做了哪些努力吧。

先简单的说下,浏览器在网络层面的步骤吧。

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

从进程和线程讲起


上面的说明中,一直提到一个词语--进程,那什么是进程呢。

一个进程就是一个程序的运行实例。详细解释就是,启动一个程序的时候,操作系统会为该程序创建一块内存,用来存放代码、运行中的数据和一个执行任务的主线程,我们把这样的一个运行环境叫进程线程是依附于进程的,而进程中使用多线程并行处理能提升运算效率。

那线程和进程之间,有什么特点呢?

  1. 进程中的任意一线程执行出错,都会导致整个进程的崩溃。
  2. 线程之间共享进程中的数据。
  3. 当一个进程关闭之后,操作系统会回收进程所占用的内存。
  4. 进程之间的内容相互隔离。

看到上面的特点,经过浏览器的发展和使用,人们也发现,如果只是开辟了一块内存,只用一个进程来执行所有的浏览器线程处理,会出现以下的问题:

  1. **首先,不稳定。**一但某个线程崩溃,对整个浏览器的进程都是影响巨大的,影响客户使用。想想你正在吃着火锅唱着歌,忽然就遇到麻匪了。
  2. 其次,不流畅。因为所有的渲染都是单个线程完成的,一旦渲染里出现个渲染时间很久的js脚本,用户只能等着白屏或者直接跑路了。
  3. 最后,不安全。所有的线程都在一个进程内,有人注入恶意代码的话,就会获取所有的信息的。

鉴于以上缺点,现代浏览器才用了多进程的运行模式:

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

image.png

聊一聊HTTP和TCP的传输


那说完进程,我们继续看整个的流程中的第二部涉及到的网络进程。不管是现在还是以后的万物互联时代,网络肯定都是我们要去接触和学的知识。

最简单的,我们了解下网络的传输层和网络层

image.png

image.png

  • 互联网中的数据是通过数据包来传输的,数据包在传输过程中容易丢失或出错。
  • IP 负责把数据包送达目的主机。
  • UDP 负责把数据包送达具体应用。
  • 而 TCP可以 保证了数据完整地传输,它的连接可分为三个阶段:建立连接、传输数据和断开连接。

那浏览器和服务器之间是如何进行信息传输的呢,请看下图:

image.png

在主机A里面将内容通过一层层传递下去,并加上TCP头和Ip头。然后在主机B里面,将传输的内容一层层的分开,最后在上层获得传输的内容。

image.png

从上图可以看出,一个完整的 TCP 连接的生命周期包括了“建立连接”“传输数据”和“断开连接”三个阶段。

  • 首先,建立连接阶段。这个阶段是通过“三次握手”来建立客户端和服务器之间的连接。TCP 提供面向连接的通信传输。面向连接是指在数据通信开始之前先做好两端之间的准备工作。所谓三次握手,是指在建立一个 TCP 连接时,客户端和服务器总共要发送三个数据包以确认连接的建立。
  • 其次,传输数据阶段。在该阶段,接收端需要对每个数据包进行确认操作,也就是接收端在接收到数据包之后,需要发送确认数据包给发送端。所以当发送端发送了一个数据包之后,在规定时间内没有接收到接收端反馈的确认消息,则判断为数据包丢失,并触发发送端的重发机制。同样,一个大的文件在传输过程中会被拆分成很多小的数据包,这些数据包到达接收端后,接收端会按照 TCP 头中的序号为其排序,从而保证组成完整的数据。
  • 最后,断开连接阶段。数据传输完毕之后,就要终止连接了,涉及到最后一个阶段“四次挥手”来保证双方都能断开连接。

准备渲染进程


默认情况下,Chrome 会为每个页面分配一个渲染进程,也就是说,每打开一个新页面就会配套创建一个新的渲染进程。但是也有特殊情况,就是如果从一个页面打开了另一个新页面,而新页面和当前页面属于同一站点的话,那么新页面会复用父页面的渲染进程

准备好渲染进程后,只要等待文档数据从网络进程过来后,就可以进行渲染了。过程如下:

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

这也就解释了为什么在浏览器的地址栏里面输入了一个地址后,之前的页面没有立马消失,而是要加载一会儿才会更新页面。

所以在浏览器更新页面之后,整个的从URL输入到页面展示的过程就讲完了。 下期,我们再讲下渲染进程具体做了哪些事情吧。也就是我们通常涉及到重绘和重排的那些过程。

感谢


谢谢你读完本篇文章,希望对你能有所帮助,如有问题欢迎各位指正。

我是南瓜小神(✿◡‿◡),如果觉得写得可以的话,请点个赞吧❤。