Next.js Best Practices
Prinzipien für die Entwicklung mit dem Next.js App Router.
1. Server- vs. Client-Komponenten
Entscheidungsbaum
Braucht es...?
│
├── useState, useEffect, Event-Handler
│ └── Client-Komponente ('use client')
│
├── Direkter Datenabruf, keine Interaktivität
│ └── Server-Komponente (Standard)
│
└── Beides?
└── Aufteilen: Server-Elternkomponente + Client-Kindkomponente
Standardmäßig
| Typ | Verwendung |
|---|
| Server | Datenabruf, Layout, statischer Inhalt |
| Client | Formulare, Buttons, interaktive UI |
2. Datenabrufmuster
Fetch-Strategie
| Muster | Verwendung |
|---|
| Standard | Statisch (beim Build gecached) |
| Revalidate | ISR (zeitbasierte Aktualisierung) |
| No-store | Dynamisch (bei jeder Anfrage) |
Datenfluss
| Quelle | Muster |
|---|
| Datenbank | Datenabruf in Server-Komponente |
| API | fetch mit Caching |
| Benutzereingabe | Client-Status + Server-Aktion |
3. Routing-Prinzipien
Dateikonventionen
| Datei | Zweck |
|---|
page.tsx | Routen-UI |
layout.tsx | Gemeinsames Layout |
loading.tsx | Ladezustand |
error.tsx | Fehlergrenze |
not-found.tsx | 404-Seite |
Routenorganisation
| Muster | Verwendung |
|---|
Routengruppen (name) | Organisation ohne URL |
Parallele Routen @slot | Mehrere Seiten auf gleicher Ebene |
Abfangen (.) | Modale Overlays |
4. API-Routen
Routen-Handler
| Methode | Verwendung |
|---|
| GET | Daten lesen |
| POST | Daten erstellen |
| PUT/PATCH | Daten aktualisieren |
| DELETE | Daten löschen |
Best Practices
- Eingaben mit Zod validieren
- Korrekte Statuscodes zurückgeben
- Fehler ordentlich behandeln
- Wenn möglich Edge-Runtime verwenden
5. Performance-Prinzipien
Bildoptimierung
- next/image-Komponente verwenden
- Priorität für Inhalte oberhalb der Falz setzen
- Blur-Placeholder bereitstellen
- Responsive Größen verwenden
Bundle-Optimierung
- Dynamische Imports für schwere Komponenten
- Routenbasiertes Code-Splitting (automatisch)
- Mit Bundle-Analyzer analysieren
6. Metadaten
Statisch vs. Dynamisch
| Typ | Verwendung |
|---|
| Static export | Feste Metadaten |
| generateMetadata | Dynamisch pro Route |
Essentielle Tags
- title (50-60 Zeichen)
- description (150-160 Zeichen)
- Open Graph-Bilder
- Kanonische URL
7. Caching-Strategie
Cache-Ebenen
| Ebene | Kontrolle |
|---|
| Anfrage | fetch-Optionen |
| Daten | revalidate/tags |
| Vollständige Route | Routenkonfiguration |
Aktualisierung
| Methode | Verwendung |
|---|
| Zeitbasiert | revalidate: 60 |
| On-Demand | revalidatePath/Tag |
| Kein Cache | no-store |
8. Server-Aktionen
Anwendungsfälle
- Formularübermittlungen
- Datenänderungen
- Revalidierungsauslöser
Best Practices
- Mit 'use server' markieren
- Alle Eingaben validieren
- Typisierte Antworten zurückgeben
- Fehler behandeln
9. Anti-Patterns
| ❌ Nicht tun | ✅ Besser so |
|---|
| 'use client' überall | Standardmäßig Server |
| Datenabruf in Client-Komponenten | Datenabruf im Server |
| Ladezustände überspringen | loading.tsx verwenden |
| Fehlergrenzen ignorieren | error.tsx verwenden |
| Große Client-Bundles | Dynamische Imports |
10. Projektstruktur
app/
├── (marketing)/ # Routengruppe
│ └── page.tsx
├── (dashboard)/
│ ├── layout.tsx # Dashboard-Layout
│ └── page.tsx
├── api/
│ └── [resource]/
│ └── route.ts
└── components/
└── ui/
Denk dran: Server-Komponenten sind aus gutem Grund der Standard. Fang dort an, füg Client-Komponenten nur hinzu, wenn nötig.