Core Web Vitals in the Next.js App Router: what actually moves the needle
In an App Router codebase, four decisions dominate Core Web Vitals: where each route renders, where the server-client boundary sits, how the largest image is loaded, and whether space is reserved before content arrives. Almost everything else is noise by comparison.
Part ofWeb & Portal Development
Performance work attracts busywork. It is possible to spend a week shaving kilobytes off a bundle that was never on the critical path, while the hero image remains unoptimised and a client component at the root of the tree hydrates the entire page. The three Core Web Vitals metrics respond to a small number of structural decisions, and it is worth knowing which.
Measure the field, not the laboratory
A Lighthouse run on a development machine is a debugging tool, not an assessment. It uses one device profile, one network shape, a cold cache and no real user behaviour. Interaction to Next Paint in particular cannot be meaningfully measured without real interactions.
- Use the Chrome User Experience Report or your own field collection for the assessment of record
- Use Lighthouse and traces for diagnosis once the field data has told you which metric and which page to look at
- Segment by device class — a 75th-percentile mobile figure and a desktop figure often tell opposite stories
- Record the baseline before changing anything, or the improvement claim is unverifiable
Decision one: rendering strategy per route
This is the decision with the largest effect on Largest Contentful Paint, and in the App Router it is made per route rather than per application. A marketing page whose content changes weekly should be static; a dashboard cannot be. Getting it wrong on a high-traffic route costs more than every micro-optimisation combined.
Decision two: where the client boundary sits
Interaction to Next Paint degrades when the main thread is busy, and the main thread is busy in proportion to how much JavaScript hydrates. The App Router's default is server components, which ship no JavaScript; every 'use client' directive opts a subtree back in. The cost is therefore determined by how high in the tree those directives sit.
Two habits follow. Push client directives to the leaves, and pass server-rendered children through client wrappers rather than re-implementing them inside the client boundary. A provider that wraps the application is fine; a provider that forces every descendant to become a client component is not.
Decision three: how the largest element loads
On most content pages the LCP element is an image or a large text block in the hero. If it is an image, its loading behaviour is the single highest-leverage change available.
- Identify the actual LCP element from field data rather than by assumption — it is frequently not the element designers expect.
- If it is an image, mark it priority so it is preloaded and not lazily deferred.
- Give explicit width and height, or a defined aspect ratio, so no layout shift occurs when it arrives.
- Serve modern formats and correct responsive sizes — an image scaled down in CSS still downloads at full size.
- Never lazy-load anything above the fold; it is the most common self-inflicted LCP regression.
Fonts: subset, self-host, and reserve the space
Web fonts affect LCP when text is the largest element and CLS when fallback metrics differ from the loaded face. Loading fonts through next/font self-hosts them, removes the third-party connection, and generates a size-adjusted fallback so the swap does not reflow the page. Limit weights to those actually used; each additional weight is a separate download on the critical path.
Decision four: reserve space before content arrives
Cumulative Layout Shift is almost entirely preventable, and almost every instance traces to the same short list.
- Images and embeds without dimensions or an aspect ratio
- Banners, consent notices and promotional bars injected above existing content
- Web font swaps without a size-adjusted fallback
- Content that expands after a client-side fetch resolves, with no skeleton holding the space
- Animations that transition layout properties instead of transform and opacity
Third-party scripts are usually the largest remaining cost
After the structural decisions are right, the biggest remaining main-thread consumer is typically code you did not write. Audit what each tag actually delivers, load what survives the audit with a deferred strategy after the page is interactive, and self-host what can be self-hosted. A tag manager containing seven years of accumulated tags is worth a morning of archaeology.
Hold the gains with a budget in CI
Performance work decays. Without a gate, a future pull request will add an unoptimised image or hoist a client directive and nobody will notice for a quarter. Set explicit budgets — bundle size per route, LCP and CLS thresholds on key pages — and fail the build when they are exceeded. A budget that only warns is a budget that will be ignored.
The honest summary: rendering strategy, the client boundary, the largest image, and reserved space. Get those four right and the metrics generally follow. Reach for the exotic optimisations only after field data says the ordinary ones are already correct.
Questions
Why does our Lighthouse score look good while field data does not?
Lighthouse runs one simulated profile with a cold cache and no real interaction; field data aggregates real devices, networks and behaviour. Interaction to Next Paint especially requires genuine interactions to measure. Use field data for assessment and Lighthouse for diagnosis.
Does server rendering always improve Core Web Vitals?
No. Server rendering improves how quickly content appears, but if the resulting page then hydrates a large client tree, Interaction to Next Paint can still be poor. Rendering strategy and the client boundary are separate decisions, and both have to be right.
Are Core Web Vitals a ranking factor?
They are part of Google's page experience signals, and their effect is real but modest compared with relevance and content quality. The stronger argument for fixing them is not ranking: slow, shifting pages lose users regardless of where they rank.