Why performance matters
If users have a slow, laggy experience with your product, they won't want to use it. And if you rely heavily on SEO value, Web Vitals are a ranking factor in Google’s search algorithm.
You've probably seen this quote on the lighthouse loading screen:
"Walmart noticed a 1% increase in revenue for every 100 milliseconds of improvement in page load time."
Common performance optimizations
Memoization
Memoization is the process of caching a function's output for a given set of parameters.
React hooks that implement this technique can dramatically reduce unnecessary re-renders.
Check out useMemo
, useCallback
, and React.memo
.
The experimental React Compiler tool already implements many of these optimizations by default, so in the future we may not need to write them manually as often.
Check your dependency arrays
Try to include as few items as possible in your dependency arrays. For example, avoid putting an entire object in there if you only want to re-render when one of its keys changes.
Virtualization (windowing large lists)
Packages like react-window can help you implement virtualization.
If you render a ton of DOM elements (e.g., a very long list), performance will suffer. Virtualization removes elements that are outside the viewport, replacing them with placeholders. As the user scrolls, the relevant elements are re-inserted into the DOM.
Instagram is a classic example of this technique.
Lazy loading
You can use Suspense
or next/dynamic
to split JavaScript into its own chunk or load it on demand based on a user action (like a click).
React Profiler
The React Profiler is a great tool for finding the biggest performance offenders in your app. With a flamegraph, you can see which components take the longest time to render and optimize accordingly.
@next/bundle-analyzer
This tool gives you a visual breakdown of the largest items in your bundles.
- You might be importing a third-party package that's much larger than expected.
- Or maybe you imported all of lodash instead of a single utility.
Complex SVGs can also inflate bundle size. If you have a lot of nested shapes, consider referencing the SVG in an <img>
tag instead of embedding it inline.
Web Workers
If you have intensive data computations to run, Web Workers are very useful. For example, if you have a dataset with thousands of items and need to transform it client-side, a Web Worker can complete the computation without blocking the main thread. This helps keep your UI responsive during CPU-intensive tasks.
Sampling
Analytics platforms often use sampling to avoid holding massive datasets in memory. Sampling involves taking a subset of a large dataset to create a smaller, representative set that’s faster to process.
Pagination
Pagination breaks large datasets into smaller pages or chunks. For example, request posts 1-5 first; when the user wants to see more, fetch 6-10 from your API.