jsmanifest logojsmanifest

5 Chrome DevTools Features That Will Save You Hours

5 Chrome DevTools Features That Will Save You Hours

Stop using Chrome DevTools like it's 2015. Discover network request blocking, logpoints, memory snapshots, and performance profiling techniques that actually work in production debugging.

While I was looking over some production debugging sessions the other day, I realized something unsettling: I was once guilty of spending hours adding console.log statements, refreshing my browser, and hoping something would magically reveal the bug. Little did I know that Chrome DevTools had features sitting right there that could have saved me countless afternoons of frustration.

Most developers I've met use maybe 20% of what DevTools offers. We stick to the Elements panel, throw in some console.log calls, and maybe peek at the Network tab when things get really desperate. But here's the thing—there are features built into DevTools that completely change how you debug and profile applications.

Today I want to share five features that transformed my debugging workflow. These aren't hidden Easter eggs or experimental flags. They're production-ready tools that you can start using immediately.

Why Most Developers Only Scratch the Surface of DevTools

When I finally decided to dig deeper into DevTools, I discovered a pattern: the most powerful features are often the least intuitive to discover. You won't stumble upon them by clicking around. They require deliberate exploration or, in my case, watching a colleague fix a memory leak in under five minutes while I would have spent an entire morning on it.

The ROI on learning these features is enormous. I'm talking about the difference between spending two hours adding debug logs versus spending ten minutes identifying the exact line causing issues. Between restarting your backend server repeatedly versus simulating network failures instantly in your browser.

Let's look at what you're missing.

Network Request Blocking: Test Failure Scenarios Without Backend Changes

Here's a scenario I've encountered more times than I'd like to admit: You need to test how your application handles a failed API request, but your backend team won't give you a development endpoint that returns errors. Or maybe you're working offline and need to simulate what happens when certain resources don't load.

I was once guilty of asking backend developers to modify their code just so I could test error states. What a waste of everyone's time!

Chrome DevTools has a feature called Network Request Blocking that solves this instantly. You can block specific URLs or use patterns to block multiple requests at once.

Here's how to use it: Open DevTools, go to the Network tab, and click the three dots menu. Select "Show Request Blocking" and you'll see a new drawer appear. Click the plus icon and enter a URL pattern like *api.example.com/users* to block all requests to that endpoint.

Chrome DevTools Network Request Blocking interface

Now refresh your page. Your application will behave exactly as if that endpoint is down. You can test your error handling, loading states, and fallback UI without changing a single line of backend code.

The pattern matching is powerful too. Use *.js to block all JavaScript files, or *tracking* to block analytics scripts. This is wonderful for testing how your app performs when third-party services fail—and they will fail.

Logpoints: Debug Without Breaking Flow (Or Adding console.log Everywhere)

I cannot stress this enough! Stop littering your codebase with console.log statements that you'll inevitably forget to remove before committing.

Logpoints are breakpoints that log messages to the console without pausing execution. They're dynamic, temporary, and they don't require modifying your source code.

Let me show you a practical example. Imagine you have this function that's behaving strangely:

function processUserData(users: User[]) {
  return users
    .filter(user => user.isActive)
    .map(user => ({
      id: user.id,
      fullName: `${user.firstName} ${user.lastName}`,
      email: user.email
    }))
    .sort((a, b) => a.fullName.localeCompare(b.fullName));
}

You suspect the filtering isn't working correctly, but you don't want to add logs and rebuild. Instead, right-click on the line number where you want to inspect values (say, line 3) and select "Add logpoint."

In the logpoint expression box, type: 'Active users:', users.filter(user => user.isActive).length

Now every time that line executes, you'll see the count logged to the console—without modifying your code or pausing execution. You can add multiple logpoints throughout your function to trace data transformations.

When I finally decided to use logpoints regularly, my debugging speed doubled. No more committing debug code. No more switching between editor and browser. Just pure, focused debugging.

Memory Snapshots: Find and Fix Memory Leaks in Minutes

Memory leaks used to terrify me. I'd see the browser tab's memory usage climbing steadily, know something was wrong, but have no idea where to start looking.

The Memory panel in DevTools changed everything. Luckily we can take heap snapshots that show us exactly what objects are consuming memory and, more importantly, what's keeping them from being garbage collected.

Here's the workflow I use: Take a heap snapshot before performing an action (like opening a modal). Perform the action. Take another snapshot. Close the modal. Take a third snapshot. If the third snapshot shows more memory than the first, you've got a leak.

The Comparison view will show you exactly which objects increased. In other words, it's pointing directly at your leak.

I came across this technique when debugging a React application that was adding event listeners but never cleaning them up:

function BadComponent() {
  useEffect(() => {
    const handleResize = () => {
      console.log('Window resized');
    };
    
    window.addEventListener('resize', handleResize);
    
    // Oops! Forgot to return cleanup function
    // This creates a new listener every render
  }, []);
  
  return <div>Content</div>;
}
 
function GoodComponent() {
  useEffect(() => {
    const handleResize = () => {
      console.log('Window resized');
    };
    
    window.addEventListener('resize', handleResize);
    
    // Proper cleanup prevents the leak
    return () => {
      window.removeEventListener('resize', handleResize);
    };
  }, []);
  
  return <div>Content</div>;
}

The memory snapshot immediately showed hundreds of event listener objects accumulating. Without this tool, I would have been reading through thousands of lines of code hoping to spot the issue.

Command Menu: Navigate DevTools 10x Faster

This one sounds simple but it's fascinating how much time you save once it becomes muscle memory.

Press Cmd+Shift+P (or Ctrl+Shift+P on Windows) anywhere in DevTools to open the Command Menu. This is your universal search for every DevTools feature.

Want to disable JavaScript? Type "disable javascript" and hit enter. Need to capture a full-page screenshot? Type "screenshot" and you'll see all screenshot options. Want to switch to the Network tab? Type "network."

The command menu eliminates all that clicking through panels and settings. I use it dozens of times per day for tasks like:

  • Taking screenshots (full page, area, or node)
  • Clearing storage, cache, or cookies
  • Toggling device emulation
  • Switching between panels
  • Running custom audits
  • Changing DevTools themes

It's the same concept you see in VS Code or Slack—one input box that can trigger any action. Once you internalize this, going back to manual navigation feels painfully slow.

Chrome DevTools Command Menu showing various options

Performance Profiler Deep Dive: Identify Exact Bottlenecks in Your React App

The Performance panel intimidated me for years. All those flame graphs and millisecond timings felt like information overload. But when I finally learned to read it properly, I could pinpoint performance issues down to the exact function call causing slowdowns.

Here's how I use it: Open the Performance panel, click the record button, perform the slow action in your app (like scrolling a list or opening a dropdown), then stop recording. DevTools will show you a detailed breakdown of everything that happened.

The Main thread section is where you'll spend most of your time. Long yellow bars indicate JavaScript execution. Purple bars show rendering and painting. If you see a lot of long tasks (anything over 50ms), you've found your bottleneck.

Click on any section to see the call stack. In React apps, you'll often find that re-renders are the culprit. You might discover that a component is re-rendering on every keystroke when it only needs to update once:

// Before: Re-renders entire list on every search input change
function SearchableList({ items }: { items: Product[] }) {
  const [search, setSearch] = useState('');
  
  const filtered = items.filter(item => 
    item.name.toLowerCase().includes(search.toLowerCase())
  );
  
  return (
    <>
      <input 
        value={search} 
        onChange={(e) => setSearch(e.target.value)} 
      />
      {filtered.map(item => (
        <ExpensiveListItem key={item.id} item={item} />
      ))}
    </>
  );
}
 
// After: Memoize the expensive list component
const MemoizedList = memo(({ items }: { items: Product[] }) => (
  <>
    {items.map(item => (
      <ExpensiveListItem key={item.id} item={item} />
    ))}
  </>
));
 
function SearchableList({ items }: { items: Product[] }) {
  const [search, setSearch] = useState('');
  
  const filtered = useMemo(
    () => items.filter(item => 
      item.name.toLowerCase().includes(search.toLowerCase())
    ),
    [items, search]
  );
  
  return (
    <>
      <input 
        value={search} 
        onChange={(e) => setSearch(e.target.value)} 
      />
      <MemoizedList items={filtered} />
    </>
  );
}

The Performance profiler will show you the difference clearly. Before optimization, you'll see long frames during typing. After, the frames drop significantly because only the filtered list reference changes, not the entire component tree.

Putting It All Together: A Real Debugging Workflow

Let me walk you through how I used these features together last week. A user reported that our dashboard was "feeling slow" and occasionally freezing.

First, I opened the Performance profiler and recorded a session while navigating the dashboard. I immediately saw several long tasks exceeding 200ms. Clicking into one revealed it was a sorting function running on every render.

Next, I used logpoints to verify how often the sorting was happening. I added a logpoint that logged 'Sort called with', items.length, 'items' and watched it fire on every keystroke in an unrelated search input. Fascinating! The component wasn't memoized properly.

To verify the fix would work, I used the Command Menu to disable JavaScript entirely, which showed me the initial HTML render was fine. The performance issue was purely in the JavaScript execution.

After implementing memoization, I took memory snapshots before and after multiple dashboard navigations. The snapshots confirmed we weren't leaking memory—just doing too much work.

Finally, I used network request blocking to simulate slow API responses and verify our loading states weren't causing layout shifts while the sorting logic ran.

Total debugging time: 40 minutes. Previous me would have spent half a day adding console.logs, making changes, and testing different theories.

Make These Features Part of Your Daily Workflow

You don't need to master all of DevTools overnight. In other words, start with one feature this week. Try logpoints tomorrow. Use the Command Menu every time you reach for your mouse. Take a memory snapshot the next time something feels leaky.

The wonderful thing about these tools is that they compound. Each feature you learn makes the next one easier to understand. Your debugging speed increases exponentially, not linearly.

I cannot stress this enough! The time you invest learning DevTools properly will pay dividends every single day of your development career. While your colleagues are still adding console.logs, you'll be identifying issues in minutes.

And that concludes the end of this post! I hope you found this valuable and look out for more in the future!