Next.js 16: Der komplette Migrations-Guide
Next.js 16 wurde am 21. Oktober 2025 veröffentlicht und bringt massive Änderungen: Turbopack ist jetzt Standard, ein komplett neues Caching-System mit "use cache", und zahlreiche Breaking Changes rund um async APIs. Dieser Guide hilft bei der Migration.
Die wichtigsten Neuerungen
1. Turbopack ist jetzt Standard (Stable)
Turbopack ersetzt Webpack als Default-Bundler für alle Next.js-Apps:
Performance-Verbesserungen:
- ⚡ 2-5x schnellere Production Builds
- ⚡ 10x schnellere Fast Refresh in Dev
- 📦 Über 50% aller Dev-Sessions nutzen bereits Turbopack (Next.js 15.3+)
Wichtig: Du kannst Webpack weiterhin nutzen:
# Dev mit Webpack
next dev --webpack
# Build mit Webpack
next build --webpackTurbopack File System Caching (Beta):
// next.config.ts
const nextConfig = {
experimental: {
turbopackFileSystemCacheForDev: true, // Schnellere Restarts
},
};
export default nextConfig;2. Cache Components – Das neue Caching-System
Das größte Feature in Next.js 16: Opt-in Caching mit "use cache":
Wichtig: Alle Pages sind jetzt standardmäßig dynamisch (nicht mehr statisch!):
// next.config.ts
const nextConfig = {
cacheComponents: true, // Cache Components aktivieren
};
export default nextConfig;Komponenten cachen:
// app/components/product-list.tsx
import { cacheLife } from "next/cache";
export async function ProductList() {
"use cache"; // Diese Komponente wird gecacht
cacheLife("hours"); // 1 Stunde Cache
const products = await fetch("https://api.example.com/products").then((r) => r.json());
return (
<ul>
{products.map((p) => (
<li key={p.id}>
{p.name} - {p.price}€
</li>
))}
</ul>
);
}Ganze Pages cachen:
// app/blog/page.tsx
import { cacheLife } from "next/cache";
export default async function BlogPage() {
"use cache";
cacheLife("days"); // 1 Tag Cache
const posts = await fetch("https://cms.example.com/posts").then((r) => r.json());
return <div>{/* ... */}</div>;
}Cache-Profile:
import { cacheLife } from "next/cache";
// Built-in Profiles
cacheLife("minutes"); // 5 Minuten (Standard)
cacheLife("hours"); // 1 Stunde
cacheLife("days"); // 1 Tag
cacheLife("max"); // 1 Jahr
// Custom Profile
cacheLife({
revalidate: 3600, // 1 Stunde
stale: 7200, // 2 Stunden stale erlaubt
});3. Neue Caching APIs
a) revalidateTag() – Jetzt mit SWR (Stale-While-Revalidate):
import { revalidateTag } from "next/cache";
// ✅ NEU: Zweiter Parameter erforderlich
revalidateTag("blog-posts", "max"); // SWR mit 1 Jahr Cache
// ⚠️ DEPRECATED: Funktioniert nicht mehr
revalidateTag("blog-posts");b) updateTag() – NEU: Read-Your-Writes:
"use server";
import { updateTag } from "next/cache";
export async function updateUserProfile(userId: string, profile: Profile) {
await db.users.update(userId, profile);
// Benutzer sieht Änderungen SOFORT (nicht stale)
updateTag(`user-${userId}`);
}c) refresh() – NEU: Nur dynamische Daten refreshen:
"use server";
import { refresh } from "next/cache";
export async function markNotificationAsRead(notificationId: string) {
await db.notifications.markAsRead(notificationId);
// Nur ungecachte Daten refreshen (z.B. Notification-Count)
refresh();
}4. React 19.2 Features
Next.js 16 nutzt React 19.2 mit neuen APIs:
View Transitions:
import { useTransition, ViewTransition } from "react";
function ProfileCard({ user }) {
const [isPending, startTransition] = useTransition();
return (
<ViewTransition>
<img src={user.avatar} alt={user.name} />
<h2>{user.name}</h2>
</ViewTransition>
);
}useEffectEvent:
import { useEffect, useEffectEvent } from "react";
function ChatRoom({ roomId }) {
const onMessage = useEffectEvent((msg) => {
// Diese Funktion wird nicht neu erstellt bei jedem Re-Render
showNotification(msg);
});
useEffect(() => {
const connection = createConnection(roomId);
connection.on("message", onMessage);
return () => connection.disconnect();
}, [roomId]); // onMessage NICHT in Dependencies!
}5. proxy.ts (vorher middleware.ts)
Breaking Change: middleware.ts → proxy.ts:
// proxy.ts (NEU)
export default function proxy(request: NextRequest) {
return NextResponse.redirect(new URL("/Startseite", request.url));
}Migration:
# Datei umbenennen
mv middleware.ts proxy.ts
# Funktion umbenennen
# middleware() → proxy()Wichtig: middleware.ts ist deprecated und wird in Zukunft entfernt!
Breaking Changes
1. Async params, searchParams, cookies, headers
Alle diese APIs sind jetzt async:
// ❌ ALT (Next.js 15)
export default function Page({ params, searchParams }) {
const id = params.id;
const query = searchParams.q;
return <div>{id}</div>;
}
// ✅ NEU (Next.js 16)
export default async function Page({
params,
searchParams,
}: {
params: Promise<{ id: string }>;
searchParams: Promise<{ q?: string }>;
}) {
const { id } = await params;
const { q } = await searchParams;
return <div>{id}</div>;
}cookies() und headers():
// ❌ ALT
import { cookies } from "next/headers";
export default function Page() {
const token = cookies().get("auth-token");
return <div>{token}</div>;
}
// ✅ NEU
import { cookies } from "next/headers";
export default async function Page() {
const cookieStore = await cookies();
const token = cookieStore.get("auth-token");
return <div>{token}</div>;
}2. fetch() ist jetzt standardmäßig NICHT gecacht
Riesiger Breaking Change:
// ❌ ALT: fetch() war automatisch gecacht
const data = await fetch("https://api.example.com/data");
// ✅ NEU: Explizites Caching erforderlich
const data = await fetch("https://api.example.com/data", {
next: { revalidate: 3600 }, // 1 Stunde Cache
});
// Oder: "use cache" Directive
async function getData() {
"use cache";
return fetch("https://api.example.com/data");
}3. next/image Änderungen
a) Lokale Bilder mit Query Strings benötigen localPatterns:
// next.config.ts
const nextConfig = {
images: {
localPatterns: [
{
pathname: "/assets/images/**",
search: "", // Erlaubt Query Strings
},
],
},
};b) Neue Defaults:
// Neue Defaults in Next.js 16
const nextConfig = {
images: {
minimumCacheTTL: 14400, // 4 Stunden (vorher 60s)
imageSizes: [32, 48, 64, 96, 128, 256, 384], // 16 entfernt
qualities: [75], // Vorher [1..100]
maximumRedirects: 3, // Vorher unlimited
dangerouslyAllowLocalIP: false, // NEU: Sicherheits-Flag
},
};4. Entfernte Features
Vollständig entfernt:
- ❌ AMP Support (
useAmp,export const config = { amp: true }) - ❌
next lint(nutzeeslintdirekt) - ❌
serverRuntimeConfig/publicRuntimeConfig(nutze.env) - ❌
experimental.ppr(jetztcacheComponents) - ❌
experimental.dynamicIO(jetztcacheComponents) - ❌
unstable_rootParams()(Alternative kommt bald)
Codemod nutzen:
npx @next/codemod@canary upgrade latestMigration Schritt-für-Schritt
Schritt 1: Dependencies aktualisieren
# Next.js 16 + React 19.2
npm install next@latest react@latest react-dom@latest
# TypeScript-Typen aktualisieren
npm install -D @types/react@latest @types/react-dom@latest
# ESLint-Config aktualisieren
npm install -D eslint-config-next@latestSchritt 2: Breaking Changes automatisch fixen
# Offizieller Codemod
npx @next/codemod@canary upgrade latest
# Oder manuell einzelne Codemods:
npx @next/codemod@canary next-async-request-api .
npx @next/codemod@canary metadata-to-viewport-export .Schritt 3: middleware.ts → proxy.ts
# Datei umbenennen
git mv middleware.ts proxy.ts// proxy.ts
// Funktion umbenennen: middleware → proxy
export default function proxy(request: NextRequest) {
// Deine Logik bleibt gleich
return NextResponse.next();
}Schritt 4: Async params/searchParams fixen
Quick Fix mit TypeScript:
// Globale Type Helper
type AwaitedParams<T> = T extends Promise<infer U> ? U : T;
// In deinen Pages
type PageParams = { id: string };
export default async function Page({ params }: { params: Promise<PageParams> }) {
const { id } = await params;
// ...
}Schritt 5: fetch() Caching überarbeiten
Strategie 1: next.revalidate nutzen:
// Überall wo fetch() war:
const data = await fetch(url, {
next: { revalidate: 3600 }, // 1 Stunde
});Strategie 2: "use cache" nutzen (empfohlen):
// config aktivieren
// next.config.ts: cacheComponents: true
async function getData() {
"use cache";
cacheLife("hours");
return fetch(url);
}Schritt 6: Cache Components aktivieren
// next.config.ts
const nextConfig = {
cacheComponents: true,
};
export default nextConfig;Dann Pages opt-in cachen:
// app/products/page.tsx
import { cacheLife } from "next/cache";
export default async function ProductsPage() {
"use cache";
cacheLife("max"); // 1 Jahr mit SWR
// Page wird gecacht, bleibt aber aktuell durch Background-Revalidation
return <div>...</div>;
}Häufige Probleme & Lösungen
Problem 1: Build schlägt fehl mit "params is not defined"
Ursache: params nicht awaited
Lösung:
// ❌ Falsch
export default function Page({ params }) {
console.log(params.id); // Error!
// ✅ Richtig
export default async function Page({ params }) {
const { id } = await params;
console.log(id);
}Problem 2: fetch() liefert alte Daten trotz "use cache"
Ursache: cacheComponents nicht aktiviert
Lösung:
// next.config.ts
const nextConfig = {
cacheComponents: true, // MUSS aktiviert sein!
};Problem 3: Turbopack Build bricht ab
Ursache: Custom Webpack Loaders inkompatibel
Lösung:
# Fallback auf Webpack
next build --webpack
# Oder: Turbopack-Adapter konfigurieren// next.config.ts
const nextConfig = {
turbopack: {
rules: {
"*.svg": ["@svgr/webpack"], // Custom Loader
},
},
};Problem 4: TypeScript Errors mit async params
Lösung: Types explizit definieren:
// types/params.ts
export type PageProps<T = {}> = {
params: Promise<T>;
searchParams: Promise<{ [key: string]: string | string[] | undefined }>;
};
// In Page nutzen
import type { PageProps } from "@/types/params";
export default async function Page({ params, searchParams }: PageProps<{ id: string }>) {
const { id } = await params;
const { q } = await searchParams;
// ...
}Performance-Best Practices
1. Cache Components strategisch nutzen
// ✅ CACHEN: Relativ statische Inhalte
export async function BlogPostList() {
"use cache";
cacheLife("hours");
// ...
}
// ❌ NICHT CACHEN: User-spezifische Daten
export async function UserDashboard() {
// Kein "use cache" - immer fresh
const user = await getCurrentUser();
return <div>Welcome {user.name}</div>;
}2. Partial Prerendering (PPR) mit Cache Components
// app/dashboard/page.tsx
import { Suspense } from "react";
export default async function Dashboard() {
return (
<>
{/* Statisch (gecacht) */}
<Header />
<Navigation />
{/* Dynamisch (on-demand) */}
<Suspense fallback={<Skeleton />}>
<UserProfile />
</Suspense>
<Suspense fallback={<Skeleton />}>
<RealtimeData />
</Suspense>
</>
);
}3. Bundle Analyzer nutzen
# Bundle-Größe analysieren
npm install -D @next/bundle-analyzer// next.config.ts
import bundleAnalyzer from "@next/bundle-analyzer";
const withBundleAnalyzer = bundleAnalyzer({
enabled: process.env.ANALYZE === "true",
});
export default withBundleAnalyzer({
cacheComponents: true,
});# Analyse starten
ANALYZE=true npm run build4. React Compiler aktivieren (optional)
# React Compiler installieren
npm install babel-plugin-react-compiler@latest// next.config.ts
const nextConfig = {
reactCompiler: true, // Automatische Memoisierung
};Achtung: Build-Zeit erhöht sich, da React Compiler Babel nutzt!
Node.js & Browser Requirements
Neue Mindestanforderungen:
| Requirement | Version | | ----------- | ------------- | | Node.js | 20.9.0+ (LTS) | | TypeScript | 5.1.0+ | | Chrome | 111+ | | Edge | 111+ | | Firefox | 111+ | | Safari | 16.4+ |
Node.js 18 wird nicht mehr unterstützt!
Entfernte Deprecations
Diese Features wurden komplett entfernt:
// ❌ Funktioniert nicht mehr
export const config = { amp: true };
import { useAmp } from "next/amp";
// ✅ Alternativen
// Nutze reguläre Next.js Pages ohne AMPPowerShell 2.0 Skripte migrieren:
# Scripts auf PS 5+ prüfen
Get-ChildItem -Recurse -Filter "*.ps1" |
Select-String "-Version 2"
# PowerShell 7+ installieren
winget install Microsoft.PowerShellFazit: Lohnt sich das Upgrade?
JA, wenn:
- ✅ Du von Turbopack profitieren willst (5-10x Fast Refresh!)
- ✅ Du mehr Kontrolle über Caching brauchst (
"use cache") - ✅ React 19.2 Features nutzen möchtest (View Transitions, useEffectEvent)
- ✅ Dein Projekt aktiv entwickelt wird
WARTEN, wenn:
- ⏸️ Du viele custom Webpack Loaders hast (erst Kompatibilität prüfen)
- ⏸️ Dein Code stark auf implizites fetch()-Caching baut
- ⏸️ Du AMP nutzt (wird nicht mehr unterstützt!)
Empfohlene Timeline:
- Woche 1-2: Test-Branch mit
next@latest+ Codemod - Woche 3: Breaking Changes manuell fixen, Tests grün machen
- Woche 4:
cacheComponentstesten, Performance messen - Woche 5+: Schrittweiser Rollout mit Monitoring
Wichtig: Nutze npx @next/codemod@canary upgrade latest für automatische Migration!
Quelle: Next.js 16 – Release-Ankündigung
Hinweis: Alle Inhalte wurden mit größter Sorgfalt erstellt, dennoch übernehme ich keine Gewähr für Aktualität, Vollständigkeit oder technische Auswirkungen. Eine Haftung für Schäden, die aus der Umsetzung entstehen, ist ausgeschlossen.
Probleme bei der Migration? Kontaktieren Sie POETSCHKE-IT für professionelle Next.js 16 Migration und Performance-Optimierung!