前端日誌上報的新姿式「Beacon」

在前端應用越來複雜的今天,爲了監控前端應用是否正常運行,一般會在前端收集一些錯誤與性能等數據,最終咱們會將這些數據上報到服務端。javascript

上報的方式有不少,理論上咱們只要能把數據發給服務端就好了。在瀏覽器中能夠發送請求的方式很是多,包括不限於:xhrfetchscript標籤、img標籤、link標籤、CSS背景圖等。前端

不一樣的上報方式之間存在很大的差別。目前主流的上報方式是利用img標籤的src屬性發送請求,例如:java

(new Image).src = `/haopv.gif?a=xx&b=xxx`
複製代碼

由於日誌上報不須要響應處理,只須要把數據發過去就行。而且大部分接收日誌的服務器地址與業務方可能不是一個部門,甚至可能不是一個公司,因此會涉及到跨域問題。使用img標籤的src屬性既能夠把數據發送給服務端又不須要接收響應,同時解決了跨域問題,因此是目前比較受歡迎的日誌上報實現方式。跨域

可是這樣就真的沒問題了麼?瀏覽器

日誌上報並非應用的主要功能邏輯,也就是說,日誌上報是低優先級的,它不該該與其餘高優先級操做(例如:獲取關鍵資源、輸入響應、運行動畫等)去競爭網絡與計算資源(通俗的說就是日誌上報行爲不該該影響業務邏輯,不該該佔用業務計算資源)。可是這種單向請求又負責傳遞應用的錯誤與性能數據,因此咱們必需要確保它會被交付到服務端。服務器

一般,爲了提升交付率,咱們會選擇當即交付每一個收集到的數據,而不是合併與推遲交付。延遲傳遞可能意味着請求沒有足夠的時間來成功完成,這可能致使重要的應用數據丟失。網絡

這就意味着咱們的交付行爲有可能會被插入到正在忙碌工做的事件循環中,從而搶佔了其餘高優先級的任務的資源,由於JS是單線程的。這有可能會損害用戶體驗。異步

咱們如何確保日誌數據會被交付的同時,儘量地減小與其餘關鍵操做的資源爭用呢?答案是信標(Beacon)。性能

信標(Beacon)

信標(Beacon)能夠異步與非阻塞的數據傳輸,從而最大限度地減小與其餘關鍵操做的資源爭用,同時它能夠確保這些請求必定會被處理並將其傳遞到服務端:fetch

  • 信標請求優先避免與關鍵操做和更高優先級的網絡請求競爭。
  • 信標請求能夠有效地合併,以優化移動設備上的能量使用。
  • 保證頁面卸載以前啓動信標請求,並容許運行完成且不會阻塞請求或阻塞處理用戶交互事件的任務。

信標的使用很是簡單:

var data = JSON.stringify({
  name: 'Berwin'
});
navigator.sendBeacon('/haopv', data)
複製代碼

參數

  • url:上報的目標地址
  • data:被上報的數據
  • 返回值(Return Value):sendBeacon方法被執行後返回一個布爾值,true表明用戶代理成功地將信標請求加入到隊列中,不然返回false

用戶代理對經過信標發送的數據量進行限制,以確保請求被成功傳遞到服務端,而且對瀏覽器活動的影響降到最小。若是要排隊的數據量超出了用戶代理的限制,sendBeacon方法將返回false,返回true表明瀏覽器已將數據排隊等待傳遞。然而,因爲實際數據傳輸是異步的,因此此方法不提供任何關於數據傳輸是否成功的信息。

雖然信標獲得了很高的支持度,但仍是沒法在全部瀏覽器中使用,因此若是您想使用信標上報前端日誌,一些特徵檢測是必要的。

還有一個須要注意的是,經過信標發送的請求,請求方法均爲POST,且不支持修改。

總結

日誌上報在生產環境下不只僅是把請求發出去。日誌上報並非主要邏輯因此優先級很低,爲了最佳的用戶體驗,在考慮避免佔用業務計算資源和避免競爭業務網絡請求的同時咱們還要保證數據必定會交付到服務端,最好的方式是儘量的使用信標(Beacon)。

相關文章
相關標籤/搜索