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.
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
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
| Heavy | Light |
|---|---|
| moment (300KB) | date-fns / dayjs / Temporal |
| full lodash | per-import or just JS |
| draft-js | TipTap / Slate / Lexical |
| momentjs + timezones | Intl.DateTimeFormat |
| chart.js full | chart-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
deferorasyncon 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
<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%
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.