网络优化
一、认识
网络优化: 包括 HTTP2
、DNS
预解析、Preload
、Prefetch
等手段
二、HTTP2
传统的 HTTP 1.1
存在队头阻塞的问题,同一个 TCP
管道中同一时刻只能处理一个 HTTP
请求,也就是说如果当前请求没有处理完,其它的请求都处于阻塞状态,另外浏览器对于同一域名下的并发请求数量都有限制,比如 Chrome
中只允许 6
个请求并发(这个数量不允许用户配置),也就是说请求数量超过 6
个时,多出来的请求只能排队、等待发送。
因此,在 HTTP 1.1
协议中,队头阻塞和请求排队问题很容易成为网络层的性能瓶颈。而 HTTP 2
的诞生就是为了解决这些问题,它主要实现了如下的能力:
-
多路复用: 将数据分为多个二进制帧,多个请求和响应的数据帧在同一个
TCP
通道进行传输,解决了之前的队头阻塞问题。而与此同时,在HTTP2
协议下,浏览器不再有同域名的并发请求数量限制,因此请求排队问题也得到了解决。 -
Server Push
: 即服务端推送能力。可以让某些资源能够提前到达浏览器,比如对于一个html
的请求,通过HTTP 2
我们可以同时将相应的js
和css
资源推送到浏览器,省去了后续请求的开销。
三、DNS 预解析
浏览器在向跨域的服务器发送请求时,首先会进行 DNS
解析,将服务器域名解析为对应的 IP
地址。我们通过 dns-prefetch
技术将这一过程提前,降低 DNS
解析的延迟时间,具体使用方式如下:
<!-- href 为需要预解析的域名 -->
<link rel="dns-prefetch" href="https://fonts.googleapis.com/">
一般情况下 dns-prefetch
会与 preconnect
搭配使用,前者用来解析 DNS
,而后者用来会建立与服务器的连接,建立 TCP
通道及进行 TLS
握手,进一步降低请求延迟。使用方式如下所示:
<link rel="preconnect" href="https://fonts.gstatic.com/" crossorigin>
<link rel="dns-prefetch" href="https://fonts.gstatic.com/">
值得注意的是,对于 preconnect
的 link
标签一般需要加上 crorssorigin
(跨域标识),否则对于一些字体资源 preconnect
会失效。
四、Preload/Prefetch
对于一些比较重要的资源,我们可以通过 Preload
方式进行预加载,即在资源使用之前就进行加载,而不是在用到的时候才进行加载,这样可以使资源更早地到达浏览器。具体使用方式如下:
<link rel="preload" href="style.css" as="style">
<link rel="preload" href="main.js" as="script">
其中我们一般会声明 href
和 as
属性,分别表示资源地址和资源类型。Preload
的浏览器兼容性也比较好,目前 90%
以上的浏览器已经支持。
与普通 script
标签不同的是,对于原生 ESM
模块,浏览器提供了 modulepreload
来进行预加载:
<link rel="modulepreload" href="/src/app.js" />
仅有 70%
左右的浏览器支持这个特性,不过在 Vite
中我们可以通过配置一键开启 modulepreload
的 Polyfill
,从而在使所有支持原生 ESM
的浏览器(占比 90%
以上)都能使用该特性,配置方式如下:
// vite.config.ts
export default {
build: {
polyfillModulePreload: true
}
}
除了 Preload
,Prefetch
也是一个比较常用的优化方式,它相当于告诉浏览器空闲的时候去预加载其它页面的资源,比如对于 A
页面中插入了这样的 link
标签:
<link rel="prefetch" href="https://B.com/index.js" as="script">
这样浏览器会在 A
页面加载完毕之后去加载B这个域名下的资源,如果用户跳转到了B页面中,浏览器会直接使用预加载好的资源,从而提升 B
页面的加载速度。而相比 Preload
, Prefetch
的浏览器兼容性不太乐观