debugging in Visual Studio Code with babel-node
Asked Answered
J

6

58

I'm using:

  • VS Code v1.3.1
  • node v6.3.1
  • babel-node v6.11.4
  • Windows 10

I'm unable to get a stop at a breakpoint with the following launch file. The debugger runs and attaches to a port, but when I run the applications with a breakpoint, it doesn't stop at the breakpoint and runs straight through. Anyone that has gotten this to work, please advise.

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch",
            "type": "node",
            "request": "launch",
            "program": "${workspaceRoot}/src/app.js",
            "stopOnEntry": false,
            "args": [],
            "cwd": "${workspaceRoot}",
            "preLaunchTask": null,
            "runtimeExecutable": "${workspaceRoot}/node_modules/.bin/babel-node.cmd",
            "runtimeArgs": [
                "--nolazy"
            ],
            "env": {
                "NODE_ENV": "development"
            },
            "externalConsole": false,
            "sourceMaps": false,
            "outDir": null
        },
        {
            "name": "Attach",
            "type": "node",
            "request": "attach",
            "port": 5858,
            "address": "localhost",
            "restart": false,
            "sourceMaps": false,
            "outDir": null,
            "localRoot": "${workspaceRoot}",
            "remoteRoot": null
        },
        {
            "name": "Attach to Process",
            "type": "node",
            "request": "attach",
            "processId": "${command.PickProcess}",
            "port": 5858,
            "sourceMaps": false,
            "outDir": null
        }
    ]
}
Joellajoelle answered 24/7, 2016 at 23:20 Comment(0)
P
34

I was able to get it working following these steps:

Package.json

Ensure you have a build script with sourcemaps generation.

"scripts": {
    "build": "babel src -d dist --source-maps"
}

tasks.json

Ensure you have the task that lets VS Code to build with the npm script.

{
    "version": "0.1.0",
    "command": "npm",
    "isShellCommand": true,
    "showOutput": "always",
    "suppressTaskName": true,
    "tasks": [
        {
            "taskName": "build",
            "args": [ "run", "build" ],
            "isBuildCommand": true
        }
    ]
}

launch.json

Configure the script to build before launch with a preLaunchTask, start the program from the source entry point, but with the outDir pointing to the dist folder and with sourceMaps enabled.

{
    "name": "Launch",
    "type": "node",
    "request": "launch",
    "program": "${workspaceRoot}/src/server.js",
    "stopOnEntry": false,
    "args": [],
    "cwd": "${workspaceRoot}",
    "preLaunchTask": "build",
    "runtimeExecutable": null,
    "runtimeArgs": [ "--nolazy" ],
    "env": {
        "NODE_ENV": "development"
    },
    "externalConsole": false,
    "sourceMaps": true,
    "outDir": "${workspaceRoot}/dist"
}

Now, each time you press F5, the babel transpilation runs before the Node process starts, but with all sourcemaps synced. With it I was able use breakpoints and all other debugger things.

Pitiable answered 28/7, 2016 at 13:58 Comment(1)
Don't need to run any scripts. Babel-node does it for youEpidemic
O
101

No need to transpile with @babel/node

Basic setup (sourcemaps - always)

Note the sourceMaps and retainLines options in .babelrc:

{
  "presets": [
    "@babel/preset-env"
  ],
  "sourceMaps": "inline",
  "retainLines": true
}

And then in launch.json:

{
  "type": "node",
  "request": "launch",
  "name": "Debug",
  "program": "${workspaceFolder}/index.js",
  "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/babel-node",
  "runtimeArgs": [
    "--nolazy"
  ]
}

Advance setup (sourcemaps - development only)

You can tweak the above so only to generate source-maps/retainLines in development mode:

{
  "presets": [
    "@babel/preset-env"
  ],
  "env": {
    "development": {
      "sourceMaps": "inline",
      "retainLines": true
    }
  }
}

And:

{
  "type": "node",
  "request": "launch",
  "name": "Debug",
  "program": "${workspaceFolder}/index.js",
  "runtimeExecutable": "${workspaceFolder}/node_modules/.bin/babel-node",
  "runtimeArgs": [
    "--nolazy"
  ],
  "env": {
    "BABEL_ENV": "development"
  }
}

Notes

  • Currently "type": "pwa-node" (see more) doesn't work with this setup.
  • For "--nolazy" see this.
  • "BABEL_ENV": "development" - Unless a different value is set the default is development, so adding this in the launch config is not essential (but does make things more explicit).
Oujda answered 6/6, 2018 at 21:29 Comment(7)
Trying your setup, but cannot place a breakpoint. Getting 'unverified breakpoint' notice. Inside class declaration all breakpoints moves to line with class name. Any ideas?Woodley
That's odd. Been using this setup with async and never had this problem.Oujda
Thanks for a reply! What babel version are you using? 7?Woodley
Nope bable 5/6.Oujda
Nowdays, babel is replaced with @babel/core and presets: ["env"] is replaced with presets: ["@babel/preset-env"]Epidemic
This answer still works great with VSCode 1.45, babel-node 7.8.7 and node 14.0. Thank you @OujdaAllopatric
This is a better answer than the accepted one.Isogamy
P
34

I was able to get it working following these steps:

Package.json

Ensure you have a build script with sourcemaps generation.

"scripts": {
    "build": "babel src -d dist --source-maps"
}

tasks.json

Ensure you have the task that lets VS Code to build with the npm script.

{
    "version": "0.1.0",
    "command": "npm",
    "isShellCommand": true,
    "showOutput": "always",
    "suppressTaskName": true,
    "tasks": [
        {
            "taskName": "build",
            "args": [ "run", "build" ],
            "isBuildCommand": true
        }
    ]
}

launch.json

Configure the script to build before launch with a preLaunchTask, start the program from the source entry point, but with the outDir pointing to the dist folder and with sourceMaps enabled.

{
    "name": "Launch",
    "type": "node",
    "request": "launch",
    "program": "${workspaceRoot}/src/server.js",
    "stopOnEntry": false,
    "args": [],
    "cwd": "${workspaceRoot}",
    "preLaunchTask": "build",
    "runtimeExecutable": null,
    "runtimeArgs": [ "--nolazy" ],
    "env": {
        "NODE_ENV": "development"
    },
    "externalConsole": false,
    "sourceMaps": true,
    "outDir": "${workspaceRoot}/dist"
}

Now, each time you press F5, the babel transpilation runs before the Node process starts, but with all sourcemaps synced. With it I was able use breakpoints and all other debugger things.

Pitiable answered 28/7, 2016 at 13:58 Comment(1)
Don't need to run any scripts. Babel-node does it for youEpidemic
S
11

As of version 1.9, VS Code automatically tries to use source maps by default, but you have to specify outFiles if the transpiled files are not in the same folder as the source files.

As an example, here are the relevant files. In this case, babel is transpiling from the src folder to the lib folder.

Note: The entries in package.json and .vscode/tasks.json are only required if you want VS Code to transpile the files before debugging.


.vscode/launch.json

Ctrl+Shift+P, >Debug: Open launch.json

{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "node",
            "request": "launch",
            "name": "Launch Program",
            "program": "${workspaceRoot}/lib/index.js",
            "cwd": "${workspaceRoot}",
            "preLaunchTask": "build",
            "outFiles": [
                "${workspaceRoot}/lib/**.js"
            ]
        }
    ]
}

Note: Only specify preLaunchTask if you also set up the build tasks in package.json and .vscode/tasks.json.


package.json

Ctrl+P, package.json

{
  "scripts": {
    "build": "babel src -d lib -s"
  },
  "devDependencies": {
    "babel-cli": "^6.23.0",
    "babel-preset-env": "^1.1.10"
  }
}

Note: You may use a different version of babel-cli and different babel presets.


.vscode/tasks.json

Ctrl+Shift+P, >Tasks: Configure Task Runner

{
    "version": "0.1.0",
    "command": "npm",
    "isShellCommand": true,
    "showOutput": "always",
    "suppressTaskName": true,
    "tasks": [
        {
            "taskName": "build",
            "args": ["run", "build"],
            "isBuildCommand": true
        }
    ]
}

Official VS Code Documentation

Source Maps

The Node.js debugger of VS Code supports JavaScript Source Maps which help debugging of transpiled languages, e.g. TypeScript or minified/uglified JavaScript. With source maps, it is possible to single step through or set breakpoints in the original source. If no source map exists for the original source or if the source map is broken and cannot successfully map between the source and the generated JavaScript, then breakpoints show up as unverified (gray hollow circles).

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.

The source map feature is controlled by the sourceMaps attribute which defaults to true starting with VS Code 1.9.0. This means that node debugging always tries to use source maps (if it can find any) and as a consequence you can even specify a source file (e.g. app.ts) with the program attribute.

If you need to disable source maps for some reason, you can set the sourceMaps attribute to false.

If the generated (transpiled) JavaScript files do not live next to their source but in a separate directory, you must help the VS Code debugger locating them by setting the outFiles attribute. This attribute takes multiple glob patterns for including and excluding files from the set of generated JavaScript files. Whenever you set a breakpoint in the original source, VS Code tries to find the generated JavaScript code in the files specified by outFiles.

Since source maps are not automatically created, you must configure the transpiler you are using to create them. For TypeScript this can be done in the follwoing way:

tsc --sourceMap --outDir bin app.ts

This is the corresponding launch configuration for a TypeScript program:

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch TypeScript",
            "type": "node",
            "request": "launch",
            "program": "app.ts",
            "outFiles": [ "bin/**/*.js" ]
        }
    ]
}

Source

Sememe answered 27/2, 2017 at 6:22 Comment(1)
in 2019 this is the best approach that works. Oldest will fire erros and deprecated warnings.Karakoram
R
5

Here is what worked for me (None of the other solutions worked for me with vscode v1.33):

./project.json

"scripts": {
  "build": "babel src -d dist --source-maps",
},

.vscode/task.json

{
  "version": "2.0.0",
  "tasks": [{
    "label": "build-babel",
    "type": "npm",
    "script": "build",
    "group": "build"
  }]
}

.vscode/launch.json

{
  "version": "0.2.0",
  "configurations": [{
    "type": "node",
    "request": "launch",
    "preLaunchTask": "build-babel",
    "name": "Debug",
    "program": "${workspaceRoot}/src/server.js",
    "outFiles": ["${workspaceRoot}/dist/**/*.js"]
  }]
}
Regeneration answered 19/5, 2019 at 2:57 Comment(0)
M
2

Add this config to your launch.json,

{
"version": "0.2.0",
"configurations": [
    {   
        "cwd":"<path-to-application>",
        "type": "node",
        "request": "launch",
        "name": "babel-node debug",
        "runtimeExecutable": "<path-to-app>/node_modules/.bin/babel-node",
        "program": "<path-to-app-entry-file>/server.js",
        "runtimeArgs": ["--nolazy"]
    }
]
}

Don't forget to have .babelrc file with preset defined in your project root. Also cwd attribute in launch.json must be correct, otherwise babel compiler won't be able to find .babelrc and you will get compilation errors.

    {
        "presets": ["@babel/preset-env"]
    }

Running with this config will automatically start application on default port (usually 5000) and attach to generated debug port. Source maps will work without any additional config unless you use some super old vscode

Minestrone answered 18/7, 2019 at 13:18 Comment(0)
W
0

What what missing in my case (VSCode 1.36.0) was the override of source map paths:

{
    "version": "0.2.0",
    "configurations": [
        {
            "type": "node",
            "request": "launch",
            "name": "Debug",
            "program": "${workspaceRoot}/src/cli/index.js",
            "sourceMaps": true,
            "sourceMapPathOverrides": {
                "*": "${workspaceRoot}/src/*"
            },
            "outFiles": [
                "${workspaceRoot}/lib/**/*.js"
            ]
        }
    ]
}

The compilation was invoked through gulp pipeline and the sourcemaps were referring to cli/index.js instead of src/cli/index.js. Remapping with sourceMapPathOverrides fixed that.

Warrick answered 18/6, 2019 at 5:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.