Skip to content

Version 15

Upgrading from 14 to 15

To update to Next.js version 15, run the following command using your preferred package manager:

Terminal
npm i next@rc react@rc react-dom@rc eslint-config-next@rc
Terminal
yarn add next@rc react@rc react-dom@rc eslint-config-next@rc
Terminal
pnpm up next@rc react@rc react-dom@rc eslint-config-next@rc
Terminal
bun add next@rc react@rc react-dom@rc eslint-config-next@rc

Good to know:

  • If you see a peer dependencies warning, you may need to update react and react-dom to the suggested versions, or you use the --force or --legacy-peer-deps flag to ignore the warning. This won't be necessary once both Next.js 15 and React 19 are stable.
  • If you are using TypeScript, you'll need to temporarily override the React types. See the React 19 RC upgrade guide for more information.

Minimum React version

  • The minimum react and react-dom is now 19.

React 19

  • useFormState has been replaced by useActionState. The useFormState hook is still available in React 19, but it is deprecated and will be removed in a future release. useActionState is recommended and includes additional properties like reading the pending state directly. Learn more.
  • useFormStatus now includes additional keys like data, method, and action. If you are not using React 19, only the pending key is available. Learn more.
  • Read more in the React 19 upgrade guide.

fetch requests

fetch requests are no longer cached by default.

To opt specific fetch requests into caching, you can pass the cache: 'force-cache' option.

app/layout.js
export default async function RootLayout() {
  const a = await fetch('https://...') // Not Cached
  const b = await fetch('https://...', { cache: 'force-cache' }) // Cached
 
  // ...
}

To opt all fetch requests in a layout or page into caching, you can use the export const fetchCache = 'default-cache' segment config option. If individual fetch requests specify a cache option, that will be used instead.

app/layout.js
// Since this is the root layout, all fetch requests in the app
// that don't set their own cache option will be cached.
export const fetchCache = 'default-cache'
 
export default async function RootLayout() {
  const a = await fetch('https://...') // Cached
  const b = await fetch('https://...', { cache: 'no-store' }) // Not cached
 
  // ...
}

Route Handlers

GET functions in Route Handlers are no longer cached by default. To opt GET methods into caching, you can use a route config option such as export const dynamic = 'force-static' in your Route Handler file.

app/api/route.js
export const dynamic = 'force-static'
 
export async function GET() {}

Client-side Router Cache

When navigating between pages via <Link> or useRouter, page segments are no longer reused from the client-side router cache. However, they are still reused during browser backward and forward navigation and for shared layouts.

To opt page segments into caching, you can use the staleTimes config option:

next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  experimental: {
    staleTimes: {
      dynamic: 30,
      static: 180,
    },
  },
}
 
module.exports = nextConfig

Layouts and loading states are still cached and reused on navigation.

next/font

The @next/font package has been removed in favor of the built-in next/font. A codemod is available to safely and automatically rename your imports.

app/layout.js
// Before
import { Inter } from '@next/font/google'
 
// After
import { Inter } from 'next/font/google'

bundlePagesRouterDependencies

experimental.bundlePagesExternals is now stable and renamed to bundlePagesRouterDependencies.

next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  // Before
  experimental: {
    bundlePagesExternals: true,
  },
 
  // After
  bundlePagesRouterDependencies: true,
}
 
module.exports = nextConfig

serverExternalPackages

experimental.serverComponentsExternalPackages is now stable and renamed to serverExternalPackages.

next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
  // Before
  experimental: {
    serverComponentsExternalPackages: ['package-name'],
  },
 
  // After
  serverExternalPackages: ['package-name'],
}
 
module.exports = nextConfig

Speed Insights

Auto instrumentation for Speed Insights was removed in Next.js 15.

To continue using Speed Insights, follow the Vercel Speed Insights Quickstart guide.

NextRequest Geolocation

The geo and ip properties on NextRequest have been removed. These values had to be provided by your hosting provider.

If you are using Vercel, you can alternatively use the geolocation and ipAddress functions from `@vercel/functions instead:

middleware.ts
import { geolocation } from '@vercel/functions'
import type { NextRequest } from 'next/server'
 
export function middleware(request: NextRequest) {
  const { city } = geolocation(request)
 
  // ...
}
middleware.ts
import { ipAddress } from '@vercel/functions'
import type { NextRequest } from 'next/server'
 
export function middleware(request: NextRequest) {
  const ip = ipAddress(request)
 
  // ...
}