白屏时间和首屏时间是我们衡量网站加载性能的两个重要指标。在开发中,我们需要根据业务页面的具体情况,相应地统计页面白屏时间和首屏时间。对于白屏时间和首屏时间,计算的原理是不变的,但计算的的方式可能会根据页面情况有所改变,因此大家需要具体问题具体分析。
白屏时间
白屏时间指的是浏览器开始显示内容的时间。因此我们只需要知道是浏览器开始显示内容的时间点,即页面白屏结束时间点即可获取到页面的白屏时间。
通过浏览器工作原理,我们可以知道:
- 浏览器在加载页面的刚开始,页面是处于空白的状态,只有当页面发生绘制操作时会开始显示内容。
- 浏览器加载页面是一个渐进的过程。为达到更好的用户体验,呈现引擎会力求尽快将内容显示在屏幕上。它不必等到整个 HTML 文档解析完毕之后,就会开始构建呈现树和设置布局。在不断接收页面内容的同时,呈现引擎会将部分内容解析并显示出来。
- 非可视化的 DOM 元素不会显示到窗口中,例如 <head>,这就意味着浏览器在绘制之前,至少需要先解析完head元素中的内容。
计算白屏时间
因此,我们通常认为浏览器开始渲染 <body> 标签或者解析完 <head> 标签的时刻就是页面白屏结束的时间点。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>白屏</title>
<script type="text/javascript">
// 不兼容performance.timing 的浏览器,如IE8
window.pageStartTime = Date.now();
</script>
<!-- 页面 CSS 资源 -->
<link rel="stylesheet" href="common.css">
<link rel="stylesheet" href="page.css">
<script type="text/javascript">
// 白屏时间结束点
window.firstPaint = Date.now();
</script>
</head>
<body>
<!-- 页面内容 -->
</body>
</html>
因此白屏时间则可以这样计算出:
可使用 Performance API 时
白屏时间 = firstPaint - performance.timing.navigationStart;
不可使用 Performance API 时
白屏时间 = firstPaint - pageStartTime;
首屏时间
首屏时间是指用户打开网站开始,到浏览器首屏内容渲染完成的时间。对于用户体验来说,首屏时间是用户对一个网站的重要体验因素。通常一个网站,如果首屏时间在5秒以内是比较优秀的,10秒以内是可以接受的,10秒以上就不可容忍了。超过10秒的首屏时间用户会选择刷新页面或立刻离开。
计算首屏时间
明白了首屏时间的概念后,我们计算首屏时间则更加清晰了。现实中,不同业务的首屏内容并不是一样的。因此计算首屏时间,需要根据业务页面情况,相应地选择计算首屏时间的方法。
通常计算首屏的方法有
- 首屏模块标签标记法
- 统计首屏内加载最慢的图片的时间
- 自定义首屏内容计算法
1、首屏模块标签标记法
首屏模块标签标记法,通常适用于首屏内容不需要通过拉取数据才能生存以及页面不考虑图片等资源加载的情况。我们会在 HTML 文档中对应首屏内容的标签结束位置,使用内联的 JavaScript 代码记录当前时间戳。如下所示:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首屏</title>
<script type="text/javascript">
window.pageStartTime = Date.now();
</script>
<link rel="stylesheet" href="common.css">
<link rel="stylesheet" href="page.css">
</head>
<body>
<!-- 首屏可见模块1 -->
<div class="module-1"></div>
<!-- 首屏可见模块2 -->
<div class="module-2"></div>
<script type="text/javascript">
window.firstScreen = Date.now();
</script>
<!-- 首屏不可见模块3 -->
<div class="module-3"></div>
<!-- 首屏不可见模块4 -->
<div class="module-4"></div>
</body>
</html>
此时首屏时间等于 firstScreen - performance.timing.navigationStart;
事实上首屏模块标签标记法 在业务中的情况比较少,大多数页面都需要通过接口拉取数据才能完整展示,因此我们会使用 JavaScript 脚本来判断首屏页面内容加载情况。
2、统计首屏内图片完成加载的时间
通常我们首屏内容加载最慢的就是图片资源,因此我们会把首屏内加载最慢的图片的时间当做首屏的时间。
由于浏览器对每个页面的 TCP 连接数有限制,使得并不是所有图片都能立刻开始下载和显示。因此我们在 DOM树 构建完成后将会去遍历首屏内的所有图片标签,并且监听所有图片标签 onload 事件,最终遍历图片标签的加载时间的最大值,并用这个最大值减去 navigationStart 即可获得近似的首屏时间。
此时首屏时间等于 加载最慢的图片的时间点 - performance.timing.navigationStart;
3、自定义模块内容计算法
由于统计首屏内图片完成加载的时间比较复杂。因此我们在业务中通常会通过自定义模块内容,来简化计算首屏时间。如下面的做法:
- 忽略图片等资源加载情况,只考虑页面主要 DOM
- 只考虑首屏的主要模块,而不是严格意义首屏线以上的所有内容
总结
对于首屏时间和白屏时间,业界并没有一个统一的计算标准。大家不能通过死记硬背来实现首屏时间和白屏时间的统计,而应该根据首屏时间和白屏时间的具体原理,切合自身业务情况来制定统计的方法。统计首屏时间和白屏时间是为了让我们能够更明白我们业务页面的情况,而不是为了统计而去统计。