网络优化
一、认识
网络优化: 包括 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
(预加载)和prefetch
(预加载) 通常用于本页面用到的关键资源,包括关键js
、字体、css
文件。preload
(预加载)与prefetch
(预加载) 的区别为:
-
preload
告诉浏览器一定会用到某个资源,浏览器会提升这个资源的加载优先级为**High
** -
prefetch
告诉浏览器可能会用到某个资源,浏览器会以一个非常低的优先级**lowest
**,在空闲时间段加载这个资源
深入学习 Preload、Prefetch 以及网络加载优先级
4.1 preload
entry1.js
动态引入util.js
脚本,并将webpackPreload
开启
const btn = document.createElement("button");
btn.innerHTML = "动态插入";
btn.onclick = () => {
const { foo2 } = import(/* webpackPreload:true */ "./utils");
foo2();
};
document.body.append(btn);
- 通过
@vue/preload-webpack-plugin
插件向index.html
模板插入Link
标签
const Path = require("path");
const HtmlWebpackPlugin = require('html-webpack-plugin');
const PreloadWebpackPlugin = require('@vue/preload-webpack-plugin');
module.exports = {
mode: "production",
entry: {
entry1: Path.resolve(__dirname, "src", "entry1.js"),
},
output: {
filename: "[name].js",
path: Path.resolve(__dirname, "build"),
},
plugins:[
new HtmlWebpackPlugin({
template:Path.resolve(__dirname,'index.html')
}),
new PreloadWebpackPlugin()
]
};
- 动态插入 preload 效果如下:
深入学习 Preload、Prefetch 以及网络加载优先级
4.2 prefetch
entry1.js
动态引入util.js
脚本,并将webpackPrefetch
开启
const btn = document.createElement("button");
btn.innerHTML = "动态插入";
btn.onclick = () => {
const { foo2 } = import(/* webpackPrefetch:true */ "./utils");
foo2();
};
document.body.append(btn);
- 动态插入 prefetch 效果如下: