← Back to DevBytes

WebStorm Debugging: Complete Guide

WebStorm Debugging: Complete Guide

Debugging is one of the most valuable skills a developer can master, and JetBrains' WebStorm ships with a powerful, deeply integrated debugger that can save you hours of console.log detective work. This guide walks you through everything from your first breakpoint to advanced remote debugging scenarios, with practical examples you can apply immediately.

What Is WebStorm Debugging?

WebStorm's debugger is a built-in tool that attaches to JavaScript and TypeScript runtimes — Node.js, browsers, and even Docker containers — allowing you to pause execution, inspect variables, evaluate expressions on the fly, and step through your code line by line. Unlike print-based debugging, the WebStorm debugger gives you a live snapshot of your application's state at any moment, making it far easier to reason about complex logic and asynchronous flows.

Under the hood, WebStorm uses the Chrome DevTools Protocol for browser debugging and the V8 Inspector Protocol for Node.js. This means you get the same low-level inspection capabilities as Chrome DevTools, but integrated directly into your IDE alongside your source code, version control, and tests.

Why Debugging in WebStorm Matters

Getting Started: Your First Debug Session

Let's start with a simple Node.js script. Create a file named calculator.js in your project:

// calculator.js
function calculateTotal(items, taxRate) {
  let subtotal = 0;
  for (const item of items) {
    subtotal += item.price * item.quantity;
  }
  const tax = subtotal * taxRate;
  return {
    subtotal: subtotal,
    tax: tax,
    total: subtotal + tax
  };
}

const cart = [
  { name: "Widget", price: 9.99, quantity: 3 },
  { name: "Gadget", price: 24.50, quantity: 1 },
  { name: "Sprocket", price: 4.25, quantity: 6 }
];

const result = calculateTotal(cart, 0.08);
console.log("Order summary:", result);

To debug this script, click in the gutter next to the line number on the subtotal += item.price * item.quantity; line. A red dot appears, indicating an active breakpoint. Now, instead of running the file normally, right-click anywhere in the editor and select Debug 'calculator.js'. WebStorm launches the script in debug mode and pauses execution when it hits your breakpoint.

Once paused, the Debug tool window opens at the bottom of the screen. Here you will see:

Stepping Through Code

Once execution is paused, you control the flow using the stepping toolbar. These are the essential controls:

Try stepping through the calculateTotal function. Press F8 repeatedly and watch the subtotal variable update in the Variables panel with each iteration of the loop. This immediate feedback is what makes the debugger so powerful for understanding how data flows through your code.

Conditional and Logging Breakpoints

Sometimes you only want to pause when a specific condition is true. Right-click on an existing breakpoint (or the gutter) and you will see a popup with advanced options. Enter a condition in the Condition field:

item.price > 20

Now the debugger only pauses when the current item's price exceeds 20. This is extremely useful when debugging loops that process hundreds of items but only misbehave on a few.

You can also create logging breakpoints (sometimes called tracepoints). These do not pause execution — instead, they log a message to the console each time the line is hit. Enable the Evaluate and log option and enter an expression:

`Processing ${item.name} - price: ${item.price}, qty: ${item.quantity}`

Logging breakpoints are a clean replacement for sprinkling console.log statements throughout your code, because they live in the debugger configuration rather than your source files.

Debugging Client-Side JavaScript in the Browser

WebStorm can debug JavaScript running in a browser. The most common approach is to create a JavaScript Debug run configuration. Go to Run > Edit Configurations, click the + button, and select JavaScript Debug. Enter the URL of your local dev server, for example http://localhost:3000.

Consider this simple front-end example:

<!-- index.html -->
<!DOCTYPE html>
<html>
<head>
  <title>Todo Debug Demo</title>
</head>
<body>
  <input id="taskInput" type="text" placeholder="Add a task" />
  <button id="addBtn">Add</button>
  <ul id="taskList"></ul>

  <script src="app.js"></script>
</body>
</html>
// app.js
const tasks = [];

document.getElementById("addBtn").addEventListener("click", () => {
  const input = document.getElementById("taskInput");
  const value = input.value.trim();

  if (value === "") {
    return;
  }

  const task = {
    id: Date.now(),
    text: value,
    completed: false
  };

  tasks.push(task);
  renderTasks();
  input.value = "";
});

function renderTasks() {
  const list = document.getElementById("taskList");
  list.innerHTML = "";

  for (const task of tasks) {
    const li = document.createElement("li");
    li.textContent = task.text;
    li.dataset.taskId = task.id;

    li.addEventListener("click", () => {
      task.completed = !task.completed;
      li.style.textDecoration = task.completed ? "line-through" : "none";
    });

    list.appendChild(li);
  }
}

Set a breakpoint inside the click handler on the line const value = input.value.trim();. Start your dev server, then run the JavaScript Debug configuration. WebStorm opens a Chromium-based browser (or your configured browser) and attaches the debugger. Click the Add button in the browser, and execution pauses inside WebStorm at your breakpoint. You can inspect the input element, the tasks array, and the DOM directly from the IDE.

Debugging Node.js Applications with Nodemon

In real projects, you often run Node servers with file watchers like nodemon. To debug these, create a Node.js run configuration and configure it to use nodemon. In Edit Configurations, add a new Node.js configuration, then set the following:

Node parameters: --inspect
JavaScript file: node_modules/nodemon/bin/nodemon.js
Application parameters: server.js

Here is a small Express server to demonstrate:

// server.js
const express = require("express");
const app = express();
const PORT = 3000;

app.use(express.json());

const users = [];

app.get("/users", (req, res) => {
  res.json(users);
});

app.post("/users", (req, res) => {
  const { name, email } = req.body;

  if (!name || !email) {
    return res.status(400).json({ error: "Name and email are required" });
  }

  const existing = users.find(u => u.email === email);
  if (existing) {
    return res.status(409).json({ error: "User already exists" });
  }

  const user = {
    id: users.length + 1,
    name,
    email,
    createdAt: new Date().toISOString()
  };

  users.push(user);
  res.status(201).json(user);
});

app.listen(PORT, () => {
  console.log(`Server running on http://localhost:${PORT}`);
});

Set a breakpoint on the line const existing = users.find(u => u.email === email);. Start the debug configuration, then send a POST request using curl or your HTTP client:

curl -X POST http://localhost:3000/users \
  -H "Content-Type: application/json" \
  -d '{"name":"Alice","email":"alice@example.com"}'

Execution pauses at your breakpoint. Inspect req.body in the Variables panel, step through the validation logic, and watch how the users array changes. Because you are using nodemon, any file changes will restart the server while keeping the debugger attached.

Debugging Tests

WebStorm integrates deeply with test runners like Jest, Mocha, and Vitest. You can debug individual tests by clicking the green gutter icon next to a test and selecting Debug. Consider this Jest test file:

// math.test.js
function fibonacci(n) {
  if (n < 2) return n;
  return fibonacci(n - 1) + fibonacci(n - 2);
}

describe("fibonacci", () => {
  it("returns correct values for small inputs", () => {
    expect(fibonacci(0)).toBe(0);
    expect(fibonacci(1)).toBe(1);
    expect(fibonacci(5)).toBe(5);
    expect(fibonacci(10)).toBe(55);
  });

  it("handles edge cases", () => {
    expect(fibonacci(-1)).toBe(-1);
  });
});

Set a breakpoint inside the fibonacci function on the return fibonacci(n - 1) + fibonacci(n - 2); line. Right-click the test file and select Debug 'math.test.js'. WebStorm runs Jest in debug mode and pauses at your breakpoint. You can step through recursive calls and watch how n changes with each invocation, which makes it trivial to understand why the edge case test fails.

Remote and Docker Debugging

For applications running inside Docker, WebStorm can attach to the Node inspector exposed by the container. First, ensure your Dockerfile or docker-compose configuration starts Node with the inspect flag:

# docker-compose.yml
version: "3.8"
services:
  api:
    build: .
    ports:
      - "3000:3000"
      - "9229:9229"
    command: node --inspect=0.0.0.0:9229 server.js

In WebStorm, create an Attach to Node.js/Chrome run configuration. Set the host to localhost and the port to 9229. Start your Docker container, then run the attach configuration. WebStorm connects to the remote inspector, and your breakpoints in the local source files map to the executing code inside the container. This workflow is essential for debugging microservices and production-like environments.

Using the Evaluate Expression Tool

One of the most underused features in WebStorm's debugger is the Evaluate Expression dialog, accessible via Alt+F8 while paused. It lets you run arbitrary JavaScript in the context of the current frame. For example, while paused inside the calculateTotal function, you could type:

items.filter(i => i.quantity > 2).map(i => i.name)

The result appears immediately, letting you prototype logic without modifying your source code. You can also use the inline Console in the Debug window for quick one-off evaluations.

Best Practices for Effective Debugging

Conclusion

WebStorm's debugger is a feature-rich tool that transforms how you investigate and fix bugs in JavaScript and TypeScript applications. By mastering breakpoints, stepping controls, conditional logic, expression evaluation, and remote attachment, you can diagnose issues in a fraction of the time it takes with traditional logging. The key is to make debugging a habit — reach for the debugger instead of console.log, and over time you will build an intuitive understanding of how your code executes. Start with the simple examples in this guide, then gradually incorporate advanced techniques like Docker attachment and exception breakpoints into your daily workflow. Happy debugging.

— Ad —

Google AdSense will appear here after approval

← Back to all articles