< Back to blog
Blog/engineering

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.

01 Mar 2026/7 min read
why React website is slowReact performance optimization 2025fix slow React app

Article

Clean hierarchy, tighter spacing, and readable markdown blocks across desktop and mobile.

7 minute read

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.js with date-fns (much smaller)
  • Using lodash-es instead of full lodash for 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:

  1. Convert images to WebP using tools like Squoosh or Sharp (Node.js library)
  2. Add loading="lazy" to all <img> tags below the fold
  3. Use srcSet for 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"
/>
  1. 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:

PlatformBest ForFree Tier
VercelNext.js, SSR/SSGYes
NetlifyStatic React sitesYes
Cloudflare PagesGlobal CDN, edgeYes
AWS AmplifyEnterprise, custom infraLimited

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

  1. Load all third-party scripts with async or defer attributes
  2. Use Partytown (by Builder.io) to run third-party scripts in a Web Worker, off the main thread
  3. Audit which scripts you actually need — remove unused ones
  4. For Next.js, use the <Script> component with strategy="lazyOnload" or strategy="afterInteractive"

Quick Wins Checklist

Here's a summary of everything you can do right now:

  1. Run Lighthouse in Chrome DevTools and note your scores for Performance, LCP, CLS, and FID
  2. Analyse your bundle with webpack-bundle-analyzer — remove or replace heavy libraries
  3. Enable code splitting on all routes using React lazy
  4. Convert images to WebP and add lazy loading
  5. Add React.memo to heavy components that receive stable props
  6. Move to Next.js if you need SSR/SSG (most production apps do)
  7. Deploy to Vercel or Netlify with a global CDN
  8. Defer third-party scripts using async/defer or 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.


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.

View all articles