Design wechseln

Next.js App Router: Häufige Fallstricke und Lösungen – 8 praxiserprobte Tipps

Easton editorial illustration: route-map drafting table

Als ich Next.js App Router zum ersten Mal nutzte, bin ich richtig reingefallen.

Ende letzten Jahres musste unser Firmenprojekt auf Next.js 15 upgraden. Da wir sowieso upgraden, migrierten wir gleich vom Pages Router zum App Router – die Docs versprachen „schnellere Performance“, „bessere Developer Experience“ und eine „revolutionäre Server-Components-Architektur“. Am ersten Tag stapelten sich die merkwürdigen Probleme.

Daten aktualisierten sich nicht, Seiten drehten sich im Kreis, Caching schien wirkungslos, Server Component und Client Component verwechselt … Am schlimmsten: Drei Stunden Debug für einen Bug, weil in error.tsx 'use client' fehlte. Da wollte man am liebsten weinen.

Wir haben im Team eine Umfrage gemacht: Etwa 80 % der Probleme wiederholten sich. Diese Fallstricke habe ich zusammengetragen – damit Sie weniger Umwege machen.

Keine Theorie – nur Praxis. Pro Problem: warum es passiert, wie wir es entdeckt haben, wie wir es gelöst haben. Danach wissen Sie, wo App Router typischerweise stolpert.

Fallstricke beim Datenabruf

Fallstrick 1: Redundanter Client-seitiger Datenabruf

Szenario:

Ich wollte Benutzerinfos auf einer Seite anzeigen und schrieb aus Gewohnheit:

// app/profile/page.tsx
'use client'
import { useEffect, useState } from 'react'

export default function ProfilePage() {
  const [user, setUser] = useState(null)

  useEffect(() => {
    fetch('/api/user')
      .then(res => res.json())
      .then(data => setUser(data))
  }, [])

  if (!user) return <div>Loading...</div>
  return <div>Hello, {user.name}</div>
}

Sieht harmlos aus – ist aber ein klassisches Anti-Pattern. Daten fließen: Datenbank → API Route → Client, ein unnötiger Netzwerk-Hop.

Warum passiert das:

Im Pages-Router-Zeitalter holten wir Daten per useEffect im Client. App-Router-Server Components holen Daten direkt auf dem Server – ohne extra API-Schicht.

Der richtige Weg:

// app/profile/page.tsx (Standard: Server Component)
import { db } from '@/lib/db'

export default async function ProfilePage() {
  const user = await db.user.findFirst()

  return <div>Hello, {user.name}</div>
}

Sofort spürbar:

  • Ein API-Request weniger
  • Server-zu-Datenbank oft unter 10 ms (Client-zu-Server 100 ms+)
  • Kleineres Client-JavaScript-Bundle

Merksatz:

Was in einer Server Component abrufbar ist, nicht im Client fetchen. Client-Abruf nur bei Interaktion (Suche, Filter, Echtzeit-Updates).

Fallstrick 2: Standard-Caching bei Route Handlers

Szenario:

Eine API liefert die aktuelle Uhrzeit – egal wie oft ich refreshe, die Zeit bleibt gleich:

// app/api/time/route.ts
export async function GET() {
  return Response.json({ time: new Date().toISOString() })
}

Zehnmal refreshen, immer derselbe Zeitstempel.

Warum passiert das:

Next.js cached GET-Route-Handler standardmäßig – gut für statische Daten, schlecht für dynamische.

Lösung 1: Explizit dynamisch markieren

// app/api/time/route.ts
export const dynamic = 'force-dynamic'

export async function GET() {
  return Response.json({ time: new Date().toISOString() })
}

Lösung 2: Next.js 15

Ab Next.js 15 sind GET-Route-Handler standardmäßig nicht gecacht. Bei Next.js 14:

// app/api/time/route.ts
export async function GET() {
  return Response.json(
    { time: new Date().toISOString() },
    { headers: { 'Cache-Control': 'no-store' } }
  )
}

Meine Regel heute:

  • Statische Daten: export const revalidate = 3600
  • Dynamische Daten: export const dynamic = 'force-dynamic'

Nicht auf Defaults vertrauen – Absicht klar machen.

Fallstrick 3: Revalidierung nach Datenänderung vergessen

Szenario:

Todo-App: Nach neuem Task aktualisiert sich die Liste nicht:

// app/todos/page.tsx
export default async function TodosPage() {
  const todos = await db.todo.findMany()
  return <TodoList todos={todos} />
}

// app/actions.ts
'use server'
export async function addTodo(text: string) {
  await db.todo.create({ data: { text } })
  // Revalidierung vergessen!
}

Nach Submit alte Daten – manueller Refresh nötig.

Warum passiert das:

App-Router-Caching ist aggressiv. Ohne explizites Signal bleibt die Seite alt.

Der richtige Weg:

// app/actions.ts
'use server'
import { revalidatePath } from 'next/cache'

export async function addTodo(text: string) {
  await db.todo.create({ data: { text } })
  revalidatePath('/todos')
}

Fortgeschritten:

Mehrere Seiten mit Todo-Liste → revalidateTag:

// app/todos/page.tsx
export default async function TodosPage() {
  const todos = await fetch('http://localhost:3000/api/todos', {
    next: { tags: ['todos'] }
  })
  return <TodoList todos={todos} />
}

// app/actions.ts
'use server'
import { revalidateTag } from 'next/cache'

export async function addTodo(text: string) {
  await db.todo.create({ data: { text } })
  revalidateTag('todos')
}

Merksatz:

Datenänderung: Schreiben → revalidatePath / revalidateTag → Redirect (optional)

Server Components und Client Components

Fallstrick 4: Context in Server Components

Szenario:

ThemeProvider für globalen Theme-Wechsel:

// app/providers.tsx
import { createContext } from 'react'

export const ThemeContext = createContext('light')

export function Providers({ children }) {
  return (
    <ThemeContext.Provider value="dark">
      {children}
    </ThemeContext.Provider>
  )
}

// app/layout.tsx
export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <Providers>{children}</Providers>
      </body>
    </html>
  )
}

Fehler: You're importing a component that needs createContext. This only works in a Client Component.

Warum passiert das:

Server Components unterstützen kein React Context – kein clientseitiges State-Management auf dem Server.

Der richtige Weg:

// app/providers.tsx
'use client'

import { createContext, useState } from 'react'

export const ThemeContext = createContext('light')

export function Providers({ children }: { children: React.ReactNode }) {
  const [theme, setTheme] = useState('light')

  return (
    <ThemeContext.Provider value={{ theme, setTheme }}>
      {children}
    </ThemeContext.Provider>
  )
}

// app/layout.tsx (Server Component)
import { Providers } from './providers'

export default function RootLayout({ children }) {
  return (
    <html>
      <body>
        <Providers>{children}</Providers>
      </body>
    </html>
  )
}

Mein Fehler:

'use client' zuerst in layout.tsx – ganze App wurde Client Component, Server-Vorteile weg. Nur Provider als Client Component, Layout Server Component.

Fallstrick 5: SSR-Missverständnis bei Client Components

Szenario:

localStorage in Client Component – lokal ok, deployed: localStorage is not defined.

// app/components/user-info.tsx
'use client'

export default function UserInfo() {
  const user = JSON.parse(localStorage.getItem('user') || '{}')
  return <div>{user.name}</div>
}

Warum passiert das:

'use client' heißt nicht „nur Client“. Client Components werden auch serverseitig vorgerendert (SSR). localStorage gibt es nur im Browser.

Lösung 1: Umgebung prüfen

'use client'
import { useEffect, useState } from 'react'

export default function UserInfo() {
  const [user, setUser] = useState(null)

  useEffect(() => {
    const userData = JSON.parse(localStorage.getItem('user') || '{}')
    setUser(userData)
  }, [])

  if (!user) return null
  return <div>{user.name}</div>
}

Lösung 2: Bedingte Prüfung

'use client'

export default function UserInfo() {
  const user = typeof window !== 'undefined'
    ? JSON.parse(localStorage.getItem('user') || '{}')
    : null

  if (!user) return null
  return <div>{user.name}</div>
}

Merksatz:

Client Component = interaktiv im Client, aber SSR bleibt. Browser-APIs (localStorage, window, document) in useEffect oder mit Umgebungsprüfung.

Fallstrick 6: ‘use client’ überall

Szenario:

Bei Fehlern reflexartig 'use client' – am Ende fast alles Client Components.

Warum passiert das:

Manchmal ist es Code-Organisation, nicht wirklich Client-Bedarf.

Anti-Beispiel:

// app/dashboard/page.tsx
'use client'

import { useState } from 'react'

export default function Dashboard() {
  const [count, setCount] = useState(0)

  return (
    <div>
      <Header />
      <Stats />
      <Counter count={count} setCount={setCount} />
    </div>
  )
}

Ganze Seite Client – Stats-Daten müssen clientseitig gefetcht werden.

Richtig:

// app/dashboard/page.tsx (Server Component)
import { db } from '@/lib/db'
import { Counter } from './counter'

export default async function Dashboard() {
  const stats = await db.stats.findFirst()

  return (
    <div>
      <Header />
      <Stats data={stats} />
      <Counter />
    </div>
  )
}

// app/dashboard/counter.tsx
'use client'

import { useState } from 'react'

export function Counter() {
  const [count, setCount] = useState(0)
  return <button onClick={() => setCount(count + 1)}>{count}</button>
}

Drei Kriterien für ‘use client’:

  1. React Hooks (useState, useEffect, useContext …)
  2. Browser-Events (onClick, onChange …)
  3. Browser-APIs (localStorage, window …)

Sonst Server Component behalten.

Fallstricke beim Caching

Fallstrick 7: Client Router Cache

Szenario:

Artikel auf /posts/1 bearbeitet, gespeichert, Redirect zu /posts – Titel in der Liste noch alt. Erst nach manuellem Refresh sichtbar.

Warum passiert das:

App Router hat einen Client Router Cache – besuchte Seiten werden clientseitig gecacht, auch wenn sich Daten geändert haben.

Lösung 1: Beim Navigieren refreshen

// app/posts/[id]/edit/page.tsx
'use server'
import { redirect } from 'next/navigation'
import { revalidatePath } from 'next/cache'

export async function updatePost(id: string, title: string) {
  await db.post.update({ where: { id }, data: { title } })

  revalidatePath('/posts')
  revalidatePath(`/posts/${id}`)

  redirect('/posts')
}

Lösung 2: router.refresh()

'use client'
import { useRouter } from 'next/navigation'

export function EditForm() {
  const router = useRouter()

  async function handleSubmit() {
    await updatePost(...)
    router.refresh()
    router.push('/posts')
  }
}

Next.js 15:

Client Router Cache ist standardmäßig deaktiviert. Bei Next.js 14 manuell handhaben.

Fallstrick 8: revalidate wirkt nicht

Szenario:

revalidate = 60 gesetzt – Daten ändern sich trotzdem nicht:

// app/news/page.tsx
export const revalidate = 60

export default async function NewsPage() {
  const news = await fetch('https://api.example.com/news')
  return <NewsList news={news} />
}

Nach Deploy den ganzen Tag alte News.

Warum passiert das:

revalidate gilt nur in Productionnpm run dev cached nicht. Außerdem nur bei statisch generierten Seiten; bei Dynamic Rendering ignoriert.

Debug-Schritte:

  1. Production bestätigen:
npm run build
npm run start
  1. Seitentyp prüfen:

Build-Ausgabe: ○ Static oder ● SSG. Bei λ Dynamic ist die Seite dynamisch.

  1. Ursache für Dynamic Rendering:

Häufig:

  • cookies() oder headers()
  • searchParams
  • Route Handler ohne explizites revalidate

Lösung:

// app/news/page.tsx
export const revalidate = 60

export default async function NewsPage() {
  const news = await fetch('https://api.example.com/news', {
    next: { revalidate: 60 }
  })

  return <NewsList news={news} />
}

Meine Regel heute:

  • Rein statisch: generateStaticParams + revalidate
  • Dynamische Parameter: ISR
  • Echtzeitdaten: dynamic = 'force-dynamic', kein revalidate

Fallstricke bei der Fehlerbehandlung

Fallstrick 9: ‘use client’ in error.tsx vergessen

Szenario:

error.tsx erstellt – Fehler: ReactServerComponentsError: Client Component must be used in a Client Component boundary.

// app/error.tsx (falsch)
export default function Error({ error, reset }) {
  return (
    <div>
      <h2>Ein Fehler ist aufgetreten!</h2>
      <button onClick={reset}>Erneut versuchen</button>
    </div>
  )
}

Warum passiert das:

error.tsx braucht Reacts Error Boundary – funktioniert nur clientseitig.

Richtig:

// app/error.tsx
'use client'

export default function Error({
  error,
  reset,
}: {
  error: Error & { digest?: string }
  reset: () => void
}) {
  return (
    <div>
      <h2>Ein Fehler ist aufgetreten!</h2>
      <p>{error.message}</p>
      <button onClick={reset}>Erneut versuchen</button>
    </div>
  )
}

Merksatz:

Bei error.tsx, loading.tsx, not-found.tsx muss nur error.tsx Client Component sein.

Fallstrick 10: redirect in try/catch

Szenario:

Server Action mit Validierung – redirect wird vom catch gefangen, Navigation scheitert.

// app/actions.ts (falsch)
'use server'
import { redirect } from 'next/navigation'

export async function createUser(data: FormData) {
  try {
    const user = await db.user.create({ data })
    redirect(`/users/${user.id}`)
  } catch (error) {
    console.error(error)
    return { error: 'Failed to create user' }
  }
}

Warum passiert das:

redirect() wirft einen speziellen Fehler für Next.js. Im try/catch fängt Ihr catch ihn ab.

Richtig:

// app/actions.ts
'use server'
import { redirect } from 'next/navigation'

export async function createUser(data: FormData) {
  try {
    const user = await db.user.create({ data })
    return { success: true, userId: user.id }
  } catch (error) {
    console.error(error)
    return { error: 'Failed to create user' }
  }
}

export async function handleSubmit(data: FormData) {
  const result = await createUser(data)
  if (result.success) {
    redirect(`/users/${result.userId}`)
  }
}

Alternativ:

'use server'
import { redirect } from 'next/navigation'

export async function createUser(data: FormData) {
  try {
    const user = await db.user.create({ data })
  } catch (error) {
    console.error(error)
    return { error: 'Failed to create user' }
  }

  redirect(`/users/${user.id}`)
}

Fallstricke bei der Migration

Fallstrick 11: 404.js und 500.js funktionieren nicht

Szenario:

Beim Migrieren pages/404.js und pages/500.js behalten – greifen nicht.

Warum passiert das:

App Router hat neues Error Handling:

  • 404.jsnot-found.tsx
  • 500.jserror.tsx
  • Globale Fehler → global-error.tsx

Richtig:

// app/not-found.tsx
export default function NotFound() {
  return (
    <div>
      <h2>404 – Seite nicht gefunden</h2>
      <Link href="/">Zur Startseite</Link>
    </div>
  )
}

// app/error.tsx
'use client'

export default function Error({ error, reset }) {
  return (
    <div>
      <h2>500 – Serverfehler</h2>
      <p>{error.message}</p>
      <button onClick={reset}>Erneut versuchen</button>
    </div>
  )
}

// app/global-error.tsx
'use client'

export default function GlobalError({ error, reset }) {
  return (
    <html>
      <body>
        <h2>Globaler Fehler</h2>
        <p>{error.message}</p>
        <button onClick={reset}>Erneut versuchen</button>
      </body>
    </html>
  )
}

Fallstrick 12: next-seo funktioniert nicht

Szenario:

Projekt nutzt next-seo – nach Migration zum App Router wirkungslos.

// pages/blog/[slug].tsx (Pages Router)
import { NextSeo } from 'next-seo'

export default function BlogPost({ post }) {
  return (
    <>
      <NextSeo
        title={post.title}
        description={post.excerpt}
        openGraph={{
          title: post.title,
          description: post.excerpt,
          images: [{ url: post.coverImage }],
        }}
      />
      <article>{post.content}</article>
    </>
  )
}

Warum passiert das:

App Router hat natives generateMetadatanext-seo ist deprecated.

Migration:

// app/blog/[slug]/page.tsx
import { Metadata } from 'next'

export async function generateMetadata({ params }): Promise<Metadata> {
  const post = await getPost(params.slug)

  return {
    title: post.title,
    description: post.excerpt,
    openGraph: {
      title: post.title,
      description: post.excerpt,
      images: [post.coverImage],
    },
  }
}

export default async function BlogPost({ params }) {
  const post = await getPost(params.slug)
  return <article>{post.content}</article>
}

Vorteile:

  1. Typsicher (TypeScript)
  2. async/await (direkt DB-Abfrage)
  3. Bessere Performance (Server-Rendering)

Performance-Optimierung

Unnötige Client Components vermeiden

Problem: Ganze Seite wird Client Component – Server-Vorteile weg.

Lösung: „Leaf-Node Client Components“:

// ❌ Schlecht
// app/dashboard/page.tsx
'use client'
export default function Dashboard() {
  return (
    <div>
      <Header />
      <Sidebar />
      <MainContent />
      <Footer />
    </div>
  )
}

// ✅ Gut
// app/dashboard/page.tsx (Server Component)
import { Header } from './header'
import { Sidebar } from './sidebar'
import { MainContent } from './main-content'
import { Footer } from './footer'

export default function Dashboard() {
  return (
    <div>
      <Header />
      <Sidebar />
      <MainContent />
      <Footer />
    </div>
  )
}

// app/dashboard/sidebar.tsx
'use client'
export function Sidebar() {
  const [collapsed, setCollapsed] = useState(false)
  return <aside>...</aside>
}

Suspense-Grenzen optimieren

Problem: Ganze Seite wartet auf langsame Daten – langer weißer Bildschirm.

Lösung:

// app/dashboard/page.tsx
import { Suspense } from 'react'
import { FastComponent } from './fast'
import { SlowComponent } from './slow'

export default function Dashboard() {
  return (
    <div>
      <FastComponent />
      <Suspense fallback={<div>Laden …</div>}>
        <SlowComponent />
      </Suspense>
    </div>
  )
}

Parallelen Datenabruf nutzen

Problem: Seriell – Gesamtzeit = Summe aller Requests.

Lösung:

// ❌ Seriell (langsam)
export default async function Page() {
  const user = await getUser()
  const posts = await getPosts()
  const comments = await getComments()
}

// ✅ Parallel (schnell)
export default async function Page() {
  const [user, posts, comments] = await Promise.all([
    getUser(),
    getPosts(),
    getComments(),
  ])
}

Fallstricke in der Entwicklungsumgebung

Fallstrick 13: Connection Leaks durch Hot Reload

Szenario:

Dev-Server läuft eine Weile – DB-Fehler: too many connections.

Warum passiert das:

Hot Reload führt Modulcode neu aus. Globale DB-Verbindungen werden bei jedem Reload neu erstellt, alte nicht geschlossen.

Lösung:

// lib/db.ts
import { PrismaClient } from '@prisma/client'

const globalForPrisma = global as unknown as { prisma: PrismaClient }

export const prisma =
  globalForPrisma.prisma ||
  new PrismaClient({
    log: ['query'],
  })

if (process.env.NODE_ENV !== 'production') {
  globalForPrisma.prisma = prisma
}

In der Entwicklung wird dieselbe Prisma-Instanz wiederverwendet.

Fallstrick 14: Dev-Server wird langsamer

Szenario:

npm run dev nach 30 Minuten – Hot Reload extrem langsam, manchmal Einfrieren.

Warum passiert das:

App-Router-Dev-Server frisst viel Speicher bei vielen Seiten, besonders dynamischen Routen.

Kurzfristig:

  1. Dev-Server neu starten
  2. File-Watching reduzieren:
// next.config.js
module.exports = {
  webpack: (config) => {
    config.watchOptions = {
      poll: 1000,
      aggregateTimeout: 300,
      ignored: /node_modules/,
    }
    return config
  },
}

Langfristig:

Next.js 15 + Turbopack:

npm run dev --turbo

Turbopack: Hot Reload 10× schneller, auch bei großen Projekten flüssig.

Zusammenfassung: Checkliste

Nach all diesen Fallstricken – schnelle Checkliste für 90 % weniger Probleme:

Datenabruf

  • ☑ Daten in Server Component holen, nicht Client + useEffect
  • ☑ Route Handler: dynamic = 'force-dynamic' oder revalidate explizit setzen
  • ☑ Nach Datenänderung revalidatePath / revalidateTag

Server/Client Components

  • ☑ Provider = Client Component, Layout = Server Component
  • ☑ Browser-APIs (localStorage, window) in useEffect oder mit Umgebungsprüfung
  • 'use client' nur wo wirklich nötig – nicht die ganze Seite

Fehlerbehandlung

  • error.tsx braucht 'use client'
  • redirect nicht in try/catch
  • ☑ Root-Layout-Fehler: global-error.tsx, nicht error.tsx

Caching

  • ☑ Next.js 15 für sinnvollere Cache-Defaults
  • ☑ revalidate nur in Production – in Dev nicht darauf verlassen
  • ☑ Dynamische Seiten: dynamic = 'force-dynamic', kein revalidate

Migration

  • 404.jsnot-found.tsx, 500.jserror.tsx
  • next-seogenerateMetadata
  • getServerSideProps → Server Component direkt fetchen
  • useRouter von next/routernext/navigation

Performance

  • ☑ Suspense für schnelle/langsame Teile
  • ☑ Paralleler Datenabruf (Promise.all)
  • ☑ DB-Verbindung in Dev als Singleton
  • ☑ Turbopack (npm run dev --turbo)

Abschluss

Ehrlich gesagt: App Router hat eine Lernkurve, anfangs stolpert man. Wer die Muster kennt, arbeitet deutlich effizienter.

Mein Vorgehen heute:

  1. Datenfluss zuerst: Server-Rendering oder Client-Interaktion?
  2. Bei Problemen Build-Ausgabe prüfen: Static oder Dynamic – warum?
  3. DevTools nutzen: Network für Requests, Console für Stack Traces
  4. Nicht auf Defaults vertrauen: Caching, Rendering, Revalidierung explizit machen

Wichtig: Nicht abschrecken lassen – ausprobieren. Jeder Fallstrick bleibt hängen, wenn man ihn einmal erlebt hat. Die Next.js-Docs sind ausführlich – bei Problemen zuerst dort nachschlagen.

Hat Ihnen der Artikel geholfen? Teilen Sie ihn mit anderen, die gerade stolpern. Neue Fallstricke? Gerne in die Kommentare – ich ergänze die Liste laufend.

Weniger Umwege auf dem App-Router-Weg – und mehr eleganter Code (statt Bugs)!

FAQ

Wie unterscheide ich Server Component und Client Component?
Server Component (Standard):
• Läuft auf dem Server, wird nicht an den Client gesendet
• Keine useState-, useEffect-Hooks usw.
• Keine Browser-APIs

Client Component (muss markiert werden):
• Mit der 'use client'-Direktive markiert
• Alle React-Hooks nutzbar
• Browser-APIs nutzbar

Faustregel: Bei Interaktivität oder Browser-APIs → Client Component
Warum aktualisieren sich die Daten nicht?
Next.js fetch ist standardmäßig gecacht.

Lösungen:
• cache: 'no-store' setzen (bei jedem Request frische Daten)
• next: { revalidate: 60 } nutzen (nach 60 Sekunden neu validieren)
• router.refresh() in Client Component für erzwungenes Refresh

Prüfung: Build-Ausgabe ansehen – Dynamic oder Static?
Was tun, wenn die Seite endlos lädt?
Mögliche Ursachen:
• async Server Component ohne korrekten Loading-State
• Suspense-Grenze falsch konfiguriert
• Datenabruf fehlgeschlagen, aber kein Error Handling

Lösungen:
• loading.tsx hinzufügen
• Asynchrone Komponenten mit Suspense umschließen
• error.tsx für Fehlerbehandlung
Warum funktioniert error.tsx nicht?
error.tsx muss eine Client Component sein.

'use client'-Direktive erforderlich:
'use client'

export default function Error({ error, reset }) {
return <div>Fehler: {error.message}</div>
}

Hinweis: error.tsx fängt nur Fehler in Kindkomponenten, nicht eigene Fehler
Wie migriere ich vom Pages Router zum App Router?
Hauptänderungen:
• getServerSideProps → async Server Component
• getStaticProps → statische Generierung (Standard)
• next/router → next/navigation
• _app.js → layout.tsx
• _document.js → entfällt (layout.tsx übernimmt)

Empfehlung: Mit 1–2 Seiten pilotieren, dann ausrollen
Wie funktioniert das Caching?
Next.js Cache-Ebenen:
• Request Memoization: Gleicher fetch in einem Request nur einmal
• Data Cache: fetch-Antworten werden gecacht
• Full Route Cache: Ganze Seite gecacht (statische Generierung)
• Router Cache: Client-seitiger Routen-Cache

Steuerung: cache: 'no-store', next: { revalidate } usw.
Wie debugge ich App-Router-Probleme?
Debug-Methoden:
• Build-Ausgabe (npm run build) – Seitentyp prüfen
• DevTools Network-Panel für Requests
• Console auf Fehlermeldungen prüfen
• Next.js-Terminalausgabe ansehen

Häufige Probleme:
• Static statt Dynamic → fetch-Cache prüfen
• Daten aktualisieren nicht → Cache/revalidate prüfen
• Seite lädt endlos → loading.tsx und Suspense prüfen

13 Min. Lesezeit · Veröffentlicht am: 25. Dez. 2025 · Aktualisiert am: 14. Juli 2026

Ähnliche Beiträge

Kommentare

Melde dich mit GitHub an, um einen Kommentar zu hinterlassen

Easton BlogEaston Blog