Debugging in VSCode with a npm script - node.js

In my package.json I have some scripts defined that look like this:
"scripts": {
"build": "tsc -p tsconfig.json",
"run": "node --experimental-specifier-resolution=node .",
"start": "npm run build && npm run run"
}
For now I just used npm run start from the terminal to compile and run everything but I want to use breakpoints now and would like to switch to the VSCode debugging.
I don't know what the launch.json configuration should look like to run scripts.
My project structure looks something like this:
.
├── package.json
├── src/
│ └── start.ts
└── dist/
└── start.js
What I think my best attempt so far was:
{
"name": "Launch via NPM",
"request": "launch",
"type": "node",
"cwd": "${workspaceRoot}",
"runtimeExecutable": "npm",
"runtimeArgs": [
"run",
"start"
],
},
Which sadly gives me the following error:
Exception has occurred: Error: ENOENT: no such file or directory, stat '{cwd}\git.COM'
Replacing "runtimeArgs": ["run","start"], with "command": "npm run start", gives me the same error.

Using a NPM script
You could create an additional script in your package.json to launch node with the instruction to wait for a debugger to be attached. IMHO, this is not ideal and I would avoid it but it's sometimes necessary (for example when node is launched by some shell script):
"scripts": {
"debug": "npm run build && node --experimental-specifier-resolution=node --inspect-brk ."
}
Then you would need a configuration in your launch.json to attach the debugger to the waiting node process:
{
"name": "Attach",
"type": "node",
"request": "attach",
"skipFiles": ["<node_internals>/**"],
"outFiles": ["${workspaceFolder}/dist/**/*.js"]
}
Launching node directly
Another possibility is to launch node in your launch.json with the appropriate arguments. There is a little code duplication with your package.json but that's how I do it myself.
Note that if you want to debug directly your TS files, you have to generate the source maps and indicate the location of the generated JS files.
Here is how it would look like:
{
"name": "Debug",
"type": "node",
"request": "launch",
"skipFiles": ["<node_internals>/**"],
"program": "${workspaceFolder}/src/start.ts",
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
"runtimeArgs": [
"--experimental-specifier-resolution=node"
]
}
To ensure your TS code is built, I would run TSC in watch mode in another terminal window:
tsc -p tsconfig.json --watch

Related

How to debug nodeJS (ExpressJS) app in visual studio code?

I have tried many different solutions available online but nothing works in my case,
I am trying to debug a nodeJS app while its running, invoking the API through UI/postman
My launch.json: took guide from here
{
"type": "node",
"request": "attach",
"name": "Attach by Process ID",
"processId": "${command:PickProcess}",
"skipFiles": [
"<node_internals>/**"
]
}
After starting local server, when I start debugger, it ask to pick a process, I select the one ending with --exec babel-node server.js it attaches successfully but deosn't load my project scripts, only node_modules, eval and node_internal.
In my code if I put break point, I see this error "Break point set but not yet bound"
My package.json start sctipt:
"scripts": {
"start": "nodemon --exec babel-node server.js"
}
My code is in ES6, I start the server though a shell script which first set some environment then do npm start
My .bablerc
{
"presets": [
[
"#babel/preset-env",
{
"targets": {
"node": "current"
}
}
]
]
}
Here is my launch.json and I run nodejs with express and it work fine.
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"program": "${workspaceFolder}/app.js",
"args": ["--env","local"]
}
]
}
Turns out I was picking wrong process ID.
When we start the debugger, it shows us the list of running processes to select with which debugger will be attached.
I picked the one ending with _babel-node server.js instead of --exec babel-node server.js. Doing this loaded all my script and started working as expected.

Can't get VSCode debbuging to work with my NodeJs app

I'm having trying to debug my app on Visual Studio Code. I have the following config on my package.json:
"scripts": {
"build": "rimraf dist/ && babel ./ --out-dir dist/ --ignore ./node_modules,./.babelrc,./package.json,./npm-debug.log --copy-files",
"start": "npm run build && node --inspect=12345 dist/app.js"
}
Im using ES6 on my Node app, that's why it is kinda messy my build config.
When I run npm start everything works fine, I can use my app.
Now to try to debug it, I have set the following launch configurations:
"configurations": [
{
"type": "node",
"name": "Attach to Remote",
"request": "attach",
"port": 12345
},
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"program": "${workspaceFolder}\\dist\\app.js"
}
]
Both of them ""work"": VS Code switch to "debug mode" but I can't hit any breakpoints. They all get grayed out:
I have tried to fix using this answer, but couldn't get it to work...
Any help?
Thanks in advance!
I am using VS Code v 1.28.2 and I'm able to debug both ways.
1) With the built in debuger ( Menu -> Debug -> Start Debuging)
2) starting the application with node inspect index.js. In that case you have to declare breakpoints in your code with the debugger; keyword. Then, when in debug-mode and stoped in a breakpoint, you continue execution typing cont in the command line.
hope it helps
I found out I was just missing the --source-maps from my babel-cli command... -.-
After adding it, VSCode is able to find the breakpoints.
So basically the solution was:
Add --source-maps to my build command:
"scripts": {
"build": "rimraf dist/ && babel ./ --out-dir dist/ --ignore ./node_modules,./.babelrc,./package.json,./npm-debug.log --copy-files --source-maps",
"start": "npm run build && node --inspect=12345 dist/app.js"
}
And I configured a launch as follows:
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"program": "${workspaceFolder}\\dist\\app.js",
"preLaunchTask": "npm: build"
}
]
Hope it helps someone!

Can't launch VSCode debugger for node with babel-node

When I type npm run debug into the console I get: "Debugger listening on ws://127.0.0.1:3090/d17dfe56-4fa4-4686-a62e-d07cff78c834". When I go to this adress in chrome the only thing I see is "WebSockets request was expected". What parts of my config should I tweak to make the debugger work? I'm using the latest version of nodejs.
package.json scripts
"scripts": {
"prod": "webpack -p --env.production --progress",
"start": "babel-node --presets es2015 server/server.js",
"watch": "nodemon --exec npm run start",
"debug": "babel-node --presets es2015 server/server.js --inspect --debug-brk=3090"
}
launch.json:
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch via NPM",
"type": "node",
"request": "launch",
"runtimeExecutable": "npm",
"program": "${workspaceRoot}/server/server.js",
"restart": true,
"runtimeArgs": [
"run-script", "debug"
],
"port": 3090
},
{
"type": "chrome",
"request": "launch",
"name": "Launch Chrome against localhost",
"url": "http://localhost:3090",
"webRoot": "${workspaceRoot}"
},
{
"type": "chrome",
"request": "attach",
"name": "Attach to Chrome",
"port": 3090,
"webRoot": "${workspaceRoot}"
}
]
}
File structure:
├───.vscode
├───js
├───server
│ ├───db
│ ├───middleware
│ ├───models
│ ├───server.js
This seems to be an issue with nodejs library version >= 7.0.0.
First Workaround:
A small workaround to open this file in chrome with dev tools is to copy the code of link after ws in your case:
Debugger listening on ws://127.0.0.1:3090/d17dfe56-4fa4-4686-a62e-d07cff78c834
and append it in the end of the line of dev tools link with ws= just as shown below:
chrome-devtools://devtools/bundled/inspector.html?experiments=true&v8only=true&ws=127.0.0.1:3090/d17dfe56-4fa4-4686-a62e-d07cff78c834
This will enable you to open your program in chrome dev tools. Link and solution to the issue is given here
Second Workaround:
I tried installing old version of node i.e. 6.11.2 and npm 3.10 and gave it a try in visual studio code, it was working perfectly fine without any problems.
however, with the trick shown above in first method I am still able to use latest version of both node and npm.
EDIT: Formatted my answer for better understanding

Running NodeJS project in Visual Studio Code with yarn

I have a NodeJS project which I can start from command line with yarn start command. My package.json looks similar to this:
{
"name": "projectname",
"version": "0.0.1",
"description": "",
"author": "My Name",
"license": "",
"scripts": {
"start": "yarn dev",
"dev": "yarn stop && pm2 start pm2-dev.yaml && webpack-dev-server --progress",
"prod": "yarn stop && yarn build && pm2 start pm2-prod.yaml",
"build": "rimraf dist lib && babel src -d lib --ignore test.js && cross-env NODE_ENV=production webpack -p --progress",
"stop": "rimraf logs/* && pm2 delete all || true"
},
"dependencies": {
"body-parser": "~1.16.0",
"ejs": "2.5.5",
"express": "^4.14.1",
"pg": "^6.1.2",
"react": "^15.4.2",
"redux": "^3.6.0",
},
"devDependencies": {
"babel-cli": "^6.22.2",
"cross-env": "^3.1.4",
"eslint": "^3.13.0",
"pm2": "^2.3.0",
"redux-mock-store": "^1.2.2",
"rimraf": "^2.5.4",
"webpack": "^2.2.1",
"webpack-dev-server": "^2.2.1"
}
}
I am trying to start this project in debugging mode with Visual Studio Code but with almost no luck. I have defined my launch configuration in VS Code launch.json file like this:
{
// Use IntelliSense to learn about possible Node.js debug attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "yarn",
"runtimeExecutable": "yarn",
"runtimeArgs": [
"start"
],
"port": 5858,
"cwd": "${workspaceRoot}",
"timeout": 10000
}
]
}
The problem with this configuration is that it usually times-out because webpack-dev-server build is longer than 10 seconds. I can increase the timeout in my configuration, but I have noticed that VS Code results with a message Cannot connect to runtime process (timeout after 30000 ms). eventually, so I assume that this is not a good solution. Also, my breakpoints are ignored with this kind of config which tells me that I am definitely doing something wrong here.
This is the first time I am trying out Visual Studio Code and I usually don't use NodeJS, but I got this project with all these scripts in package.json already defined so I'm trying to adopt to it and therefore all the confusion about how to run it properly.
Can Visual Studio Code run a project like this with full debugging functionality at all, and if so, how should I configure my launch script?
I ended up having the following configuration in launch.json:
{
"type": "node",
"request": "launch",
"name": "Launch via Yarn",
"runtimeExecutable": "yarn",
"cwd": "${workspaceFolder}",
"runtimeArgs": ["start:debug"],
"port": 5858
}
And the following entry in the scripts property inside package.json:
"start:debug": "node --inspect-brk=5858 ./server/index.js",
You could include a timeout key (which defaults to 10000) and increase its value if have any prestart:debug script in your package.json which could lead to delay the launch of the actual node app.
I can't specifically answer the webpack parts of the question. However, your script above won't work because you haven't enabled debugging. Exposing debugging allows a debugger to attach to this process, and it also blocks program execution until a debugger attaches. You'll need to make another script in your package.json that allows for debugging. Then, you can use your debugging-specific script to debug and your non-debugging script to run normally. For example:
"scripts": {
"start": "yarn dev",
"dev": "node entry.js",
"dev-debug": "node --inspect-brk=5858 entry.js",
Then, in your launch.json replace "start" with "dev-debug". The debugging port is already set to 5858 in both launch.json and package.json, so this should work. The key is running node with the --inspect-brk command, forcing the execution of the node app to stop until a debugger attaches to it.
Additionally to the above - to get mine working I had to add the following to my package.json (the exec was still required) -
"start:debug": "nodemon --inspect-brk=5858 --exec \"babel-node\" src/index.js"
Haven't used the debugged in VS Code however I'm using nodemon to debug with Chrome with a shell script.
bin_dir="$__dirname/../node_modules/.bin"
src_dir="$__dirname/../src"
"$bin_dir/nodemon" --ext js,yaml \
--watch "$src_dir/package.json" \
--watch "$src_dir" \
"$src_dir/index.js" \
--exec "yarn && babel-node --inspect=0.0.0.0:9229"
Open chrome://inspect/#devices and start up your debugger
Thanks for the information shared in this thread, What exactly is the 'react-scripts start' command?, by #johndpope.
Here is the setup I used in vscode's launch.json file in configurations section for launching a react process.
{
"name": "Launch: Frontend Server",
"program": "${workspaceFolder}/node_modules/react-scripts/bin/react-scripts.js",
"args": ["start"],
"request": "launch",
"type": "node",
"console": "integratedTerminal",
"localRoot": "${workspaceFolder}",
}
So, response to the original post, you may try to see what is the script used in rimraf library.

vscode debug ES6 application

I have VSCode 0.5.0. I set the compilerOptions flag to "ES6" and the editor started recognizing my ES6 code as correct.
I have babel installed.
My Mocha tests use the babel compilers and my tests pass.
My app runs from the command line with no problems when I launch it with babel-node .
When I debug the app from within VSCode, it starts up without the ES6 support, and the app fails for ES6 syntax issues.
Are there debug settings that I missed turning on?
Here's how to get VSCode debugger to work with Babel 6+:
First install dependencies locally:
$ npm install babel-cli --save
$ npm install babel-preset-es2015 --save
Then run babel-node:
$ node_modules/babel-cli/bin/babel-node.js --inspect --presets es2015 -- server.js --inspect
By default, the debugger will listen on port 5858, so make sure the port matches in launch.json for Attach configuration:
{
"name": "Attach",
"type": "node",
"request": "attach",
"port": 5858
}
Now attach the debugger in VSCode:
make sure debug configuration is set to Attach and not Launch
run with F5
Nodemon
Although not required, if you also want to use nodemon to pickup code changes without restarting the server, you can do this:
Make sure nodemon is installed:
$ npm install nodemon --save-dev
Run the server
$ node_modules/.bin/nodemon node_modules/babel-cli/bin/babel-node.js --inspect --presets es2015 -- server.js --inspect
Finally, attach the debugger as shown above.
Assuming you have babel-cli installed as a local module in your project the following should work.
launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch",
"type": "node",
"request": "launch",
"program": "${workspaceRoot}/node_modules/babel-cli/bin/babel-node.js",
"stopOnEntry": false,
"args": [
"${workspaceRoot}/server.js"
],
...
You can try babel-register (you'll also need other companion babel modules as req'd):
npm install --save-dev babel-register
with a launch.json configuration along these lines:
{
"version": "0.2.0",
"configurations": [
{
"name": "Launch",
"type": "node",
"request": "launch",
"program": "${workspaceRoot}/src/index.js",
"stopOnEntry": false,
"args": [],
"cwd": "${workspaceRoot}",
"preLaunchTask": null,
"runtimeExecutable": null,
"runtimeArgs": [
"--nolazy",
"--require",
"babel-register"
],
"env": {
"NODE_ENV": "development"
},
"console": "internalConsole",
"sourceMaps": true,
"outFiles": [
]
},
{
"name": "Attach",
"type": "node",
"request": "attach",
"port": 5858,
"address": "localhost",
"restart": false,
"sourceMaps": false,
"outFiles": [],
"localRoot": "${workspaceRoot}",
"remoteRoot": null
},
{
"name": "Attach to Process",
"type": "node",
"request": "attach",
"processId": "${command.PickProcess}",
"port": 5858,
"sourceMaps": false,
"outFiles": []
}
]
}
This is loosely based on vscode-debug-nodejs-es6 with the addition of the babel-register runtime argument.
By default VSCode launches node just with a --debug-brk option. This is not enough to enable ES6 support. If you can find out what options 'babel-node' passes to node, you could specify the same options in the VSCode launch config (through the runtimeArgs attribute). But this does not solve the issue that babel-node transpiles your ES6 code before running it.
Alternatively you could try to set the 'runtimeExecutable' in your launch config to 'babel-node'. This approach works with other node wrappers, but I haven't verified that is works with babel-node.
A third option (which should work) is to use the attach mode of VSCode: for this launch babel-node from the command line with the '--debug' option. It should print a port number. Then create an 'attach' launch config in VSCode with that port.
babel + nodemon
In the VS Code Terminal, launch your server with the --inspect argument:
nodemon --inspect --watch src --exec node_modules/.bin/babel-node --presets react,es2015 src/server.js
Among the other lines, one will show the port on which the debugger is listening:
...
Debugger listening on port 9229
...
Create the following debug configuration:
{
"type": "node",
"request": "attach",
"name": "Attach to Port",
"address": "localhost",
"port": 9229
}
Launch the debugger, and if everything went fine you will see in the output Terminal:
Debugger attached.
From now on, you can debug your application.
There are two ways of doing it:
First Option using npm command prompt
In package.json file create build command that will execute babel
{
"scripts": {
"build": "babel src --out-dir dist --watch --source-maps"
},
"devDependencies": {
"babel-cli": "^6.23.0",
"babel-preset-es2015-node6": "^0.4.0",
"eslint": "^3.16.0"
}
}
In launch.json Enter following code:
{
"configurations": [
{
"name": "Launch",
"type": "node",
"request": "launch",
"program": "${workspaceRoot}/src/index.js",
"stopOnEntry": false,
"args": [],
"cwd": "${workspaceRoot}",
"runtimeArgs": [
"--nolazy"
],
"sourceMaps": true,
"outFiles": [
"${workspaceRoot}/dist/**/*.js"
]
}
]
}
Open your cmd window, navigate to your package.json file and execute:
npm run build
Open your VS Code and run your code. It will run and it will stop at all your breakpoints. The reason it works because source maps are generated and VS knows how to map them to your code.
Second option using VS Code task:
In VS Code add following task (Ctrl + Shift + P) and type 'Tasks: Configure Task Runner':
Add following code to tasks.json file
{
"version": "0.1.0",
"command": "${workspaceRoot}/node_modules/.bin/babel",
"isShellCommand": true,
"tasks": [
{
"taskName": "watch",
"args": [
"src",
"--out-dir",
"dist",
"--watch",
"--source-maps"
],
"suppressTaskName": true,
"isBuildCommand": true
}
]
}
Now execute task, but pressing Ctrl + Shift + B (build command) and now you can run and debug your code. VS Code doing the same as what npm is doing in step one.
You will also need to configure babel in .babelrc (located in the root of the project) file like this:
{
"presets": [
"es2015-node6"
]
}
and jsconfig.json (located in the root of the project)
{
"compilerOptions": {
"target": "ES6"
},
"include": [
"src/**/*"
]
}
This is my configuration and it works great! I am using the VSCode debugging, mocha 6.1.4, node: v8.16.0, and Babel version 6.
Make sure to load babel-register and babel-polyfill in runtimeArgs, or else you will get regeneratorRuntime is not defined!
{
"type": "node",
"request": "launch",
"name": "Mocha test debug",
"runtimeExecutable": "${workspaceRoot}/node_modules/.bin/mocha",
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen",
"protocol": "inspector",
"stopOnEntry": false,
"runtimeArgs": [
"--nolazy",
"--require",
"babel-register",
"--require",
"babel-polyfill",
"tests/*.js"
],
"sourceMaps": true
}
babel-node & vs code attach
config a npm script in package.json:
"scripts": {
"debug": "babel-node --debug-brk demo.js --presets es2015,stage-2"
}
add vs code debug configuration:
{
"name": "Attach",
"type": "node",
"protocol": "legacy",
"request": "attach",
"port": 5858
}
When transpiling with bael-node, you should add "--inspect-brk" in the script, so that the script may break when a breakpoint is hit.
Ex:
"start": "babel-node --inspect-brk app.js --presets es2015,stage-2"
Now when you run using npm run start, debugger will be launched and you can see following in your console:
Debugger listening on ws://127.0.0.1:9229/cf72a33c-ab38-4798-be5e-8b8df072f724
For help see https://nodejs.org/en/docs/inspector
That shows debugging process has started and we can attach to it on port# 9229.
Now, you need to add the following debugger config for vs-code to attach to this process: (in launch.json)
{
"version": "0.2.0",
"configurations": [
{
"name": "Attach to Process",
"type": "node",
"request": "attach",
"port": 9229
}
]
}
After saving, click the "start debugging" button, to attach to process initiated by node earlier. You may read more about this here

Resources