Summary of the use of source map in Node.js

Abstract: ## Origin Node application functions are becoming more and more complex, and many businesses have begun to try to use TypeScript to develop. Most of the JS written in the front-end is now compiled. Through the use of source maps in the browser, the problem of the difference between the source code and the compiled runtime code can be well resolved. So, how should source map be used in Node server environment? Recently, I am rebuilding a Node application based entirely on ts. All the related processes seem to be good. However,

the
functions of the original Node application are becoming more and more complex, and many businesses have begun to use TypeScript to develop. Most of the JS written in the front-end is now compiled. Through the use of source maps in the browser, the problem of the difference between the source code and the compiled runtime code can be well resolved.

So, how should source map be used in Node server environment? Recently, I am rebuilding a Node application based entirely on ts. All the related processes seem to be fine. The only flaw is that the error message is pointing to the js file. I think it's time to explore how to get Node to support source maps.

Principle
For Node, the greatest value of the server source map is that the error information has the correct error stack, so as long as we can implement custom error stack information, it is fine.

It happens that the v8 engine provides a private (Stack-Trace-API), which provides the ability for developers to customize the error stack information. Specifically, developers can implement the prepareStackTrace method of the Error object. If this method is defined on the Error object, each error message will be processed by Error.prepareStackTrace and returned.

The Error.prepareStackTrace method can get two parameters, the basic error information and the structured error stack. The second parameter is an array, through which the error file and location information can be obtained. Finally, a string is returned based on this information, so that the stack property of the Error object can be overridden.

The basic code structure is as follows:

function prepareStackTrace(error, stack) {
  return error + stack.map(function(frame) {
    return '\n at ' + wrapCallSite(frame);;
  }).join('');
}
Error. prepareStackTrace = prepareStackTrace;
In the wrapCallSite method, you can find the sourceMap by analyzing the source code and then return the correct location information.

The principle is very simple. There is already an npm package source-map-support that encapsulates related functions.

This already looks perfect. The source map reading is only executed when an error occurs, so **this function will not have performance problems, and it can also be enabled** in the generation environment.

The Problem
The Stack Trace API looks great, but the real world is always more complicated. After I introduced source-map-support, it runs fine, but when I run the test case, the location information of the error stack is completely wrong.

After investigating this problem for a long time, it was finally located that the line number returned by the frame object obtained in the wrapCallSite method is wrong, and the method of obtaining the line number is native code, which is almost impossible to debug. I thought, could it be Node's problem? Want to debug to Node source code?

After tossing for a long time, there was no effect. Just when I was about to give up, I changed an assumption. Could it be affected by a certain package dependency? Then I tried to delete the required packages in turn when running the use case, and finally found that it was caused by the power-assert introduced by egg-bin by default.

Once the problem is located, it is easy to solve. But to solve this problem, we must first talk about how power-assert is implemented.

power-assert and sourceMap
power-assert as an assertion library, the biggest feature is that the error information report is very friendly, a picture can clearly see the difference between

img

implementation such a cool report needs to do some special processing, Convert the code of the test case, for example

it('foo', function foo() {
  var a = 'foo';
  var b = 'b';
  assert(a === b);
});
after After espower-source processing, it becomes like this

it('foo', function foo() {
  var a = 'foo';
  var b = 'b';
  assert(expr(capture(capture(a, '/0/left') === capture(b, '/0/right'), '/0'), {
      content: 'assert(a === b) ',
      filepath: 'bizLogger.test.ts',
      line: 107
  }));
})
Note: The above code is not the real running code, after some deletions
For an expression like assert(a === b); , will capture the position and value of each operation process through capture, and finally calculate through expr. After this conversion, the code running logic remains unchanged, but the return value of each step in the assert expression can be returned when an exception occurs.

The problem I encountered was because power-assert converted the code, and when the exception was finally thrown, the real js exception location information was the converted location, which naturally could not be correctly located to the source code location.
http://click.aliyun.com/m/23751/

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=326639866&siteId=291194637
Recommended