7.6 KiB
Next.js 15 Upgrade Guide
Overview
This guide provides comprehensive instructions for upgrading from Next.js 13 to Next.js 15, covering breaking changes, new features, and migration strategies for professional developers.
Quick Start
Automated Upgrade (Recommended)
npx @next/codemod@canary upgrade latest
Manual Upgrade
npm install next@latest react@latest react-dom@latest
# or with force flag if peer dependency warnings
npm install next@latest react@latest react-dom@latest --force
Breaking Changes
1. Async Request APIs ⚠️ CRITICAL
APIs like cookies(), headers(), draftMode(), params, and searchParams are now async.
Before (Next.js 13):
// layout.tsx, page.tsx, route.ts
export default function Page({ params, searchParams }) {
const cookieStore = cookies();
const headersList = headers();
// ...
}
After (Next.js 15):
// layout.tsx, page.tsx, route.ts
export default async function Page({ params, searchParams }) {
const cookieStore = await cookies();
const headersList = await headers();
const resolvedParams = await params;
const resolvedSearchParams = await searchParams;
// ...
}
Codemod Available:
npx @next/codemod@canary next-async-request-api .
2. Runtime Configuration
Before:
export const runtime = 'experimental-edge';
After:
export const runtime = 'edge';
3. Font Imports
Before:
import { Inter } from '@next/font/google';
After:
import { Inter } from 'next/font/google';
4. Geolocation in NextRequest
Before:
// middleware.ts
export function middleware(request: NextRequest) {
const { geo, ip } = request;
// ...
}
After:
import { geolocation, ipAddress } from '@vercel/functions';
export function middleware(request: NextRequest) {
const geo = geolocation(request);
const ip = ipAddress(request);
// ...
}
New Caching Semantics
Default Behavior Changes
fetchrequests are uncached by default (was cached)- GET Route Handlers are uncached by default
- Client navigations are uncached by default
Opt-in to Caching
// Force static caching for specific routes
export const dynamic = 'force-static';
// Or configure in next.config.ts
const nextConfig = {
experimental: {
staleTimes: {
dynamic: 30, // 30 seconds
static: 180, // 3 minutes
},
},
};
New Features
1. React 19 Support
- App Router uses React 19 RC
- Pages Router remains on React 18 for compatibility
- React Compiler support (experimental)
// next.config.ts
const nextConfig = {
experimental: {
reactCompiler: true,
},
};
2. Turbopack for Development (Stable)
# 76.7% faster local server startup
# 96.3% faster code updates with Fast Refresh
# 45.8% faster initial route compile
next dev --turbo
3. Static Route Indicator
Visual indicator in development to identify static vs dynamic routes.
// next.config.ts - to disable
const nextConfig = {
devIndicators: {
appIsrStatus: false,
},
};
4. unstable_after API (Experimental)
Schedule work after response completion:
import { unstable_after as after } from 'next/server';
export default function Layout({ children }) {
after(() => {
// This runs after the response is sent
console.log('Logged after response');
});
return <>{children}</>;
}
Enable in config:
// next.config.ts
const nextConfig = {
experimental: {
after: true,
},
};
5. Enhanced <Form> Component
import Form from 'next/form';
export default function SearchForm() {
return (
<Form action="/search">
<input name="query" placeholder="Search..." />
<button type="submit">Search</button>
</Form>
);
}
6. Instrumentation.js (Stable)
// instrumentation.ts
export function onRequestError(err, request, context) {
console.error('Request error:', err, request.url);
}
7. Self-Hosting Improvements
// next.config.ts
const nextConfig = {
// Configure ISR expiration (default: 1 year)
expireTime: 60 * 60 * 24 * 30, // 30 days
};
8. Security Enhancements
- Server Actions now have secure, unguessable IDs
- Dead code elimination for unused Server Actions
- Treated as public HTTP endpoints
9. Bundling Optimization
// next.config.ts
const nextConfig = {
// App Router: external packages bundled by default
serverExternalPackages: ['package-to-exclude'],
// Pages Router: opt-in bundling
bundlePagesRouterDependencies: true,
transpilePackages: ['package-to-bundle'],
};
10. ESLint 9 Support
# Migrate to flat config
ESLINT_USE_FLAT_CONFIG=false npm run lint
Migration Checklist
Pre-Migration
- Backup your project
- Review breaking changes
- Update TypeScript types:
@types/react@latest @types/react-dom@latest - Test in development environment
During Migration
- Run automated upgrade:
npx @next/codemod@canary upgrade latest - Update async request APIs (use codemod)
- Fix runtime configurations
- Update font imports
- Handle geolocation changes
- Review caching behavior
Post-Migration
- Test all routes and functionality
- Enable Turbopack:
next dev --turbo - Configure new caching semantics
- Explore React 19 features
- Update ESLint configuration
- Performance testing
Common Issues & Solutions
1. Peer Dependency Warnings
npm install --legacy-peer-deps
# or
npm install --force
2. TypeScript Errors with Async APIs
Ensure all request API calls are awaited and functions are marked async.
3. Caching Behavior Changes
If experiencing performance issues, opt-in to caching:
export const dynamic = 'force-static';
4. React 19 Compatibility
Some third-party packages may not be React 19 compatible yet. Consider:
- Checking package compatibility
- Using Pages Router for problematic components
- Waiting for package updates
Performance Improvements
Development
- Turbopack: 76.7% faster server startup
- Fast Refresh: 96.3% faster code updates
- Route Compilation: 45.8% faster initial compile
Production
- Bundle Optimization: Automatic external package bundling
- Security: Enhanced Server Actions with dead code elimination
- Caching: More predictable caching behavior
Resources
Official Documentation
Tools & Codemods
Community Resources
Summary
Next.js 15 represents a significant evolution with:
- Async Request APIs requiring code changes
- Improved caching semantics with opt-in behavior
- React 19 support with new features
- Turbopack stability for faster development
- Enhanced security and performance optimizations
The upgrade process is well-supported with automated tools and codemods, making the transition manageable for most projects. Focus on testing async API changes and reviewing caching behavior for the smoothest upgrade experience.