preface
Take some time to clean up the error handling/error catching capabilities of the project for a summary. To facilitate reading, first summarize the general idea:
1. Perform Dr And try for important steps by yourself. catch... Finally; 2. Wrap most of the try statements in the package utility (I use Vite, I implement rollup plugin). Catch statement, and complete the error message (file name, method name); 1. The onError event catches global errors. 2. Unhandledrejection catches asynchronous errors; ErrorHandler (e.g. vue.config. errorHandler, react ErrorBoundary); 3. Axios and other TCP/IP error processing; Window. addEventListener('error',(event)=>{}); 1. Use Sourcemap to parse the error message and locate the specific error code;Copy the code
Error handling
The plugin I implemented is rollup-plugin-trycatch, which is not mature:
Unit test coverage may be inadequate when it comes to translate business code (currently only dealing with a few types of functions, PR is welcome);Copy the code
If the project is stable and the test coverage is high, this solution is not recommended.
rollup-plugin-trycatch
Unlike WebPack, rollup does not have a plugin or loader, but implements a plugin through a plugin. The main process is as follows: 1. Create rollup plug-in; 2. Convert code to ast syntax tree via acorn plugin rollup; 3. Use stack-utils plug-in to add the current file/file name line number and other information to ERR. 3. Traversing the syntax tree through Estree-Walker, add wrap nodes to related statements (functions); 4. Convert the syntax tree to code through the EscodeGen plugin; FunctionDeclaration, FunctionExpression, ArrowFunctionExpression, ObjectMethod package layer try… Catch c. 2, try… Catch error completion (add error information, original file name, method name and other error analysis, but it is still not accurate enough to locate the specific error statement); Specific content and use can be viewed source code, which has the use of vite demo;
Error trapping
The difficulty of error capture lies in two aspects: 1. How to capture errors comprehensively; 2. If specific problems are found through error analysis (generally speaking, online codes are packaged and compressed, how to locate problems through packaged and compressed codes);
Comprehensive (as much as possible) error capture
Before we try to catch errors, we need to understand the errors, which are divided into three categories (there are many ways to classify them, but I will try to interpret them in my own way) :
1. Remote resource loading error;
window.addEventListener('error', (err) => {let _url = "if(err.target instanceof HTMLElement) {if(err.target instanceof HTMLAnchorElement) { _url = err.target.href } else { // maybe other htmlelement has src property _url = (err.target as HTMLImageElement).src} console.log(err, _URL)}}, true) // Note that there are three parameters. The third parameter is triggered when the capture stage is propagated to the EventTargetCopy the code
2, synchronous code error && asynchronous code (setTimeout/setInterval, etc.);
Window. onerror = (message, source, lineno, colno, error) => {console.log(message, source, lineno, colno, error) => { error) }Copy the code
3. Asynchronous code error;
// promise window.addEventListener("unhandledrejection", (e) => {console.log(e.eason) e.preventDefault() // Prevent error bubbling}, true)Copy the code
4. Error handling provided by the framework, LLDB.
ErrorHandler = (err, vm, info) => {console.log(err, vm, info)}Copy the code
5. XHR, FETCH and other asynchronous request methods;
// xhr function xhr() { const oReq = new XMLHttpRequest(); const url = "http://www.example.org/example.txt" oReq.addEventListener("error", (err) => { console.log(err, url) }); oReq.open("GET", url); oReq.send(); } // fetch function fetchMethod() { const url = 'http://www.example.org/example.txt' fetch(url, { method: 'GET', mode: 'cors', cache: 'default'}). Then (data => {console.log(data)}). Catch (err => {// error handling console.log(url, err)})}Copy the code
Specific code can refer to demo;
The wrong location
Our code is generally packaged and compressed, and it is sometimes difficult to locate the specific content of the error message, especially the error content that is difficult to reproduce. We often need more accurate error information to locate.
The solutions and corresponding solutions are as follows
Rollup-plugin-trycatch rollup-trycatch rollup-trycatch rollup-trycatch rollup-trycatch rollup-trycatch rollup-trycatch rollup-trycatch The catch. Error path, method name and other information have been recorded in the plug-in. 2. Remote static resources; Error path information has been recorded. 3. Promise asynchronous code error; It is recommended to add catch to handle errors; 4. Error handling within the framework; Vue3, 'info' is a vue-specific error info, e.g. which lifecycle hook); 5. XHR, FETCH, etc. It is recommended to record the processing by oneself; 5, synchronous code error && asynchronous code (setTimeout/setInterval, etc.); This error is actually one of the major errors, and the current solution is to parse sourcemap by packaging it in advanceCopy the code
Sourcemap parsing error
Here’s how to implement parsing (some services, e.g. sentry already provide sourcemap, but we built it ourselves, so we need to implement it ourselves): 1. Upload the latest Sourcemap overlay to the parsing service when packaging (if you need different versions of the query problem, you can consider multiple versions, I haven’t done it yet);
At present, most companies use automated tools (Jenkins, GitLab, etc.) to package and compile on the baler. After successful packaging, upload sourcemAP files to the resolved service directory (SSH can be used for operation and maintenance, or file upload service can be built by themselves).Copy the code
2. Parse the file through source-map and return the specific error location;
// Call source, lineno, colnoCopy the code
Parse the sourcemap source code
The problem record
Error.prototype.stack is an experimental feature that works differently in different browsers and versions (including try… Catch, unhandledrejection, etc are all instances of error). See StackOverflow compatible with major browsers (not tested); Another option is to automate the wrap try as in my plugin… Catch method records downlink information; For promises, it is recommended to try to handle them all with catch (or become synchronous code async await);
2, Rollup or Acorn does not provide ast->code methods, how to convert? After modifying ast, you need to implement AST ->code through another plug-in. Escodegen is recommended by most people in the issue.
3, Module not found problem occurs when estree-walker calls jest; It is OK to use version 2.0.2, there is an issue to follow up
4. Experimental properties that are supported by browsers but not by Rollup should be used with caution.
1, class private property related issue: https://github.com/rollup/rollup/issues/4292, you can through the plug-in @ rollup/plugin - typescript into use;Copy the code
Reference documentation
React gracefully catch exceptions: juejin.cn/post/697438… 2, Allow plugin transforms to only return AST: github.com/rollup/roll… 3, source-map-demo: github.com/Joeoeoe/sou…