Why Your React Website Is Slow (And How to Fix It in 2025)
React site feeling sluggish? Here are the real reasons and proven fixes — including code splitting, lazy loading, and Core Web Vitals tips.
On this page
Article
Clean hierarchy, tighter spacing, and readable markdown blocks across desktop and mobile.
TL;DR: Most React websites are slow because of bloated bundles, unoptimised images, and too many re-renders. The fixes — code splitting, lazy loading, memoisation, and a proper hosting setup — can cut load times by 50–80%. This guide walks through each fix step by step.
You built your React app, deployed it, and now users are complaining it feels sluggish. Google Search Console is flagging poor Core Web Vitals. Your Lighthouse score is sitting at 42.
Sound familiar? You're not alone.
React is powerful, but its default setup does almost nothing to protect you from performance pitfalls. Here's what's really going on — and how to fix it.
The Real Cost of a Slow Website
Before we get into fixes, let's talk about why this matters beyond just "feeling fast."
Google uses Core Web Vitals as a ranking signal. A slow site directly hurts your SEO. A one-second delay in page load time can reduce conversions by 7% (source: Akamai). For a SaaS or e-commerce site, that number adds up fast.
Speed is not a nice-to-have. It's a business metric.
Reason 1: Your JavaScript Bundle Is Too Large
This is the most common culprit. When React builds your app for production, it bundles everything — all your components, libraries, utilities — into one or a few large JS files.
A bundle over 200KB (gzipped) starts to hurt. Many React apps ship 500KB–1MB+ without realising it.
How to diagnose it
Run this command in your project:
npx source-map-explorer build/static/js/*.js
Or use the webpack-bundle-analyzer plugin to see exactly what's inside your bundle. You'll often find that a single library like moment.js (66KB gzipped) or a rich-text editor accounts for 40% of your bundle.
How to fix it
Code splitting is the solution. Instead of loading everything at once, load only what the current page needs.
With React's built-in lazy and Suspense:
import { lazy, Suspense } from 'react';
const Dashboard = lazy(() => import('./Dashboard'));
function App() {
return (
<Suspense fallback={<div>Loading...</div>}>
<Dashboard />
</Suspense>
);
}
This defers loading the Dashboard component until it's actually needed. Apply this to every route in your app using React Router's route-based code splitting.
Also consider:
- Replacing
moment.jswithdate-fns(much smaller) - Using
lodash-esinstead of fulllodashfor tree-shaking - Auditing every
npm install— each package adds weight
Reason 2: Images Are Not Optimised
Images are often the single largest payload on a page. A hero image that's 3MB on a mobile screen is inexcusable in 2025.
The problems
- Serving PNG/JPG when WebP or AVIF would be 30–50% smaller
- No lazy loading — all images download immediately even if they're below the fold
- No responsive sizing — a 2400px image delivered to a 375px phone screen
How to fix it
If you're using Next.js, this is almost solved for you. The <Image> component handles format conversion, lazy loading, and responsive sizing automatically.
If you're on plain React:
- Convert images to WebP using tools like Squoosh or Sharp (Node.js library)
- Add
loading="lazy"to all<img>tags below the fold - Use
srcSetfor responsive images
<img
src="hero.webp"
srcSet="hero-400.webp 400w, hero-800.webp 800w, hero-1200.webp 1200w"
sizes="(max-width: 768px) 100vw, 50vw"
loading="lazy"
alt="Hero section"
/>
- Serve images from a CDN — Cloudflare, Cloudinary, or AWS CloudFront
Reason 3: Too Many Re-Renders
React re-renders a component every time its state or props change. When this gets out of control — especially in large component trees — it tanks performance.
Common causes
- Passing new object/array literals as props on every render
- Not memoising expensive computations
- Fetching data inside components without caching
How to fix it
Use React DevTools Profiler to find which components are re-rendering most. Then apply these fixes:
React.memo — prevents a component from re-rendering if its props haven't changed:
const UserCard = React.memo(({ name, avatar }) => {
return <div>{name}</div>;
});
useMemo — memoise expensive calculations:
const sortedList = useMemo(() => {
return items.sort((a, b) => a.price - b.price);
}, [items]);
useCallback — stabilise function references passed as props:
const handleClick = useCallback(() => {
doSomething(id);
}, [id]);
Don't over-apply these — use them only where the Profiler shows actual problems. Premature memoisation adds complexity without benefit.
Reason 4: No Server-Side Rendering or Static Generation
Plain React apps are client-side rendered (CSR) by default. The browser downloads a near-empty HTML file, then runs JavaScript to build the page. This means:
- The page is blank until JS loads and executes
- Search engines see empty HTML (bad for SEO)
- First Contentful Paint (FCP) is delayed
The fix: move to Next.js
Next.js gives you Static Site Generation (SSG) and Server-Side Rendering (SSR) out of the box.
- SSG pre-builds pages at deploy time — users get fully rendered HTML instantly
- SSR renders pages on the server per request — better for dynamic data
- Both dramatically improve FCP and SEO
This is one of the most impactful changes you can make. It's also one of the first things I recommend when auditing a client's React project at dipanshudev.com.
Reason 5: Poor Hosting and No CDN
Hosting on a shared server in one region means users in the US, UK, or Australia wait longer for a server response from your Mumbai or US-East data centre.
The fix
Use a platform built for React/Next.js:
| Platform | Best For | Free Tier |
|---|---|---|
| Vercel | Next.js, SSR/SSG | Yes |
| Netlify | Static React sites | Yes |
| Cloudflare Pages | Global CDN, edge | Yes |
| AWS Amplify | Enterprise, custom infra | Limited |
All of these come with global CDN distribution built in. Your static assets are served from the edge closest to each user.
Also set proper cache headers for static assets. CSS, JS, and images should be cached for at least 1 year with content-hashed filenames (Create React App and Next.js do this by default).
Reason 6: Blocking Third-Party Scripts
Google Analytics, Intercom, HubSpot, Facebook Pixel — these are loaded on almost every marketing site. Each one can add 100–500ms to your page load.
How to fix it
- Load all third-party scripts with
asyncordeferattributes - Use Partytown (by Builder.io) to run third-party scripts in a Web Worker, off the main thread
- Audit which scripts you actually need — remove unused ones
- For Next.js, use the
<Script>component withstrategy="lazyOnload"orstrategy="afterInteractive"
Quick Wins Checklist
Here's a summary of everything you can do right now:
- Run Lighthouse in Chrome DevTools and note your scores for Performance, LCP, CLS, and FID
- Analyse your bundle with
webpack-bundle-analyzer— remove or replace heavy libraries - Enable code splitting on all routes using React
lazy - Convert images to WebP and add lazy loading
- Add
React.memoto heavy components that receive stable props - Move to Next.js if you need SSR/SSG (most production apps do)
- Deploy to Vercel or Netlify with a global CDN
- Defer third-party scripts using
async/deferor Partytown
Real-World Example
A client came to me with a React landing page scoring 38 on Lighthouse mobile. The bundle was 1.1MB, images were uncompressed PNGs, and everything was loaded synchronously.
After code splitting, WebP image conversion, lazy loading, and moving to Vercel, the score went to 87. Time to Interactive dropped from 8.4 seconds to 2.1 seconds. This is exactly the kind of work showcased at dipanshudev.com/projects.
FAQ
Q: How do I check my React website's performance for free? A: Open Chrome DevTools, go to the Lighthouse tab, and run an audit. It gives you scores for Performance, Accessibility, SEO, and Best Practices. Also try PageSpeed Insights (pagespeed.web.dev) for real-world data from the Chrome User Experience Report.
Q: Does React affect SEO negatively? A: Client-side React can hurt SEO because search engines receive near-empty HTML. The fix is using Next.js with Static Site Generation (SSG) or Server-Side Rendering (SSR), which pre-renders HTML before it reaches the browser or search bot.
Q: What is a good Lighthouse performance score? A: 90+ is excellent, 50–89 is needs improvement, and below 50 is poor. For business websites competing in search, aim for at least 80+ on both desktop and mobile.
Q: What is code splitting in React?
A: Code splitting breaks your JavaScript bundle into smaller chunks that load on demand. Instead of loading all 1MB of JS upfront, the browser only loads what's needed for the current page. React's lazy() function and dynamic import() make this straightforward to implement.
Q: How much does React performance optimization cost? A: For a typical React site, a thorough performance audit and implementation takes 10–20 hours of developer time. The ROI — better SEO rankings, lower bounce rates, and higher conversions — typically pays back within weeks.
Article snapshot
Published
01 Mar 2026
Read time
7 min
Category
engineering
Media
0 visuals
Internal links
Need this done properly
Build, performance, SEO, and content can be handled in one delivery flow.
If you are planning a business site, technical blog, or product build that needs to look sharp and rank cleanly, the same approach can be applied to your stack.
Keep reading
Related articles
More posts connected to the same delivery, SEO, or product engineering themes.
web development
Why Your React Website Is Slow (And How to Fix It)
Is your React site failing Core Web Vitals? Here are the real reasons it is slow and exactly how to fix each one in 2025.
seo
Core Web Vitals 2025 Checklist for Founders
Core Web Vitals explained for non-technical founders. 2025 checklist, what each metric means, how to test, and exactly what to ask your developer to fix.
engineering
Next.js vs React: Which Should You Build On?
Next.js vs React for your startup — a clear, honest comparison covering SEO, performance, deployment, and when each is the right choice in 2025.
