Core Web Vitals and performance SEO rules for Next.js. Use when optimizing page load, working with third-party scripts, fonts, bundle size, or addressing LCP/CLS/INP issues.
Core Web Vitals are a Google ranking factor. Follow these rules for optimal performance.
| Metric | Target | Measures |
|---|---|---|
| LCP | < 2.5s | Main content load speed |
| CLS | < 0.1 | Visual stability during load |
| INP | < 200ms | Interaction responsiveness |
getServerSideProps/getStaticProps"use client" / useEffect) when truly needed for interactivity// GOOD — Server Component (default)
export default async function Page({ params }: Props) {
const data = await getData(params.id);
return <h1>{data.title}</h1>;
}
// Client component ONLY for interactive parts
"use client";
export function InteractiveWidget() { /* state, effects, handlers */ }
priority prop on next/imageexport const revalidate = 300;next/font with display: 'swap' — prevents font-related layout shiftimport { Inter } from 'next/font/google';
const inter = Inter({ subsets: ['latin'], display: 'swap', weight: ['400', '700'] });
import Script from 'next/script';
// Analytics, tag managers — after page is interactive
<Script id="analytics" strategy="afterInteractive" src="..." />
// Non-critical (chat, surveys) — lazy load
<Script id="chat" strategy="lazyOnload" src="..." />
// NEVER use beforeInteractive for analytics — blocks rendering
@next/bundle-analyzer to monitorimport dynamic from 'next/dynamic';
const HeavyComponent = dynamic(() => import('./HeavyComponent'));
import { Suspense } from 'react';
export default function Page() {
return (
<>
<FastContent />
<Suspense fallback={<Skeleton />}>
<SlowContent />
</Suspense>
</>
);
}
beforeInteractive for analytics — blocks page render<link> — use next/font