Alexgogoing

web首屏性能优化

字数统计: 1.3k阅读时长: 5 min
2021/05/09 Share

web首屏性能优化

web首屏性能和多个方面有关,白屏时间、首屏时间、网络请求时间等,由此衍生了多个定义如FCP、LCP、TTI等。

定义解释

示意1

  • 白屏时间:

    一般指浏览器开始渲染或者解析完的时间是白屏结束的时间点。白屏时间 = firstPaint - performance.timing.navigationStart || pageStartTime

  • navigationStart:

  • unloadEventStart:

    表示前一个网页(与当前页面同域)unload 的时间戳,如果无前一个网页 unload 或者前一个网页与当前页面不同域,则值为 0。

  • unloadEventEnd:

    返回前一个页面 unload 时间绑定的回掉函数执行完毕的时间戳。

  • redirectStart:

    第一个 HTTP 重定向发生时的时间。有跳转且是同域名内的重定向才算,否则值为 0。

  • redirectEnd:

    最后一个 HTTP 重定向完成时的时间。有跳转且是同域名内部的重定向才算,否则值为 0。

  • fetchStart:

    浏览器准备好使用 HTTP 请求抓取文档的时间,这发生在检查本地缓存之前。

  • domainLookupStart/domainLookupEnd:

    DNS 域名查询开始/结束的时间,如果使用了本地缓存(即无 DNS 查询)或持久连接,则与 fetchStart 值相等

  • connectStart:

    HTTP(TCP)开始/重新 建立连接的时间,如果是持久连接,则与 fetchStart 值相等。

  • connectEnd:

    HTTP(TCP) 完成建立连接的时间(完成握手),如果是持久连接,则与 fetchStart 值相等。

  • secureConnectionStart:

    HTTPS 连接开始的时间,如果不是安全连接,则值为 0。

  • requestStart:

    HTTP 请求读取真实文档开始的时间(完成建立连接),包括从本地读取缓存。

  • responseStart:

    HTTP 开始接收响应的时间(获取到第一个字节),包括从本地读取缓存。

  • responseEnd:

    HTTP 响应全部接收完成的时间(获取到最后一个字节),包括从本地读取缓存。

  • domLoading:

    开始解析渲染 DOM 树的时间,此时 Document.readyState 变为 loading,并将抛出 readystatechange 相关事件。

  • domInteractive:

    完成解析 DOM 树的时间,Document.readyState 变为 interactive,并将抛出 readystatechange 相关事件,注意只是 DOM 树解析完成,这时候并没有开始加载网页内的资源。

  • domContentLoadedEventStart:

    DOM 解析完成后,网页内资源加载开始的时间,在 DOMContentLoaded 事件抛出前发生。

  • domContentLoadedEventEnd:

    DOM 解析完成后,网页内资源加载完成的时间(如 JS 脚本加载执行完毕)。

  • domComplete:

    DOM 树解析完成,且资源也准备就绪的时间,Document.readyState 变为 complete,并将抛出 readystatechange 相关事件。

  • loadEventStart:

    load 事件发送给文档,也即 load 回调函数开始执行的时间。

  • loadEventEnd:

    load 事件的回调函数执行完毕的时间。

关键指标

  1. 网页重定向耗时(Redirect)
  1. 检查本地缓存耗时(AppCache)
  1. DNS查询耗时(DNS)
  1. TCP连接耗时(TCP)
  1. 从客户端发起请求到接收到响应的时间(Time To First Byte)
  1. 下载服务端返回数据的时间(HTTP total time)
  1. DOM加载完成时间(DOMContentLoaded)
  1. 页面load的总耗时(Loaded)

实践:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>白屏</title>
<!-- 模拟页面 CSS 资源 -->
<link href="https://cdn.bootcdn.net/ajax/libs/basscss/8.1.0/css/basscss-cp.css" rel="stylesheet">
</head>
<body>
<script>
// 白屏结束时间
window.firstPaint = Date.now()
// 白屏时间
console.log(firstPaint - performance.timing.navigationStart)

function getPerformanceTiming1(){
var e = window.performance;
if (e) {
var t = e.getEntriesByType("navigation")[0]
, r = 0;
t || (r = (t = e.timing).navigationStart);
var n = [{
key: "Redirect",
desc: "\u7f51\u9875\u91cd\u5b9a\u5411\u7684\u8017\u65f6",
value: t.redirectEnd - t.redirectStart
}, {
key: "AppCache",
desc: "\u68c0\u67e5\u672c\u5730\u7f13\u5b58\u7684\u8017\u65f6",
value: t.domainLookupStart - t.fetchStart
}, {
key: "DNS",
desc: "DNS\u67e5\u8be2\u7684\u8017\u65f6",
value: t.domainLookupEnd - t.domainLookupStart
}, {
key: "TCP",
desc: "TCP\u8fde\u63a5\u7684\u8017\u65f6",
value: t.connectEnd - t.connectStart
}, {
key: "Waiting(TTFB)",
desc: "\u4ece\u5ba2\u6237\u7aef\u53d1\u8d77\u8bf7\u6c42\u5230\u63a5\u6536\u5230\u54cd\u5e94\u7684\u65f6\u95f4 / Time To First Byte",
value: t.responseStart - t.requestStart
}, {
key: "Content Download",
desc: "\u4e0b\u8f7d\u670d\u52a1\u7aef\u8fd4\u56de\u6570\u636e\u7684\u65f6\u95f4",
value: t.responseEnd - t.responseStart
}, {
key: "HTTP Total Time",
desc: "http\u8bf7\u6c42\u603b\u8017\u65f6",
value: t.responseEnd - t.requestStart
}, {
key: "DOMContentLoaded",
desc: "dom\u52a0\u8f7d\u5b8c\u6210\u7684\u65f6\u95f4",
value: t.domContentLoadedEventEnd - r
}, {
key: "Loaded",
desc: "\u9875\u9762load\u7684\u603b\u8017\u65f6",
value: t.loadEventEnd - r
}];
console && console.log && console.log(n);
}
}

// 计算加载时间
function getPerformanceTiming() {
var t = performance.timing;
var times = {};
// 页面加载完成的时间,用户等待页面可用的时间
times.loadPage = t.loadEventEnd - t.navigationStart;
// 解析 DOM 树结构的时间
times.domReady = t.domComplete - t.responseEnd;
// 重定向的时间
times.redirect = t.redirectEnd - t.redirectStart;
// DNS 查询时间
times.lookupDomain = t.domainLookupEnd - t.domainLookupStart;
// 读取页面第一个字节的时间
times.ttfb = t.responseStart - t.navigationStart;
// 资源请求加载完成的时间
times.request = t.responseEnd - t.requestStart;
// 执行 onload 回调函数的时间
times.loadEvent = t.loadEventEnd - t.loadEventStart;
// DNS 缓存时间
times.appcache = t.domainLookupStart - t.fetchStart;
// 卸载页面的时间
times.unloadEvent = t.unloadEventEnd - t.unloadEventStart;
// TCP 建立连接完成握手的时间
times.connect = t.connectEnd - t.connectStart;
return times;
}
setTimeout(() => {
getPerformanceTiming1();
}, 0)
</script>

<h1>Hello World</h1>
</body>
</html>
CATALOG
  1. 1. web首屏性能优化
    1. 1.1. 定义解释
    2. 1.2. 关键指标