Next.js-Entwickler in Hamburg

Next.js für Unternehmen in Hamburg von einer Person: aktueller Bestand, Status und Buchungsdaten per Polling, Server-Sent Events oder WebSocket, Route Handler als Stream, Grenzen bei Serverless und Revalidierung auf Ereignis.

Next.js-Entwickler

Mein Platz in der WordPress-Community

  • Mein wordpress.org-Konto besteht seit 2006.
  • Ich habe zum WordPress-Core in den Versionen 7.0 und 7.1 beigetragen.
  • Ich betreue 30 Plugins auf wordpress.org.
  • Ich organisiere WordCamps und trete dort als Speaker auf.
  • Ich war bei jedem WordCamp Europe von 2017 bis 2026 dabei.

Mein WordPress.org-Profil

#Wie frisch müssen die Daten wirklich sein?

Am Anfang einer Live-Daten-Anfrage steht selten eine Technik, sondern eine Zahl: Wie alt darf der angezeigte Wert sein? Fünf Sekunden, eine Minute, eine Stunde? Danach richten sich Aufwand und Betriebskosten, und danach wählen Sie das Verfahren. Diese Seite ordnet die Möglichkeiten in Next.js, nennt die Grenzen und zeigt, wie Sie aktuellen Bestand, Status oder Buchungsdaten anzeigen, ohne das Backend bei jedem Aufruf zu fragen.

Glasfassade der Elbphilharmonie in der Hamburger HafenCity

Foto: Dietmar Rabich, CC BY-SA 4.0, Wikimedia Commons.

Ein Hamburger Beispiel für die Frage nach der Frische liefert die Hafenverwaltung selbst. Die Hamburg Port Authority hält auf ihrer Website getrennte Seiten für Verkehrsinformationen im Hafen, für Öffnungs- und Betriebszeiten von Brücken und Schleusen und für aktuelle Wasserstände bereit. Die Seite des Hafens zeigt zusätzlich einen Zähler mit den erwarteten Schiffen (Port of Hamburg). Jeder dieser Werte altert anders: Ein Wasserstand ändert sich laufend, eine Betriebszeit selten. Dieselbe Unterscheidung brauchen Sie in Ihrer Anwendung, Wert für Wert.

#Polling, Server-Sent Events und WebSockets im Vergleich

PollingServer-Sent EventsWebSocket
RichtungBrowser fragtServer sendet, Browser empfängtbeide Richtungen
Verbindungje Abfrage neueine offene Verbindungeine offene Verbindung
WiederverbindenentfälltStandard des Browsersselbst bauen
Passt zuWerte, die sich in Minuten ändernStatus, Zähler, FortschrittChat, Zusammenarbeit, Steuerung

Die Angaben zu SSE stammen aus der MDN-Dokumentation. Eine EventSource öffnet eine dauerhafte Verbindung zu einem HTTP-Server, der Ereignisse im Format text/event-stream sendet; MDN beschreibt EventSource. Standardmäßig wird die Verbindung neu aufgebaut, wenn sie abreißt (Using server-sent events). Das Feld retry legt die Wartezeit in Millisekunden fest, und nach der HTML-Spezifikation stoppt der Browser, wenn der Server mit 204 No Content antwortet. Es ist eine Einbahnstraße: Vom Browser zum Server können Sie über SSE nichts senden.

Das Limit gehört in jede Planung. Ohne HTTP/2 gelten laut MDN höchstens 6 offene Verbindungen je Browser und Domain, über alle Tabs hinweg. Mit HTTP/2 handeln Server und Client die Zahl gleichzeitiger Streams aus, der Standard liegt bei 100. Wer ein Dashboard in mehreren Tabs offen hält, stößt über HTTP/1.1 schnell an die Grenze.

Die WebSocket-API öffnet laut MDN eine interaktive Zweiwege-Sitzung, ohne dass der Browser nach Antworten fragen muss. Dafür gibt es keinen Gegendruck: Kommen Nachrichten schneller an, als die Anwendung sie verarbeitet, füllen sie den Speicher oder lasten die CPU aus. MDN verweist für solche Fälle auf die WebTransport-API.

Meine Faustregel, nicht aus der Dokumentation: Wenn der Browser nur zuschauen muss, ist SSE fast immer die einfachere Wahl als ein WebSocket.

#Was ein Route Handler streamen kann

Route Handler sind nach der Next.js-Dokumentation standardmäßig nicht gecacht und bauen auf den Web-APIs Request und Response auf. Außerhalb von React-Rendering können sie rohe Antworten über die Web Streams API senden; die Streaming-Anleitung nennt dafür ausdrücklich Server-Sent Events. Ein minimaler Stream, den ich lokal mit Node als reinen ReadableStream geprüft habe:

// app/api/bestand/route.ts
export async function GET() {
  const encoder = new TextEncoder()
  let timer: ReturnType<typeof setInterval>

  const stream = new ReadableStream({
    start(controller) {
      controller.enqueue(encoder.encode('retry: 5000\n\n'))
      timer = setInterval(() => {
        controller.enqueue(encoder.encode(`data: ${JSON.stringify({ stand: Date.now() })}\n\n`))
      }, 15000)
    },
    cancel() {
      clearInterval(timer)
    },
  })

  return new Response(stream, {
    headers: {
      'Content-Type': 'text/event-stream',
      'Cache-Control': 'no-cache',
      'X-Accel-Buffering': 'no',
    },
  })
}

Im Browser genügt new EventSource('/api/bestand'). In echten Projekten steht an Stelle des Zeitgebers eine Quelle, die Änderungen meldet, und der Stream enthält nur das Nötigste: eine Artikelnummer und den neuen Wert, keine Namen. Die HTML-Spezifikation empfiehlt außerdem, etwa alle 15 Sekunden eine Kommentarzeile zu senden, die mit einem Doppelpunkt beginnt, damit ältere Proxys die Verbindung nicht schließen. Wie ein Route Handler Webhooks fremder Systeme annimmt, steht auf der Seite zu Route Handlern und Schnittstellen; hier geht es um die Gegenrichtung.

#Wo es auf Serverless-Plattformen eng wird

Die Dokumentation zu Next.js als Backend beschreibt, was passiert, wenn ein Host Route Handler als Lambda-Funktionen bereitstellt:

  • Route Handler können keine Daten zwischen Anfragen teilen.
  • Die Umgebung unterstützt womöglich keine Schreibzugriffe auf das Dateisystem.
  • Lang laufende Handler werden unter Umständen durch Timeouts beendet.
  • WebSockets funktionieren nicht, weil die Verbindung beim Timeout oder nach der Antwort schließt.

Streaming selbst hängt von der Plattform ab. Die Streaming-Anleitung nennt AWS Lambda als Beispiel: Der Antwort-Streaming-Modus muss ausdrücklich eingeschaltet werden, er ist nicht voreingestellt; Vercel unterstützt Streaming nach derselben Seite nativ. Auf einem Node-Server oder in einem Docker-Container wird Streaming unterstützt, bei einem statischen Export nicht. Welche Laufzeitgrenzen Ihr Anbieter für eine offene Verbindung setzt, steht in dessen eigener Dokumentation und gehört vor der Wahl des Hostings geklärt. Zum Betrieb auf eigenen Servern gibt es auf dieser Seite zu Self-Hosting mehr.

Dazwischen liegende Schichten können jeden Stream zunichtemachen. Laut Dokumentation puffern Nginx und ähnliche Proxys Antworten standardmäßig, CDNs puffern unter Umständen die ganze Antwort, und Gzip oder Brotli halten Teile zurück, bis genug Daten zum Komprimieren vorliegen. Safari und WebKit puffern Streams bis 1024 Byte, was nur sehr kleine Antworten betrifft. Prüfen Sie den Weg deshalb einmal Ende zu Ende, nicht nur lokal.

#Revalidierung auf Ereignis statt Takt

Viele Fälle brauchen gar keinen offenen Kanal. Wenn sich Bestand oder Status nur gelegentlich ändern, ist ein Cache, der auf das Ereignis hin ungültig wird, ruhiger und billiger. Die ISR-Anleitung empfiehlt eine hohe Revalidierungszeit, etwa eine Stunde statt einer Sekunde, und für mehr Genauigkeit die Revalidierung auf Zuruf; wer echte Echtzeitdaten braucht, soll dynamisch rendern.

Der Ablauf mit revalidateTag, wie ihn die Referenz beschreibt:

  1. Die Abfrage des Bestands trägt ein Tag, zum Beispiel bestand.
  2. Das Warenwirtschaftssystem ruft bei einer Änderung einen Route Handler auf.
  3. Der Handler ruft revalidateTag('bestand', 'max') auf. Der Aufruf markiert die Daten als veraltet.
  4. Die nächste Anfrage bekommt noch den alten Stand und stößt die Neuberechnung an. Der Besucher wartet nicht.

Kommt der Aufruf von außen, etwa über einen Webhook, nennt die Referenz { expire: 0 } als Variante, bei der die Daten sofort ungültig werden und die nächste Anfrage blockierend neu lädt. Zwei Eigenschaften sind für Ihre Planung wichtig. Die Neuberechnung beginnt mit einer Anfrage, nicht mit dem Aufruf von revalidateTag; Seiten werden also beim Besuch aktualisiert, nicht alle auf einmal. Und läuft die Anwendung auf mehreren Instanzen, wirkt der Aufruf laut ISR-Anleitung zunächst nur auf der Instanz, die ihn erhält. Dann braucht es einen gemeinsamen Cache Handler, wie ihn der Self-Hosting-Leitfaden beschreibt. Grundlagen zu Cache-Lebensdauern und updateTag finden Sie auf der Seite zu Cache und Revalidierung, hier wiederhole ich sie nicht.

#Das Backend schonen

Vier Stellschrauben, alle aus der Next.js-Dokumentation oder aus dem Aufbau der Verfahren abgeleitet:

  • Eine Quelle, viele Leser. Ein Server hält eine Verbindung zur Datenquelle und verteilt Änderungen an alle verbundenen Browser. So fragt nicht jeder Browser einzeln.
  • Server Components lesen direkt. Die Dokumentation rät, Daten in Server Components direkt aus der Quelle zu holen und nicht über einen Route Handler, weil jeder Umweg eine zusätzliche HTTP-Runde kostet.
  • Häufig abgefragte Daten gehören an den Client. Für diesen Fall nennt dieselbe Seite die Bibliotheken swr und react-query.
  • Ratenbegrenzung zählt je Instanz. Hält ein Begrenzer seine Zähler im Speicher, zählt jede Instanz für sich, und ein Neustart setzt sie zurück. Mehrere Instanzen brauchen einen gemeinsamen Speicher oder die Begrenzung des Hosts.

#Welches Verfahren für welchen Wert

Das ist meine Empfehlung, abgeleitet aus den genannten Eigenschaften:

AnzeigeÄnderungsrhythmusVerfahrenHinweis
Lagerbestand im ShopgelegentlichRevalidierung auf EreignisVerfügbarkeit beim Bestellen erneut prüfen
Buchungsstatus im Kundenkontoje VorgangPolling alle paar Sekunden oder SSEAntwort nur für den angemeldeten Nutzer
Freie Plätze, ZählerlaufendSSE mit ZusammenfassungVerbindungslimit ohne HTTP/2 beachten
Betriebsdashboardlaufend, viele LeserSSEeine Quelle verteilt an alle
Chat, gemeinsames Bearbeitenin beide RichtungenWebSocket als eigener DienstGegendruck und Wiederverbinden planen

Bei Zahlen, die für eine Kaufentscheidung zählen, zeige ich neben dem Wert den Stand, also die Uhrzeit der letzten Aktualisierung. Eine Anzeige, die ehrlich sagt, wie alt sie ist, verträgt eine Verzögerung besser als eine, die Aktualität vortäuscht.

#Datenschutz: was in einem Stream steht

Ein Bestandszähler enthält keine Personendaten. Ein Buchungsstatus mit Namen schon, und er gehört nur in die Antwort an den angemeldeten Nutzer, nicht in einen öffentlichen Kanal. Die zuständige Aufsicht ist in Hamburg der Hamburgische Beauftragte für Datenschutz und Informationsfreiheit; auf seiner Website finden Sie die Beschwerde- und Meldeformulare sowie einen Bereich zum Handel, der unter anderem Online-Händler betrifft. Ob ein bestimmter Datenstrom unter die DSGVO fällt, klärt Ihre Rechtsberatung. Ich liste vorher, welcher Kanal welche Felder an wen sendet, damit diese Prüfung eine Grundlage hat.

#Checkliste für Ihre Live-Anzeige

  1. Wie alt darf jeder Wert höchstens sein? Eine Zahl je Wert, nicht je Seite.
  2. Wer ändert den Wert, und kann diese Quelle ein Ereignis senden?
  3. Wie viele Besucher sind gleichzeitig verbunden, und über welche HTTP-Version?
  4. Läuft die Anwendung auf einem Node-Server, in einem Container oder serverless? Welche Zeitgrenze gilt für eine offene Verbindung?
  5. Steht zwischen Server und Browser ein Proxy, CDN oder Load Balancer, der puffert?
  6. Enthält der Kanal Personendaten, und für wen darf er sichtbar sein?
  7. Was zeigt die Anzeige, wenn der Kanal ausfällt: den letzten Wert mit Stand oder eine Fehlermeldung?

#So läuft ein Projekt mit mir

Ich arbeite allein, aus der Ferne und in Schriftform, ohne Termine und Telefonate. Sie schreiben mir Ziel, Stack und Frist, ich antworte mit Rückfragen und einer schriftlichen Beschreibung von Umfang und Annahmen. Gebaut wird auf einer Staging-Umgebung; nach Ihrer schriftlichen Freigabe folgt der Livegang, auf Wunsch mit laufender Wartung. Für dieses Thema gehört ein Frischeplan dazu: eine Tabelle, die je Wert das Alter, die Quelle und das Verfahren festhält. Von Ihnen brauche ich Zugang zur Datenquelle, eine Beschreibung der Ereignisse, die sie melden kann, und das Layout. Es kommt von Ihnen, zum Beispiel als ausgefüllte Tabellenvorlage; Gestaltung gehört nicht zu meinem Angebot.

#Häufige Fragen

Reicht Polling, oder brauche ich SSE oder WebSockets? Für Daten, die sich in Minuten ändern, reicht Polling oder zeitgesteuerte Revalidierung. SSE lohnt sich, wenn der Server Änderungen sofort an viele Browser schicken soll und der Browser nichts zurückschicken muss. WebSockets brauchen Sie erst bei echtem Zweiwegeverkehr, etwa bei einem Chat.

Kann ein Next.js Route Handler WebSockets bedienen? Die Dokumentation nennt für Hosts, die Route Handler als Lambda-Funktionen betreiben, ausdrücklich, dass WebSockets nicht funktionieren. Ich plane einen WebSocket-Server deshalb als eigenen Prozess neben Next.js und nicht innerhalb eines Route Handlers.

Warum kommt mein Stream beim Nutzer erst am Ende an? Häufig puffert eine Schicht dazwischen: Nginx, ein Load Balancer, ein CDN oder die Kompression. Next.js empfiehlt für Nginx den Header X-Accel-Buffering mit dem Wert no. Ob die Teile wirklich einzeln eintreffen, prüfe ich mit einem kleinen Skript, das die Antwort als Stream liest.

Wie zeige ich aktuellen Bestand, ohne bei jedem Seitenaufruf das Warenwirtschaftssystem zu fragen? Das Warenwirtschaftssystem meldet Änderungen per Webhook, ein Route Handler ruft revalidateTag auf, und die Seite wird aus dem Cache bedient. Die Antwort kommt immer aus dem Cache, die Neuberechnung läuft einmal im Hintergrund, nicht je Besucher.

Was ändert sich, wenn die Anwendung auf mehreren Instanzen läuft? Der Cache liegt standardmäßig je Instanz auf der lokalen Platte, und revalidateTag wirkt zunächst nur auf der Instanz, die den Aufruf erhält. Mehrere Instanzen brauchen einen gemeinsamen Cache Handler, zum Beispiel auf Redis.

Gestalten Sie auch die Oberfläche? Nein. Das Layout liefern Sie, zum Beispiel als ausgefüllte Tabellenvorlage, in der Sie je Ansicht markieren, welches Element wohin gehört. Ich setze es responsiv um.

#Ihre Live-Anzeige in einer E-Mail

Soll in Hamburg ein Bestand, ein Status oder eine Buchungsübersicht aktueller werden, ohne dass Ihr Backend unter der Last leidet? Das Kontaktformular ist der Weg zu mir. Nennen Sie die Adresse der Anwendung, die Datenquelle dahinter, wie alt die Werte höchstens sein dürfen und Ihren Wunschtermin. Die erste schriftliche Schätzung ist kostenlos; ich antworte an Werktagen mit Rückfragen.

Brauchen Sie die Leistung: Next.js-Entwickler in Hamburg?

Beschreiben Sie Ihr Projekt per E-Mail. Antwort innerhalb von 48 Stunden.

Projekt beschreiben

Weitere WordPress-Dienste und Wissensbasis entdecken