前端經常出現Script error. 如何定位,如何解決

Hello,大家好。今天我們來講一下前端出現頻率非常高的一種錯誤:Script error。

Script error.這個錯誤非常的高傲和神祕,爲什麼呢?因爲它出現的時候,不會給你提供任何有關它的線索。正常我們寫的前端代碼報錯的時候,瀏覽器通常拋出錯誤代碼的行列號,以及它的堆棧代碼,這樣我們就可以快速定位到錯誤的位置。而這個錯誤發生的時候,連根毛的線索都沒有提供,有毛的線索嗎 ,一根都沒有。那麼它憑什麼這麼囂張呢?

一、Script error是如何產生的呢?

很多同學看到這個錯誤的時候一臉懵,不知道該咋整,其實他是由第三方js代碼產生了報錯,而瀏覽器存在着同源策略導致它無法像你提供第三方文件的堆棧,除非得到第三方服務器的允許。

最常見的情形是使用CDN託管JS資源。爲了更好地理解,假設以下HTML頁面部署在http://www.webfunny.com域名下:

<!doctype html>
<html>
<head>
  <title>這個頁面在這個域名:https://www.webfunny.com</title>
</head>
<body>
  <script src="http://www.CDN.com/test.js"></script>
  <script>
   window.onerror = function (message, url, line, column, error) {
     console.log(message, url, line, column, error);
   }
   // 假如test.js中的代碼發生了報錯
  </script>
</body>

假如這個時候,test.js代碼中發生了報錯,這個時候你將會得到 "Script error."。出於安全考慮,瀏覽器會刻意隱藏其他域的JS文件拋出的具體錯誤信息,這樣做可以有效避免敏感信息無意中被不受控制的第三方腳本捕獲。因此,瀏覽器只允許同域下的腳本捕獲具體錯誤信息,而其他腳本只知道發生了一個錯誤,但無法獲知錯誤的具體內容。更多信息,請參見Webkit源碼

bool ScriptExecutionContext::sanitizeScriptError(String& errorMessage, int& lineNumber, String& sourceURL)
{
  KURL targetURL = completeURL(sourceURL);
  if (securityOrigin()->canRequest(targetURL))
      return false;
  errorMessage = "Script error.";
  sourceURL = String();
  lineNumber = 0;
  return true;
}

其實這個並不能算是你們代碼的報錯,所以正常情況下,只要不影響業務,你們是可以睜一隻眼閉一隻眼的(悄悄說的)。但是webfunny作爲一款監控系統,即使不影響業務,我們也得上報並保存下來(這是我們最後的倔強:)

二、Script error這種錯誤怎麼定位呢?

我看很多人都寫了如何去解決script error,但是鮮有人介紹怎麼定位到它。 也許大家可能是忽略了,但是因爲缺乏線索,想定位到它的位置還真是不容易呢。 特別是項目引入了不止一個第三方js文件的時候,你怎麼知道是發生在哪個文件中呢?

其實這就離不開行爲記錄,鏈路追蹤的功能了。通過記錄用戶的行爲軌跡,可以準確的找到Script error的具體時間節點,在那個時間節點你就可以知道調用了什麼方法,從而找到具體位置。

三、Script error這種錯誤怎麼解決呢?

解決方式1:開啓CORS跨域資源共享

爲了跨域捕獲JavaScript異常,可執行以下兩個步驟:

1. 添加crossorigin="anonymous"屬性。此步驟的作用是告知瀏覽器以匿名方式獲取目標腳本。這意味着請求腳本時不會向服務端發送潛在的用戶身份信息(例如Cookies、HTTP證書等)。

<script src="http://www.CDN/test.js" crossorigin="anonymous"></script>

2. 添加跨域HTTP響應頭。

Access-Control-Allow-Origin: *  // 或者業務域名

完成上述兩步之後,即可通過window.onerror捕獲跨域腳本的報錯信息。回到之前的案例,頁面重新運行後,捕獲到的結果是:

解決方式2:利用try catch重新捕獲

已添加 crossorigin 依然有 script error。由於部分瀏覽器對crossorigin屬性不支持,又或者我們無法往HTTP請求響應頭裏面添加跨域屬性,因此依然可能產生script error。

這時還可以通過try catch獲取頁面報錯信息,將JS錯誤重新拋出或者上報。

try {
    run(); // 調用test.js中定義的run方法
  } catch (e) {
    console.log(e);
    throw e; 
  }

最後、Script error.其實並不是什麼嚴重的問題,很少遇到這種錯誤會影響到正常的業務,一般第三方都會做好兼容處理。 但是呢,它會讓人看着心煩,所以在確認對業務沒有影響的時候,可考慮把它過濾掉。這樣就不會影響線上的錯誤率了(以防背鍋挨批,哈哈)

 

參考文檔:https://help.aliyun.com/zh/arms/browser-monitoring/support/causes-and-solutions-for-script-errors

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章