Optimizing Performance for ++React Virtual DOM Elements

2/2023 Aman Azad

React Profiler Flamegraph React Profiler Flamegraph

Resolving large render times

Our artist feeds over at legaci.com were getting to be very React-component/Virtual DOM heavy. I'm sure rendering large, complicated feed pages is a Web 2.0 solved problem given the likes of Reddit/FB/Twitter/etc. However, given we're a pre-seed company with two technical cofounders, we're all we had to get this feature working well for our users.

Our feed pages are pretty typical from other social media platforms, users can upload native photo/video content, link out to Twitter/IG/TikTok posts, and drop text-only posts.

Untitled

The issue we were running into was certain pages with a lot of activity would be unusable as hundreds of asset heavy components were rendering in at the same time.

Below are some techniques I spent roughly a week or two on, diving in and making quick changes to improve performance significantly.

React Profiler

Use the buttons in the top right corner to record a page load or transition. What’s presented is a list of all the components rendered. The more orange a component, the more longer it took to load in this commit. The timing for a component such as BrandPosts (1.1ms of 633.7ms) means BrandPosts and its children collectively took 633.7ms to load, but BrandPosts itself only took 1.1ms. Dive into why BrandPosts is taking so long to render by repeating the process in child components, look for anomalies or refactors.

Full details here: https://reactjs.org/blog/2018/09/10/introducing-the-react-profiler.html.

Chrome Performance Tool

Similar to the React profiler, this tool also shows time for components to render, but gives a bit more insight.

Untitled

Dive into the function call stacks and see why certain files are taking time a long time to load:

Untitled

Unused Dependencies

npx depcheck

Finds unused dependencies.

https://stackoverflow.com/questions/22675725/find-unused-npm-packages-in-package-json

Related, to find the bundle size: https://bundlephobia.com/

General Solves

The above methods are what really chunked away slowness on our feed pages. Below are a few techniques I used that seemed correct in theory, but I wasn't able to determine a significant ROI:

  • useMemo - memoize large components.
  • React.memo(…) - another option for memoizing components.
  • Look for unnecessary component renders - leverage use effects and watch variables that may be volatile.
  • Reduce the overall number of components - paginate data sources
  • react-window - a good option, but trying to understand fixed heights and widths for our feed components was requiring far too many brain cycles.