webdev.complete
🪲 Debugging Like a Pro
🛠️Dev Toolbelt
Lesson 54 of 117
30 min

Chrome DevTools

Elements, Network, Sources, Performance, Lighthouse.

Open any web page. Press Cmd+Option+I (Mac) or F12 (Windows/Linux). That panel that just appeared is the single most powerful tool in your career. Most developers use about 5% of it. This lesson is the guided tour to push that to 50%.

Elements: the live DOM

The Elements panel shows the current DOM, not the original HTML. If JavaScript added a <div> after page load, it shows up here. You can edit anything live and the page updates instantly.

  • Right-click any element → Edit as HTML to rewrite a chunk of the page on the fly.
  • Styles pane shows the cascade. Toggle any property with its checkbox. Click + to add a new rule.
  • Computed pane shows the final resolved value of every CSS property, with which rule won.
  • :hov in the styles header lets you force pseudo-states like :hover and :focus-visible so you can inspect them.
Right-click → Inspect
Instead of opening DevTools and then hunting for an element, right-click the thing you want to inspect and choose "Inspect." DevTools opens with that element already selected.

Console: your REPL inside the page

The Console runs JS in the context of the current page. You have access to global variables, the DOM, and a bunch of dev-only utilities.

js
// $0 is whatever is currently selected in the Elements panel
$0                        // <div class="hero">...</div>
$0.style.outline = "2px solid red"

// $ and $$ are shorthand for querySelector/querySelectorAll
$("nav a")                // first <a> inside <nav>
$$(".btn")                // NodeList of all .btn elements

// inspect the value clearly
console.log({ user, count })       // labels included
console.dir($0)                    // expandable object view

// tables: a game-changer for arrays of objects
console.table([
  { id: 1, name: "Ada", role: "admin" },
  { id: 2, name: "Bob", role: "user" }
]);
// ┌─────────┬────┬───────┬─────────┐
// │ (index) │ id │ name  │ role    │
// │ 0       │ 1  │ "Ada" │ "admin" │
// │ 1       │ 2  │ "Bob" │ "user"  │
// └─────────┴────┴───────┴─────────┘

Other console verbs you should know:

js
console.warn("Deprecated API used")     // yellow
console.error("Validation failed")        // red, with stack trace

console.group("Loading user");            // collapse-friendly section
console.log("fetching ...");
console.log("got response");
console.groupEnd();

console.time("query");                    // measure elapsed time
await db.query("SELECT ...");
console.timeEnd("query");                 // query: 124.5ms

console.count("render");                  // increment a named counter
// render: 1, render: 2, render: 3 ...

console.assert(arr.length > 0, "Array should not be empty");

Network: what the browser is actually fetching

Every request the page makes shows up here: HTML, CSS, JS, fonts, API calls, web sockets. Each row gives you method, status, size, timing.

  • Filter row - narrow by Fetch/XHR, JS, CSS, Img, etc. Most days you just want Fetch/XHR to watch API calls.
  • Preserve log - keeps requests across page reloads. Essential when debugging auth redirects.
  • Disable cache (with DevTools open) - forces the browser to refetch everything, useful for testing cold loads.
  • Throttling- pretend you're on a slow 3G connection. Your homepage probably needs this test.
  • Click a request - Headers, Payload, Preview, Response, Timing tabs. The waterfall in Timing shows DNS, TLS, waiting, downloading.
Copy as fetch / curl
Right-click a request → Copy → Copy as fetch (or cURL). You get a runnable snippet that reproduces the exact request. Paste it into the console or Postman to debug auth or replay it with tweaks.

Sources: breakpoints, the real debugger

Yes, you can console.log. But a breakpoint lets you pause time, inspect every variable, and step through one line at a time.

  • Line breakpoint - click the line number in any source file. Code stops there before executing.
  • Conditional breakpoint - right-click the line number, set a condition like userId === 42. Only pauses when the condition is true.
  • Logpoint - same right-click menu. Logs an expression to the console without pausing. The unbeatable replacement for adding console.log and re-deploying.
  • DOM breakpoint - right-click an element in Elements → Break on → subtree modifications. Pauses when JS mutates that part of the DOM.
  • XHR/Fetch breakpoint - pause every time a URL containing a substring is requested. Magic for finding where a mystery request comes from.

When paused, the right panel shows: Scope (all variables in scope), Call Stack (how you got here), Watch (expressions you want to re-evaluate at each step), and Breakpoints.

js
function reducer(state, action) {
  // set a logpoint here:
  //   "reducer called with", action.type, action.payload
  // → console messages appear with no code change required

  switch (action.type) {
    case "increment":
      return { count: state.count + 1 };
    // ...
  }
}
The debugger keyword
Putting a literal debugger;statement in your code is the same as setting a breakpoint there. It only triggers when DevTools is open, so it's a fine way to pause from a build-step file you can't easily click in.

Application: storage, cookies, service workers

Where the browser keeps your state.

  • Local Storage / Session Storage - see and edit every key. Right-click → Clear to nuke the lot.
  • Cookies - including HttpOnly ones. Watch what your auth flow is setting.
  • IndexedDB - the heavyweight client-side store. You can browse object stores like a tiny database.
  • Service Workers- "Update on reload" and "Bypass for network" checkboxes have saved many an hour of debugging a stale cached app.
  • Cache Storage - what your service worker has cached.

Lighthouse: an instant audit

Lighthouse runs the page through automated tests and gives you scores for Performance, Accessibility, Best Practices, and SEO. Each finding is actionable, with documentation links.

bash
# you can also run it from the CLI
npx lighthouse https://example.com --view

Don't obsess over a perfect 100 on every metric. Use it to find the easy wins: missing alt text, unused JavaScript, oversized images, no-cache headers on assets.

Performance: flame charts in 60 seconds

When something feels slow, the Performance panel records what the browser actually did. Hit record, interact with the page, stop. You get:

  • Frames timeline at the top, showing dropped frames in red.
  • Main thread flame chart - call stacks over time. Wide blocks at the top are functions that took long. Tall stacks deep below are nested call chains.
  • Bottom-up / Call Tree tabs - aggregate the same data by time spent.

The standard playbook: record 5 seconds of slow interaction, find the widest block in the flame chart, click it, see what file and line is the hot spot. 9 times out of 10 the culprit is obvious.

Production builds are different
DevTools profiles whatever's running. A dev build has source maps, dev warnings, no minification, and is usually slower. Profile a production build (or use the ?profile bundle for React) for results that match reality.

Hidden gems

  • Cmd+Shift+Popens the "command palette" in DevTools. Type "screenshot" for a full-page screenshot command. Type "disable JavaScript" to see if your site works at all without JS.
  • Coverage tab (in More Tools) shows you which CSS and JS your page actually used during load. Reveals dead code that ships but never runs.
  • Rendering tabhas "Paint flashing" (highlights re-paints) and a layout shift visualizer. Animation debugging gold.
  • copy(value) in the Console copies any value to your clipboard, even objects (as JSON).

Quick quiz

Quiz1 / 3

You're staring at an API bug and want to log every render of a function without changing the code. What's the right DevTools tool?

Recap

  • Elements: live DOM and CSS. Edit anything, force pseudo-states.
  • Console: $0, $$, console.table, group, time, count.
  • Network: filter, preserve log, throttle, copy as fetch.
  • Sources: conditional breakpoints, logpoints, DOM breakpoints, the debugger; keyword.
  • Application: storage, cookies, service workers.
  • Lighthouse for audits. Performance for flame charts on real production builds.