Loading...
Loading...
Complete guide to Next.js 16 features, breaking changes, and migration from v15. Use when building new Next.js projects or upgrading existing ones to leverage Turbopack, Cache Components, and latest performance optimizations.
npx skill4agent add fernandofuc/nextjs-claude-setup nextjs-16-complete-guide| Feature | Next.js 15 | Next.js 16 |
|---|---|---|
| Bundler | Webpack (default), Turbopack (opt-in beta) | Turbopack (default, stable) |
| Caching | Implicit, confusing defaults | Explicit with "use cache" |
| Network Layer | middleware.ts (edge runtime) | proxy.ts (Node.js runtime) |
| DevTools | Basic error messages | MCP integration for AI debugging |
| React Compiler | Experimental | Stable, production-ready |
| Performance | Baseline | 2-5× faster builds, 10× faster Fast Refresh |
// Enable in next.config.ts
const nextConfig = {
cacheComponents: true,
};
export default nextConfig;// app/dashboard/page.tsx
import { Suspense } from 'react';
// This component caches its output
async function UserMetrics() {
'use cache'; // 🎯 Explicit caching
const metrics = await fetchMetrics(); // Cached result
return <MetricsCard data={metrics} />;
}
// This stays dynamic
async function LiveBalance() {
const balance = await fetchBalance(); // Always fresh
return <BalanceWidget balance={balance} />;
}
export default function Dashboard() {
return (
<div>
<Suspense fallback={<LoadingMetrics />}>
<UserMetrics /> {/* Cached, instant load */}
</Suspense>
<LiveBalance /> {/* Dynamic, real-time */}
</div>
);
}// Cache entire page
export default async function Page() {
'use cache';
return <PageContent />;
}
// Cache individual component
async function ExpensiveWidget() {
'use cache';
return <Chart data={await getData()} />;
}
// Cache function result
async function getStats() {
'use cache';
return await database.query('...');
}// next.config.ts
// Turbopack is now default - no config required!# Use Webpack instead
next build --webpack// next.config.ts
const nextConfig = {
experimental: {
turbopackFileSystemCacheForDev: true, // Faster restarts
},
};# Before (Webpack)
✓ Compiled in 4.2s
# After (Turbopack)
✓ Compiled in 0.4s # 10× faster# Old (Next.js 15)
middleware.ts # Edge runtime, confusing
# New (Next.js 16)
proxy.ts # Node.js runtime, explicit// OLD: middleware.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
return NextResponse.redirect(new URL('/home', request.url));
}
export const config = {
matcher: '/about/:path*',
};// NEW: proxy.ts
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export default function proxy(request: NextRequest) { // Changed function name
return NextResponse.redirect(new URL('/home', request.url));
}
export const config = {
matcher: '/about/:path*',
};middleware.tsproxy.tsexport function middlewareexport default function proxyYou: "Why is this page not caching?"
AI Agent (with MCP):
- Reads server logs
- Sees route configuration
- Checks cache headers
- Knows Next.js 16 caching rules
→ "You're missing 'use cache' directive in your component"useMemouseCallbackReact.memonpm install babel-plugin-react-compiler@latest// next.config.ts
const nextConfig = {
reactCompiler: true, // Moved from experimental to stable
};// You had to do this everywhere
const MemoizedComponent = React.memo(function Component({ data }) {
const processed = useMemo(() => processData(data), [data]);
const handleClick = useCallback(() => {
console.log(processed);
}, [processed]);
return <div onClick={handleClick}>{processed}</div>;
});// Just write code, compiler optimizes automatically
function Component({ data }) {
const processed = processData(data); // Auto-memoized
const handleClick = () => { // Auto-memoized
console.log(processed);
};
return <div onClick={handleClick}>{processed}</div>;
}# Minimum: Node.js 20.9+
# Next.js 15: Node.js 18 worked
# Next.js 16: Node.js 18 no longer supported// ❌ OLD (Next.js 15)
export default function Page({ params, searchParams }) {
const id = params.id; // Synchronous
}
// ✅ NEW (Next.js 16)
export default async function Page({ params, searchParams }) {
const { id } = await params; // Must await
const { query } = await searchParams;
}// ❌ OLD
import { cookies } from 'next/headers';
export function MyComponent() {
const token = cookies().get('token'); // Synchronous
}
// ✅ NEW
import { cookies } from 'next/headers';
export async function MyComponent() {
const cookieStore = await cookies(); // Must await
const token = cookieStore.get('token');
}// ❌ OLD
revalidateTag('posts');
// ✅ NEW
revalidateTag('posts', 'max'); // Options: 'max', 'hours', 'days'# Required migration
mv middleware.ts proxy.ts
# Update function name
export default function proxy(request) { ... }next lint# Check current versions
node --version # Should be 20.9+
npm list next # Current Next.js version
npm list react # React version# Upgrade to latest Next.js 16
npm install next@latest react@latest react-dom@latest
# Run codemod (handles most changes automatically)
npx @next/codemod@canary upgrade latest// next.config.ts
import type { NextConfig } from 'next';
const nextConfig: NextConfig = {
// Enable Cache Components
cacheComponents: true,
// Enable React Compiler
reactCompiler: true,
// Optional: File system caching
experimental: {
turbopackFileSystemCacheForDev: true,
},
};
export default nextConfig;# If you have middleware.ts
git mv middleware.ts proxy.ts
# Update function name in proxy.ts
export default function proxy(request: NextRequest) {
// Your logic
}// Search codebase for:
// - params.
// - searchParams.
// - cookies()
// - headers()
// - draftMode()
// Add await before each# Development
npm run dev # Should use Turbopack automatically
# Production build
npm run build # Should be 2-5× faster
# Run tests
npm test# Verify Node.js version in production
# Deploy to Vercel/platform
# Monitor for errors in first 24hnpx create-next-app@latest my-app
# Automatically uses Next.js 16, Turbopack, TypeScript, Tailwind// ✅ Good: Cache expensive, infrequent-changing data
async function MonthlyReport() {
'use cache';
return await generateReport();
}
// ❌ Bad: Don't cache user-specific real-time data
async function CurrentBalance() {
'use cache'; // Wrong! This should be fresh
return await getUserBalance();
}# Next.js 16 shows detailed timing
npm run build
# Example output:
Route (app) Size First Load JS
┌ ○ / 142 B 87.2 kB
├ ○ /_not-found 142 B 87.2 kB
└ ○ /dashboard 1.23 kB 88.4 kB
Build time: 14.2s # Was 57s in Next.js 15 with Webpack// Only if you have performance issues
reactCompiler: truenpm install next@latest react@latest react-dom@latest// next.config.ts
const nextConfig = {
cacheComponents: true, // Cache Components
reactCompiler: true, // React Compiler
experimental: {
turbopackFileSystemCacheForDev: true, // Faster dev restarts
},
};npm install next@latestnpx @next/codemod@canary upgrade latestmiddleware.tsproxy.tsawaitrevalidateTag()npm run buildnpm run dev