# What This Checklist Covers (and Why It Matters)#
Website performance optimization directly impacts conversion, SEO, and user retention. Multiple industry studies consistently show that small speed improvements move business metrics; for example, Deloitte reported that shaving 0.1s off load time can improve conversion rates on retail sites (impact varies by industry and device mix).
This guide is a Next.js-focused, production checklist covering Core Web Vitals, images, lazy loading, CDN, and caching—plus concrete before/after metrics you can use as benchmarks. If you’re early in your Next.js journey, start with Getting started with Next.js and come back here once your app is deployed.
# Baseline First: Measure Before You Optimize#
Without a baseline, “optimization” often becomes guesswork. You want field data (real users) for truth and lab data (Lighthouse) for debugging.
The Metrics That Actually Matter (Core Web Vitals)#
Core Web Vitals are evaluated at the 75th percentile of page loads, not the average. This matters because outliers (slow devices, bad networks) affect the user experience and Google’s assessment.
| Metric | What it represents | Good target | Common causes in Next.js |
|---|---|---|---|
| LCP (Largest Contentful Paint) | Time to render the main content | ≤ 2.5s | Unoptimized hero image, slow TTFB, blocking CSS/JS |
| INP (Interaction to Next Paint) | Responsiveness to user input | ≤ 200ms | Heavy JS, long tasks, third-party scripts, excessive client components |
| CLS (Cumulative Layout Shift) | Visual stability | ≤ 0.1 | Images without dimensions, late-loading fonts, injected UI banners |
Tools: What to Use and When#
| Goal | Tool | Why it’s useful |
|---|---|---|
| Field (real-user) CWV | CrUX / PageSpeed Insights | Shows CWV at p75; what Google uses |
| Lab debugging | Lighthouse (Chrome DevTools) | Identifies render-blocking, LCP element, long tasks |
| Next.js-specific profiling | Next.js build output + bundle analyzer | Finds large client bundles and heavy dependencies |
| Backend latency | APM (Datadog/New Relic) or server logs | TTFB is often the hidden bottleneck |
ℹ️ Note: A common trap is “Lighthouse chasing.” You can get a 100 score while still failing CWV in the field if your real users are on slower phones and networks. Always validate improvements with field data.
Before/After Example (Realistic Next.js E-commerce PDP)#
Here’s a typical improvement pattern we see on product detail pages after fixing images, caching, and third-party scripts.
| Metric (p75) | Before | After | What changed |
|---|---|---|---|
| LCP | 4.1s | 2.2s | Optimized hero image, preloading, CDN caching |
| INP | 320ms | 170ms | Reduced client JS, deferred non-critical scripts |
| CLS | 0.21 | 0.05 | Fixed image sizes, stabilized font loading |
| TTFB | 900ms | 180ms | ISR + CDN cache headers, reduced server work |
Use this as a sanity check: if your LCP is high but TTFB is low, it’s usually front-end payload and images. If TTFB is high, look at rendering strategy and caching first.
# Next.js Rendering Strategy: Choose the Fast Path#
Next.js gives you multiple ways to render pages. Your performance profile depends heavily on this choice.
Quick Decision Matrix (SSR vs SSG vs ISR)#
| Page type | Recommended | Why | Typical cache strategy |
|---|---|---|---|
| Marketing pages | SSG | Fastest, static HTML | CDN cache “immutable” |
| Blog/content | ISR | Freshness + speed | CDN cache with revalidate |
| Authenticated dashboards | SSR or client fetch | Per-user data | Private/no-store where needed |
| Product/category pages | ISR (often) | Huge SEO surface, needs updates | Revalidate by time or tags |
Avoid Unnecessary Client Components#
In the Next.js App Router, server components are your default advantage. Every client component increases JS shipped to the browser, which often hurts INP.
Checklist:
- Keep layout, navigation, and content rendering as server components.
- Use client components only for interactive parts (filters, carts, complex forms).
- Replace “global client wrapper” patterns with granular client islands.
If you’re building a high-performing marketing site or storefront, this often matters more than micro-optimizing JavaScript.
# Core Web Vitals Checklist (Next.js Implementation)#
1) Improve LCP: Optimize the LCP Element (Usually the Hero Image)#
In many Next.js sites, the LCP element is a large image above the fold. Treat it as critical content.
Checklist:
- Use
next/imagefor responsive sizing and modern formats. - Set
priorityonly for true above-the-fold images. - Provide
sizesso the browser downloads the right variant. - Ensure the hero image is not accidentally lazy-loaded.
// app/(marketing)/page.tsx
import Image from "next/image";
export default function Hero() {
return (
<Image
src="/images/hero.jpg"
alt="Product hero"
width={1600}
height={900}
priority
sizes="(max-width: 768px) 100vw, 1200px"
style={{ width: "100%", height: "auto" }}
/>
);
}Why this matters: without proper sizes, mobile users may download desktop-sized images, which inflates LCP on real devices.
2) Improve INP: Reduce Main-Thread Work and Client JS#
INP typically degrades because the browser is busy executing JavaScript when the user tries to interact.
Checklist:
- Remove heavy libraries from the client bundle (date libs, charting, WYSIWYG editors).
- Split interactive widgets and load them only on pages that need them.
- Replace expensive client-side state where server rendering works.
To identify large client bundles, use the analyzer.
npm i -D @next/bundle-analyzer// next.config.js
const withBundleAnalyzer = require("@next/bundle-analyzer")({
enabled: process.env.ANALYZE === "true",
});
module.exports = withBundleAnalyzer({
reactStrictMode: true,
});ANALYZE=true npm run buildActionable rule: if a dependency is used on 10% of pages, don’t ship it to 100% of users.
3) Improve CLS: Reserve Space for Everything That Loads Late#
CLS issues often come from images, fonts, and injected UI (cookie banners, chat widgets).
Checklist:
- Always specify
widthandheight(or aspect ratio) for images. - Avoid inserting banners above content without reserving space.
- Use
font-display: swapand consistent fallback fonts to reduce layout jumps.
⚠️ Warning: A common CLS killer is a cookie consent bar that appears at the top and pushes the whole page down. Reserve space from the start or render it in a non-layout-shifting way (e.g., overlay).
# Image Optimization (Biggest LCP Lever for Most Sites)#
Images are often the majority of transferred bytes on content-heavy pages. Modern formats and correct sizing reduce bandwidth, decode time, and LCP.
The Practical Image Checklist for Next.js#
| Item | Target | How in Next.js |
|---|---|---|
| Use modern formats | AVIF/WebP | next/image auto-optimizes; ensure source quality |
| Correct responsive sizing | No oversized downloads | sizes + correct layout |
| Avoid layout shifts | Reserve space | width/height or stable container |
| Compress appropriately | Balanced quality | Pre-compress originals; avoid huge JPEGs |
| Optimize thumbnails | Small and fast | Use separate smaller assets or rely on image resizing |
Remote Images: Configure Domains Safely#
If you load images from a CMS or CDN, whitelist domains.
// next.config.js
module.exports = {
images: {
remotePatterns: [
{ protocol: "https", hostname: "images.example-cms.com" },
{ protocol: "https", hostname: "cdn.example.com" },
],
},
};Example: Before/After on a Blog Listing#
| Item | Before | After |
|---|---|---|
| Thumbnail size served to mobile | 1200px wide | 400–600px wide (responsive) |
| Format | JPEG | WebP/AVIF |
| Total image transfer on listing | 3.8MB | 1.2MB |
| LCP (lab) | 3.2s | 2.0s |
This improvement is common when a listing page renders 10–20 thumbnails with no sizes and no proper resizing.
# Lazy Loading (Done Right, Not Everywhere)#
Lazy loading saves bandwidth and reduces initial work, but misusing it can hurt LCP and cause jank.
What to Lazy Load#
| Element | Lazy load? | Why |
|---|---|---|
| Below-the-fold images | Yes | Frees bandwidth for LCP |
| Below-the-fold sections | Often | Reduce initial JS/HTML work |
| Above-the-fold hero image | No | It’s usually the LCP element |
| Primary navigation | No | Needed for immediate interaction |
| Third-party widgets (chat, ads) | Yes (defer) | Often heavy and not critical |
Dynamic Imports for Heavy Client Widgets#
Keep heavy components out of the initial bundle.
// app/product/[slug]/page.tsx
import dynamic from "next/dynamic";
const Reviews = dynamic(() => import("./Reviews"), {
ssr: false,
loading: () => null,
});
export default function ProductPage() {
return (
<>
{/* main content */}
<Reviews />
</>
);
}Use this for widgets that are not needed for first render (reviews, recommendations, advanced filters).
💡 Tip: If you defer a widget that affects layout, reserve space with a fixed-height skeleton to prevent CLS.
# CDN: Reduce Latency and Stabilize Performance Globally#
A CDN improves performance by caching content closer to users and smoothing traffic spikes. For global audiences, it’s one of the highest ROI improvements.
What to Serve Through a CDN#
| Asset type | CDN suitability | Notes |
|---|---|---|
Static assets (/_next/static/*) | Excellent | Typically immutable and cacheable |
| Images | Excellent | Use image CDN or Next image optimization |
| HTML (SSG/ISR) | Good | Cache and revalidate; avoid caching personalized pages |
| API responses | Depends | Cache public data; keep private data uncached |
If your app is on Vercel, you already benefit from edge caching for many assets. The remaining work is correct cache headers and choosing ISR/SSG where possible.
CDN Configuration Checklist#
- Cache immutable assets for a long time (
max-age=31536000, immutable). - Cache HTML for static and ISR pages according to freshness needs.
- Bypass cache for personalized content (cookies, auth headers).
- Enable Brotli compression if your platform supports it (most do).
# Caching Strategies (Next.js + HTTP): The Money Section#
Caching is where performance becomes predictable. You’re trying to reduce:
- Server compute per request (TTFB)
- Repeated DB calls
- Variance during traffic spikes
Caching Layers You Should Consider#
| Layer | Examples | What it improves |
|---|---|---|
| Browser cache | Cache-Control | Repeat visits, back/forward navigation |
| CDN/edge cache | Vercel edge, Cloudflare | TTFB globally, traffic smoothing |
| Server data cache | Next.js data cache, fetch caching | SSR performance, DB load |
| App cache | Redis | Expensive computations, shared state |
HTTP Cache-Control: Recommended Defaults#
| Content type | Suggested header | When to use |
|---|---|---|
| Fingerprinted assets | public, max-age=31536000, immutable | /_next/static/* |
| Public API (fast-changing) | public, s-maxage=60, stale-while-revalidate=300 | Lists, search suggestions |
| ISR HTML | Platform-controlled + revalidate | Content pages |
| Personalized HTML | private, no-store | Account pages |
If you serve an API route that returns public content, you can add caching like this:
// app/api/products/route.ts
export async function GET() {
const body = JSON.stringify({ items: [] });
return new Response(body, {
headers: {
"Content-Type": "application/json",
"Cache-Control": "public, s-maxage=60, stale-while-revalidate=300",
},
});
}This reduces repeated origin hits while keeping data acceptably fresh.
ISR in Practice: High Performance Without Stale Content Anxiety#
Incremental Static Regeneration is often the best default for SEO pages that change occasionally.
Checklist:
- Use ISR for product, category, and content pages.
- Revalidate by time for simplicity, or by tags when you have a CMS.
- Confirm that your CDN honors ISR behavior (Vercel does; other setups may need tuning).
Even a modest shift from SSR to ISR can drop TTFB from 800–1200ms to 100–250ms for global users, especially under load.
# Third-Party Scripts: The Silent INP Killer#
Analytics, A/B testing, chat widgets, and tag managers frequently degrade INP due to long tasks. You don’t need to remove them—you need to control when they execute.
Checklist:
- Audit third-party scripts and remove unused tags.
- Load non-critical scripts after interaction or after page is stable.
- Prefer server-side tracking where feasible.
A practical approach:
- Keep only one analytics tool.
- Defer chat widgets until the user scrolls or spends 10–15 seconds on the page.
- Avoid “all pages” injection for scripts needed only on checkout or pricing.
# Network and Payload: Keep the First Load Small#
Even with perfect caching, large JS and CSS payloads hurt. The goal is not “small for the sake of small,” but fast-to-interactive.
Payload Checklist#
| Item | Target | How to achieve it |
|---|---|---|
| JS per route | As low as possible | Server components, code splitting, remove heavy deps |
| CSS blocking | Minimal | Avoid giant global CSS, split per route where possible |
| Fonts | 1–2 families | Subset fonts, preload only what’s needed |
| JSON data | Don’t overfetch | Request only required fields, paginate |
# Operational Checklist: Prevent Performance Regressions#
Performance improvements often disappear after a few sprints. Put guardrails in place.
Add Performance Budgets#
Checklist:
- Set a maximum JS size per route (e.g., 170–250KB gzipped as a starting point).
- Track CWV over time (weekly) and alert on regressions.
- Make performance part of Definition of Done for new pages.
Use Synthetic Monitoring for Critical Paths#
For high-value flows (homepage → PDP → checkout), synthetic checks catch CDN and backend issues before customers do.
Track:
- TTFB
- LCP
- INP proxies (total blocking time in lab)
- Error rates
# Complete Website Performance Optimization Checklist (Copy/Paste)#
Use this list to run a full audit.
Core Web Vitals (CWV)#
- 1Identify LCP element per template (home, listing, detail).
- 2Fix LCP with image optimization, preloading, and reduced TTFB.
- 3Reduce INP by cutting client JS, deferring third-party scripts, and avoiding big client wrappers.
- 4Reduce CLS by reserving space for images, fonts, and injected UI.
Images#
- 1Use
next/imagefor all content images. - 2Add
sizesfor responsive behavior. - 3Use
priorityonly for true above-the-fold images. - 4Enforce compression and reasonable source dimensions.
Lazy Loading#
- 1Lazy load below-the-fold images and sections.
- 2Dynamic import heavy client widgets.
- 3Reserve space for lazy-loaded UI to avoid CLS.
CDN#
- 1Ensure immutable caching for fingerprinted assets.
- 2Cache public HTML/API where safe.
- 3Verify compression (Brotli) and HTTP/2/3 support.
Caching#
- 1Prefer SSG/ISR for SEO pages.
- 2Add
Cache-Controlheaders to public API responses. - 3Avoid caching personalized responses.
- 4Validate cache hit ratio at CDN and origin.
Next.js-Specific#
- 1Minimize client components; use server components by default.
- 2Analyze bundles and remove heavy dependencies.
- 3Keep route-level JS small with code splitting.
Proof (Metrics)#
- 1Record baseline (p75 CWV + Lighthouse + bundle sizes).
- 2Re-test after each change.
- 3Roll out gradually when changes affect caching or rendering strategy.
# Key Takeaways#
- Optimize what drives Core Web Vitals: LCP (hero/content), INP (JS + third parties), CLS (reserved space), using field data at the 75th percentile.
- In Next.js, performance often improves fastest by reducing client components and shipping less JavaScript to the browser.
- Image work is usually the biggest win: use
next/image, correctsizes, modern formats, and avoid lazy-loading the LCP image. - Treat caching as a system: SSG/ISR + correct Cache-Control + CDN can drop TTFB from ~1s to ~200ms in real deployments.
- Use lazy loading selectively: defer below-the-fold content and heavy widgets, but keep above-the-fold critical elements eager and stable.
- Prevent regressions with budgets, bundle analysis, and recurring CWV checks—performance is a product feature, not a one-time task.
# Conclusion#
Website performance optimization is easiest when you treat it as a checklist: measure CWV, fix the LCP element (usually images), cut client-side JavaScript to improve INP, stabilize layouts for CLS, and make caching/CDN behavior explicit.
If you want a hands-on audit and a prioritized optimization plan for your Next.js app—complete with measurable before/after KPIs—Samioda can help: Mobile & Web Development. For teams getting started or migrating, begin with Getting started with Next.js and then apply this checklist to your key templates.
FAQ
More in Web Development
All →Best Headless CMS in 2026: Sanity vs Strapi vs Contentful (and 2 More)
A practical 2026 comparison of the top 5 headless CMS options—Sanity, Strapi, Contentful, Directus, and Storyblok—focused on developer experience, Next.js integration, features, and pricing.
Progressive Web Apps (PWA): Complete Guide for 2026
A practical progressive web app PWA guide for 2026: concepts, business benefits vs native apps, and a step-by-step Next.js implementation with manifest and service worker code.
Next.js vs Remix in 2026: Which React Framework Should You Choose?
A comprehensive comparison of Next.js and Remix in 2026. Explore SSR, routing, data loading, and ecosystem to find out which framework suits your project best.
Need help with your project?
We build custom solutions using the technologies discussed in this article. Senior team, fixed prices.
Related Articles
Why Next.js Is the Best Framework for SEO in 2026
Learn why Next.js dominates SEO performance in 2026. Server-side rendering, Core Web Vitals, structured data, and real performance comparisons.
Progressive Web Apps (PWA): Complete Guide for 2026
A practical progressive web app PWA guide for 2026: concepts, business benefits vs native apps, and a step-by-step Next.js implementation with manifest and service worker code.
Best Headless CMS in 2026: Sanity vs Strapi vs Contentful (and 2 More)
A practical 2026 comparison of the top 5 headless CMS options—Sanity, Strapi, Contentful, Directus, and Storyblok—focused on developer experience, Next.js integration, features, and pricing.