這裡記錄工作中遇到的技術點,以及自己對生活的一些思考,周三或周五釋出。
封面圖
![](https://img.laitimes.com/img/__Qf2AjLwojIjJCLyojI0JCLiQDOxEzX3xCZlhXam9VbsUmepNXZy9CXwJWZ3xCdh1mcvZ2Lc1zaHRGcWdUYuVzVa9GczoVdG1mWfVGc5RHLwIzX39GZhh2csATMflHLwEzX4xSZz91ZsAzMfRHLGZkRGZkRfJ3bs92YskmNhVTYykVNQJVMRhXVEF1X0hXZ0xiNx8VZ6l2cssmch1mclRXY39CXldWYtlWPzNXZj9mcw1ycz9WL49DciV2dukTOxAjZzkzMyQDM5EDZyYzXyITNwADM2EzLcdDMyIDMy8CXn9Gbi9CXzV2Zh1WavwVbvNmLvR3YxUjLyM3Lc9CX6MHc0RHaiojIsJye.webp)
通常情況下我們不會遇到前端性能監控的需求,但是當我們的關鍵項目真的有這個需求的時候應該怎麼做呢?
我們通常會接入第三方的監控API,但是如何實作這種監控,也是我們需要思考的問題,隻有從全局出發,思考前端監控的實作發案,我們才能從這個思考的過程中有所收獲。
上圖是我對前端性能監控的一些思考,當然,這個圖表示的隻是一個思考的過程,具體的實施,需要我找時間去畫另一張圖,實施圖,可能就包括的比較詳細一些,資料格式的定義,資料上報的實作方式,頁面監控的實作方案等等。
監控什麼
前端監控通常情況下監控的内容可以分為三類:
第一,js錯誤。
js錯誤又分大概四種:一是
uncaught error
,這種錯誤通常情況下發生在我們的開發過程中。理論上不需要我們進行上報。二是
js runtime error
, 這種錯誤會觸發
window.onerror
事件,我們可以通過監聽onerror事件,擷取到相關的資訊進行上報。三是資源錯誤,比如圖檔加載失敗等,它也會觸發error事件。四是
unhandledregection
錯誤,這種錯誤由promise觸發,我們可以監聽
onunhandledrejection
方法擷取相關資訊進行上報。
第二,使用者行為。
使用者行為大體上可以了解為,誰,在什麼時間,做了哪些操作。比如,使用者,登入了什麼應用,應用的版本是什麼,應用所在的平台資訊,頁面的通路情況,停留時長等。
第三,應用的性能。
應用的性能指的是,比如頁面加載時長,接口請求時長,資源大小等等。
以哪種方式進行監控
監控方式,其實指的就是我們平常說的埋點方式。通常情況分為自動埋點,和手動埋點。
自動埋點的實作方式稍微複雜一些,需要我們去hack很多内容。比如需要重寫
XHR
對象,或者已一種更優雅的方式實作
fetch
等。
而手動埋點則是我們直接在業務代碼中需要監控的地方,直接調用接口上報所需的資料即可。
簡單高效,但是繁瑣。
自動監控,自動上報資料時。我們需要考慮以哪種方式進行上報比較好一些,比如開啟定時任務,或者開啟任務隊列。每隔一分鐘上報一次資料,或者每10條,20條資料上報一次。以免上報邏輯對應用本身産生不好的影響。
資料格式如何定義
根據我們需要上報的資訊,我們可以先把需要上報的資料格式先簡單定義一下。
對于JS錯誤,我們需要知道錯誤資訊,發生錯誤的代碼,代碼行号以及列号。
interface JsErrorInfo {
msg:string,
source:string,
lineno:number,
colno:number,
...
}
對于使用者行為,我們需要知道目前使用者是誰,使用者使用的什麼平台,登陸的什麼應用,目前應用是哪個版本,使用者進行什麼樣的操作,使用者所在的頁面位址,甚至目前頁面的路由模式,以及是頁面是否帶有參數。
interface UserActionInfo {
userId:string,
platform:string,
appType:string,
appld:string,
appVersion:string,
userAction:string, // click
timeStamp:number, // time
visitedUrl:string,
visitedUrlMode:string,
visitedParams:any,
...
}
對于頁面性能,我們需要了解一些基本的性能名額及監聽方式。
PerfInfo {
currentUrl:string,
source:string,
requestUrl:string,
loadtime:string,
size:size,
...
}
API如何定義?
當我們從整體上有一個思路之後,我們就可以思考如何對外提供一套api。 API如何定義呢?
通常情況下都會提供一個構造函數,然後通過init方法進行初始化。
例如:
import {Vue} from 'vue
let myApp = new Vue(config)
亦或是通過定義方法來示例化新的對象:
import {createApp} from 'vue
let myApp = createApp(config)
有了這個思考的流程之後,我們隻需要思考我們的構造函數需要哪些方法,然後不斷的去完善即可。比如:上報資訊方法,監聽錯誤資訊,計算頁面加載時間,生成任務隊列...
最後
最近的事情太多了,這一篇隻是一個思考的過程,後面會有一個簡單的實作過程,接口如何定義,如何計算相關名額等等。