Next.js 15 in Produktion: App Router, PPR und Caching at Scale
Ein praktischer Leitfaden zum Aufbau einer Next.js-15-Anwendung für die Produktion — Server Components, Partial Prerendering, Cache-Invalidierung und Deployment-Muster.

Dies ist ein technischer Artikel für Entwickler. Sie führen einen Salon, ein Restaurant oder einen Handwerksbetrieb? Dann sind diese Artikel für Sie: Was eine Website wirklich kostet und was Ihre Website wirklich braucht.
Next.js 15 bringt eine Reihe von Funktionen mit, die — richtig eingesetzt — Anwendungen ermöglichen, die gleichzeitig schnell laden, günstig auszuliefern und leicht zu warten sind. Falsch eingesetzt, erzeugen dieselben Funktionen Caching-Bugs, die in der Produktion schmerzhaft zu debuggen sind. Dieser Beitrag behandelt die Architekturentscheidungen, auf die es ankommt.
Das mentale Modell: Wo läuft der Code?
Bevor Sie eine einzige Zeile schreiben, beantworten Sie das für jede Komponente:
| Frage | Antwort → |
| -------------------------------------- | ---------------------------------------- |
| Ändern sich diese Daten pro Request? | Server Component mit cache: 'no-store' |
| Ändern sich diese Daten nach Zeitplan? | Server Component mit revalidate |
| Ändern sich diese Daten nie? | Server Component, vollständig statisch |
| Braucht das Interaktivität? | Client Component ('use client') |
Der Standard im App Router sind Server Components. 'use client' hinzuzufügen ist ein bewusstes Opt-in, nicht der Ausgangspunkt.
Ordnerstruktur für eine echte Anwendung
app/
[locale]/
(public)/ ← Layout mit Navbar/Footer
page.tsx ← Startseite, statisch
blog/
page.tsx ← Übersicht, revalidate: 60
[slug]/page.tsx ← Detail, statisch + ISR
portfolio/
page.tsx ← statisch
(protected)/ ← Layout mit Auth-Prüfung
dashboard/
page.tsx ← dynamisch, kein Cache
api/
contact/route.ts ← POST, rate-limited
og/route.ts ← dynamisches OG-Bild
Route-Gruppen (public) und (protected) teilen unterschiedliche Layouts, ohne die URL zu beeinflussen. Das ist sauberer, als jede geschützte Seite einzeln in eine Auth-Prüfung zu wickeln.
Server Components: Muster für das Datenholen
Paralleles Fetching mit Promise.all
Warten Sie nie seriell, wenn die Requests unabhängig sind:
// ❌ 600ms (zwei serielle Requests) const projects = await getProjects(); const testimonials = await getTestimonials(); // ✅ 300ms (parallel) const [projects, testimonials] = await Promise.all([getProjects(), getTestimonials()]);ts
Request-Deduplizierung mit React cache
Wenn mehrere Komponenten auf derselben Seite dieselben Daten brauchen, sorgt React.cache dafür, dass das Fetch nur einmal pro Render läuft:
import { cache } from 'react'; export const getUser = cache(async (id: string) => { return prisma.user.findUnique({ where: { id } }); });ts
Sowohl <Header> als auch <Dashboard> können getUser(id) aufrufen — die Datenbankabfrage wird nur einmal ausgeführt.
Partial Prerendering (PPR)
PPR ist die bedeutendste Architekturänderung in Next.js 15. Sie erlaubt es, eine einzelne Route teilweise statisch zu machen:
// next.config.ts export default { experimental: { ppr: 'incremental', }, }; // app/[locale]/page.tsx export const experimental_ppr = true; export default function HomePage() { return ( <> <HeroSection /> {/* statische Hülle — sofort vom CDN */} <Suspense fallback={<ProjectsSkeleton />}> <FeaturedProjects /> {/* dynamisch — nach der Hülle gestreamt */} </Suspense> </> ); }ts
Die HTML-Hülle mit <HeroSection> wird am Edge gecacht. Die dynamischen Teile streamen hinter einer Suspense-Grenze nach. Der Nutzer sieht Inhalt in unter 100 ms; personalisierte Daten kommen kurz danach.
Strategie zur Cache-Invalidierung
Next.js 15 hat drei Cache-Ebenen. Wissen Sie, welche Sie invalidieren:
import { revalidatePath, revalidateTag } from 'next/cache'; // Eine bestimmte URL invalidieren (z. B. nach Veröffentlichung eines Blogposts) await revalidatePath('/blog/[slug]', 'page'); // Alle mit 'projects' getaggten Seiten invalidieren (bevorzugt für datengetriebene Invalidierung) await revalidateTag('projects'); // Ein Fetch taggen, damit es per Tag invalidiert werden kann const data = await fetch('/api/projects', { next: { tags: ['projects'], revalidate: 300 }, });ts
Der revalidateTag-Ansatz skaliert besser als revalidatePath, weil Sie Daten auf Fetch-Ebene taggen, nicht auf Routen-Ebene. Ein API-Aufruf invalidiert jede Seite, die diese Daten verwendet hat.
Middleware für i18n und Auth
Middleware läuft am Edge, bevor irgendeine Seite rendert. Halten Sie sie minimal — sie läuft bei jedem Request:
// middleware.ts import { NextRequest, NextResponse } from 'next/server'; import createIntlMiddleware from 'next-intl/middleware'; import { routing } from '@/i18n/routing'; const intlMiddleware = createIntlMiddleware(routing); export function middleware(request: NextRequest) { // Auth-Prüfung für geschützte Routen const isProtected = request.nextUrl.pathname.startsWith('/dashboard'); if (isProtected) { const session = request.cookies.get('next-auth.session-token'); if (!session) { return NextResponse.redirect(new URL('/login', request.url)); } } return intlMiddleware(request); }ts
Vermeiden Sie Datenbankaufrufe in der Middleware. Prüfen Sie nur Cookies oder JWT-Claims — alles Schwerere gehört in die Server Component der Seite.
Checkliste fürs Produktions-Deployment
Vor dem Push zu Vercel:
# 1. Type-Check npx tsc --noEmit # 2. Lint npm run lint # 3. Lokaler Build, um Fehler in der statischen Generierung zu finden npm run build # 4. Bundle-Größe prüfen ANALYZE=true npm run buildbash
Achten Sie auf:
- Server Components, die versehentlich client-only Pakete importieren (
window,localStorage) cookies()oderheaders()außerhalb eines dynamischen Kontexts aufgerufen — das nimmt die gesamte Route aus der statischen Generierung- Bilder ohne explizite
width/height, die Layout-Shift verursachen
Fazit
Die Stärke des App Routers entsteht aus dem Verständnis der Grenze zwischen statisch und dynamisch — und daraus, sie bewusst zu setzen. Standardmäßig statisch, Suspense-Grenzen für dynamische Abschnitte, getaggte Fetches für granulare Invalidierung und eine schlanke Middleware. Diese vier Entscheidungen decken 90 % der Performance-Probleme in der Produktion ab, bevor sie entstehen.
Sie arbeiten an etwas Ähnlichem?
Ich baue schnelle Websites und Buchungssysteme für kleine Unternehmen in ganz Europa — freiberuflich, remote. Antwort innerhalb von 24 Stunden.
Kontakt aufnehmen