microsoft / vscode

Visual Studio Code
https://code.visualstudio.com
MIT License
163.29k stars 28.89k forks source link

Debugging with babel-register + NodeJs does not work #5728

Closed mattflix closed 6 years ago

mattflix commented 8 years ago

Setup Steps:

  1. Download and expand NodeJsWithBabelDebuggingExample.ZIP into a local folder.
  2. Open the Terminal and point it to the folder from Step 1.
  3. Run npm install (to install the Babel dependencies).
  4. Run npm start (to demonstrate that the project is working Node program) which should produce a few lines of output and no errors.

Steps to Reproduce (on Mac OS):

  1. In VS Code, open the folder created in the steps above.
  2. Press F5 to start debugging the program.
  3. Observe the debugger break at line 1 of ./index.js, which is a comment. (This is the first sign of trouble.)
  4. Repeatedly press F10 (to step) and observe the debugger break on various other lines of ./index.js that have nothing to do with the code being executed.

Apparently, the inline source map generated by Babel is either being missed, ignored, or misinterpreted. It is also possible that the source map may be faulty, but seeing as a similar setup using other tools (such as Chrome Dev Tools) results in accurate debugging (and only when the source map is supplied) suggests that this is not the case.

Btw, VS Code gives zero feedback (as far as I can see) as to whether a source map was found and/or is being used, making it almost impossible to diagnose this type of trouble.

A few questions:

  1. Have a done something wrong in this setup? Is there something wrong or missing in my launch.json or package.json (where the Babel settings are)?
  2. Are there some diagnostics that I can enable in VS Code to help determine what is going wrong?
  3. Should I even expect to be able to successfully perform source-level debugging of dynamically-transpiled code with VS Code like this, or not? (Other tools can do it, so I will be disappointed if this is not a supported use-case for VS Code.)

The VS Code web pages (https://code.visualstudio.com/docs/editor/debugging) certainly make this sound like I should reasonably expect debugging to work:

Source maps can be generated with two kinds of inlining:

  • Inlined source maps: the generated JavaScript file contains the source map as a data URI at the end (instead of referencing the source map through a file URI).
  • Inlined source: the source map contains the original source (instead of referencing the source through a path).

VS Code supports both the inlined source maps and the inlined source.

As far as I know, setting { "sourceMaps": "inline" } in the Babel configuration (which this project does via package.json) adheres to the first case ("inlined source maps") which the above quote from the VS Code web pages seems to suggest is supported.

Thanks.

bpasero commented 8 years ago

@isidorn @weinand fyi

weinand commented 8 years ago

@mattflix VS Code does support inlined source maps but it does not yet support dynamically generated source maps at all. We are working on this feature already (and it was planned that the April release would already include some experimental support for dynamically generated source maps).

The babel-register setup is especially tricky because it maps the original source .js to .js.source and the generated JavaScript to the original source. This is not a big problem in a debug-only tool like node-inspector which gets all its files through node.js. But in VS Code it is much more difficult because we have to map the files seen by node.js back to the workspace files that VS Code sees. And VS Code does not know what babel-register is actually doing.

mattflix commented 8 years ago

@weinand Thanks for the reply. Good to know that the feature is being worked on.

Fwiw, Chrome DevTools with a workspace configured (where it can read/write from the local file system, turning into a more or less full editor/debugger) manages to work well with the source maps produced by dynamic Babel transpilation.. so it can't be that tricky. :) It creates the illusion that you are debugging and editing only the original source files. It even subtly shades the lines in the code editor that have been mapped by the source map (which is as example of providing feedback about whether or not source maps have been used).

weinand commented 8 years ago

@mattflix VS Code's node debugging is limited by the v8 debugger protocol, it cannot (yet) use the Remote Debugging Protocol. On the other hand the VS Code debugger supports many more languages/runtimes than the Chrome DevTools. One consequence of this is that the VS Code debugger doesn't know anything about source maps. Providing source map feedback in the UI requires more abstractions and protocol enhancements which we will add over time.

BTW, how do you debug node.js with the Chrome DevTools?

mattflix commented 8 years ago

@weinand Thanks for the reply. I don't debug Node.js per se in the regular Chome DevTools, but I can debug projects that take advantage of dynamic Babel transpilation via SystemJS there. The source maps are provided inline (by Babel) and Chrome consumes them. Used in conjunction with a DevTools workspace, to point to my local files, the debugging experience is very good. Plus, I find that it is one of the fastest (most responsive) Javascript debugging environments out there.

In any case, the source map issues are a bit orthogonal to the "pure Node" debugging case but, to answer your question, I can simulate Node-style module resolution using SystemJS by "pre-resolving" all my module locations and writing them to a configuration for SystemJS (a bit like how JSPM works) such that all my requires and imports work as they would running under Node.exe. Of course, I can't use Node-only APIs this way (fs, http), but I am usually debugging "pure" Javascript code, rather than anything Node-specific.

Anujan commented 8 years ago

@weinand Is this still being worked on?

TheTFo commented 8 years ago

Is this being worked on?

roblourens commented 7 years ago

This mostly works right now. The only real problem I see is that sometimes the debugger hangs. It's more reliable if you use "type": "node2" if you're targeting Node 6.3+. A couple things still show up, in both 'node' and 'node2' -

RyanMitchellWilson commented 7 years ago

Is this still being worked on? Without this, vscode is basically just another text editor

roblourens commented 7 years ago

Did you see my last comment? Last I tried, I considered it usable.

RyanMitchellWilson commented 7 years ago

I think you may want to take another look at it. Every time I set a break point it moves it to a completely unrelated line, it usually even moves my breakpoints outside of the functions I'm trying to test. If this is an unrelated issue I've opened an issue a couple days ago https://github.com/Microsoft/vscode/issues/16170 but I thought that this could be related

roblourens commented 7 years ago

I'll follow up in that issue.

katopz commented 7 years ago

Seem to work for me atm, maybe other case going on here? https://medium.com/@katopz/how-to-debug-es6-nodejs-with-vscode-8d00bd6c4f94#.uvgdebiw0

lostpebble commented 7 years ago

@katopz using your configuration I managed to get the breakpoints working, but they are still jumping around a bit unexpectedly. But at least its functional.

wonbyte commented 7 years ago

@katopz what command are you running with babel-register? Right now I am running babel-node.js --debug --presets es2015 -- index.js --debug in the terminal and the I am using your launch.json to try an attach to it. But my breakpoints are not being hit. How would I use babel-register?

katopz commented 7 years ago

@wonbyte I use F5 to debug and it run with node not babel-node as I mention in my blog.

for babel-node you'll need https://github.com/katopz/universal-boilerplate/blob/master/.vscode/launch.json#L13 and run it with F5 no terminal and babel-register need here. And you can't just put everything there it'll mess up, try start from working one. e.g. here which super easy to follow.

Cheers

wonbyte commented 7 years ago

@katopz when I hit F5 I see, 'There are not entries to pick from'

mrukas commented 7 years ago

@katopz The solution you provided in your blog, seems to work the best for me. I really wanted to use the node2 debugger, but the old node debugger works better. node2 does work, but the problem is that it doesn't show me the values of variables if i hover them. It's also nice that you mention to enable the retainLines option, because it doesn't work if you leave the option disabled. What exactly does this option do? Maybe i don't quite get the concept of this option, i thought the original line numbers always get mapped into the source file?!

Thanks!

osenvosem commented 7 years ago

I'm also looking for a good way to debug babel transpiled code with vscode.

mengxingshike2012 commented 7 years ago

I tried but failed, can it work with async features?

weinand commented 7 years ago

@mengxingshike2012 yes, debugging async features works. But the use of babel could be a problem because of its dynamically generated JavaScript and source maps. I suggest that you add "protocol": "inspector" to your launch config.

su-rm-rf commented 7 years ago

@mattflix i got it.

lanunch.json

{
  "version": "0.2.0",
  "configurations": [
    {
      "name": "Launch",
      "type": "node",
      "program": "${workspaceRoot}/app.js",
      "runtimeExecutable": "/usr/local/bin/babel-node",
      "sourceMaps": true
    }
  ]
}

.babelrc

{
  "presets": ["env"],
  "retainLines": true
}
ccjoe commented 7 years ago

vscode can't hit the breakpoint, too, just debug on chrome-dev-tools, without source map Is this being worked on?

linomarcos commented 7 years ago

@su-rm-rf I tried your suggestion on launch.json and .babelrc but still have the same problem. My problem happens only on an "export default" for a class that has a async/await method.

When I use "export async function" debugging works fine!

If the class method is not async it works too!

Here some example from my code:

users.js - (On this file works fine!)

import UserBusiness from './UserBusiness'

export async function authenticate (req, res) {
  const result = await UserBusiness.authenticate(req.body)
  return result
}

UserBusiness.js - (On this too!)

import BaseBusiness from './BaseBusiness'

const base = BaseBusiness('Users')

export async function authenticate (parameters) {
  return base.authenticate(parameters)
}

BaseBusiness.js - (On this start mess up!)

export default class BaseBusiness {
  constructor (modelName) {
    this.modelName = modelName
  }
  async authenticate (params) {
    return params
  }
}

On the last file i can put the breakpoint, the debugger stops on the line and I can use the console.log to print the params value, but cannot see the params value only passing mouse over!

Can u help me?

Izhaki commented 6 years ago

@linomarcos You have explicitly stated that you don't have the issue mentioned - in all 3 cases the debugger stops.

Your actual issue is well known and is still open.

Izhaki commented 6 years ago

So. Anyone still can't get this to work?

Or can we close this ticket?

roblourens commented 6 years ago

I will close this - using "inspector", I believe it works as well as it can.

FelikZ commented 6 years ago

In case somebody find it through google.

electron 1.7* + babel-register example of debugging configuration that works for me.

VSCode debug config:

        {
            "name": "Launch",
            "type": "node",
            "request": "launch",
            "stopOnEntry": false,
            "args": [],
            "cwd": "${workspaceRoot}",
            "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/electron",
            "runtimeArgs": [
                "-r",
                "babel-register",
                "./app"
            ],
            "sourceMaps": true,
            "outFiles": []
        },

package.json

  "devDependencies": {
    "babel-preset-es2015": "6.16.0",
    "babel-preset-es2016": "6.16.0",
    "babel-preset-react": "6.16.0",
    "babel-register": "6.16.0",
    "electron": "1.7.9",
    "electron-builder": "19.42.2",
    "electron-rebuild": "1.6.0",
    "eslint": "3.17.0",
    "gulp-util": "3.0.8"
  }

.babelrc

{
    "presets": ["es2016", "es2015", "react"],
    "sourceMaps": "inline",
    "retainLines": true
}