Engineering

Debugging React performance with React 16 and Chrome Devtools.

Published on

React was one of the first major front-end frameworks to not only name, but tout its rendering performance. React’s virtual dom is famous for efficiently rendering components—but what happens when those components suddenly don’t feel fast anymore? Where do you look? How do you fix it?

Today I’m going to use real React code and Chrome DevTools to demonstrate powerful new performance tracking features and how you can use them to diagnose slow rendering components.

This new performance tooling has three requirements:

  • Use React 16 in development mode
  • Export your JS with source-maps (This is optional, but highly recommended)
  • Use Google Chrome or Chromium’s Dev Tools (available in all current releases)

👷‍ Setting up your audit

Firstly, you’re going to need some room to breathe, so go and pop Dev Tools out. Make it as large as your screen allows. “Ahh. That’s better.”

When we’re doing performance audits it’s essential that we’re working towards realistic (real world) targets. Not everyone has a $3000 computer or current model phone.

Luckily Chrome has got that covered too—we’re going to slow down JavaScript execution. Doing this will make performance issues more apparent, with that added bonus that if you can make it fast on a slow device, it’ll fly on a desktop.

Slowing your current model Macbook by at least 4x will have it perform similarly to a Motorola Moto G4.
Slowing your current model Macbook by at least 4x will have it perform similarly to a Motorola Moto G4.

🔬 Viewing a performance trace

In development mode, as React 16 renders, it creates ‘mark and measure’ events for each component.

To create a performance profiler audit, navigate to the page that you’d like to test (on localhost) and press the ‘Start profiling and reload page’ button.

This will record a performance trace for the current page. Chrome will automatically stop recording the trace after the page has settled.

Or, use the keyboard shortcut:⌘+⇧E
Or, use the keyboard shortcut:⌘+⇧E

Once you’ve got a trace, your window will look something like this:

What we can see above from left to right is a timeline of our page’s load and initialisation.
What we can see above from left to right is a timeline of our page’s load and initialisation.

I’d like to take a second or two to point out a few things that may not be immediately obvious to someone who is new to the Performance tab.

This red bar indicator shows that there was some significant ‘CPU burn’ (long tasks) around this part of the trace timeline. We probably want to investigate there.

The colours used in the graph at the top of the performance window correspond to different types of activity. Each category has various causes, fixes, and analysis required.

Today we’re focusing on “Scripting” (JavaScript runtime performance).

Expand the window, click open user timing, and use the screenshot timeline to investigate how your page painted 👀
Expand the window, click open user timing, and use the screenshot timeline to investigate how your page painted 👀

Now we’re going to want to investigate that red CPU-burn area. We can see that the page rendered elements on the page during that period of the trace.

Zoom the timeline by dragging on the chart area. Did you spot the emoji ⚛️?
Zoom the timeline by dragging on the chart area. Did you spot the emoji ⚛️?

Zooming immediately displays user-timing information and a component labelled ‘Pulse’ (that takes 500ms to render).

Beneath the Pulse component, there appears to be child components rendering, although the size of those items indicates that they aren’t costing a lot of execution time.


⏳ Discovering slow functions

  1. Click the component you’d like to investigate, in this case, Pulse. This scopes the lower portion of the window to focus on only activity from the Pulse component.
  2. Choose “Bottom-Up”.
  3. Sort by total time descending. In some cases, you may want to sort by Self time, or group by something other than the URL. See what works best for what you’re investigating.
  4. Click open the arrows until you’ve found a point in the code you’d like to investigate. In this case the map call looks suspect. It’s called a number of times and amounts to 90ms of execution time.
  5. This is why you need sourcemaps: Clicking MetricStore.js:59 will take you to that spot in the code. Let’s go!
Code that took longer to execute has a time indicator down the left hand side. (Perhaps not my finest hour of code on display to the world.)

🤝 Improvement is easy when you know how

Using this approach over the last couple of weeks I’ve managed to shave seconds from areas of code that I thought “well, it’s complicated, so I guess it takes a while for it”. Now I know exactly how and where to look for JavaScript performance. I’m certain I’ll write better UI code in the future. 🙈


🛣 Sidenote: Calibre monitors JavaScript parse, compile and runtime metrics

If you’re a little curious about what’s happening to your sites in production when they’re loaded with ads and tracking pixels and in-app chat, you can use Calibre to get a clear picture of which scripts (or services) are costing your customers time.

🏊 Calibre has a free 14-day trial, dive in while it’s fresh.

Yeowch. Almost a whole second for Intercom’s frame.js.
Yeowch. Almost a whole second for Intercom’s frame.js.

🤔 Why is there React specific tooling built into Chrome?

Internally, React is publishing these metrics via the User Timing API, which can also be used to place timing markers around your code.

Think “Component initialised in 0.4 seconds” or “The user took 15 seconds to press the buy button.”

For a good introduction to the User Timing API, see Alex Danilo’s aptly named HTML5 Rocks article “User Timing API” from 2014.


All major browsers support the User Timing API, but Chrome’s performance tab goes a long way further to make debugging a React application a whole lot easier.


Optimise your JavaScript

I sincerely hope this article has helped you level up your performance auditing skills. Please leave comments to explain what you learned or of improvements you’ve been able to make on your apps. Enjoy 🙋

Subscribe to the Blog
Subscribe to the Blog
Join thousands user-experience obsessed readers on our mailing list.
Subscribe