A real debugger finds bugs far faster than print statements, and VS Code makes it available for almost every language.
VS Code's debugger is generic; language extensions provide debug adapters (Node.js is built in, Python via the Python extension, and so on).
Basics: click left of a line number or press F9 to set a breakpoint, then F5 to start. When execution stops you get:
- Variables and Watch panels, plus hovering over any variable in the editor.
- The Call Stack, letting you inspect callers' frames.
- The Debug Console, where you can evaluate expressions in the paused context.
- Controls:
F5continue,F10step over,F11step into,Shift+F11step out,Shift+F5stop.
Right-click the gutter for smarter breakpoints:
- Conditional breakpoints stop only when an expression is true (
order.total > 1000), or after a hit count. - Logpoints print a message with
{expressions}without stopping or editing code, ideal for production-like runs.
For anything beyond "run this file", create .vscode/launch.json (Run and Debug view > "create a launch.json file"). Each configuration has a type (debugger), a request (launch starts a program, attach connects to one already running, such as a server in a container), and options like program, args, env and cwd. Variables such as ${workspaceFolder} and ${file} keep it portable. preLaunchTask can run a build first.
Example
// .vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Run API",
"type": "node",
"request": "launch",
"program": "${workspaceFolder}/src/server.js",
"args": ["--port", "3000"],
"env": { "NODE_ENV": "development" },
"preLaunchTask": "build"
},
{
"name": "Attach to container",
"type": "node",
"request": "attach",
"port": 9229
}
]
}Remember
- F9 breakpoint, F5 start/continue, F10 over, F11 into
- Conditional breakpoints and logpoints avoid code edits
- launch.json: type, request (launch/attach), program, args, env
Watch out for
- Leaving debug-only code edits (prints, sleeps) in place when a logpoint would have done the job.