Back to React
React
medium
mid

How would you reduce the initial page load time of a React application by forty percent?

Audit: bundle analyzer (heavy deps), Lighthouse (render-blocking, LCP image), web-vitals RUM. Fixes: replace heavy deps (moment → date-fns), code split per route + lazy modals/charts, RSC for non-interactive parts, AVIF/WebP + responsive srcset for LCP image, preconnect to CDN, critical CSS inline, self-host fonts, eliminate render-blocking JS. Each lever measured for delta.

5 min read·~12 min to think through

A 40% LCP cut is achievable but needs a measured plan, not generic best-practices spam.

Step 1 — audit current state

  • Lighthouse on the slow route. Note LCP element, render-blocking resources, unused JS/CSS.
  • Bundle analyzer. Identify > 50KB deps that don't earn their weight.
  • web-vitals RUM for production p75 numbers. Lab tests lie.

Pick the worst contributor and measure.

Step 2 — high-impact levers (in order)

1. Code splitting per route

tsx
const Dashboard = React.lazy(() => import('./Dashboard'));

Or Next.js dynamic. Cuts initial bundle by N% where N is the proportion of code other routes own.

2. Replace heavy deps

HeavyLight
moment (300KB)date-fns / dayjs / Temporal
full lodashper-import or just JS
draft-jsTipTap / Slate / Lexical
momentjs + timezonesIntl.DateTimeFormat
chart.js fullchart-specific lib

Often a single swap cuts 100KB+.

3. RSC / SSG for static parts

In Next.js App Router, default Server Components ship zero client JS. Move presentational components to RSC; mark only interactive ones "use client".

4. LCP image optimization

If LCP is an image (often is for marketing):

  • AVIF or WebP with JPEG fallback (<picture>).
  • Responsive srcset so phones don't download 4K images.
  • fetchpriority="high" on the LCP image.
  • Eager load (don't lazy-load above-the-fold).
  • Image CDN with on-the-fly resize/format conversion.

40-70% byte reduction on hero images is common.

5. Eliminate render-blocking

  • defer or async on third-party scripts.
  • Inline critical CSS; defer the rest with preload + onload trick.
  • Self-host fonts; font-display: swap; preload above-the-fold fonts.
  • Reduce <head> size — analytics, polyfills, etc.

6. Preconnect to third-party origins

html
<link rel="preconnect" href="https://api.example.com">
<link rel="preconnect" href="https://cdn.example.com">

Saves 100–200ms on first request to that origin.

7. Streaming SSR + Suspense

Flush above-the-fold HTML first; let slow data stream below.

8. Edge SSR / CDN

Serve close to the user; cuts TTFB on cold connections.

9. Critical CSS extraction

Inline only the CSS for above-the-fold; load the rest async. Next.js does this; in Vite you can use critters.

Step 3 — measure delta per change

Lighthouse before/after for each change. RUM after the change ships. If a lever didn't move LCP, revert and try another.

Common over-claims

  • "We made it faster" with no number.
  • Lab metric improvements that don't translate to RUM (different conditions).
  • Optimizing CSR-only paint when the real LCP is server-side TTFB.

Example targeting 40%

ts
Before: LCP 4.0s
- Code split per route       → 3.4s   (-15%)
- AVIF + responsive image    → 2.8s   (-15%)
- Preconnect + edge SSR      → 2.4s   (-10%)
- Replace moment + critical CSS → 2.4s (small)
Total: 40% reduction.

Interview framing

"Audit with Lighthouse + bundle analyzer + web-vitals RUM. Identify the actual contributors — bundle size, LCP image, render-blocking, slow TTFB. High-impact fixes in order: per-route code splitting, swap heavy deps (moment → date-fns saves 300KB), RSC for non-interactive parts, optimize the LCP image with AVIF + responsive srcset + fetchpriority + eager-load, defer/async non-critical scripts, inline critical CSS, self-host fonts with font-display swap, preconnect to third-party origins, streaming SSR with Suspense, edge SSR. Measure delta per change in RUM, not just lab. 40% reduction is achievable in a single sprint on most apps that haven't been optimized."

Follow-up questions

  • What if LCP is dominated by TTFB?
  • How would you replace moment without breaking everything?
  • How do you avoid regression after the fix?

Common mistakes

  • Optimizing without measuring.
  • Lazy-loading the LCP image.
  • Trusting lab over RUM.

Performance considerations

  • Image pipeline + code split + RSC are the durable wins. Avoid micro-memo for initial load.

Edge cases

  • Auth-only pages with no SEO need (CSR can be fine).
  • Highly dynamic pages where caching is limited.
  • Cold serverless start variance.

Real-world examples

  • Web.dev LCP case studies, Vercel customer stories, Next.js App Router migrations.

Senior engineer discussion

Seniors plan in measured steps with budgets, gate regressions in CI, and articulate which lever moves which metric.

Related questions