Back to blog
Performance Apr 28, 2026 10 min read

Optimising Core Web Vitals in React: a deep dive

The specific patterns and anti-patterns that make or break Core Web Vitals in React applications.

article.body

Why React apps struggle with CWV

React's defaults — client rendering, hydration, virtual DOM diffing — are at odds with the metrics Google measures. LCP suffers because the browser can't paint until the React bundle parses and runs. INP suffers because hydration and re-renders block the main thread. CLS suffers because hydration replaces server-rendered content with client-rendered content of a different size. Every CWV optimisation in React is fighting the framework's defaults.

LCP: server-render the hero

The single biggest LCP win for React apps is server-rendering the above-the-fold content. With Next.js App Router, RSC handles this by default. With TanStack Start, use SSR for the hero. With Remix, the framework's default is already SSR. Whatever you do, do not client-render the hero — it's a guaranteed LCP failure.

LCP: preload the hero image

Even with SSR, the browser doesn't know about your hero image until it parses the HTML and discovers the img tag. Add a link rel=preload as=image fetchpriority=high to the document head. The browser starts the download immediately and the hero paints 200-400ms earlier.

INP: break up long tasks

Hydration in React is a long task that blocks the main thread for hundreds of milliseconds on slow devices. The fix in 2026 is scheduler.yield() — break hydration into chunks and yield to the browser between them. React 19's concurrent rendering does this automatically for new code; legacy class-component code needs manual scheduling.

INP: virtualise long lists

A list of 1,000 items in React renders 1,000 components, even if only 20 are visible. Use react-virtual or react-window to render only the visible items. INP improves by an order of magnitude on scroll-heavy pages.

INP: memoise expensive components

useMemo and useCallback are not free, but they're cheaper than the re-renders they prevent for expensive components. Profile with React DevTools to find the components that re-render frequently with the same props. Memo them. INP improves measurably.

CLS: aspect-ratio for media

Every image and video must have width and height attributes (or aspect-ratio CSS). This reserves the layout space before the asset loads. Without it, every image load triggers a layout shift. With it, CLS stays at 0.

CLS: avoid layout-shifting hydration

If your client-rendered content has different dimensions than your server-rendered content, hydration causes a shift. The fix: render the same content on the server as the client. If you must show different content (e.g. personalised data), reserve space with a skeleton of identical dimensions.

The continuous loop

Measure with field data (Search Console, Cloudflare Web Analytics, SpeedCurve). Fix the worst metric first. Re-measure. Move on. CWV optimisation is a continuous process, not a project — every new feature has the potential to regress your metrics.

Want this for your site?
Get in touch with our SEO experts.
Contact us