Target KPIs (75th percentile, mobile):
LCP: ≤ 2.5s
CLS: ≤ 0.10
INP: ≤ 200ms
Who this is for: CTOs, product leads, and ReactJS development company teams shipping React web app development, Next.js development, SPAs/SSRs, and anyone running React code audit & optimization sprints in 2025.
TL;DR: the 7 fixes
- Ship less JavaScript with route-level and component-level code splitting.
- Make the LCP element stupid fast (image, HTML, CSS critical path).
- Kill CLS by reserving space and taming fonts.
- Lower INP by breaking long tasks and deferring non-urgent work.
- Pick the right rendering strategy (RSC, SSG/ISR, streaming) and cache smart.
- Treat images & fonts as first-class citizens (built-in Next.js optimizations).
- De-fang third-party scripts with strict loading strategies.
Fix 1 — Ship less JavaScript (this is where most teams win)
Every extra KB blocks interactivity and tanks INP. Do both route-level and component-level splitting:
Route/feature splitting (Next.js):
// app/dashboard/page.tsx – load heavy charts only when needed
import dynamic from 'next/dynamic'
const Chart = dynamic(() => import('@/components/Chart'), { ssr: false })
export default function Dashboard() {
return
}
Component-level splitting (React):
import { lazy, Suspense } from 'react'
const SettingsPanel = lazy(() => import('./SettingsPanel'))
export default function Account() {
return (
Loading settings…}>
)
}
Use React.lazy with Suspense to split component code; pair with a real loading UI.
Brutal but necessary:
- Kill dead code with a bundle analyzer.
- Prefer server-only utilities in RSC so they never hit the client.
- Avoid shipping admin-only modules to public routes.
Fix 2 — Make the LCP element fast
Your LCP is typically the hero image, headline, or above-the-fold card. Get it painted quickly:
For images (Next.js):
import Image from 'next/image'
export default function Hero() {
return (
src="/hero.avif"
alt="SaaS dashboard"
width={1280}
height={720}
priority // preloads and marks as highest priority
sizes="100vw"
/>
)
}
- Serve AVIF/WebP, exact width/height, and priority for the one LCP image.
- Inline critical CSS for above-the-fold.
- Preconnect to your CDN.
- Keep the HTML for the LCP element close to the top of the document (avoid deep component trees before it).
Targets: LCP ≤ 2.5s at p75.
**Fix 3 — Kill CLS (layout shifts)
**
CLS is death by a thousand cuts: images without dimensions, dynamic ads, late fonts.
- Always set width/height or aspect-ratio on images and embeds.
- Use CSS aspect-ratio for responsive shells, skeletons for lazy content.
- Load web fonts with fallbacks that have similar metrics; use font-display: swap or next/font to keep layout stable.
- Avoid inserting DOM elements above existing content until after first paint.
Target: CLS ≤ 0.10.
Fix 4 — Lower INP (the FID replacement)
Since March 12, 2024, INP replaced FID. INP measures worst end-to-end interaction latency across the visit. You fix it by not doing heavy work in input handlers and by breaking long tasks.
Patterns that help:
// Avoid blocking the main thread on click
import { useTransition } from 'react'
function SaveButton({ onSave }) {
const [pending, startTransition] = useTransition()
return (
disabled={pending}
onClick={() => startTransition(() => onSave())}
>
{pending ? 'Saving…' : 'Save'}
)
}
- Move heavy work to web workers or the server.
- Break long tasks (>50ms) with setTimeout(0), requestIdleCallback, or scheduler utilities.
- Keep event handlers tiny; precompute or cache expensive selectors.
- Limit synchronous layout thrash (measuring and writing styles back-to-back).
Target: INP ≤ 200ms.
Fix 5 — Choose the right rendering & caching strategy
The fastest byte is the one you never ship.
- React Server Components (RSC) to keep logic on the server.
- SSG/ISR for stable marketing/product pages; SSR streaming for dynamic templates.
- Edge caching for HTML and stale-while-revalidate for data.
- Use and partial rendering to speed route changes.
Next.js provides built-in optimizations for Core Web Vitals and a production checklist; use them.
Fix 6 — Treat images & fonts as first-class citizens
- Use next/image for responsive, optimized images, not
.
- Use next/font with local hosting to avoid layout shifts and reduce TTFB for fonts.
- Icon strategy: sprite or SVG components; avoid font icons.
- Responsive sizes and proper sizes attributes to stop over-downloading.
Next.js includes automatic image, font, and script optimizations aimed at better Core Web Vitals.
Fix 7 — De-fang third-party scripts
Analytics, chat, A/B testing, tag managers… all of them compete for your JS budget.
- Audit quarterly; delete or defer anything not tied to revenue or DX data.
- Load with Next.js .</li> <li>Self-host assets where possible; cap total third-party script weight.</li> <li>If you must, load heavy widgets on user intent (click to expand), not on page load.</li> </ul> <p>For most apps, script governance alone makes a visible dent in LCP and INP. </p> <h2> <a name="measurement-how-we-prove-the-wins" href="#measurement-how-we-prove-the-wins" class="anchor"> </a> <strong>Measurement: how we prove the wins</strong> </h2> <ul> <li>Lab: Lighthouse CI for PRs; bundle analyzer; React Profiler; WebPageTest for filmstrips.</li> <li>Field: Web Vitals JS to GA4; Search Console’s <a href="https://budventure.technology/hire-react-js-developers">Core Web Vitals</a> report to confirm p75 over time. </li> <li>Track a dashboard per template: route, LCP element selector, CLS offenders, INP slow interactions.</li> </ul> <p><strong>Shipping rule:</strong> no merge if budgets fail.</p> <h2> <a name="implementation-checklist-copy-into-your-issue-tracker" href="#implementation-checklist-copy-into-your-issue-tracker" class="anchor"> </a> <strong>Implementation checklist (copy into your issue tracker)</strong> </h2> <ul> <li>Analyze bundle; split at route and component boundaries.</li> <li> Promote hero image to priority; AVIF/WebP; explicit dimensions.</li> <li> Inline critical CSS; preconnect CDN; trim render-blockers.</li> <li> Reserve space for images/ads/iframes; stabilize fonts via next/font.</li> <li> Replace long synchronous handlers; introduce useTransition; offload heavy work.</li> <li> Pick SSG/ISR/Streaming + RSC where applicable; cache HTML and data.</li> <li> Audit and defer third-party scripts; remove dead tags.</li> <li> Add Lighthouse CI + Web Vitals to GA4; set budgets and alerts.</li> </ul> <p>**</p> <h2> <a name="faqs" href="#faqs" class="anchor"> </a> FAQs </h2> <p>**</p> <p><strong>Q1. What are “good” Core Web Vitals in 2025?</strong><br> LCP ≤ 2.5s, CLS ≤ 0.10, INP ≤ 200ms at the 75th percentile (mobile/desktop tracked separately). INP replaced FID in 2024. </p> <p><strong>Q2. Is Next.js required to pass Core Web Vitals?</strong><br> No, but Next.js gives built-in image, font, script optimizations and production guidance that make it easier. </p> <p><strong>Q3. Where do I confirm field results?</strong><br> Use Search Console’s Core Web Vitals report and Web Vitals in GA4 to validate p75 over time.</p>
Top comments (0)