a、RAIL 模型
RAIL 是一种以用户为中心的性能模型。每个网络应用均具有与其生命周期有关的四个不同方面,且这些方面以不同的方式影响着性能。
1.响应:输入延迟时间(从点按到绘制)小于 100 毫秒。
一般指的是用户输入网页快速给出结果的过程,比如点击按钮,切换表单,启动动画之类的。
2.动画:每个帧的工作(从 JS 到绘制)完成时间小于 16 毫秒。
指的是涉及style,layout,paint,composite过程的行为。比如:用户滚动页面,拖动刷新,页面动画等
3.空闲:主线程 JS 工作分成不大于 50 毫秒的块。
用户没有与页面交互,但主线程应足够用于处理下一个用户输入。
4.加载:页面可以在 1000 毫秒内就绪。
一般指网页加载这一段时间。
b、用户对于网站延迟的反应
- 0-16ms:动画的一帧渲染不大于16ms时,用户会感觉动画是流畅的。
- 0-100ms:当用户进行操作时,100ms内窗口响应用户操作,用户会有一种立即获得结果的感觉。
- 100-300ms:用户可能微微察觉到一点延迟。
- 300-1000ms:此时长范围是用户能接受的页面的加载或者视图的改变所用时长。
- 1000+ms:用户的注意力将离开正在执行的任务。
- 10000+ms:用户已经没有耐心等待下去。
c、性能指标
常用的指标就是:白屏,首屏,domready,pageloaded四个指标,在通常的index.html中,我们通过性能API获取到响应的指标值。
1、白屏:一般认为浏览器开始渲染<body>标签或者解析完<head>标签的时刻就是页面白屏结束的时间点。
白屏开始时间相当于performance.timing.navigationStart
白屏结束时间相当于performance.timing.responseStart
2、首屏:首屏是指用户看到的第一屏,就是网页当前窗口的区域完整显示的时间。
首屏内容加载最慢的就是图片资源,在DOM树构建完成后将会去遍历首屏内所有图片标签,并监听所有图片的onload事件,最终遍历图片标签的加载时间的最大值,用这个最大值减去navigationStart可获取近似的首屏时间。
首屏时间相当于最后一张图片加载的时间减去navigationStart时间
3、domready:指浏览器开始对基础页文件内容进行解析到文本中构建出一个内部数据结构(DOM树)的时间。
dom渲染完成时间是DOMContentLoaded事件监听的,所有它的结束时间相当于performance.timing.domContentLoadedEventEnd。
4、pageloaded:整页加载完成时间,该结束时间通过window.onload()进行采集。
pageloaded结束时间相当于performance.timing.loadEventEnd。
总结:
unload | 前一个页面卸载耗时 | unloadEventEnd - unloadEventStart | 前一个页面卸载时可能监听了 unload 做些数据收集,会影响页面跳转 |
redirect | 重定向耗时 | redirectEnd - redirectStart | 过多重定向影响性能 |
appCache | 缓存耗时 | domainLookupStart - fetchStart | |
dns | DNS 解析耗时 | domainLookupEnd - domainLookupStart | |
tcp | TCP 连接耗时 | connectEnd - connectStart | |
ssl | SSL 安全连接耗时 | connectEnd - secureConnectionStart | 只在 HTTPS 下有效 |
ttfb | Time to First Byte(TTFB),网络请求耗时 | responseStart - requestStart | |
response | 数据传输耗时 | responseEnd - responseStart | |
dom | 可交互 DOM 解析耗时 | domInteractive - responseEnd | Interactive content |
dom2 | 剩余 DOM 解析耗时 | domContentLoadedEventStart - domInteractive | DOMContentLoaded 所有DOM元素都加载完毕(除了 async script) |
DCL | DOMContentLoaded 事件耗时 | domContentLoadedEventEnd - domContentLoadedEventStart | document.addEventListener('DOMContentLoaded', cb) |
resources | 资源加载耗时 | loadEventStart - domContentLoadedEventEnd | 完整DOM(DOMContentLoaded)到资源加载完毕(window.onLoad)时间 |
onLoad | onLoad事件耗时 | loadEventEnd - loadEventStart | |
firstbyte | 首包时间 | responseStart - domainLookupStart | |
fpt | First Paint Time, 首次渲染时间 / 白屏时间 | responseStart - navigationStart | 从请求开始到浏览器开始解析第一批 HTML 文档字节的时间差 |
tti | Time to Interact,首次可交互时间 | domInteractive - navigationStart | 浏览器完成所有 HTML 解析并且完成 DOM 构建,此时浏览器开始加载资源 |
ready | HTML 加载完成时间, 即 DOM Ready 时间 | domContentLoadedEventEnd - navigationStart | 如果页面有同步执行的 JS,则同步 JS 执行时间 = ready - tti |
load | 页面完全加载时间 | loadEventEnd - navigationStart | load = 首次渲染时间 + DOM 解析耗时 + 同步 JS 执行 + 资源加载耗时 |
navigationStart | 表示从上一个文档卸载结束时的unix时间戳,如果没有上一个文档,则与fetchStart一致 |
unloadEventStart | 表示前一个网页(与当前页面同域)unload的时间戳,如果无前一个网页unload或者前一个网页与当前页面不同域,则值为0 |
unloadEventEnd | 返回前一个页面unload事件绑定的回调函数执行完毕的时间戳 |
redirectStart | 重定向开始的时间戳,同域内才算,否则为0 |
redirectEnd | 重定向结束的时间戳,同域内才算,否则为0 |
fetchStart | 浏览器准备使用http请求抓取文档的时间戳,这发生在检查本地缓存之前 |
domaInLookupStart/domaInLookupEnd | DNS域名查询开始/结束时间,如果使用了本地缓存(无DNS查询)或持久链接,则与fetchStart值相等 |
connectStart | TCP开始建立连接的时间戳,如果是持久链接,则与fetchStart值一致 |
connectEnd | TCP完成握手的时间戳,如果是持久链接,则与fetchStart值一致 |
secureConnectionStart | HTTPS链接开始的时间,如果不是安全链接,值为0 |
requestStart | HTTP请求开始时间,包括从本地读取缓存 |
responseStart | HTTP开始接收响应的时间(获取到第一个字节),包括从本地读取缓存 |
responseEnd | HTTP接收响应完成的时间(获取到最后一个字节),包括从本地读取缓存 |
domLoading | 开始解析DOM树的时间,此时Document.readyState变为loading,抛出readystatechange事件 |
domInteractive | 完成解析DOM树的时间,此时Document.readyState变为interactive,此时并没有加载资源,抛出readystatechange事件 |
domContentLoadEventStart | DOM树解析完成后,网页资源开始加载的时间,在domContentLoaded事件抛出前发生 |
domContentLoadEventEnd | DOM树解析完成后,网页资源加载完成的时间 |
domComplete | DOM树解析完成后,资源准备就绪的时间,此时Document.readyState变为complete,抛出readystatechange事件 |
loadEventStart | load事件开始时间 |
loadEventEnd | load事件结束时间,网页加载完成 |
d、TTI(Time to Interactive)
1、TTI:The TTI metric measures the time from when the page starts loading to when its main sub-resources have loaded and it is capable of reliably responding to user input quickly.
TTI指标测量时间是从页面开始加载到其主要子资源已加载的时间,并且能够可靠地快速响应用户输入。
2、计算TTI
- Start at First Contentful Paint (FCP).从(FCP)首次内容绘制开始
- Search forward in time for a quiet window of at least five seconds, where quiet window is defined as: no long tasks and no more than two in-flight network GET requests.向前搜索5秒,没有长任务,且不能超过2个get请求
- Search backwards for the last long task before the quiet window, stopping at FCP if no long tasks are found.向后搜索最后一个长任务,如果没有长任务被发现就到FCP停止
- TTI is the end time of the last long task before the quiet window (or the same value as FCP if no long tasks are found).TTI的时间是最后一个长任务的时间,如果没有长任务的话,则等于FCP时间
引入tti-polyfill.js(可通过npm包获取),获取到tti值
import ttiPolyfill from './path/to/tti-polyfill.js';
ttiPolyfill.getFirstConsistentlyInteractive().then((tti) => {
...
});
3、long task
对于用户而言,任务耗时较长表现为滞后或卡顿,而这也是目前网页不良体验的主要根源
测量长任务
var observer = new PerformanceObserver(function(list) {
var perfEntries = list.getEntries();
for (var i = 0; i < perfEntries.length; i++) {
// Process long task notifications:
// report back for analytics and monitoring
// ...
}
});
// register observer for long task notifications
observer.observe({entryTypes: ["longtask"]});
// Long script execution after this will result in queueing
// and receiving "longtask" entries in the observer.
参考文档:https://developer.mozilla.org/zh-CN/docs/Web/API/Long_Tasks_API
4、模型
旧标准参考文档:https://www.w3.org/TR/navigation-timing/#dom-window-performance
新标准参考文档:https://www.w3.org/TR/2020/WD-navigation-timing-2-20200121/
5、navigation和performance.timing
- 优先使用:performance.getEntriesByType('navigation')[0],简称 navigation
- 不可用时降级处理:performance.timing,简述 timing
- timing 时间属性是以类似 Date.now() 这样的时间戳标识,navigation 是每个页面都从 0 开始计时,精度也更高;
- timing 是 navigationStart 开始,navigation 是以startTime开始;
- timing 和 navigationStart 都被新的标准废弃,但兼容较高;
- navigation 新增了资源大小和 serverTiming,可以分析资源是否压缩是否过大过小和离线应用处理时间。
6、名词解释
- FP (First Paint) 首次绘制: 标记浏览器渲染任何在视觉上不同于导航前屏幕内容之内容的时间点.
- FCP (First Contentful Paint) 首次内容绘制 标记浏览器渲染来自 DOM 第一位内容的时间点,该内容可能是文本、图像、SVG 甚至 元素.
- LCP (Largest Contentful Paint) 最大内容渲染: 代表在viewport中最大的页面元素加载的时间. LCP的数据会通过PerformanceEntry对象记录, 每次出现更大的内容渲染, 则会产生一个新的PerformanceEntry对象.(2019年11月新增)
- DCL (DomContentloaded): 当 HTML 文档被完全加载和解析完成之后,DOMContentLoaded 事件被触发,无需等待样式表、图像和子框架的完成加载.
- FMP(First Meaningful Paint) 首次有效绘制
- L (onLoad), 当依赖的资源, 全部加载完毕之后才会触发.
- TTI (Time to Interactive) 可交互时间: 指标用于标记应用已进行视觉渲染并能可靠响应用户输入的时间点.
- TBT (Total Blocking Time) 页面阻塞总时长: TBT汇总所有加载过程中阻塞用户操作的时长,在FCP和TTI之间任何long task中阻塞部分都会被汇总.
参考文档:https://developer.mozilla.org/zh-CN/docs/Web/API/PerformanceEntry/entryType
https://developer.mozilla.org/zh-CN/docs/Web/API/PerformanceNavigationTiming