Heim >Web-Frontend >js-Tutorial >Next.js v – Nachdenken über Fehler
Hallo! Dies ist ein weiterer Artikel über next.js. Und zum Schluss noch zur neuen Version! Jede Veröffentlichung enthält eine Reihe neuer, interessanter und kontroverser Funktionen. Diese Version wird keine Ausnahme sein. Allerdings ist die neue Version nicht so sehr wegen ihrer neuen Funktionalität interessant, sondern wegen der Änderung der Prioritäten und der Organisation in next.js. Und ja, wie Sie vielleicht anhand des Titels erraten haben, ist ein erheblicher Teil dieser Veröffentlichung wertvoll, um über frühere Fehler nachzudenken.
Ich arbeite seit etwa Version 8 mit next.js. Die ganze Zeit über habe ich seine Entwicklung mit Interesse verfolgt (manchmal nicht ohne Enttäuschung). Kürzlich habe ich eine Reihe von Artikeln über die Probleme mit dem neuen App Router veröffentlicht: „Next.js App Router. Ein Weg in die Zukunft oder eine falsche Wendung“, „Next.js-Caching. Ein Geschenk oder ein Fluch“, „ Weitere Bibliotheken für den Gott der Bibliotheken oder wie ich i18n neu gedacht habe. All dies war das Ergebnis einer sehr schwachen Entwicklung von Ideen und Fähigkeiten in früheren Versionen von next.js. Und aus diesem Grund ist mein Interesse an der neuen Version nur noch gewachsen. Darüber hinaus besteht der Wunsch, den Vektor der Änderungen im Rahmenwerk zu verstehen.
In diesem Artikel werde ich nicht näher darauf eingehen, was App-Router- oder Serverkomponenten sind – diese werden in früheren Artikeln ausführlich beschrieben. Wir konzentrieren uns nur auf die neue Version und nur auf die neuen Änderungen.
Hinweis: Der Artikel spiegelt die interessantesten Änderungen aus Sicht des Autors wider. Sie weichen von der offiziellen Liste ab, da der Autor sie aus Commits und PRs im Framework ausgewählt hat.
Zuerst ein wenig über Änderungen in den internen Entwicklungsprozessen von next.js. Zum ersten Mal hat das Framework-Team einen Release Candidate (RC-Version) veröffentlicht. Dies geschah offensichtlich aufgrund der Entscheidung des React.js-Teams, React v19 RC zu veröffentlichen.
Normalerweise verwendet das next.js-Team in seinen stabilen Releases ruhig React aus dem „Canary“-Release-Zweig (dieser Zweig gilt als stabil und wird für die Verwendung durch Frameworks empfohlen). Dieses Mal haben sie sich jedoch entschieden, die Dinge anders zu machen (Spoiler – nicht umsonst).
Der Plan für beide Teams war einfach: eine Vorabversion veröffentlichen, die Community auf Probleme prüfen lassen und in ein paar Wochen eine vollständige Version veröffentlichen.
Es ist über sechs Monate her, seit der Release Candidate von React.js veröffentlicht wurde, aber die stabile Version wurde immer noch nicht veröffentlicht. Die Verzögerung bei der Veröffentlichung der stabilen Version von React.js hat sich auch auf die Pläne von next.js ausgewirkt. Entgegen der Tradition veröffentlichten sie daher insgesamt 15 zusätzliche Patch-Versionen, während sie bereits an der 15. Version arbeiteten (normalerweise 3-5 Patches und dann ein Release). Bemerkenswert hierbei ist, dass diese Patch-Versionen nicht alle gesammelten Änderungen enthielten, sondern nur kritische Probleme behoben, was auch von den üblichen Prozessen von next.js abweicht.
Der grundlegende Release-Prozess in next.js besteht darin, dass alles in den Canary-Zweig übergeht und dieser Zweig dann irgendwann als stabile Version veröffentlicht wird.
Aus diesem Grund hat das Team von next.js jedoch beschlossen, sich von der React.js-Veröffentlichung zu trennen und eine stabile Version des Frameworks zu veröffentlichen, bevor die stabile Version von React.js veröffentlicht wird.
Eine weitere sehr nützliche organisatorische Änderung. Schließlich ist es möglich, verschiedene Versionen der Dokumentation anzuzeigen. Deshalb ist das so wichtig:
Erstens kann die Aktualisierung von next.js aufgrund großer Änderungen oft eine ziemlich herausfordernde Aufgabe sein. Tatsächlich gibt es aus diesem Grund immer noch über 2 Millionen Downloads für Version 12 und über 4 Millionen für Version 13 pro Monat (um fair zu sein, Version 14 hat über 20 Millionen Downloads).
Folglich benötigen Benutzer früherer Versionen eine spezifische Dokumentation für ihre Version, da die neue Version möglicherweise eine halbe Stunde lang neu geschrieben wird.
Ein weiteres Problem besteht darin, dass Next.js im Wesentlichen einen einzigen Kanal verwendet. Es werden auch Änderungen an der Dokumentation vorgenommen. Daher erschienen Beschreibungen von Änderungen gegenüber Canary-Versionen sofort in der Hauptdokumentation. Jetzt werden sie im Abschnitt „Kanarienvogel“ angezeigt.
Zu Beginn habe ich erwähnt, dass Next.js derzeit die RC-Version von React.js verwendet. Aber in Wirklichkeit stimmt das nicht ganz, oder besser gesagt, nicht ganz. Tatsächlich verwendet Next.js derzeit zwei React.js-Konfigurationen: die 19. Canary-Version für App Router und die 18. Version für Pages Router.
Interessanterweise wollten sie einmal auch die 19. Version für Pages Router einbinden, haben diese Änderungen dann aber rückgängig gemacht. Nun wird die volle Unterstützung für React.js Version 19 nach der Veröffentlichung der stabilen Version versprochen.
Darüber hinaus wird die neue Version mehrere nützliche Verbesserungen für Server-Aktionen-Funktionen enthalten (ja, das React-Team hat sie umbenannt):
Ich denke, ich werde auch die neue Funktion von Next.js in diesen Abschnitt aufnehmen – die Form-Komponente. Im Großen und Ganzen handelt es sich um die bekannte Form von React-Dom, jedoch mit einigen Verbesserungen. Diese Komponente wird vor allem dann benötigt, wenn die erfolgreiche Formularübermittlung das Navigieren zu einer anderen Seite erfordert. Für die nächste Seite werden die Abstraktionen „loading.tsx“ und „layout.tsx“ vorinstalliert.
import Form from 'next/form' export default function Page() { return ( <Form action="/search">; {/* On submission, the input value will be appended to the URL, e.g. /search?query=abc */} <input name="query" />; <button type="submit">Submit</button>; </Form>; ) }
Wenn wir über Next.js sprechen, können wir die Entwicklererfahrung nicht außer Acht lassen. Zusätzlich zum Standard „Schneller, höher, stärker“ (auf den wir auch etwas später eingehen werden) wurden mehrere nützliche Verbesserungen veröffentlicht.
Lang erwartete Unterstützung für das neueste ESLint. Next.js unterstützte ESLint v9 bisher nicht. Dies trotz der Tatsache, dass sowohl eslint selbst (v8) als auch einige seiner Unterabhängigkeiten bereits als veraltet markiert sind. Dies führte zu einer unangenehmen Situation, in der Projekte im Wesentlichen gezwungen waren, veraltete Pakete beizubehalten.
Die Fehlerschnittstelle wurde leicht verbessert (was in Next.js bereits klar und praktisch ist):
Ein „Statischer Indikator“ wurde hinzugefügt – ein Element in der Ecke der Seite, das anzeigt, dass die Seite im statischen Modus erstellt wurde.
Im Großen und Ganzen ist es eine Kleinigkeit, aber es ist amüsant, dass sie es als etwas Neues in die wichtigsten Änderungen aufgenommen haben. Den Indikator für eine „vorgefertigte“ Seite gibt es ungefähr seit Version 8 (2019) und hier wurde er im Wesentlichen nur leicht aktualisiert und für den App Router angepasst.
Ein Verzeichnis mit Debugging-Informationen wurde ebenfalls hinzugefügt – .next/diagnostics. Es enthält Informationen über den Build-Prozess und alle auftretenden Fehler. Es ist noch nicht klar, ob dies im täglichen Gebrauch nützlich sein wird, aber es wird sicherlich bei der Fehlerbehebung von Problemen mit Vercel-Devrels verwendet werden (ja, sie helfen manchmal, Probleme zu lösen).
Nachdem wir über DX gesprochen haben, lohnt es sich, über den Build-Prozess zu sprechen. Und dazu noch Turbopack.
Und die größte Neuigkeit in diesem Bereich. Turbopack ist jetzt vollständig für den Entwicklungsmodus fertiggestellt! „100 % der bestehenden Tests haben mit Turbopack fehlerfrei bestanden“
Jetzt arbeitet das Turbo-Team an der Serienversion, geht die Tests nach und nach durch und verfeinert sie (derzeit etwa 96 % abgeschlossen)
Turbopack fügt außerdem neue Funktionen hinzu:
import Form from 'next/form' export default function Page() { return ( <Form action="/search">; {/* On submission, the input value will be appended to the URL, e.g. /search?query=abc */} <input name="query" />; <button type="submit">Submit</button>; </Form>; ) }
Diese und andere Verbesserungen in Turbopack „reduzierten die Speichernutzung um 25–30 %“ und „beschleunigten auch den Aufbau schwerer Seiten um 30–50 %“.
Erhebliche Stilprobleme wurden behoben. In Version 14 kam es häufig zu Situationen, in denen die Reihenfolge der Stile während der Navigation unterbrochen wurde, was dazu führte, dass Stil A höher wurde als Stil B und umgekehrt. Dadurch änderte sich ihre Priorität und folglich sahen die Elemente anders aus.
Die nächste lang erwartete Verbesserung. Jetzt kann die Konfigurationsdatei in TypeScript geschrieben werden – next.config.ts
const nextConfig = { experimental: { turbo: { treeShaking: true, memoryLimit: 1024 * 1024 * 512 // in bytes / 512MB }, }, }
Ein weiteres interessantes Update sind Wiederholungsversuche für statische Seitenerstellung. Das heißt, wenn eine Seite zum Zeitpunkt der Erstellung fehlschlägt (z. B. aufgrund von Internetproblemen), wird versucht, sie erneut zu erstellen.
import type { NextConfig } from 'next'; const nextConfig: NextConfig = { /* config options here */ }; export default nextConfig;
Und um diesen Abschnitt abzuschließen, eine von der Community sehr gewünschte Funktionalität – die Möglichkeit, den Pfad zu zusätzlichen Dateien für die Erstellung anzugeben. Mit dieser Option können Sie beispielsweise festlegen, dass Dateien nicht im App-Verzeichnis, sondern in Verzeichnissen wie „modules/main“, „modules/invoices“ liegen.
Im Moment haben sie es jedoch nur für interne Teamzwecke hinzugefügt. Und in dieser Version werden sie es definitiv nicht präsentieren. In Zukunft wird es entweder für Vercel-Anforderungen verwendet oder es wird getestet und in der nächsten Version vorgestellt.
Der schmerzhafteste Teil von Next.js-Updates – API-Änderungen. Und in dieser Version gibt es auch aktuelle Updates.
Mehrere interne Framework-APIs sind asynchron geworden – Cookies, Header, Parameter und Suchparameter (sogenannte dynamische APIs).
const nextConfig = { experimental: { staticGenerationRetryCount: 3, }, }
Es ist eine große Änderung, aber das Next.js-Team verspricht, dass alle diese Funktionen automatisch aktualisiert werden können, indem ihr Codemod aufgerufen wird:
npx @next/codemod@canary next-async-request-api .
Eine weitere Änderung, aber wahrscheinlich für viele nicht relevant. Die Schlüssel geo und ip wurden aus NextRequest entfernt (in Middleware und API-Routen verwendet). Im Wesentlichen funktionierte diese Funktionalität nur in Vercel, während Entwickler an anderen Orten ihre eigenen Methoden entwickelten. Für Vercel wird diese Funktionalität in das Paket @vercel/functions
verschobenUnd noch ein paar Updates:
import Form from 'next/form' export default function Page() { return ( <Form action="/search">; {/* On submission, the input value will be appended to the URL, e.g. /search?query=abc */} <input name="query" />; <button type="submit">Submit</button>; </Form>; ) }
Meiner persönlichen Meinung nach haben hier die wichtigsten Änderungen für Next.js stattgefunden. Und die größte Neuigkeit ist: Caching ist jetzt standardmäßig deaktiviert! Ich werde nicht näher auf Caching-Probleme eingehen, diese wurden weitgehend im Artikel „Next.js Caching. Geschenk oder Fluch“ behandelt.
Lass uns alle wichtigen Änderungen beim Caching durchgehen:
const nextConfig = { experimental: { turbo: { treeShaking: true, memoryLimit: 1024 * 1024 * 512 // in bytes / 512MB }, }, }
import type { NextConfig } from 'next'; const nextConfig: NextConfig = { /* config options here */ }; export default nextConfig;
Das betrifft die „historischen Missverständnisse“. Neue APIs werden auch in Next.js erscheinen. Nämlich das sogenannte Dynamic I/O. Es wurde noch nirgendwo darüber geschrieben, daher handelt es sich im Folgenden um die Vermutungen des Autors, die auf den Änderungen basieren.
Dynamisches I/O scheint eine fortgeschrittene Art des dynamischen Aufbaus zu sein. So etwas wie PPR (Partial Prerendering), oder genauer gesagt, seine Ergänzung. Kurz gesagt, Partial Prerendering ist ein Seitenerstellungsmodus, bei dem die meisten Elemente zum Zeitpunkt der Erstellung erstellt und zwischengespeichert werden, während einzelne Elemente für jede Anfrage erstellt werden.
Dynamisches I/O stellt also [wahrscheinlich] die Architektur für diese Logik fertig. Es erweitert die Caching-Funktionen, sodass es je nach Modus und Verwendungsort genau aktiviert und deaktiviert werden kann (ob in einem „dynamischen“ Block oder nicht).
import Form from 'next/form' export default function Page() { return ( <Form action="/search">; {/* On submission, the input value will be appended to the URL, e.g. /search?query=abc */} <input name="query" />; <button type="submit">Submit</button>; </Form>; ) }
Gleichzeitig wird die Anweisung „Cache verwenden“ hinzugefügt. Es wird in NodeJS und Edge-Runtimes und offenbar in allen Serversegmenten und Abstraktionen verfügbar sein. Durch Angabe dieser Direktive am Anfang einer Funktion oder eines Moduls, das eine Funktion exportiert, wird das Ergebnis zwischengespeichert. Die Direktive ist nur verfügbar, wenn DynamicIO aktiviert ist.
const nextConfig = { experimental: { turbo: { treeShaking: true, memoryLimit: 1024 * 1024 * 512 // in bytes / 512MB }, }, }
Außerdem wurden speziell für die Verwendung von Cache die Methoden „cacheLife“ und „cacheTag“ hinzugefügt
import type { NextConfig } from 'next'; const nextConfig: NextConfig = { /* config options here */ }; export default nextConfig;
cacheTag wird für die erneute Validierung mit revalidateTag verwendet und CacheLife legt die Cache-Lebensdauer fest. Für den CacheLife-Wert müssen Sie einen der voreingestellten Werte verwenden. Mehrere Optionen sind standardmäßig verfügbar („Sekunden“, „Minuten“, „Stunden“, „Tage“, „Wochen“, „Max“), zusätzliche können in next.config.js angegeben werden:
const nextConfig = { experimental: { staticGenerationRetryCount: 3, }, }
Wahrscheinlich das Hauptfeature der nächsten Version. Wie bereits erwähnt, handelt es sich bei PPR um einen Seitenerstellungsmodus, bei dem die meisten Elemente zum Zeitpunkt der Erstellung zusammengestellt und zwischengespeichert werden, während einzelne Elemente für jede Anfrage zusammengestellt werden. Gleichzeitig wird der vorgefertigte Teil sofort an den Client gesendet, während der Rest dynamisch geladen wird.
Die Funktionalität selbst wurde vor sechs Monaten im Release Candidate als experimentelle API eingeführt. Diese API wird in diesem Zustand bleiben und wir werden sie wahrscheinlich erst in Version 16 als stabil sehen (was gut ist, da wichtige Funktionen oft innerhalb von sechs Monaten bis zu einem Jahr auf stabil umgestellt werden).
Zu den Änderungen. Wie bereits erwähnt, wurden vor allem die Arbeitsprinzipien aktualisiert. Aus Sicht des PPR-Einsatzes hatte dies jedoch kaum Auswirkungen. Gleichzeitig erhielt es mehrere Verbesserungen:
Früher gab es nur ein Flag in der Konfiguration, aber um PPR jetzt zu aktivieren, müssen Sie „inkrementell“ angeben. Dies geschieht offenbar, um die Logik transparenter zu machen – Inhalte können von Entwicklern sogar in PPR zwischengespeichert werden, und um sie zu aktualisieren, müssen Sie Revalidierungsmethoden aufrufen.
import { cookies } from 'next/headers'; export async function AdminPanel() { const cookieStore = await cookies(); const token = cookieStore.get('token'); // ... }
Außerdem wurde PPR zuvor für das gesamte Projekt gestartet, jetzt muss es jedoch für jedes Segment (Layout oder Seite) aktiviert werden:
const nextConfig = { images: { localPatterns: [ { pathname: '/assets/images/**', search: 'v=1', }, ], }, }
Eine weitere Änderung ist Partial Fallback Prerendering (PFPR). Gerade durch diese Verbesserung wird der vorgefertigte Teil sofort an den Client gesendet, während der Rest dynamisch geladen wird. Anstelle dynamischer Elemente wird in dieser Zeit eine Callback-Komponente angezeigt.
import Form from 'next/form' export default function Page() { return ( <Form action="/search">; {/* On submission, the input value will be appended to the URL, e.g. /search?query=abc */} <input name="query" />; <button type="submit">Submit</button>; </Form>; ) }
Instrumentation ist als stabile API gekennzeichnet. Die Instrumentierungsdatei ermöglicht es Benutzern, sich in den Lebenszyklus des Next.js-Servers einzubinden. Es funktioniert in der gesamten Anwendung (einschließlich aller Segmente von Pages Router und App Router).
Derzeit unterstützt die Instrumentierung die folgenden Hooks:
register – wird einmal beim Initialisieren des Next.js-Servers aufgerufen. Es kann zur Integration mit Observability-Bibliotheken (OpenTelemetry, datadog) oder für projektspezifische Aufgaben verwendet werden.
onRequestError – ein neuer Hook, der für alle Serverfehler aufgerufen wird. Es kann für Integrationen mit Fehlerverfolgungsbibliotheken (Sentry) verwendet werden.
const nextConfig = { experimental: { turbo: { treeShaking: true, memoryLimit: 1024 * 1024 * 512 // in bytes / 512MB }, }, }
Interceptor, auch bekannt als Middleware auf Routenebene. Es ist so etwas wie eine vollwertige [bereits vorhandene] Middleware, aber im Gegensatz zu letzterer:
Darüber hinaus werden beim Erstellen einer Interceptor-Datei alle Seiten unten im Baum dynamisch.
import type { NextConfig } from 'next'; const nextConfig: NextConfig = { /* config options here */ }; export default nextConfig;
Apropos Vercel: Middleware wird nun als primäre einfache Prüfung auf CDN-Ebene wirksam sein (so dass beispielsweise Weiterleitungen sofort zurückgegeben werden, wenn die Anfrage nicht zulässig ist), während Interceptoren daran arbeiten Server, der umfassende Prüfungen und komplexe Vorgänge durchführt.
Beim Selbsthosting wird eine solche Aufteilung jedoch offenbar weniger effektiv sein (da beide Abstraktionen auf dem Server funktionieren). Es kann ausreichend sein, nur Abfangjäger zu verwenden.
Überschreiben des Abrufs, aggressives Caching, zahlreiche Fehler und Ignorieren von Community-Anfragen. Das Next.js-Team traf falsche Entscheidungen, beschleunigte Veröffentlichungen und hielt trotz des Feedbacks der Community an seinen Ansichten fest. Es dauerte fast ein Jahr, bis man die Probleme erkannte. Und erst jetzt gibt es endlich das Gefühl, dass sich das Rahmenwerk erneut mit Gemeinschaftsproblemen befasst.
Andererseits gibt es auch andere Frameworks. Vor einem Jahr schien es bei der React.js-Präsentation, dass alle Frameworks bald auf Augenhöhe mit Next.js sein würden. React erwähnte Next.js seltener als Haupttool, Frameworks stellten kommende Build-Systeme, Unterstützung für Serverkomponenten und -funktionen sowie eine Reihe globaler Änderungen und Integrationen vor. Die Zeit ist vergangen und im Grunde hat noch keiner von ihnen diesen Punkt erreicht.
Endgültige Schlussfolgerungen können natürlich erst nach einiger Zeit gezogen werden, aber im Moment fühlt es sich so an, als hätten die Änderungen in React.js statt der erwarteten Nivellierung der Frameworks zu einer noch größeren Dominanz von Next.js und a geführt größere Divergenz zwischen Frameworks (da die Implementierung von Serverkomponenten und -aktionen dem Ermessen der Frameworks überlassen wurde).
Gleichzeitig wechselte OpenAI zu Remix („aufgrund der größeren Stabilität und Bequemlichkeit“):
Und anscheinend begannen sie vor wesentlichen Änderungen in Next.js
Im Allgemeinen werden wir in den nächsten Stateofjs- und Stackoverflow-Umfragen wahrscheinlich eine erhebliche Umstrukturierung erleben.
Credits
Codebeispiele oder ihre Grundlagen stammen aus der Dokumentation von next.js sowie aus Commits, PRs und dem Kern von next.js;
Postskriptum
Wenn Sie ein Tool zur Erstellung von Dokumentationen auf Basis von MD-Dateien benötigen – werfen Sie einen Blick auf robindoc.com, wenn Sie mit next.js arbeiten – finden Sie möglicherweise etwas Nützliches in den Lösungen von nimpl.tech.
Das obige ist der detaillierte Inhalt vonNext.js v – Nachdenken über Fehler. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!