后面会把前端进阶的课程内容都总结一遍。有些都是很常见的知识,但是为了梳理自己的知识树,所以尽量模糊的地方都会记录
笔记列表在公众号右下角
今天要记录的知识盲区是 白屏 和 首屏
作为衡量网站性能的重要指标之一
这两个指标是非常重要的,这两个的时间越长,你的网站体验越差,流失用户就越多
所以作为前端,非常有必要深入了解这两个东东,所涉及的内容是 performance,所以请先了解下,可以通过这个文章
白屏时间
页面开始请求,到 页面刚开始显示内容,叫做白屏时间
白屏时间 = 页面开始展示时间点 - 开始请求时间点
但是怎么获取 页面刚开始解析的时间啊,我们需要了解 HTML 文档是怎么解析的
浏览器绘制页面是渐进的,上到下解析,不需要等到 所有 HTML 文档都解析完毕。
在不断地接受内容的同时,引擎会将这部分内容解析并且显示出来
1、非可视化内容不会显示到窗口。浏览器绘制之前,肯定先解析 head
2、head 结束,解析 body
所以一般我们认为,开始解析 body 就是 页面开始解析的时间
那么到底怎么获取白屏时间呢?
1、使用 performance
在 performance 中并没有提供 页面刚开始展示的时间点,所以我们只能手动在 body 标签前写一个 脚本去获取时间
<html>
<head>
<title>白屏时间</title>
<link href="xxxxx"/>
<script> var endTime = new Date() </script> </head> <body> </body></html>
而我们可以获取开始请求的时间,所以这么计算
白屏时间 = endTime - performance.timing.navigationStart
2、不使用 performance
如果不使用 performance 的话,我们就只能在 head 的 头 和 尾 各截取一个时间来相减了
<html>
<head>
<script> var startTime = new Date() </script> <title>白屏时间</title>
<link href="xxxxx"/>
<link href="xxxxx"/>
<script> var endTime = new Date() </script> </head> <body>xxxxxx</body></html>
然后这么去计算
白屏时间 = endTime - startTime
首屏时间
首屏时间是指,在不滚动屏幕下的前提下,用户看到完整第一屏内容花费的时间
首屏内容完全加载完成,才叫首屏,而不是出现内容,或者部分元素没有展示
首屏时间一般在 5秒以内是优秀,10秒以内可接受,10s 以后根本不能忍
现在呢,我们并没有一个明确的API来直接得到
首屏时间那我们到底要怎么得到首屏时间?
我们只能智取了,比如我们要知道第一屏内容底部在 html 文档的什么位置
那么这个第一屏内容底部,也称之为 首屏线
比如这样
我们已经可以获取页面开始加载的时间,和 白屏时间一样
现在只要我们找到这个首屏线,然后首屏线附近 获取一个时间 ,这样
首屏时间 = firstScreen - performance.timing.navigationStart
一切就ok 了
问题是,首屏线在哪里啊
情况分很多种,不同的场景,有不同的计算方式,我们需要根据自己的实际情况去选择相应的方法
1标记首屏标签模块
这种计算方式比较简单,通过在 html 文档中,在首屏线的位置,添加脚本的方式,去获取这个位置的时间
那在哪里添加呢?
首屏线其实我们只能大约估摸一个位置,并不能十分精确地适配任何屏幕的手机
因为手机屏大小不一,我们取的位置可能在 首屏线之上,可能在 首屏线之下,只能得到一个大约的值
但是并不需要太精确的数字,大小屏首屏内容反正不会差太多
适用场景
1、首屏内不需要拉取数据,否则可能拿到首屏线获取时间的时候,首屏还是空白
2、不需要考虑图片加载,只考虑首屏主要模块
具体做法
<html lang="en">
<body>
<div class="module-1"></div>
<div class="module-2"></div>
<script type="text/javascript"> window.firstScreen = Date.now(); </script>
<div class="module-3"></div>
<div class="module-4"></div> </body></html>
之后计算
首屏时间 = firstScreen - performance.timing.navigationStart
但是在业务中,较少使用这种算法,大多数页面需要使用接口,所以这种方法就太常用
但是如果你的页面是静态页面,或者异步数据不影响整体的首屏体验,那么就可以使用这种办法
毕竟这种办法是最为简单的,然后就大概给自己一个简单的参考值
2统计首屏最慢图片加载时间
一般来说,首屏内容加载最慢的就是图片资源
所以,可以把 首屏内加载最慢的图片的时间 ,当做首屏时间
那么我们怎么获取首屏内最慢的图片呢?
首先,我们就要拿到首屏内所有的图片,然后遍历他们,逐个监听图片标签的 onload 事件,并收集到他们的加载时间
最后比较得到加载时间的最大值
然后这么计算
首屏时间 = 加载最慢的首屏图片时间- performance.timing.navigationStart
你又问了
我怎么获取首屏内的所有图片?
在实际的生产中,我们都会给每个图片一个容器,容器是固定高度的,并且这个容器和图片素材是契合的,并不会因此导致图片的变形
然后通过高度判断哪些容器在首屏内,然后就拿到相应的 img 了
这种场景相信大家也都见过,比如图片加载失败的时候,会显示一个图片破碎的 icon,但是容器高度是没有塌陷的,就是因为提前设置了高度(上面我还专门问了腾讯的老师,因为好像我从来不给图片高度。。)
3自定义模块计算法
这个算法和 标记首屏的方法极为相似,同样忽略了首屏内图片加载的情况
但是自定义模块的方法考虑了一个重要因素,就是异步数据
在首屏标签标记法中,是无法计算到异步数据带来的首屏空白的,所以它的适配场景十分有限
自定义模块,就是根据首屏内接口计算比较得出最迟的时间
具体做法
<html>
<body>
<div class="module-1"></div>
<div class="module-2"></div>
<script type="text/javascript"> // 一个重要的模块采用了异步加载的形式 setTimeout(() => { // 这里加载一个重要模块,比如课程列表 window.firstScreen = Date.now();
}, 3000) </script>
<div class="module-3"></div>
<div class="module-4"></div> </body></html>
之后计算
首屏时间 = firstScreen - performance.timing.navigationStart
总结
首屏和白屏时间,没有统一计算标准。
上面的各种算法是作为一个参考,最好在实际生产中要通过自身业务制定方法,而不是死记硬背一个方法来实现计算
只要掌握原理,然后根据自己的项目才能定制一个适合的方法