从用户输入 URL 到页面展示,这中间发生了什么?
1.用户输入处理
当用户在地址栏中输入内容并回车确定,地址栏会判断输入的关键字是搜索内容,还是请求的 URL。
如果是搜索内容,地址栏会使用浏览器默认的搜索引擎,来合成新的带搜索关键字的 URL。
如果判断输入内容符合 URL 规则,比如输入的是 time.geekbang.org,那么地址栏会根据规则,把这段内容加上协议,合成为完整的 URL,如 https://time.geekbang.org。
当用户输入关键字并键入回车之后,这意味着当前页面即将要被替换成新的页面,不过在这个流程继续之前,浏览器还给了当前页面一次执行 beforeunload 事件的机会,beforeunload 事件允许页面在退出之前执行一些数据清理操作,还可以询问用户是否要离开当前页面,比如当前页面可能有未提交完成的表单等情况,因此用户可以通过 beforeunload 事件来取消导航,让浏览器不再执行任何后续工作。当前页面没有监听 beforeunload 事件或者同意了继续后续流程,那么浏览器便进入下图的状态:
2.浏览器进程把组装好的 URL 发送给网络进程
浏览器进程通过 IPC 进程通信技术把组装好的 URL 发送给网络进程;
网络进程查找本地缓存,如果有可用的缓存,直接返回缓存资源;如果没有,则进行网络请求流程;
3.网络请求流程
DNS 解析(获取 IP 地址)
如果请求协议是 HTTPS,那么还需要建立 TLS 连接
利用 IP 地址,和服务端建立 TCP 连接
浏览器端构建请求行、请求头等信息,并把和该域名相关的 Cookie 等数据附加到请求头中,然后向服务器发送构建的请求信息
服务器接收到请求信息后,会根据请求信息生成响应数据(包括响应行、响应头和响应体等信息),并发给网络进程。等网络进程接收了响应行和响应头之后,就开始解析响应头的内容了
4.准备渲染进程
问题来了,浏览器渲染进程分配规则?
5.提交文档阶段
渲染进程准备好之后,还不能立即进入文档解析状态,因为此时的文档数据还在网络进程中,并没有提交给渲染进程,所以下一步就进入了提交文档阶段。所谓提交文档,就是指浏览器进程将网络进程接收到的 HTML 数据提交给渲染进程,具体流程是这样的:
首先当浏览器进程接收到网络进程的响应头数据之后,便向渲染进程发起“提交文档”的消息;
渲染进程接收到“提交文档”的消息后,会和网络进程建立传输数据的“管道”;
等文档数据传输完成之后,渲染进程会返回“确认提交”的消息给浏览器进程;
浏览器进程在收到“确认提交”的消息后,会更新浏览器界面状态,包括了安全状态、地址栏的 URL、前进后退的历史状态,并更新 Web 页面。
6.进入渲染流程
HTML 经过渲染进程中的 HTML 解析器生成 DOM 树结构(document)
CSS 经过渲染进程中的 CSS 解析器生成 styleSheets(document.styleSheets),计算 DOM 节点的样式信息
创建布局树,布局计算
分层,为特定的节点生成专用的图层,并生成一棵对应的图层树(LayerTree)
图层绘制,生成绘制列表后,渲染进程的主线程把绘制列表提交给合成线程。
分块,合成线程把图层分块(图块)。合成线程会按照视口附近的图块来优先生成位图,实际生成位图的操作是由栅格化来执行的。所谓栅格化,是指将图块转换为位图。而图块是栅格化执行的最小单位。渲染进程维护了一个栅格化的线程池,所有的图块栅格化都是在线程池内执行的。通常,栅格化过程都会使用 GPU 来加速生成,使用 GPU 生成位图的过程叫快速栅格化,或者 GPU 栅格化,生成的位图被保存在 GPU 内存中。
7.合成和显示
一旦所有图块都被光栅化,合成线程就会生成一个绘制图块的命令——“DrawQuad”,然后将该命令提交给浏览器进程。浏览器进程里面有一个叫 viz 的组件,用来接收合成线程发过来的 DrawQuad 命令,然后根据 DrawQuad 命令,将其页面内容绘制到内存中,最后再将内存显示在屏幕上。
评论