引言
在平時工作中可能會遇到用户反饋:“哥們,你們的網站感覺很卡啊!”。這種來自用户的吐槽對前端同學可以説是直擊心靈的衝擊。此時就應該好好想想如何讓用户不再出現這樣的吐槽呢。首先就是指標化的瞭解自己的網站。
常用的衡量指標
可以結合兩張圖
第一張圖是瀏覽器加載整個頁面的時間線,第二張圖則是這個是Google力推的指標,主要從4個視覺反饋階段來描述頁面性能。
總結一下常用的性能指標
- 白屏時間:白屏時間是指瀏覽器從響應用户輸入網址地址,到瀏覽器開始渲染內容的時間。
- 首屏時間:首屏時間是指瀏覽器從響應用户輸入網絡地址,到首屏內容渲染完成的時間。 一般是首屏中的圖片加載完畢的時候,我們認為是首屏結束的時間點。
- 完全加載時間:DOM Tree 構建完成後,開始加載網頁資源,資源完全加載完成後,從加載開始到此為網頁的完全加載時間。
- 可交互時間 (TTI):用户第一次可以和界面進行交互的時間
- 慢會話 Long Tasks:RAIL有在100毫秒內相應用户輸入的要求。如果響應超過這個時間就是慢會話
如何採集指標數據
Performance_API
PerformanceTiming中有許多指標,選取幾個比較常用的。
- PerformanceTiming.responseStart:返回瀏覽器從服務器收到(或從本地緩存讀取)第一個字節時的Unix毫秒時間戳。這個可以用來反映服務器或者是CDN響應的指標。
- PerformanceTiming.domInteractive:返回當前網頁DOM結構結束解析、開始加載內嵌資源時間,用户可以開始輸入交互的時間點
- PerformanceTiming.loadEventEnd: 整個頁面加載結束的時間點
白屏時間的採集
可以用
window.performance.getEntriesByType('paint')
返回結果就是FP和FCP
首屏時間的採集
首屏時間需要從兩塊去衡量,一塊是圖片的加載,一塊是dom的渲染。
圖片的加載時間可以使用
window.performance.getEntriesByType('resource')
看一下返回的結果
需要判斷initiatorType,取出responseEnd。
dom部分則用MutationObserver來監聽dom變化。
另外考慮到是首屏,就需要配合getBoundingClientRect來判斷元素是否在首屏內。
最後將兩部分時間取較大值即可
拓展一下,如果你的首屏有其他資源會你也希望確認是否會大於圖片的加載,可以參考
不同資源的加載時間的獲取
TTI的採集
tti採集的庫使用非常簡單
import ttiPolyfill from './path/to/tti-polyfill.js';
ttiPolyfill.getFirstConsistentlyInteractive(opts).then((tti) => {
// Use `tti` value in some way.
});
長任務的收集
const subscribeBtn = document.querySelector('#subscribe');
subscribeBtn.addEventListener('click', (event) => {
// Event listener logic goes here...
const lag = performance.now() - event.timeStamp;
if (lag > 100) {
ga('send', 'event', {
eventCategory: 'Performance Metric'
eventAction: 'input-latency',
eventLabel: '#subscribe:click',
eventValue: Math.round(lag),
nonInteraction: true,
});
}
});
FPS
由於requestAnimationFrame會在每一幀渲染前被調用,所以fps的計算就依賴於他。
var frame = 0;
var allFrameCount = 0;
var lastTime = Date.now();
var lastFameTime = Date.now();
var loop = function () {
var now = Date.now();
var fs = (now - lastFameTime);
var fps = Math.round(1000 / fs);
lastFameTime = now;
allFrameCount++;
frame++;
if (now > 1000 + lastTime) {
//算出一秒左右的時間內總共渲染了多少幀
var fps = Math.round((frame * 1000) / (now - lastTime));
frame = 0;
lastTime = now;
};
window.requestAnimationFrame(loop);
}
loop();
參考資料
https://www.cnblogs.com/wmhua...
https://www.jianshu.com/p/456...
https://www.cnblogs.com/coco1...