目录
为什么写这份笔记?
前端面试的时候经常会被问到:
- 在浏览器中输入URL到页面加载完成发生了什么?
- 如何提升网页的加载速度?
我决定整理一下从URL输入到页面显示,这期间具体发生了什么?并从中总结出可以优化页面加载速度的点。
这篇文章最重要的作用是理清自己的思路,具体的原理和实现方案在本文中并不关键。
DNS查询
DNS(Domain Name Server,域名服务器)是进行域名(domain name)和与之相对应的IP地址 (IP address)转换的服务器。DNS中保存了一张域名(domain name)和与之相对应的IP地址 (IP address)的表,以解析消息的域名。
一句话来说,DNS能够根据域名找到IP地址。详见阮一峰:DNS 原理入门。
DNS是如何工作的?
- 分级查询
DNS查询域名www.baidu.com.root
的IP地址时,会依次查询.root -> .com -> .baidu -> www
,最终获取IP地址 - 缓存
DNS在查询域名IP地址时会先查询DNS缓存,会依次查询浏览器DNS缓存 -> 操作系统DNS缓存 -> 路由器缓存 -> DNS服务器
如果当前缓存中查询不到时,则向下一级缓存中查询,知道命中目标为止,然后返回IP地址,并且前面几级缓存会缓存这次请求DNS记录,提高下次查询的性能。
如何优化DNS查询?
减少DNS查询,提前DNS查询。
- DNS预解析
提前进行DNS解查询,使用时直接从缓存中取。
<!--meta标签-->
<meta http-equiv="x-dns-prefetch-control" content="on" />
<!--link标签-->
<link rel="dns-prefetch" href="https://lz5z.com" />
- 域名收敛
将静态资源文件放在同一个域名下,减少域名个数也就减少了进行DNS查询的次数。
建立TCP连接
传输控制协议(TCP,Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793 [1] 定义。
TCP旨在适应支持多网络应用的分层协议层次结构。 连接到不同但互连的计算机通信网络的主计算机中的成对进程之间依靠TCP提供可靠的通信服务。TCP假设它可以从较低级别的协议获得简单的,可能不可靠的数据报服务。 原则上,TCP应该能够在从硬线连接到分组交换或电路交换网络的各种通信系统之上操作。
HTTP协议是基于TCP协议的。DNS将域名解析为IP地址后,浏览器向IP地址发送TCP连接请求,也就是常说的三次握手(大学毕业后基本已忘光)。
顺带一提,前端面试经常问TCP的断开时需要四次挥手,为什么连接时只需要三次挥手呢?
原因是client发送发送连接/断开请求后,server端需要返回ack并返回连接/断开信息。区别在于连接时,server可以将ack和链接信息合并,但是断开时,必须ack和断开信息分别发送,因为client请求断开时,server端可能信息还没发送完,需要等待信息发送完毕后再通知client端关闭。
需要注意的是HTTPS协议,在TCP链接之前还有一次SSL认证。
HTTP:HTTP -> TCP -> IP
HTTPS:HTTP -> SSL/TLS -> TCP -> IP
掘金:详细解析 HTTP 与 HTTPS 的区别 - 马海祥
如何优化TCP链接?
首先我们需要了解,浏览器对一个HOST能建立大约6个TCP链接,一个TCP链接当前时刻只能处理一个HTTP请求。
(上面的结论不考虑HTTP2.0,不考虑HTTP1.0中的Pipelining)
-
Connection: keep-alive
HTTP1.0中每发送一个HTTP请求,都需要重新连接、断开TCP链接。HTTP1.1将Connection: keep-alive
请求头写进了标准。也就是说第一个HTTP请求建立了TCP链接,请求结束TCP链接不会断开,接下来的HTTP请求无需再进行TCP链接。就像下面两种图展示的那样,第一次请求Initial connection和SSL都花了时间,而图二请求的时候没有花费Initial connection和SSL的时间。
-
HTTP1.1 Pipelining(管道)
前面提到过一个TCP链接同一时刻只能处理一个HTTP请求。如果一个TCP能并行处理多个HTTP请求,性能肯定会更好。Pipelining
初衷是这样的但是现实却很残酷。具体Pipelining的资料这里不做过多解释。 -
HTTP2.0 Multiplexing
Multiplexing就是一个TCP链接并行处理多个HTTP请求的合理方案。
如下图中多个HTTP请求只占用了一个链接。
HTTP/2.0 相比1.0有哪些重大改进?
HTTP请求
这里推荐大家一本书《图解HTTP》,里面对HTTP介绍的很详情,最重要的是图例比较多!看起来不吃力!毕竟大部分技术书籍还是比较枯燥的。
如何优化HTTP的请求报文?
建立TCP链接之后,浏览器开始发送HTTP请求报文,请求报文包括:请求行、首部字段(请求首部、通用首部、实体首部)、报文主题。
-
HTTP2.0 首部压缩(Header Compression)
顾名思义,这个优化就是字面意思。HTTP请求中首部字段在请求过程中会以文本形式发送,占用流量,而且HTTP请求中有部分首部字段是重复的,首部压缩后,几乎可以减少一半的大小。
HTTP/2 头部压缩技术介绍 -
合理添加Cookie
图片、字体等静态文件,单独使用域名来访问。与主域区分开来的目的是为了访问的时候不携带无用的Cookie。
如何优化HTTP的响应报文?
服务端接受到请求报文后,经过一系列处理,返回信息给浏览器,返回的信息称之为响应报文。响应报文包括:状态行、首部字段(响应首部、通用首部、实体首部)、报文主题。
-
CDN:内容分发网络
使用内容分发网络(CDN),缓存、共享、分发。
CDN是什么?使用CDN有什么优势? -
减少HTTP请求
HTTP1.1协议下浏览器对并发有限制,当请求过多时合并HTTP请求减少请求数,可以优化页面下载性能。
合并请求是老话题了,CSS spirit、代码合并等,不过由于HTTP2.0的多路复用,这些优化方案显得有些多余。 -
GZIP压缩
GZIP最早由Jean-loup Gailly和Mark Adler创建,用于UNⅨ系统的文件压缩。我们在Linux中经常会用到后缀为.gz的文件,它们就是GZIP格式的。现今已经成为Internet 上使用非常普遍的一种数据压缩格式,或者说一种文件格式。
HTTP协议上的GZIP编码是一种用来改进WEB应用程序性能的技术。大流量的WEB站点常常使用GZIP压缩技术来让用户感受更快的速度。GZIP压缩基本可以使经过webpack打包压缩后的代码再搜小50%以上。
-
分片传输
分片传输,说白了就是讲一份完整的数据分成多个部分,分别后服务端请求。分片传输并没有减少数据的大小,甚至优于多次请求,总流量是偏大的。但是某些场景下是可以使用的。比如首屏是地图热力图,数据量比较大,为了让页面提前显示出来,可以先请求前20%的数据,拿到数据后就开始绘制地图。
-
缓存
缓存优化主要体现在:HTTP缓存、数据缓存。HTTP缓存分为强缓存和协商缓存,请求命中强缓存时不会发送到服务端,而是直接从本地读取资源。如下图红框中内容所示,资源直接从内存(memory cache)和磁盘(disk cache)中读取。
浏览器是根据什么决定「from disk cache」与「from