© Teguh Jati Prasetyo/Shutterstock.com
Next.js für Fortgeschrittene - API-Routing und Plug-ins

Der zentrale Angelpunkt


Im letzten PHP Magazin haben wir bereits die Grundlagen und die wichtigsten Features von Next.js beleuchtet. In diesem Artikel sehen wir uns einige weitere Features, wie beispielsweise das Ausliefern statischer Dateien, API-Routing oder die Erzeugung statischer Seiten, an und werfen außerdem einen Blick auf das Plug-in-System von Next.js und einige wichtige Plug-ins.

Next.js ist ein Framework für React, das einige Features bietet, die React als Bibliothek fehlen. React fokussiert sich auf die Erzeugung von grafischen Schnittstellen im Web, indem es die hierfür notwendigen Elemente zur Verfügung stellt, aber auch nicht mehr. Das bedeutet aber auch, dass React für einige typische Problemstellungen, die bei einer Single-Page-Applikation auftreten, keine Lösung parat hat. Zu diesen Problemstellungen zählen unter anderem die Validierung von Formularen, zentrales State Management, der Umgang mit Web Components oder Serverside Rendering. Glücklicherweise ist die Community, die sich um React gebildet hat, eine der aktivsten im JavaScript-Umfeld, und so gibt es für nahezu jedes Problem bereits eine Lösung. Und hier reiht sich auch Next.js ein, indem es die Entwicklung von React-Applikationen ein Stück weit vereinfacht und vorgefertigte Lösungen beispielsweise für serverseitiges Rendering (SSR) bietet.

Im vorhergehenden Artikel [1] haben wir eine einfache Einkaufsliste mit Next.js erzeugt. Der Schwerpunkt lag auf der Initialisierung der Applikation, dem Aufbau verschiedener Sichten und der Navigation zwischen diesen Sichten. Die Daten wurden auf einem Webserver persistiert, mit dem die Applikation über die Axios-Bibliothek kommunizierte. Diese Applikation wird uns auch in diesem Artikel als Beispiel dienen, und wir erweitern sie um zusätzliche Features.

API-Routing – Schnittstellen mit Next.js implementieren

Für den Betrieb einer React-Applikation mit Next.js müssen Sie serverseitig immer einen Node.js-Prozess ausführen, der für die Auslieferung der Applikation verantwortlich ist. Dieser kümmert sich dann beispielsweise um SSR. Führen Sie ohnehin einen Serverprozess aus, spricht auch nichts dagegen, mit diesem gleich auch die dynamischen Inhalte Ihrer Applikation auszuliefern.

Ähnlich wie bei den Pages gibt es auch für die APIs eine dateisystembasierte Vereinfachung. So können Sie innerhalb des pages-Verzeichnisses einen neuen Unterordner mit dem Namen api anlegen. Die Dateien und Verzeichnisse dort werden als API-Endpunkte interpretiert. Die Datei muss nur eine Funktion über einen default-Export veröffentlichen. Diese wird bei jeder Anfrage auf den jeweiligen Pfad ausgeführt. Die Funktion definiert zwei Parameter:

  • Request: Über das Request-Objekt haben Sie Zugriff auf die eingehende Anfrage und können dort beispielsweise die HTTP-Methode oder verschiedene Headerfelder auslesen.

  • Response: Mit dem Response-Objekt formulieren Sie die Antwort an den anfragenden Client und setzen Informationen wie beispielsweise den Statuscode, Headerfelder oder den Body der Antwort.

Erzeugen Sie Ihre Next.js-Applikation mit Create Next App und dem TypeScript-Template, legt Ihnen dieses bereits ein api-Verzeichnis im pages-Verzeichnis an. In diesem Verzeichnis liegt bereits ein Unterverzeichnis users mit einer index.ts-Datei als Beispielendpunkt. Für die weitere Arbeit mit der Applikation sollten Sie dieses Verzeichnis löschen. Für einen ersten Test können Sie jedoch Ihre Applikation mit dem Befehl npm run dev starten und erreichen dann unter http://localhost:3000/users diesen Endpunkt, der Ihnen eine beispielhafte Benutzerliste zurückgibt. Sie können also entweder ein Unterverzeichnis mit einer index.ts-Datei anlegen, also users/index.ts, oder Sie erzeugen direkt im api-Verzeichnis eine Datei mit dem Namen users.ts. Beide Ansätze sind äquivalent mit dem Unterschied, dass die Lösung mit den Unterverzeichnissen bei größeren APIs etwas besser zu verwalten ist, da Sie einen einzelnen Endpunkt in mehrere Dateien aufteilen können und diese dann in einem separaten Verzeichnis zusammengefasst sind.

Nachdem es sich bei den API-Routen von Next.js um ganz gewöhnliches Node.js handelt, können Sie hier auf eine Fülle von Bibliotheken zurückgreifen, die Sie über den Paketmanager installieren können.

Die Beispielapplikation hat die Daten zur Anzeige der Einkaufsliste von einem Endpunkt unter http://localhost:3030/items bezogen. Dieser soll nun in die Applikation integriert werden. Für das Speichern der Daten kann jede beliebige Datenbank verwendet werden. List-ing 1 enthält den Quellcode des Endpunkts in der Datei pages/api/items/index.ts.

Listing 1: Einfacher Endpunkt zum Laden von Daten

export default async (_: NextApiRequest, res: NextApiResponse) => { try { res.status(200).json(await itemModel.find()); } catch { res .status(500) .json({ statusCode: 500, message: 'Whoops something went wrong' }); } };

Für die lesende Schnittstelle benötigen Sie nur den zweiten Parameter der Routingfunktion, also das Response-Objekt. Die TypeScript-Unterstützung von Next.js sieht hier das NextApiResponse-Interface vor. Über die Typangabe in der Signatur erhalten Sie von Ihrer Entwicklungsumgebung Hilfestellung beim Schreiben des Quellcodes in Form von Autocompletion. Next.js erlaubt die Verwendung von async-Funktionen als API-Endpunkte, was Ihnen das Schreiben von lesbarem Code weiter vereinfacht. Innerhalb der Routingfunktion verwenden Sie ein try-catch-Statement, um eventuelle Fehler bei der Kommunikation mit der Datenbank zu fangen, eine entsprechende Fehlermeldung für den Client vorzubereiten und diese mit dem Statuscode 500 zu versenden. Diesen setzen Sie mit der status-Methode des Response-Objekts. Falls die Daten erfolgreich gelesen wurden, nutzen Sie den Statuscode 200 und hängen die Daten mit Hilfe der json-Methode an die Antwort an den Client an. Diese Methode setzt automatisch eine Reihe von Headerfeldern, unter anderem den Content Type, auf den Wert application/json. Den Verbindungsaufbau sowie das Lesen der Daten aus der Datenbank sollten Sie, wie im Beispiel, in eine separate Datei auslagern, damit die API-Endpunkte möglichst schlank und einfach zu lesen sind. Die statische Methode find des itemModel-Objekts gibt ein Promise-Objekt zurück, das mit einem Array von Items aufgelöst wird. Mit dem await-Schlüsselwort warten Sie auf die Rückmeldung aus der Datenbank und nutzen die Daten als Eingabe für die json-Methode, um die Antwort an den Client zu senden.

Beachten Sie, dass die API-Funktion bei jeder Anfrage an den Endpunkt ausgeführt wird. Das bedeutet, wenn Sie innerhalb dieser Routine eine Datenbankverbindung aufbauen, kann es schnell passieren, dass Sie das Verbindungslimit der Datenbank überschreiten und der Datenbanktreiber eine Exception wirft, was zu einer fehlerhaften Antwort an d...

Neugierig geworden? Wir haben diese Angebote für dich:

Angebote für Teams

Für Firmen haben wir individuelle Teamlizenzen. Wir erstellen Ihnen gerne ein passendes Angebot.

Das Library-Modell:
IP-Zugang

Das Company-Modell:
Domain-Zugang