7 practical tips on performance optimizations in React applications
Optimizing React apps is about smart choices, not exhaustive tweaks. (4 min)
Is optimizing every line of code worth your time?
Over the years, I’ve worked on several React projects.
Along the way, I’ve learned some valuable lessons about performance optimization.
Not all performance issues are equal.
It’s important to focus on the ones that make the biggest difference.
1. Avoid premature optimization
Chasing after every minor optimization is a trap.
It’s tempting to try to optimize every part of your application from the start. However, this might waste your time on issues that don’t matter so much.
Instead, measure which performance problems have the biggest impact. Focus on fixing those first.
This way, you spend your time where it makes a difference.
⛔ Avoid spending time optimizing parts of your app without evidence they’re slow.
✅ Prefer to measure your app’s performance to find the bottlenecks before optimizing.
Keep your codebase clean from unnecessary optimizations.
2. Focus on critical tasks
What if doing less could actually achieve more? Remember the 80-20 rule?
If something isn’t critical, don’t spend time improving it right now.
Do the least amount of work necessary to get the job done.
If a task or issue can wait, defer it for later.
This way, you avoid adding stuff to your codebase that you don’t need.
You deliver features and fixes that matter the most to your users.
⛔ Avoid working on non-essential improvements.
✅ Prefer focusing on tasks with immediate impact on functionality and performance.
Focus on what truly matters. Make better use of your time.
3. Defer non-essential work
Initial load times can make or break user engagement.
Loading all assets at once can slow down your app’s initial load time.
Instead, split your app into bundles. Load assets only when they’re needed.
Reduce the amount of code the browser has to download and process upfront.
This is known as Code-Splitting (see the next section).
⛔ Avoid including all your code in a single, large bundle that loads on startup.
✅ Prefer splitting your code and loading multiple bundles only when they’re needed.
Take care of your User Experience.
4. Use Code Splitting
Sending less code can make your app more robust and responsive.
JavaScript size affects performance in two main ways:
Sending files to the browser - large files take longer to download.
Parsing and executing files - more code means more work for the browser.
By implementing code-splitting into your project, you send only what’s necessary right away. This reduces download and execution times, which speeds up the loading time of your app.
Using HTTP/2 helps handle multiple small files efficiently. It supports request and response multiplexing.
✅ Prefer implementing Code-Splitting into your application.
5. Manage Rerenders
Unnecessary rerenders are silent performance killers.
Unnecessary rerenders can slow down your application.
They often happen when components receive props that are compared by reference, like arrays, objects, and functions.
Passing a new function or object each time causes React to think something has changed.
You can use the built-in hooks to manage that - useMemo and useCallback.
⛔ Avoid passing new object or function references as props unless necessary.
✅ Prefer memoizing expensive calculations, objects or functions to prevent unnecessary rerenders.
Reduce the workload on React’s rendering process.
6. Monitor the bundle size
Keep an eye on how much JavaScript you’re sending to the browser.
Large bundles can slow down your app.
Regularly check your bundle size and look for ways to reduce it.
7. Optimize business logic
The real performance gains often lie in our own code, not the framework.
React is fast at updating the DOM.
Sometimes, the slowdown comes from our own code.
By understanding the business domain well, we can make certain trade-offs and choices and improve the overall performance.
For example, you can:
cache frequently used data in memory
memoize expensive calculations
avoid repetitive data fetching
implement pagination or infinite scrolling
use throttling and debouncing
use web workers for heavy computations
and etc.
⛔ Avoid writing inefficient business logic that slows down your application.
✅ Prefer optimizing your business logic first.
Be careful with your business logic. Usually, that’s the bottleneck, not the framework.
📋 Recap
Avoid premature optimizations. Keep your codebase clean from unnecessary optimizations.
Focus on Critical tasks and issues. Focus on what truly matters. Make better use of your time.
Defer non-essential. Take care of your User Experience.
Use Code-Splitting. Sending less code can make your app more robust and responsive.
Manage Rerenders. Reduce the workload on React’s rendering process.
Monitor the bundle size.
Optimize business logic. Usually, that’s the bottleneck, not the framework.
👋 Let’s connect
You can find me on LinkedIn or Twitter.
I share daily practical tips to level up your skills and become a better engineer.
Thank you for being a great supporter, reader, and for your help in growing to 13.7K+ subscribers this week 🙏
This newsletter is funded by paid subscriptions from readers like yourself.
If you aren’t already, consider becoming a paid subscriber to receive the full experience!
Think of it as buying me a coffee twice a month, with the bonus that you also get all my templates and products for FREE.
You can also hit the like ❤️ button at the bottom to help support me or share this with a friend to get referral rewards. It helps me a lot! 🙏
The problem with "premature optimization" is that, more often than not, you end up with "premature complexity."
Optimization must be justified.
Thanks for the shoutout, Petar!
These could apply for any frontend codebase