Recently, I have been studying the problem of front-end abnormal monitoring and summarized the queried data as follows

1. Front-end abnormal monitoring method

1. Window. onerror exception handling

Window. onError OnError catches runtime errors whether they are asynchronous or non-asynchronous.

window.onerror = function (msg, url, row, col, error) {
    console.log('I know my mistake.');
    console.log({
        msg,  url,  row, col, error
    })
    return true;
};
Copy the code

Note:

  • 1) Window. onerror will not raise an exception until it returns true, otherwise the console will display Uncaught Error: XXXXX even if it knows the exception occurred.
  • 2) Window. onerror is an error that cannot catch network exceptions. Since network request exceptions do not bubble up, they must be caught in the capture phase, but this method can catch network request exceptions, but it is not possible to determine whether the HTTP status is 404 or something like 500. The server logs also need to be used for troubleshooting and analysis.
window.addEventListener('error', (msg, url, row, col, error) => {
    console.log('I know my mistake.');
    console.log(
        msg, url, row, col, error
    );
    return true;
}, true);
Copy the code

2. The Promise of mistakes

If a Promise instance throws an exception and you don’t catch it, there’s nothing onError or try-catch can do to catch the error. If you’re using a lot of Promise instances, especially if you’re using asynchronous promise-based libraries like Axios, you have to be careful because you don’t know when one of these asynchronous requests is going to throw an exception and you’re not handling it, So you’d better add a Promise global exception capture event, unHandledrejection.

window.addEventListener("unhandledrejection".function(e){
    e.preventDefault()
    console.log('I know I made a mistake.');
    console.log(e.reason);
    return true;
});
Copy the code

3. The iframe errors

The parent window cannot be caught directly using window.onerror. There are several ways to catch iframe exceptions if you want to.

1) If your iframe page is the same as your host, add onError to the iframe.

<iframe src="./iframe.html" frameborder="0"></iframe>
<script>
  window.frames[0].onerror = function (msg, url, row, col, error) {
    console.log('I know the iframe error and I know the error message.');
    console.log({
      msg,  url,  row, col, error
    })
    return true;
  };
</script>
Copy the code

2) If the embedded iframe page is not the same domain as your host site, but the iframe content does not belong to a third party

The exception message can be thrown to the master station by communicating with the IFrame. There are many ways to communicate with an iframe, such as postMessage, hash, or name fields across domains

3) If the site is not in the same domain and not under their own control, except through the console to see the detailed error message, there is no way to catch

Ii. Monitoring and reporting

After receiving the error information, the monitoring system needs to send the captured error information to the information collection platform. There are two main ways to send the error information:

  • Send data through Ajax
  • Dynamically create the form of an IMG tag
function error(msg,url,line){
   var REPORT_URL = "xxxx/cgi"; Var m =[MSG, url, line, navigator.userAgent, +new Date]; Network address, user agent information, and time var URL = REPORT_URL + m.join('| |'); Var img = new Image; img.onload = img.onerror =function(){ img = null; }; img.src = url; // Send data to background cgi} // listen for error report window.onerror =function(msg,url,line){
   error(msg,url,line);
}
Copy the code

3. How to position JS code after compression

This part of the original reference: https://github.com/joeyguo/blog/issues/14

Example:

1. Source code (error)

function test() {noerror // <- error}test(a);Copy the code

2. The following code is generated after webpack packaging and compression

!function(n){function r(e){if(t[e])returnt[e].exports; var o=t[e]={i:e,l:! 1,exports:{}};returnn[e].call(o.exports,o,o.exports,r),o.l=! 0,o.exports}var t={}; r.m=n,r.c=t,r.i=function(n){return n},r.d=function(n,t,e){r.o(n,t)||Object.defineProperty(n,t,{configurable:! 1,enumerable:! 0,get:e})},r.n=function(n){var t=n&&n.__esModule?function() {return n.default}:function() {return n};return r.d(t,"a",t),t},r.o=function(n,r){return Object.prototype.hasOwnProperty.call(n,r)},r.p="",r(r.s=0)}([function(n,r){function t(){noerror}t()}]);
Copy the code

3. The code reports errors as scheduled and reports relevant information

{ msg: 'Uncaught ReferenceError: noerror is not defined',
  url: 'http://127.0.0.1:8077/main.min.js',
  row: '1',
  col: '515' }
Copy the code

At this point, the number of rows and columns in the error message is 1 and 515. Combined with the compressed code, it is difficult to locate the specific problem by visual observation.

Plan 1: Change the semicolon in compressed code to a newline

Uglifyjs has a semicolons configuration parameter. If it is set to false, semicolons in the compressed code will be replaced with line breaks to improve the readability of the code, for example

!function(n){function r(e){if(t[e])returnt[e].exports var o=t[e]={i:e,l:! 1,exports:{}}returnn[e].call(o.exports,o,o.exports,r),o.l=! 0,o.exports}var t={} r.m=n,r.c=t,r.i=function(n){return n},r.d=function(n,t,e){r.o(n,t)||Object.defineProperty(n,t,{configurable:! 1,enumerable:! 0,get:e})},r.n=function(n){var t=n&&n.__esModule?function() {return n.default}:function() {return n}
return r.d(t,"a",t),t},r.o=function(n,r){return Object.prototype.hasOwnProperty.call(n,r)},r.p="",r(r.s=0)}([function(n,r){function t(){noerror}t()}])
Copy the code

At this point, the number of rows and columns in the error message is 5 and 137, which is much easier to find than normal compression. But you can still have a problem with a lot of code in a line that is not easy to locate.

Scheme 2: semi-compress JS code · keep whitespace and line feeds

When beautify, another uglifyjs configuration parameter, is set to true, the final code will appear compressed and formatted (with Spaces and newlines reserved), as in

!function(n) { // ... / /... } ([function(n, r) {
    function t() { noerror; } t(); }]);Copy the code

At this point, the number of columns and columns in the error message is 32 and 9, which can be quickly located and corresponding to the source code. However, the file size has increased due to the addition of line breaks and Spaces.

Scheme 3: SourceMap fast location

SourceMap is an information file that stores information about source files and the mapping between source files and processed files. When locating the error of compressed code, you can obtain the specific error information of the source file according to the number of error lines and the corresponding SourceMap file.

The sourcesContent field in the SourceMap file corresponds to the source code content, and you do not want the SourceMap file to be published to the Internet, but stored on the script error handling platform for handling script errors only. The SourceMap file can be used to obtain the specific error message of the source file, combined with the sourcesContent of the source file for visual display, so that the error message at a glance!

Scheme 4: Open source scheme Sentry

Sentry is a real-time error log tracking and aggregation platform that incorporates the sourcemAP solution above and supports more features such as: Error call stack, log information, issue management, multi-project, multi-user, multi-language client, etc. For details, you can check getSentry /sentry, sentry. IO, which is not expanded here.

Reference article:

  1. Cross domains. Everything you need to know is here
  2. Script error volume optimization – make the script error at a glance
  3. Front-end code abnormal monitoring actual combat