Zum Inhalt springen

Upgrade auf Next.js 16: Was laut scheitert und was leise kippt

Die meisten Breaking Changes in 16 stoppen den Build - das macht sie ungefährlich. Planen müssen Sie für die wenigen, die das Verhalten ändern, ohne etwas zu sagen.

4 Min. Lesezeit

Next.js 16 bringt eine lange Liste von Breaking Changes, und die meisten davon sind die gute Sorte: Sie stoppen den Build. Sie führen ihn aus, er schlägt fehl, Sie beheben es, weiter geht es.

Sorgfältig lesen sollten Sie die wenigen, die das Verhalten ändern, ohne irgendetwas fehlschlagen zu lassen. Die gehen in Produktion.

Dieser Text entsteht aus einer Codebasis mit 16.3 - der Website, auf der Sie ihn lesen.

Die eine architektonische Entscheidung: aus middleware wurde proxy

middleware.ts ist veraltet und heißt jetzt proxy.ts, die exportierte Funktion middleware entsprechend proxy. Die Umbenennung übernimmt der Codemod.

Was der Codemod nicht übernehmen kann, ist die Entscheidung darunter, und die ist real:

Die edge-Runtime wird in proxy nicht unterstützt. Die Proxy-Runtime ist nodejs und lässt sich nicht konfigurieren.

Wenn Ihre Middleware auf der Edge lief - und standardmäßig tat sie das -, verschiebt das Umbenennen der Datei diese Arbeit von hundert Edge-Standorten auf Ihren Node-Server. Für ein Rewrite oder einen Locale-Redirect, der bei jedem Request läuft, ist das keine Umbenennung, sondern eine Verschiebung der Latenz.

Der dokumentierte Weg, wenn Sie die Edge-Runtime brauchen: vorerst bei middleware bleiben. Das Upgrade hat also eine Weggabelung:

  • Leichte Routing-Arbeit - Rewrites, Redirects, ein Cookie-Read - nach proxy verschieben und die Node-Runtime akzeptieren.
  • Latenzkritisches auf der Edge - bei middleware bleiben, bis die Folgeanleitung kommt, im Wissen, auf einer veralteten Konvention zu sitzen.

So oder so ist das der Moment zu prüfen, ob der Matcher je richtig war. Middleware läuft bei jedem Request, auch bei denen, die Sie vergessen haben - und jeder dieser Requests geht jetzt zum Origin.

Mit umbenannt werden die Konfigurationsflags: aus skipMiddlewareUrlNormalize wird skipProxyUrlNormalize. Das erledigt der Codemod.

Was laut scheitert, sodass Sie es nicht ausliefern können

Eine Webpack-Konfiguration mit next build. Turbopack ist jetzt auch für next build der Standard, nicht nur für next dev, und ein Projekt mit eigener Webpack-Konfiguration lässt den Build bewusst scheitern, statt sie still zu ignorieren. Drei Auswege: mit --turbopack bauen und die Konfiguration ignorieren, sie auf Turbopack-Optionen portieren, oder mit --webpack aussteigen. Gut zu wissen: Möglicherweise fügt ein Plugin eine Webpack-Option hinzu, die Sie nie geschrieben haben - das ist die verwirrende Variante dieses Fehlers.

Parallele Routen ohne default.js. Jeder Slot braucht jetzt eine explizite default.js, sonst scheitert der Build. Eine Datei, die notFound() aufruft oder null zurückgibt, stellt das vorherige Verhalten her.

Node 18. Das Minimum ist jetzt Node 20.9, bei TypeScript 5.1. Die Browser-Ziele liegen bei Chrome, Edge und Firefox 111+ sowie Safari 16.4+.

next lint, AMP und Runtime-Config. Alles entfernt. serverRuntimeConfig und publicRuntimeConfig gibt es nicht mehr - nutzen Sie Umgebungsvariablen. next/legacy/image ist veraltet, ebenso images.domains, das durch remotePatterns ersetzt wurde.

Was leise kippt - und wofür Sie planen müssen

Bild-Caching ging von 60 Sekunden auf 4 Stunden. images.minimumCacheTTL liegt jetzt bei 14400. Nichts wirft einen Fehler. Wenn Sie sich auf den alten Standard verlassen haben, um tagsüber wechselnde Bilder zu aktualisieren, tun sie das nicht mehr - und das Symptom ist ein veraltetes Bild, das niemand reproduzieren kann, weil der Browser-Cache dem Optimierer widerspricht. Setzen Sie es explizit zurück, wenn Sie es brauchen:

// next.config.ts
images: { minimumCacheTTL: 60 },

next build führt kein Lint mehr aus. Wenn Ihre CI darauf zählte, dass der Build Lint-Fehler findet, tut sie das nicht mehr - still. @next/eslint-plugin-next nutzt außerdem jetzt standardmäßig die Flat Config. Führen Sie ESLint oder Biome als eigenen Schritt aus, und prüfen Sie, dass dieser Schritt existiert, bevor Sie annehmen, er sei grün.

Die Image-srcset-Standards haben sich verschoben. 16 wurde aus dem Standard-imageSizes-Array entfernt, der qualities-Standard hat sich geändert. Beides wirft keinen Fehler und ändert, was erzeugt, zwischen- gespeichert und ausgeliefert wird.

Lokale Bilder mit Query-String brauchen jetzt Konfiguration. /photo?v=1 verlangt einen images.localPatterns-Eintrag mit passendem search. Dieser Fall wirft einen Fehler - aber nur auf den Routen, die das Muster nutzen, und das sind womöglich nicht die aus Ihrem Smoke-Test.

Die Reihenfolge, die funktioniert

  1. Lesen Sie die Anleitung vor dem Codemod. Sie liegt ab 16.2 in node_modules/next/dist/docs/, passend zur tatsächlich installierten Version statt zu dem, woran sich das Internet erinnert.
  2. Führen Sie den Upgrade-Codemod aus, danach separat den Codemod für die asynchronen Request-APIs, falls Sie noch synchrone params, searchParams, cookies(), headers() oder draftMode() aus der 15er-Kompatibilitätsphase haben. Der Upgrade-Codemod führt nicht jede Migration aus.
  3. Entscheiden Sie die Proxy-Frage bewusst, denn nichts wird Sie danach fragen.
  4. Vergleichen Sie die Build-Ausgabe mit der alten. Welche Routen und welche ƒ sind, sollte sich nicht geändert haben - und wenn doch, lohnt sich das Verständnis vor dem Deployment.
  5. Prüfen Sie die leise Liste oben gegen Ihre eigene Konfiguration.

Wenn Sie mehrere Versionen zurückliegen

Der Schritt von 15 auf 16 ist überschaubar. Von 13 oder 14 aus anzukommen, mit einem Pages Router noch im Baum, ist ein anderes Projekt - und der Fehler besteht darin, es als ein Upgrade zu behandeln. Migration ohne Feature-Freeze beschreibt die Reihenfolge, die die Anwendung währenddessen auslieferbar hält, und Migration und Rettung ist genau diese Arbeit, von uns erledigt.

Zurück zu allen Artikeln