前言:

前面的很多文章都零星讲述到关于页面渲染过程,这章就简单总结下从 URL 输入到页面展现的渲染过程。了解页面渲染的流程,更方便我们开发高性能的页面和提高用户的体验有很重要的意义。

从输入 URL 到页面加载的历程:

  • 输入URL并进行跳转;
  • URL解析/DNS解析查找域名IP地址;
  • 建立TCP请求连接:三次握手;
  • 客户端发送HTTP请求;
  • 服务器接收数据;
  • 服务器响应请求/MVC;
  • 服务器返回数据;
  • 客户端接收数据;
  • 浏览器加载资源/渲染页面;
  • 断开TCP 连接:四次挥手;

大概的历程是这样的,我们对其进行解析,但是不会太过于深入。

输入URL并进行跳转:

不仅限于输入URL,从其他方式例如点击跳转,js跳转等各种方式都能进行页面的跳转进行页面的访问。

URL解析 / DNS解析:

URL : 统一资源定位器,用于定位互联网上资源,简称网址。我们通过URL从Web服务器请求页面。

URL结构:scheme://host.domain:port/path/filename

  • scheme : 定义因特网服务的类型。常见的协议有 http、https、ftp、file,其中最常见的类型是 http,而 https 则是进行加密的网络传输。
  • host :定义域主机(http 的默认主机是 www)。
  • domain: 定义因特网域名,比如 w3school.com.cn。
  • port: 定义主机上的端口号(http 的默认端口号是 80)。
  • path: 定义服务器上的路径(如果省略,则文档必须位于网站的根目录中)。
  • filename: 定义文档/资源的名称。

浏览器对 URL 进行检查时首先判断协议,如果是 http/https 就按照 Web 来处理,另外还会对 URL 进行安全检查,然后直接调用浏览器内核中的对应方法,接下来是对网络地址进行处理,如果地址不是一个IP地址而是域名则通过DNS(域名系统)将该地址解析成IP地址。IP地址对应着网络上一台计算机,DNS服务器本身也有IP,你的网络设置包含DNS服务器的IP。

DNS的解析域名的方式:递归查询和迭代查询。

查询的历程:

  • 浏览器缓存
    当用户通过浏览器访问某域名时,浏览器首先会在自己的缓存中查找是否有该域名对应的IP地址(若曾经访问过该域名且没有清空缓存便存在);
  • 系统缓存
    当浏览器缓存中无域名对应IP则会自动检查用户计算机系统Hosts文件DNS缓存是否有该域名对应IP;
  • 路由器缓存
    当浏览器及系统缓存中均无域名对应IP则进入路由器缓存中检查,以上三步均为客户端端的DNS缓存;
  • ISP(互联网服务提供商)DNS缓存
    当在用户客户端查找不到域名对应IP地址,则将进入ISP DNS缓存中进行查询。比如你用的是电信的网络,则会进入电信的DNS缓存服务器中进行查找;
  • 根域名服务器
    当以上均未完成,则进入根服务器进行查询。全球仅有13台根域名服务器,1个主根域名服务器,其余12为辅根域名服务器。根域名收到请求后会查看区域文件记录,若无则将其管辖范围内顶级域名(如.com)服务器IP告诉本地DNS服务器;
  • 顶级域名服务器
    顶级域名服务器收到请求后查看区域文件记录,若无则将其管辖范围内主域名服务器的IP地址告诉本地DNS服务器;
  • 主域名服务器
    主域名服务器接受到请求后查询自己的缓存,如果没有则进入下一级域名服务器进行查找,并重复该步骤直至找到正确纪录;
  • 保存结果至缓存
    本地域名服务器把返回的结果保存到缓存,以备下一次使用,同时将该结果反馈给客户端,客户端通过这个IP地址与web服务器建立链接。

不做过多篇幅的介绍,对DNS解析有兴趣的学习下DNS原理及其解析过程



建立TCP请求连接:

浏览器和服务端TCP请求建立的过程,是基于TCP/IP,该协议由网络层的IP和传输层的TCP组成,IP是每一台互联网设备在互联网中的唯一地址。TCP通过三次握手建立连接,并提供可靠的数据传输服务。

  • 发送端首先发送一个带有SYN(synchronize)标志地数据包给接收方。
  • 接收方接收后,回传一个带有SYN/ACK标志的数据包传递确认信息,表示我收到了。
  • 最后,发送方再回传一个带有ACK标志的数据包,代表我知道了,表示’握手‘结束。

javascript渲染进程的主线程 js页面渲染过程_IP

谢希仁著《计算机网络》中讲“三次握手”的目的是“为了防止已失效的连接请求报文段突然又传送到了服务端,因而产生错误”。

客户端发送HTTP请求:

TCP 三次握手结束后,开始发送 HTTP 请求报文。

互联网内各网络设备间的通信都遵循TCP/IP协议,利用TCP/IP协议族进行网络通信时,会通过分层顺序与对方进行通信。分层由高到低分别为:应用层、传输层、网络层、数据链路层。发送端从应用层往下走,接收端从数据链路层网上走。

javascript渲染进程的主线程 js页面渲染过程_前端性能_02


请求报文由请求行(request line)、请求头(header)、请求体四个部分组成:

  1. 请求行包含请求方法、URL、协议版本
  • 请求方法包含 8 种:GET、POST、PUT、DELETE、PATCH、HEAD、OPTIONS、TRACE;
  • URL 即请求地址,由 <协议>://<主机>:<端口>/<路径>?<参数> 组成;
  • 协议版本即 http 版本号;
  1. 请求头包含请求的附加信息,由关键字/值对组成,每行一对,关键字和值用英文冒号“:”分隔。
    请求头部通知服务器有关于客户端请求的信息。它包含许多有关的客户端环境和请求正文的有用信息。其中比如:Host,表示主机名,虚拟主机;Connection,HTTP/1.1 增加的,使用 keepalive,即持久连接,一个连接可以发多个请求;User-Agent,请求发出者,兼容性以及定制化需求。
  2. 请求体,可以承载多个请求参数的数据,包含回车符、换行符和请求数据,并不是所有请求都具有请求数据。
服务器接收数据:

服务器是网络环境中的高性能计算机,它侦听网络上的其他计算机(客户机)提交的服务请求,并提供相应的服务,比如网页服务、文件下载服务、邮件服务、视频服务。

接收端的服务器在链路层接收到数据包,再层层向上直到应用层。这过程中包括在传输层通过TCP协议将分段的数据包重新组成原来的HTTP请求报文。

服务器响应请求/MVC:

常见的 web server 产品有 apache、nginx、IIS 或 Lighttpd 等。web server 担任管控的角色,对于不同用户发送的请求,会结合配置文件,把不同请求委托给服务器上处理相应请求的程序进行处理(例如 CGI 脚本,JSP 脚本,servlets,ASP 脚本,服务器端JavaScript,或者一些其它的服务器端技术等),然后返回后台程序处理产生的结果作为响应。

MVC 是一个设计模式,将应用程序分成三个核心部件:模型(model)-- 视图(view)–控制器(controller),它们各自处理自己的任务,实现输入、处理和输出的分离。

服务器返回数据:

服务器响应请求后启动一个新的子进程去处理这个请求,处理完毕后会返回相应文件。

HTTP响应报文由响应行(request line)、响应头部(header)、响应主体三个部分组成。

  1. 响应行包含:协议版本,状态码,状态码描述;

状态码:由3位数组成

  • 1xx:指示信息–表示请求已接收,继续处理。
  • 2xx:成功–表示请求已被成功接收、理解、接受。
  • 3xx:重定向–要完成请求必须进行更进一步的操作。
  • 4xx:客户端错误–请求有语法错误或请求无法实现。
  • 5xx:服务器端错误–服务器未能实现合法的请求。
  1. 响应头部包含响应报文的附加信息,由 名/值 对组成;
  2. 服务器返回给浏览器的文本信息,通常HTML, CSS, JS, 图片等文件,并不是所有响应报文都有响应数据。
客户端接收数据:

请求的响应终于成功到达了客户端的浏览器,响应到达浏览器之后,浏览器首先会根据返回的响应报文里的一个重要信息——状态码进行判断。

浏览器加载资源/渲染页面:
  • 根据 HTML 解析出 DOM 树;
  • 根据 CSS 解析生成 CSS 规则树;
  • 结合 DOM 树和 CSS 规则树,生成渲染树;
  • 根据渲染树计算每一个节点的信息;
  • 根据计算好的信息绘制页面;

不过多描述,可以参考之前写的文章进行了解。
Dom树重绘和重排

断开TCP 连接:

当数据传送完毕,需要断开 TCP 连接,此时发起 TCP 四次挥手。

当被动方收到主动方的FIN报文通知时,它仅仅表示主动方没有数据再发送给被动方了。但未必被动方所有的数据都完整的发送给了主动方,所以被动方不会马上关闭SOCKET,它可能还需要发送一些数据给主动方后,再发送FIN报文给主动方,告诉主动方同意关闭连接,所以这里的ACK报文和FIN报文多数情况下都是分开发送的。

  • 第一次挥手:Client发送一个FIN,用来关闭Client到Server的数据传送,Client进入FIN_WAIT_1状态。
  • 第二次挥手:Server收到FIN后,发送一个ACK给Client,确认序号为收到序号+1(与SYN相同,一个FIN占用一个序号),Server进入CLOSE_WAIT状态。
  • 第三次挥手:Server发送一个FIN,用来关闭Server到Client的数据传送,Server进入LAST_ACK状态。
  • 第四次挥手:Client收到FIN后,Client进入TIME_WAIT状态,接着发送一个ACK给Server,确认序号为收到序号+1,Server进入CLOSED状态,完成四次挥手。

javascript渲染进程的主线程 js页面渲染过程_IP_03


总结:

文章主要大概讲述页面渲染的过程,没有深入进行解析,有兴趣的同学可以自行对其中的历程每一步进行深究,欢迎共同分享~