Next.js 15 App Router: Complete Performance Guide

Next.js 15 App Router: Complete Performance Guide
Your Next.js app is live. It looks great. But Lighthouse is giving you a 63, your LCP is slow, and your client is asking why competitors feel faster.
This guide shows how to fix that β with real-world architecture, not theory.
π Table of Contents
Performance Model
React Server Components
Partial Prerendering (PPR)
Streaming with Suspense
Image & Font Optimization
Code Splitting
Caching Strategy
Core Web Vitals
FAQ
Conclusion
βοΈ 1. Performance Model
Core principle:
Move as much work to the server as possible. Ship minimal JS to the client.
Architecture Shift
Component TypeBehaviorServer ComponentRuns on server, zero JSClient Component ('use client')Hydrated in browserRoute SegmentsStatic / Dynamic / PPR
π‘ A page with 80% server components β drastically smaller JS bundle.
π§ 2. React Server Components (RSC)
Correct Mental Model
Page (Server)
β Layout (Server)
β DataFetcher (Server)
β InteractiveWidget (Client)
β StaticChild (Server β
)
Example
export default async function DashboardPage() {
const stats = await db.getUserStats()
return (
<main>
<UserStats data={stats} /> // Server
<InteractiveChart data={stats} /> // Client
</main>
)
}
βοΈ Server ΰ¦°ΰ¦Ύΰ¦ΰ§:
DB queries
API calls
Auth checks
Static UI
βοΈ Client ΰ¦ ΰ¦°ΰ¦Ύΰ¦ΰ§:
useState / useEffect
Event handlers
Browser APIs
β‘ 3. Partial Prerendering (PPR)
Biggest performance unlock in Next.js 15
Enable
experimental: {
ppr: true
}
Example
<>
<ProductInfo /> {/* Instant static */}
<Suspense fallback={<Skeleton />}>
<RecommendedItems /> {/* Streamed */}
</Suspense>
</>
Result:
β‘ Instant first paint
π Better LCP
π― Better UX
π 4. Streaming with Suspense
β Waterfall
const user = await getUser()
const orders = await getOrders()
β Parallel
await Promise.all([getUser(), getOrders()])
β Best UX
<Suspense fallback={<UserSkeleton />}><User /></Suspense>
<Suspense fallback={<OrderSkeleton />}><Orders /></Suspense>
π‘ UI loads piece-by-piece instead of waiting.
πΌοΈ 5. Image & Font Optimization
next/image
<Image
src="/hero.jpg"
width={1200}
height={630}
priority
/>
β Auto optimization
β Lazy loading
β No CLS
next/font
const inter = Inter({
subsets: ['latin'],
display: 'swap'
})
β No external request
β No layout shift
π¦ 6. Code Splitting
const Editor = dynamic(() => import('./Editor'), {
loading: () => <Skeleton />,
ssr: false
})
Rule:
50KB component β lazy load it
π§© 7. Caching Strategy
Default (Next.js 15)
β No caching
Options
// ISR
fetch('/api', { next: { revalidate: 60 } })
// Tag-based
fetch('/api', { next: { tags: ['config'] } })
// No cache
fetch('/api', { cache: 'no-store' })
Decision Matrix
Data TypeStrategyReal-timeno-storeSemi-staticrevalidateStatictags
π 8. Core Web Vitals
MetricTargetLCP< 2.5sCLS< 0.1INP< 200ms
Quick Wins β
priorityon hero imagesAlways width/height
Use Server Components
Use Suspense
Enable PPR
Analyze bundle
β FAQ
App Router use ΰ¦ΰ¦°ΰ¦¬ΰ§?
β Yes β future-proof
RSC ΰ¦ΰ¦Ώ Redux replace ΰ¦ΰ¦°ΰ¦¬ΰ§?
β οΈ Partial only
Expected gains?
π 25β40% JS reduction
β‘ 30% LCP improvement
π 60% TTFB improvement
π§Ύ Conclusion
Performance = architecture discipline.
Golden Rules:
Default β Server Components
Use PPR
Stream UI
Optimize images
Be explicit with caching
Audit bundle regularly
π CTA
Want 95+ Lighthouse scores consistently?
π Portfolio: https://sonjoybarman.xyz
π Letβs build something blazing fast.
Related services
I build SaaS, Next.js apps, and AI-ready marketing sites. Explore a focused offering or go straight to contact.
