Web 性能指标

web 性能优化到底在优化什么?

你可能会说优化的是用户体验,但用户体验是不可测量的,我们必须把用户体验变成可测量的指标,这些指标包括:

  1. 用户按下回车
  2. 由内容出现时(一般3秒之内还没有内容出现,用户就会比较焦虑,会关掉页面)
  3. DOM ready 事件发生(dom content loading ,代表 HTML 内容全部解析完,js 也基本执行完了,但并不保证图片已经全部加载和 css 样式加载完,就是 network 里面那跟蓝色的线)
  4. 页面可交互(JS 都执行了,并且把事件都绑定了,用户点击按钮不会出现没反应的情况)
  5. onLoad 事件发生
  6. 动态资源加载完毕

DNS prefetch

DNS 预解析

假设 index.html 的部分代码为:

那么过程就是首先对 a.com 进行 dns 查询 => 拿到 ip 地址以后 => 下载a.js => 对 b.com 进行 dns 查询(一定会等 a.js 下载执行完毕后才开始) => 拿到 ip 地址以后 => 下载b.js
如果 a.com 和 b.com 同时先进行 dns 预解析,那么就能节省一定的时间

优化(两种方法)

前端
1
2
<link ref="des-prefetch" href="https://a.com/" >
<link ref="des-prefetch" href="https://b.com/" >
后端
1
2
// index.html 的响应头里写
Link: <http://a.com />; rel=dns=prefetch

TCP 连接复用

正常流程:开启 TCP => 请求 => 响应 => 关闭 => 开启 TCP….
可以发现一直在重复开启关闭,为何不复用呢,开启后就不关闭了,节约多次重复开启关闭的时间。

实现

1
2
// 请求头
Connection: keep-alive
1
2
// 响应头
Connection: keep-alive

但是如果服务器一直开着将会非常占用资源,用户一多,服务器就顶不住了,所以一般都会在设置一个超时时间,如果超过多少秒还没有再次发起连接,那么将会强制关闭。

1
2
// 请求头
KeepAlive: timeout=5, max=10
1
2
// 响应头
KeepAlive: timeout=10, max=100

客户端和服务器都可以设置这个字段,两者可以不一样,timeout 表示多少秒,max 表示多少次,一般来说聪明的浏览器会以服务器为准(尊重服务器的能力),而傻一点的浏览器(如:IE)就坚持自己为准

前端怎么加 keep-alive?

如果用的 http/1.1 以上,会自动加。
也就是基本上不用去优化了。

并行化连接

因为连接复用是串行的,当同时处理多个请求的时候还是太慢,所以需要并行连接。
也就是说同时建立好几个请求(一般浏览器会设置最大数量,同一个域名一般 4-12 个)
那么连接复用就没有用了吗?
答案是不会,因为浏览器设置了连接上限,如果超出的连接数,那么剩下的就会等待上一个请求结束后再进行复用。

🌰:

相同的 id 代表连接复用

HTTP 管道化

浏览器默认关闭,可能会有 BUG

🌰:

1
2
3
4
5
|一个 http 管道-------------------------
|| 1.css ----- 响应
| | 2.css ----- 响应
| | 3.css ----- 响应
|--------------------------------------

当在管道中发起(接近同时)三个请求时,会有如下问题:

  1. 浏览器必须要按照相当的顺序返回响应,否则会对应不上,不像并行一样,每次都是新的连接一一对应。
  2. 如果 1.css 因为网络波动特别慢,那么 剩下的必须得等 1.css 响应结束才可以继续,因为一旦 2.css 提前响应了就会被浏览器错误的当成 1.css 的响应。
    所以他会导致请求之前的顺序依赖,导致这样的并行没法导致最快的速度,所以一开始的 http 设计并不能满足现在的需求,所以需要升级为 HTTP/2.0