Why VS Code Debugger?
VS Code includes a powerful debugger that works with virtually any language and runtime. No more console.log debugging—set breakpoints, step through code, inspect variables, and find bugs faster.
javascript
// Instead of:
console.log('User:', user);
console.log('Data:', data);
console.log('Result:', result);
// Just set a breakpoint and inspect!
// Click in the gutter, press F9
// Hover over variables to see values
// Use Debug Console to evaluate expressionsGetting Started
Launch Configuration
json
// .vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"type": "node",
"request": "launch",
"name": "Launch Program",
"skipFiles": ["<node_internals>/**"],
"program": "${workspaceFolder}/src/index.js"
},
{
"type": "node",
"request": "attach",
"name": "Attach to Process",
"port": 9229
}
]
}Debug Panel
Variables: Shows local, global variables
Watch: Monitor expressions
Call Stack: Current execution path
Breakpoints: List of all breakpoints
Debug Console: Evaluate expressionsBreakpoint Mastery
Types of Breakpoints
javascript
// 1. Regular breakpoint (F9)
// Stops execution when hit
function processData(data) {
const result = data.map(item => { // ← Set breakpoint here
return transform(item);
});
return result;
}
// 2. Conditional breakpoint
// Right-click → Edit Breakpoint → Add condition
// Break only when: data.length > 100
// 3. Logpoint
// Right-click → Add Logpoint
// Prints message without stopping
// console.log('Data:', data);
// 4. Hit count breakpoint
// Break after N times
// Right-click → Edit Breakpoint → Set hit count
// 5. Triggered breakpoint
// Only active when another breakpoint is hit
// Right-click → Edit Breakpoint → Set triggerConditional Breakpoints
javascript
// Break when condition is true
data.length === 0
user.age < 18
response.status !== 200
// Break on specific value
item.id === 123
// Complex conditions
data.length > 100 && data.every(item => item.valid)
// Logpoint with expressions
`Processing item ${item.id}: ${item.name}`
// Call functions in conditions
isValidUser(user) // Break if returns trueDebugging Actions
Stepping Through Code
F5 - Start debugging
F9 - Toggle breakpoint
F10 - Step over (next line)
F11 - Step into (function)
Shift+F11 - Step out (return to caller)
Shift+F5 - Stop debugging
// Continue execution
F5 or Continue button
// Restart
Cmd+Shift+F5 (Mac)
Ctrl+Shift+F5 (Windows)Inspecting Variables
javascript
// Hover over variable
const user = { name: 'John', age: 30 };
// Hover to see value
// Add to Watch
// Type expression in Watch panel
user.name
data.length
calculateTotal(items)
// Scope variables
// Automatically shows:
// - Local variables
// - Closure variables
// - Global variables
// Variable inspection
// Click on object to expand
// See properties and values
// Modify values inlineAdvanced Debugging
Debug Console
javascript
// Evaluate expressions in Debug Console
// Variables are in scope
> user.name
'John'
> data.filter(item => item.active)
[...items]
> calculateTotal(cart)
123.45
// Call functions
> processData(rawData)
[...processed]
// Modify variables
> counter = 100
100
> items.push(newItem)
5
// Test code snippets
> items.map(i => i.price * 1.1)
[...prices]Call Stack Navigation
javascript
// View call stack in panel
// Shows execution path
// Click frames to navigate
// Example stack:
processData (index.js:25)
transform (utils.js:10)
validate (helpers.js:5)
// Jump to any frame
// Inspect variables at that level
// Understand how you got hereLanguage Support
JavaScript/Node.js
json
{
"type": "node",
"request": "launch",
"name": "Debug Node.js",
"program": "${workspaceFolder}/src/index.js",
"cwd": "${workspaceFolder}",
"runtimeExecutable": "node",
"runtimeArgs": ["--nolazy"],
"env": {
"NODE_ENV": "development",
"DEBUG": "*"
},
"console": "integratedTerminal",
"stopOnEntry": false,
"skipFiles": ["<node_internals>/**"]
}React/Next.js
json
{
"name": "Next.js: debug server-side",
"type": "node-terminal",
"request": "launch",
"command": "npm run dev"
}
{
"name": "Next.js: debug client-side",
"type": "chrome",
"request": "launch",
"url": "http://localhost:3000",
"webRoot": "${workspaceFolder}"
}Python
json
{
"name": "Python: Current File",
"type": "debugpy",
"request": "launch",
"program": "${file}",
"console": "integratedTerminal",
"justMyCode": true
}Go
json
{
"name": "Launch Package",
"type": "go",
"request": "launch",
"mode": "auto",
"program": "${workspaceFolder}",
"env": {},
"args": []
}Debugging Tests
Jest
json
{
"name": "Debug Jest Tests",
"type": "node",
"request": "launch",
"runtimeExecutable": "npm",
"runtimeArgs": ["test", "--", "--runInBand"],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
}Vitest
json
{
"name": "Debug Vitest",
"type": "node",
"request": "launch",
"program": "${workspaceFolder}/node_modules/.bin/vitest",
"args": ["run", "--reporter=verbose"],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
}Remote Debugging
SSH Remote Debugging
bash
# Install Remote-SSH extension
# Configure SSH hosts
# .ssh/config
Host server
HostName example.com
User ubuntu
IdentityFile ~/.ssh/key.pem
# Open remote folder
# Code → Open Folder → Select SSH host
# Debug works just like localDocker Debugging
json
{
"name": "Docker Node.js",
"type": "node",
"request": "attach",
"port": 9229,
"address": "localhost",
"localRoot": "${workspaceFolder}",
"remoteRoot": "/app"
}
// docker-compose.yml
services:
app:
build: .
ports:
- "9229:9229"
command: node --inspect=0.0.0.0:9229 index.jsAdvanced Features
Debugging Chrome
json
{
"type": "chrome",
"request": "launch",
"name": "Launch Chrome",
"url": "http://localhost:3000",
"webRoot": "${workspaceFolder}",
"sourceMaps": true,
"sourceMapPathOverrides": {
"webpack:///*": "${webRoot}/*"
}
}Multi-Target Debugging
json
{
"version": "0.2.0",
"configurations": [
{
"name": "Server",
"type": "node",
"request": "launch",
"program": "${workspaceFolder}/server.js"
},
{
"name": "Client",
"type": "chrome",
"request": "launch",
"url": "http://localhost:3000"
}
],
"compounds": [
{
"name": "Server+Client",
"configurations": ["Server", "Client"]
}
]
}Productivity Tips
Keyboard Shortcuts
F5 - Start/Continue
F9 - Toggle breakpoint
F10 - Step over
F11 - Step into
Shift+F11 - Step out
Shift+F5 - Stop
Cmd+Shift+P - Show all commands
Cmd+Shift+D - Show debug
Cmd+K Cmd+X - Cut line
Cmd+Enter - Insert line belowDebug Actions
javascript
// Add debug configuration
// Click "Add Configuration" in launch.json
// Auto-attach to process
// Debug → Attach to Process
// Select Node.js process
// JavaScript Debug Terminal
// Terminal menu → Create JavaScript Debug Terminal
// Runs code with debugger attachedTroubleshooting
Source Maps
json
// Ensure source maps work
{
"type": "node",
"request": "launch",
"sourceMaps": true,
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
"webRoot": "${workspaceFolder}",
"resolveSourceMapLocations": [
"${workspaceFolder}/**",
"!**/node_modules/**"
]
}Skipping Files
json
{
"skipFiles": [
"<node_internals>/**",
"node_modules/**",
"${workspaceFolder}/lib/**"
]
}Best Practices
1. Use Descriptive Names
json
{
"name": "Debug User Registration Flow",
"type": "node",
"request": "launch"
}2. Set Up Environments
json
{
"env": {
"NODE_ENV": "test",
"LOG_LEVEL": "debug"
},
"envFile": "${workspaceFolder}/.env"
}3. Use Pre-Launch Tasks
json
{
"preLaunchTask": "npm: build",
"outFiles": ["${workspaceFolder}/dist/**/*.js"]
}Conclusion
Master VS Code debugging to write better code faster. The built-in debugger works with any language and provides all the features you need to squash bugs efficiently.
Key takeaways:
- Use breakpoints instead of console.log
- Leverage conditional breakpoints for targeted debugging
- Master the Debug Console for live evaluation
- Set up proper launch configurations
- Use keyboard shortcuts for speed
Debug like a pro with VS Code!