Arthas Zheng
在 100 毫秒以内响应
在 10 毫秒内生成一帧
最大程度增加空闲时间
在 1000 毫秒以内呈现内容
延迟 | 用户反映 |
---|---|
0~16ms | 流畅 |
0~100ms | 感觉操作立即反馈 |
100~300ms | 轻微延迟 |
300~1000ms | 感觉到正在加载 |
1000+ms | 转移注意力 |
10000ms | 失望,放弃 |
预算:16ms
执行时间:10ms
减少 long task,任务分块,保证单个任务小于执行时间 50ms。
如何准确地衡量用户真实感受到的性能?
指标 |
---|
FP(First Paint) |
FCP(First Contentful Paint) |
FMP(First Meaningful Paint) |
TTI(Time to Interactive) |
First CPU Idle |
DOMContentLoaded |
onLoad |
Longtask 跟踪 |
输入延迟跟踪 |
... ... |
const t = window.performance.timing;
const times = {};
// 【重要】页面加载完成的时间
// 【原因】这几乎代表了用户等待页面可用的时间
times.loadPage = t.loadEventEnd - t.navigationStart;
// 【重要】解析 DOM 树结构的时间
// 【原因】反省下你的 DOM 树嵌套是不是太多了!
times.domReady = t.domComplete - t.responseEnd;
// 【重要】重定向的时间
// 【原因】拒绝重定向!比如,http://example.com/ 就不该写成 http://example.com
times.redirect = t.redirectEnd - t.redirectStart;
// 【重要】DNS 查询时间
// 【原因】DNS 预加载做了么?页面内是不是使用了太多不同的域名导致域名查询的时间太长?
// 可使用 HTML5 Prefetch 预查询 DNS ,见:[HTML5 prefetch](http://segmentfault.com/a/1190000000633364)
times.lookupDomain = t.domainLookupEnd - t.domainLookupStart;
// 【重要】读取页面第一个字节的时间
// 【原因】这可以理解为用户拿到你的资源占用的时间,加异地机房了么,加CDN 处理了么?加带宽了么?加 CPU 运算速度了么?
// TTFB 即 Time To First Byte 的意思
// 维基百科:https://en.wikipedia.org/wiki/Time_To_First_Byte
times.ttfb = t.responseStart - t.requestStart;
// 【重要】内容加载完成的时间
// 【原因】页面内容经过 gzip 压缩了么,静态资源 css/js 等压缩了么?
times.request = t.responseEnd - t.requestStart;
// 【重要】执行 onload 回调函数的时间
// 【原因】是否太多不必要的操作都放到 onload 回调函数里执行了,考虑过延迟加载、按需加载的策略么?
times.loadEvent = t.loadEventEnd - t.loadEventStart;
// 【重要】白屏时间
times.blankTime = (t.domInteractive || t.domLoading) - t.fetchStart;
// DNS 缓存时间
times.appcache = t.domainLookupStart - t.fetchStart;
// 浏览器卸载前一个页面(同一个域下)的时间
times.unloadEvent = t.unloadEventEnd - t.unloadEventStart;
// TCP 建立连接完成握手的时间
times.connect = t.connectEnd - t.connectStart;
performance.getEntities()
接口/js/link/图片平均响应时间、慢接口/js/link/图片、FP/FCP...
performance.getEntities()都能做些什么?
同源限制
缓存相关
const ttiPolyfill = require('tti-polyfill');
const tti = await ttiPolyfill.getFirstConsistentlyInteractive();
First CPU Idle
const arr = performance.getEntriesByType('paint');
let data = {};
arr.forEach(item=>{data[item.name] = item.startTime});
FP(first paint):首次绘制,第一次看到白屏的时间
FCP(first contentful paint):首次内容绘制,元素首次绘制的时间点
const observer = new PerformanceObserver((list) => {
for (const entry of list.getEntries()) {
// 上报
}
});
observer.observe({entryTypes: ['longtask']});
执行时间 >= 50ms 的任务
二娃
前端性能监控 sdk,基于神策
// npm install erwa --save --registry=https://npm.firstleap.cn
import Erwa from 'erwa';
// 传入项目名称
const erwa = new Erwa('LeapFlow', {
urlReg: /^https?:\/\/leapflow.firstleap.cn/
});
<picture>
<source
srcset="https://file-aliyun.firstleap.cn/test.png?x-oss-process=image/format,webp"
type="image/webp">
<img src="https://file-aliyun.firstleap.cn/test.png" alt="">
</picture>
// 加载图片时
function load(src){
if(isSupportWebp){
// 加载webp
}else{
// 加载原图片
}
}
Thanks