Jon
Jon

Reputation: 6265

vscode node debugger with custom webpack build

I have a JS web app that has a client and server bundle, both built using webpack's node api.

Running my project in dev mode goes through these steps:

  1. Run two webpack builds, resulting in two output files.
  2. Server bundle is output to dist/server/index.js
  3. Spawn child node process using the dist/server/index.js path
  4. Watch folder for changes. On change, kill the old child process and re-run steps 1-3

I want to add node server debugging using vscode.

So far, I've added the following flags during step 3, when I launch a new child process.

['--inspect=9222', '--no-lazy', '--inspect-brk']

My launch.json file in vscode looks like this

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Attach to dev server",
            "type": "node",
            "request": "attach",
            "protocol": "inspector",
            "address": "localhost",
            "port": 9222,
            "restart": true,
            "trace": true,
            "stopOnEntry": true
        }
    ]
}

When I start the server and run the debugger, things mostly work.

However, I'd love to fix the following two things:

  1. Even with "stopOnEntry": true, the debugger will not pick up any breakpoints, unless I include "--inspect-brk" when launching my child process. This is annoying, because if I'm not running the debugger, the process will hang and will not continue execution. With this flag included, when I run the debugger, the built dist/server/index.js file will open in my editor with a breakpoint on line 1. If I hit continue, all future debugging works.
  2. I'm generating sourcemaps using webpack's "inline-source-map" option. This puts the "original source" in the built file. However, it's the source after babel transformation, making debugging the code a little annoying. E.g. _myFunction.default instead of myFunction. Does vscode have a way to correctly map the built .js file to the pre-built source code in my project? I saw the remoteRoot and localRoot options, but could not get them to work (and am unsure if these are the correct options).

Thanks!

Upvotes: 5

Views: 4010

Answers (1)

ford04
ford04

Reputation: 74740

Update VS Code 1.47+:

With the new JavaScript debugger in VS Code 1.47 and later versions, child processes are automatically debugged in Node.js - just set breakpoints where needed.

Example launch.json (with TypeScript source to illustrate the sourcemap approach):
{
  "type": "pwa-node",
  "request": "launch",
  "name": "Launch Program",
  "skipFiles": ["<node_internals>/**"],
  "program": "${workspaceFolder}/main.ts", // use .ts source
  "outFiles": ["${workspaceFolder}/dist/**/*.js"], // search here for sourcemaps 
}
Example main.ts:
const { spawn } = require("child_process");
const args = [path.resolve("./child.js")];
const proc = spawn(process.execPath, args, { stdio: "inherit" });

See this post for an explanation of pwa-node.

VS Code debug options

program: specifies main source file to be debugged. You can directly reference the .ts source file - VS Code will search the workspace for sourcemaps or consult outFiles.

outFiles: tell VS Code to explicitely search for sourcemaps in these glob locations.

sourceMaps: if VS code shall look for sourcemaps; defaults to true, so no need to set.

stopOnEntry: breaks immediately when program launches - same, as a breakpoint on first line. 1

nolazy: ensures that breakpoints are validated before the code is run and don't "jump". Per default, VS Code sets this flag automatically, so it can be left out.

remoteRoot / localRoot: are for remote debugging and are not directly related to generating sourcemaps (see OP question).

autoAttachChildProcesses: was used to automatically attach to child processed launched in debug mode; no need to set it with new debugger.

Node debug options

--inspect: starts the program in debug mode without waiting for the debugger to be attached.
--inspect-brk: same as --inspect, but waits for the debugger to attach before starting.

You can set one of these to enable debug mode for a program started on the command-line. Note: VS Code now can also auto-attach from integrated terminal without these flags given.

Generate sourcemaps with Webpack

For webpack, you can generate sourcemaps with inline-source-map or source-map 2.

// inside webpack.config.js
devtool: "inline-source-map",

If babel-loader is used, sourcemaps should be considered and merged automatically by webpack with above config entry. For TypeScript, see the Webpack docs.


(Old) Debug child legacy solution

If that does not work in older versions, pass a conditional DEBUG environmental variable for --inspect/--inspect-brk together with autoAttachChildProcesses:

const runner = spawn(process.execPath,
  [...(process.env.DEBUG === "true" ? ["--inspect-brk"] : []), ...args],
);
// inside launch.json configuration
"env": {
  "DEBUG": "true"
},

1 Despite this developer comment, stopOnEnty has not been propagated to child processes for me - even with autoAttachChildProcesses and child processed started with --inspect.

2 These options provide best compatibility from my experience.

Upvotes: 3

Related Questions