BackZurück zum Blog

Next.js 15.1

Next.js 15.1 führt Unterstützung für React 19 (stabil) ein, verbessert die Fehlerdiagnose, bietet neue experimentelle Autorisierungs-APIs und mehr.

Next.js 15.1 bringt Kern-Upgrades, neue APIs und Verbesserungen für die Developer Experience. Die wichtigsten Neuerungen sind:

Aktualisieren Sie jetzt oder starten Sie mit:

Terminal
# Automatisches Upgrade mit der CLI
npx @next/codemod@canary upgrade latest
 
# ...oder manuelles Upgrade
npm install next@latest react@latest react-dom@latest
 
# ...oder neues Projekt erstellen
npx create-next-app@latest

React 19 (stabil)

Next.js 15.1 unterstützt nun vollständig React 19:

  • Für den Pages Router: Sie können React 19 stabil nutzen, ohne Release Candidate oder Canary-Versionen zu benötigen, bei gleichzeitiger Unterstützung für React 18.
  • Für den App Router: Wir werden weiterhin integrierte React Canary-Versionen bereitstellen. Diese enthalten alle stabilen Änderungen von React 19 sowie neuere Features, die in Frameworks validiert werden, bevor eine neue React-Version erscheint.

Seit dem Release von Next.js 15 war eine bedeutende Ergänzung in React 19 das "Sibling Pre-Warming".

Für einen umfassenden Überblick über die Neuerungen in React 19 lesen Sie bitte den offiziellen React 19 Blog-Post.

Verbesserte Fehlerdiagnose

Wir haben die Fehlerdiagnose in Next.js verbessert, sodass Sie Probleme schneller lokalisieren können – egal ob im Terminal, Browser oder angeschlossenen Debuggern. Diese Verbesserungen gelten sowohl für Webpack als auch für Turbopack (jetzt stabil mit Next.js 15).

Verbesserungen bei Source Maps

Fehler lassen sich jetzt leichter zurückverfolgen dank verbesserter Nutzung von Source Maps. Wir haben die ignoreList-Eigenschaft von Source Maps implementiert, die es Next.js ermöglicht, Stack Frames für externe Abhängigkeiten auszublenden, sodass Ihr Anwendungscode im Fokus bleibt.

Für etwas genauere Source Mapping von Methodennamen empfehlen wir die Nutzung von Turbopack (jetzt stabil), das eine verbesserte Handhabung und Erkennung von Source Maps gegenüber Webpack bietet.

Für Bibliotheksautoren: Wir empfehlen, die ignoreList-Eigenschaft in Source Maps zu befüllen, wenn Sie Ihre Bibliotheken veröffentlichen, insbesondere wenn sie als extern konfiguriert sind (z.B. in der serverExternalPackages-Konfiguration).

Zusammengefasste Stack Frames

Wir haben die Logik für das Zusammenfassen von Stack Frames verbessert, um die relevantesten Teile Ihres Codes hervorzuheben.

  • Im Browser und Error Overlay: Stack Frames von Drittanbieter-Abhängigkeiten sind standardmäßig ausgeblendet, um den Fokus auf Ihren Anwendungscode zu legen. Sie können die verborgenen Frames durch Klicken auf "Show ignored frames" in den DevTools oder im Overlay einblenden.
  • Im Terminal: Frames von Drittanbieter-Abhängigkeiten sind ebenfalls standardmäßig zusammengefasst, und die Fehlerformatierung orientiert sich nun an der Browser-Ausgabe für eine konsistente Debugging-Erfahrung. Fehler werden im Browser wiedergegeben, um sicherzustellen, dass Sie während der Entwicklung keine wichtigen Informationen verpassen, wenn Sie den gesamten Stack Trace benötigen.

Verbessertes Profiling

Ignorierte Stack Frames werden auch von integrierten Browser-Profilern erkannt. Dies erleichtert das Profiling Ihrer Anwendung, sodass Sie langsame Funktionen in Ihrem Code leichter identifizieren können, ohne durch externe Bibliotheken abgelenkt zu werden.

Verbesserungen mit dem Edge Runtime

Bei Nutzung des Edge Runtimes werden Fehler nun konsistent in allen Entwicklungsumgebungen angezeigt, was ein nahtloses Debugging ermöglicht. Zuvor enthielten protokollierte Fehler nur die Nachricht, nicht aber den Stack.

Vorher und nachher

Terminal Vorher:

Terminal
 app/page.tsx (6:11) @ eval
 Error: boom
    at eval (./app/page.tsx:12:15)
    at Page (./app/page.tsx:11:74)
    at AsyncLocalStorage.run (node:async_hooks:346:14)
    at stringify (<anonymous>)
    at AsyncLocalStorage.run (node:async_hooks:346:14)
    at AsyncResource.runInAsyncScope (node:async_hooks:206:9)
digest: "380744807"
  4 | export default function Page() {
  5 |   const throwError = myCallback(() => {
> 6 |     throw new Error('boom')
    |           ^
  7 |   }, [])
  8 |
  9 |   throwError()
 GET / 500 in 2354ms

Terminal Nachher:

Terminal
 Error: boom
    at eval (app/page.tsx:6:10)
    at Page (app/page.tsx:5:32)
  4 | export default function Page() {
  5 |   const throwError = myCallback(() => {
> 6 |     throw new Error('boom')
    |          ^
  7 |   }, [])
  8 |
  9 |   throwError() {
  digest: '225828171'
}

Error Overlay Vorher

Ein Beispiel für das Next.js Error Overlay vor Version 15.1

Error Overlay Nachher

Ein Beispiel für das Next.js Error Overlay nach Version 15.1

Diese Verbesserungen machen Fehler klarer und intuitiver, sodass Sie mehr Zeit mit dem Aufbau Ihrer Anwendung verbringen können und weniger mit dem Debugging.

Wir freuen uns auch, die Einführung eines neu gestalteten UI für das Error Overlay in kommenden Releases ankündigen zu können.

after (stabil)

Die after()-API ist nun stabil, nachdem sie im ersten Next.js 15 RC eingeführt wurde.

after() bietet eine Möglichkeit, Aufgaben wie Logging, Analytics und andere System-Synchronisationen durchzuführen, nachdem die Response an den Nutzer gestreamt wurde, ohne die primäre Response zu blockieren.

Wichtige Änderungen

Seit der Einführung haben wir after() stabilisiert und Feedback berücksichtigt, darunter:

  • Verbesserte Unterstützung für selbst gehostete Next.js-Server.
  • Bugfixes für Szenarien, in denen after() mit anderen Next.js-Features interagierte.
  • Erweiterte Erweiterbarkeit, die es anderen Plattformen ermöglicht, ihre eigenen waitUntil()-Primitive zur Unterstützung von after() einzubinden.
  • Unterstützung für Runtime-APIs wie cookies() und headers() in Server Actions und Route Handlern.
app/layout.js
import { after } from 'next/server';
import { log } from '@/app/utils';
 
export default function Layout({ children }) {
  // Sekundäre Aufgabe
  after(() => {
    log();
  });
 
  // Primäre Aufgabe
  return <>{children}</>;
}

Lesen Sie mehr über die after-API und ihre Nutzung in der Dokumentation.

forbidden und unauthorized (experimentell)

Next.js 15.1 enthält zwei experimentelle APIs, forbidden() und unauthorized(), basierend auf Community-Feedback.

Wir freuen uns auf Ihr Feedback – testen Sie es in Ihren Entwicklungsumgebungen und teilen Sie Ihre Gedanken in diesem Diskussionsthread.

Überblick

Wenn Sie mit dem App Router vertraut sind, haben Sie wahrscheinlich bereits notFound() genutzt, um 404-Verhalten auszulösen, zusammen mit der anpassbaren not-found.tsx-Datei. Mit Version 15.1 erweitern wir diesen Ansatz auf Autorisierungsfehler:

forbidden() löst einen 403-Fehler aus mit anpassbarer UI über forbidden.tsx.

unauthorized() löst einen 401-Fehler aus mit anpassbarer UI über unauthorized.tsx.

Gut zu wissen: Wie bei notFound()-Fehlern wird der Statuscode 200 sein, wenn der Fehler ausgelöst wird, nachdem die initialen Response-Header bereits gesendet wurden. Mehr erfahren.

Aktivierung des Features

Da dieses Feature noch experimentell ist, müssen Sie es in Ihrer next.config.ts-Datei aktivieren:

next.config.ts
import type { NextConfig } from 'next';
 
const nextConfig: NextConfig = {
  experimental: {
    authInterrupts: true,
  },
};
 
export default nextConfig;

Hinweis: Die Unterstützung für next.config.ts wurde in Next.js 15 eingeführt. Mehr erfahren.

Verwendung von forbidden() und unauthorized()

Sie können forbidden() und unauthorized() in Server Actions, Server Components, Client Components oder Route Handlern nutzen. Hier ein Beispiel:

import { verifySession } from '@/app/lib/dal';
import { forbidden } from 'next/navigation';
 
export default async function AdminPage() {
  const session = await verifySession();
 
  // Überprüfen, ob der Nutzer die 'admin'-Rolle hat
  if (session.role !== 'admin') {
    forbidden();
  }
 
  // Admin-Seite für autorisierte Nutzer rendern
  return <h1>Admin Page</h1>;
}

Erstellen benutzerdefinierter Fehlerseiten

Um Fehlerseiten anzupassen, erstellen Sie folgende Dateien:

app/forbidden.tsx
import Link from 'next/link';
 
export default function Forbidden() {
  return (
    <div>
      <h2>Zugriff verweigert</h2>
      <p>Sie sind nicht berechtigt, auf diese Ressource zuzugreifen.</p>
      <Link href="/">Zurück zur Startseite</Link>
    </div>
  );
}
app/unauthorized.tsx
import Link from 'next/link';
 
export default function Unauthorized() {
  return (
    <div>
      <h2>Nicht autorisiert</h2>
      <p>Bitte melden Sie sich an, um auf diese Seite zuzugreifen.</p>
      <Link href="/login">Zum Login</Link>
    </div>
  );
}

Wir möchten uns bei Clerk bedanken, die dieses Feature durch einen PR vorgeschlagen und uns beim Prototyping der API unterstützt haben. Bevor wir dieses Feature in 15.2 stabilisieren, planen wir, weitere Funktionen und Verbesserungen hinzuzufügen, um ein breiteres Anwendungsspektrum zu unterstützen.

Lesen Sie die Dokumentation für die unauthorized- und forbidden-APIs für weitere Details.

Weitere Änderungen

  • [Feature] ESLint 9 in create-next-app verwenden (PR)
  • [Feature] Maximale Cache-Tags auf 128 erhöhen (PR)
  • [Feature] Option zum Deaktivieren des experimentellen CssChunkingPlugin hinzufügen (PR)
  • [Feature] Experimentelle CSS-Inlining-Unterstützung hinzufügen (PR)
  • [Verbesserung] Sass legacy-js-api-Warnung unterdrücken (PR)
  • [Verbesserung] Unbehandelte Ablehnung bei Verwendung von Rewrites beheben (PR)
  • [Verbesserung] Sicherstellen, dass der Elternprozess beendet wird, wenn der Webpack-Worker fehlschlägt (PR)
  • [Verbesserung] Route Interception auf einer Catch-All-Route behoben (PR)
  • [Verbesserung] Response-Cloning-Problem beim Request-Deduping behoben (PR)
  • [Verbesserung] Server Action Redirects zwischen mehreren Root-Layouts unterstützt (PR)
  • [Verbesserung] Bereitstellung von MDX-Plugins als Strings für Turbopack-Kompatibilität unterstützen (PR)

Mitwirkende

Next.js ist das Ergebnis der gemeinsamen Arbeit von über 3.000 einzelnen Entwicklern. Dieser Release wurde ermöglicht durch:

Ein großes Dankeschön an @sokra, @molebox, @delbaoliveira, @eps1lon, @wbinnssmith, @JamBalaya56562, @hyungjikim, @adrian-faustino, @mottox2, @lubieowoce, @bgw, @mknichel, @wyattjoh, @huozhi, @kdy1, @mischnic, @ijjk, @icyJoseph, @acdlite, @unstubbable, @gaojude, @devjiwonchoi, @cena-ko, @lforst, @devpla, @samcx, @styfle, @ztanner, @Marukome0743, @timneutkens, @JeremieDoctrine, @ductnn, @karlhorky, @reynaldichernando, @chogyejin, @y-yagi, @philparzer, @alfawal, @Rhynden, @arlyon, @MJez29, @Goodosky, @themattmayfield, @tobySolutions, @kevinmitch14, @leerob, @emmanuelgautier, @mrhrifat, @lid0a, @boar-is, @nisabmohd, @PapatMayuri, @ovogmap, @Reflex2468, @LioRael, @betterthanhajin, @HerringtonDarkholme, @bpb54321, @ahmoin, @Kikobeats, @abdelrahmanAbouelkheir, @lumirlumir, @yeeed711, @petter, und @suu3 für ihre Hilfe!