這里給大家分享我在網上總結出來的一些知識,希望對大家有所幫助

前言
在當下前后端分離的主流環境下,前端部分的優化變得越來越重要,為了提升前端的性能和用戶體驗,我覺得可能需要從三個維度采集資料進行分析,
- 前端埋點,通過埋點收集和統計網頁的UV/PV、設備型號、瀏覽器等資料進行分析,比如可以有針對性對使用比較靠前的設備、瀏覽器等做優化和體驗,
- 網頁性能收集和監控, 采集一個頁面從請求開始到完成這個程序中的資料指標,比如收集和監控首屏加載時間、dom渲染時長、回應比較慢的介面等,有了這些資料可以很直觀和針對性的對網頁的性能進行優化和升級,
- 錯誤收集和監控,收集網頁中的js的報錯、靜態資源加載報錯,保證網頁正常訪問和降低bug率,
1.前端埋點
采集用戶的行為,監控產品在用戶端的使用情況,根據資料可以明確,前端可以針對性的做優化和體驗,
可以簡單的初步建立這樣的資料模型:
{
ip: ip地址,統計uv
ua: 瀏覽器的userAgent //方便區分瀏覽器的品牌
os: 系統名稱
current_page_all: 當前頁面訪問總次數
width:瀏覽器寬度,
height:瀏覽器高度, //統計瀏覽器的尺寸
current_enter_time: 進入當前頁面的時間戳
current_leave_time: 離開當前頁面的時間戳
project_id: 專案的id,
url: 當前url,
user_uni_id: 臨時分配給用戶唯一的id
....
還有其他
}
2.在網頁中植入對應的js代碼
//進入
document.addEventListener('DOMContentLoaded',function(){
...
let args = {
ua: navigator.userAgent,
os: navigator.platform,
width: document.body.clientWidth || document.documentElement.clientWidth,
height: document.body.clientHeight || document.documentElement.clientHeight,
project_id: md5('abcd'),
user_uni_id: '臨時分配給用戶唯一的id',
url: window.location.href,
current_enter_time: new Date().getTime()
....
};
let img = new Image();
img.onload = function() {
img = null;
};
img.src= https://www.cnblogs.com/smileZAZ/archive/2023/01/11/`https://localhost:9700/bury.gif?args=${qs(args)}`;
});
//離開
window.onbeforeunload = function() {
...
let args = {
...
leave_time: new Date().getTime()
....
};
let img = new Image();
img.onload = function() {
img = null;
};
img.src= `https://localhost:9700/bury.gif?args=${qs(args)}`;
}
- 收集資料并上報
const fs = require('fs');
route.get('/bury.gif',async (ctx)=>{
let queryStr = ctx.querystring;
let d = new Date();
let year = d.getFullYear();
let month = d.getMonth()+1;
let day = d.getDate()+1;
fs.writeFile(`../logs/${year}-${month}-${day}.log`,queryStr,{flag:'a',encoding:'utf-8',mode:'0666'},function(e){});
ctx.status = 200;
ctx.type = 'image/gif';
ctx.body = {};
});
簡單的設想方案是先把資料收集到文本檔案里,然后定時的分析這些文本檔案,然后把篩選后的放到資料庫中,
2.網頁性能收集
網頁性能主要是收集是輸入url地址到網頁請求完成資源下載完成這段時間范圍內一些請求、加載等指標,
-
比如舉幾個簡單的指標:
-
首屏加載時長
-
HTML 檔案被加載和決議完成
-
網頁加載完成時間
-
白屏時間
-
其他…
- 具體實作方案(一):
//index.html
<html>
<head>
<script>
window.startTime = Date.now();
</script>
</head>
<body>
<script>
let diff = Date.now()-window.startTime;
console.log('白屏時長'+diff);
document.addEventListener('DOMContentLoaded',()=>{
console.log('HTML 檔案被加載和決議完成時間'+Date.now()-window.startTime);
});
window.onload = function() {
console.log('網頁加載完成時間'+Date.now()-window.startTime);
};
</script>
<script src="https://www.cnblogs.com/smileZAZ/archive/2023/01/11/a.js"></script>
<script src="https://www.cnblogs.com/smileZAZ/archive/2023/01/11/b.js"></script>
....
</body>
</html>
使用performance API
Performance是W3C性能小組引入進來的一個新的API,他可以很好的獲取到首屏加載時間、白屏時間、dns查詢時間等,是一個很方便的獲取網頁性能指標的API,而且目前大部分主流瀏覽器是支持的,
https://www.caniuse.com/
1.Performance一些常用用法的總結
let timing = window.performance.timing //白屏時間 timing.responseStart - timing.navigationStart //DNS 查詢時長 timing.domainLookupEnd - timing.domainLookupStart //request請求耗時 timing.responseEnd - timing.responseStart //HTML 檔案被加載和決議完成耗時 timing.domComplete - timing.domInteractive //網頁加載完成耗時 timing.loadEventEnd - timing.navigationStart //重定向耗時 timing.redirectEnd - timing.redirectStart; //占用的記憶體 window.performance.memory.usedJSHeapSize;
2.此外還有一些高級用法,比如可以收集一些請求和靜態資源的請求時間
let time = [];
let entryLists = window.performance.getEntries();
for(let i=0;i<entryLists.length;i++) {
let item = entryLists[i];
let obj = {};
let soureTypes = ['script','css','xmlhttprequest','link','img'];
if(soureTypes.indexOf(item.initiatorType)>=0){
obj.name = item.name;
//請求時間
obj.reqTime = item.responseEnd - item.responseStart;
time.push(obj);
}
}
3.關于Performance的更多用法可以參考:
https://www.jianshu.com/p/1355232d525a https://blog.csdn.net/hb_zhouyj/article/details/89888646
4.收集資料上報
收集上報資料,使用koa2創建介面performance.gif
const fs = require('fs');
route.get('/performance.gif',async (ctx)=>{
let queryStr = ctx.querystring;
let d = new Date();
let year = d.getFullYear();
let month = d.getMonth()+1;
let day = d.getDate()+1;
fs.writeFile(`../performance-logs/${year}-${month}-${day}.log`,queryStr,{flag:'a',encoding:'utf-8',mode:'0666'},function(e){});
ctx.status = 200;
ctx.type = 'image/gif';
ctx.body = {};
});
3.錯誤收集和監控
錯誤收集主要就是針對js報錯、靜態資源加載等出錯資訊進行收集,
- 收集js報錯最先想到的可能是try catch,
try {
console.log(b);
} catch(e) {
console.log(e);
sendErrorReq();
};
但是使用使用的話,每個頁面收集錯誤都要充斥這try catch,這樣其實是不太好的,
而且catch似乎沒辦法捕獲到異步的操作,
try {
setTimeout(()=>{
console.log(b);
})
} catch(e) {
console.log(e);
sendErrorReq();
};
試了一下沒有執行到catch里邊的sendErrorReq函式,
使用try catch是一種區域錯誤監聽方式,
- 用window.onerror或者是window.addEventListener(‘error’)
window.onerror
/**
*msg 錯誤資訊
*url 錯誤所在的頁面地址
*row 錯誤所在的行數
*col 錯誤所在的列數
**/
window.onerror = function(msg,url,row,col) {
console.log(msg,url,row,col, error);
};
b();
使用window.onerror可以檢測到js的報錯,但是沒法監聽靜態資源加載失敗的情況,
<img src="https://www.cnblogs.com/smileZAZ/archive/2023/01/11/一個不存在的圖片地址" alt="">
window.addEventListener(‘error’)
window.addEventListener(‘error’)能夠監聽到靜態資源加載出錯
window.addEventListener('error',(e)=>{
let localName = e.srcElement.localName;
let currentSrc = https://www.cnblogs.com/smileZAZ/archive/2023/01/11/e.srcElement.currentSrc;
if(localName=='img') {
console.log(`圖片${currentSrc}加載失敗了`);
sendErrorData(currentSrc);
}
...
// e.preventDefault();
},true);
必須設為捕獲程序中執行,否則依然無法監聽,

3. promise錯誤的收集
new Promise((resolve,reject)=>{
reject('hi');
}).catch(e=>{
console.log(e);
sendErrorData(e)
});
axios.get(...).catch(e=>{
console.log(e);
sendErrorData(e)
})
但是有種情況,如果promise不加catch的話,
沒法通過window.onerror去監聽,但是還是通過監聽unhandledrejection事件去收集的
4.unhandledrejection
window.addEventListener('unhandledrejection', event => {
console.log('error:'+event.reason);
sendErrorData(event.reason);
});
new Promise((resolve,reject)=>{
reject('hi');
});
在看下在vue中收集報錯,以vue-cli3創建的專案進行演示
測驗了一下window.onerror這種方式 無法監聽錯誤的,
在網上找了下原因

可以看到在vue的原始碼里,因為如果沒有定義errorHandler就會走到logError這個方法,所以沒法使用window.onerror進行監聽,
5.errorHandler
在vue的手冊中,推薦監聽vue報錯的可以使用errorHandler這個配置方法,
//main.js
Vue.config.errorHandler = function (err, vm, info) {
console.log('錯誤是:', err)
sendErrorData(err);
}
然后隨便故意寫錯
mounted() {
a();
}
就能收集到報錯資訊了
當然最后把收集的錯誤上報給服務器,創建一個介面error.gif,
const fs = require('fs');
route.get('/error.gif',async (ctx)=>{
let queryStr = ctx.querystring;
....
fs.writeFile(`../error-logs/${year}-${month}-${day}.log`,queryStr,{flag:'a',encoding:'utf-8',mode:'0666'},function(e){});
ctx.status = 200;
ctx.type = 'image/gif';
...
});
本文轉載于:
http://events.jianshu.io/p/a6572eb10e00
如果對您有所幫助,歡迎您點個關注,我會定時更新技術檔案,大家一起討論學習,一起進步,

轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/541768.html
標籤:其他
上一篇:手機端H5 實作自定義拍照界面
下一篇:CSS3 中flex 布局
