1 Punkte von GN⁺ 2023-09-03 | 1 Kommentare | Auf WhatsApp teilen
  • Mux hat mux.com und docs.mux.com auf React Server Components umgestellt und dabei festgestellt, dass die Trennung der Ausführungsgrenzen zwischen Server und Client direkte Auswirkungen auf Bundle-Größe und Hydration-Kosten hat
  • RSC ermöglicht es Komponenten, Daten direkt auf dem Server abzurufen und das Ergebnis zu streamen, sodass Teile der Oberfläche schon angezeigt werden können, selbst wenn langsame Datenaufrufe noch laufen
  • Die größten Hürden der tatsächlichen Migration waren fehlende CSS-in-JS-Unterstützung, Einschränkungen von React Context in Server Components und die Komplexität, die Server/Client-Grenzen laufend nachverfolgen zu müssen
  • Im app directory von Next.js 13 sind Komponenten standardmäßig Server Components; indem man use client an der Wurzel schrittweise nach unten verschiebt, ist eine schrittweise Einführung möglich
  • Patterns wie Suspense, loading.js, das Beibehalten serverseitiger Bibliotheken und server-only sollten gezielt nur dort eingesetzt werden, wo Performance-Gewinne nötig sind; auch die kognitive Last fürs Team muss mit einkalkuliert werden

Umfang der RSC-Umstellung bei Mux

  • Mux hat im Zuge einer Neustrukturierung der Dokumentationssite und eines Rebrandings mux.com und docs.mux.com auf Server Components umgestellt
  • React Server Components sind auch in realen Codebasen einsetzbar und können sich lohnen, bringen aber zugleich Einschränkungen und Komplexität mit sich
  • Diese Erfahrung wird entlang der Fragen zusammengefasst, warum RSC nötig sind, wo sie passen, in welchen Situationen sie schwierig werden und wie man sie schrittweise in eine echte Codebasis einführen kann

Das Problem, auf das RSC nach CSR, SSR/SSG abzielt

  • Beim frühen Server-Rendering wurden mit Technologien wie PHP Daten auf dem Server abgerufen und rechenintensive CPU-Arbeit erledigt; an den Client wurde nur leichtgewichtiges HTML ausgeliefert
  • CSR/SPA schickte den Rendering-Code als JavaScript an den Client und ermöglichte so schnelle Interaktionen, zeigte aber Schwächen, wenn Suchmaschinen JavaScript nicht ausführten, Geheimwerte auf dem Server bleiben mussten oder Nutzer leistungsschwache Geräte bzw. langsame Verbindungen hatten
  • SSR/SSG erzeugt mit Tools wie Next.js und Gatsby HTML und JavaScript gemeinsam auf dem Server und sendet beides an den Client
    • Nutzer sehen das HTML sofort
    • Sobald JavaScript geladen ist, wird die Site interaktiv
    • Suchmaschinen können ebenfalls das HTML lesen
  • Auch bei bisherigem SSR/SSG bleiben Kosten bestehen
    • Ein Großteil des JavaScript, das zur Seitenerzeugung verwendet wurde, wird an den Client gesendet; der Client muss es erneut ausführen und per Hydration mit dem HTML verbinden
    • Dauert das Server-Rendering wegen langsamer Datenbankaufrufe oder viel auszuführendem Code lange, müssen Nutzer warten

Was React Server Components verändern

  • React Server Components sind React-Komponenten, die nicht auf dem Client, sondern auf dem Server ausgeführt werden
  • Frameworks mit RSC-Unterstützung ermöglichen es, explizit zu trennen, wo Code ausgeführt wird
    • Server Components: Code, der nur auf dem Server laufen soll
    • Client Components: Code, der auf dem Client laufen soll
  • Wenn der Ausführungsort getrennt ist, wird weniger JavaScript an den Client gesendet und auch während der Hydration ist weniger Arbeit nötig
  • Eine Server Component kann Daten direkt innerhalb der Komponente abrufen
    • Sie kann Node-Bibliotheken oder fetch verwenden
    • Dadurch lässt sich reduzieren, dass Daten auf Seitenebene gebündelt mit getServerSideProps geholt und dann fortlaufend als props nach unten gereicht werden
    • Auch Fälle, in denen komplexe Ladezustände mit useEffect verwaltet werden, nehmen ab
  • Eine Server Component, deren Datenabruf abgeschlossen ist, kann das Ergebnis zum Client streamen
    • Der Rest der Site kann zuerst angezeigt werden, während auf eine langsame Komponente gewartet wird
  • Es ist auch möglich, als Reaktion auf Nutzeraktionen im Client Daten auf dem Server abzurufen und die Antwort zu streamen; streng genommen gehört das jedoch nicht zu RSC, sondern zu React Actions

Was an RSC schwierig ist

  • CSS-in-JS funktioniert derzeit nicht in Server Components
    • Bei der RSC-Umstellung von Mux nahm der Wechsel von styled-components zu Tailwind CSS den größten Anteil ein
    • Codebasen, die stark von CSS-in-JS abhängen, benötigen zusätzliche Migrationsarbeit
  • React Context ist nur in Client Components zugänglich
    • Um Daten zwischen Server Components ohne props zu teilen, muss man wahrscheinlich normale Module verwenden
    • Einen guten Mechanismus, um Daten auf einen bestimmten Teilbaum einer React-Anwendung zu beschränken, gibt es in Server Components nicht
  • Auf der Dokumentationssite von Mux war das kein großes Problem, weil die Bereiche mit Context-Nutzung sehr interaktiv waren und ohnehin an den Client gesendet werden mussten
  • Auf der Marketing-Site wurde das Teilen von Theme-Informationen zum Problem
    • Jede Komponente im Pre-Footer musste wissen, dass sie auf einem grünen Hintergrund liegt, um einen dunkelgrünen Rahmen verwenden zu können
    • Als Umgehung wurden statt Context intensiv CSS custom properties genutzt
  • RSC geben Flexibilität beim Ausführungsort und beim Datenabruf, erhöhen aber ebenso die Komplexität
    • Neue Entwickler müssen ständig prüfen, „was auf dem Server läuft und was auf dem Client läuft“
    • In PRs entsteht immer wieder Feedback zu Code, der unnötig an den Client geschickt wurde
    • Während der Entwicklung wurde häufig console.log eingefügt, um zu prüfen, ob es sich um Server-Logs oder Browser-Logs handelt
    • Auch Caching bringt zusätzliche Komplexität mit sich

Die grundlegende Nutzung von RSC in Next.js 13

  • Zum Zeitpunkt des Schreibens ist die produktionsreife RSC-Implementierung das app directory von Next.js 13
  • Im app directory von Next.js 13 sind die Komponenten, die man schreibt, standardmäßig Server Components
    • Im Standardzustand wird der Seitencode nicht an den Client gesendet
    • An den Client wird nur HTML ausgeliefert
  • Wenn man einer Server Component async hinzufügt, kann sie innerhalb der Komponente Daten abrufen
  • Eine Server Component mit langsamem Datenabruf kann mit React.Suspense umschlossen werden
    • Auf dem Client wird zuerst eine Fallback-UI angezeigt
    • Sobald der Server die Daten abgerufen und das Rendering abgeschlossen hat, wird die Ergebnis-Komponente gestreamt
  • Eine Suspense Boundary kann nicht nur fürs Daten-Streaming verwendet werden, sondern auch für selective hydration, bei der die Hydration-Priorität bestimmter Bereiche je nach Nutzerinteraktion angepasst wird
  • Code, der auf dem Client ausgeführt werden muss, erhält am Dateianfang "use client"
    • Das nutzt man für Komponenten, die Client-State und Interaktion benötigen, etwa onClick-Listener oder useState
    • Alle Komponenten, die von einer Komponente mit "use client" importiert werden, werden ebenfalls an den Client gesendet
  • Bibliotheken, die RSC nicht unterstützen, können in einer Client Component importiert und in das Client-Bundle aufgenommen werden
    • Das Beispiel ist eine ClientMuxPlayer-Komponente, die @mux/mux-player-react umschließt

Entscheidungskriterien für Server Component oder Client Component

  • Server Components eignen sich für Code, der nicht an den Client gesendet werden muss
    • Rendering von Blogartikel-Inhalten
    • Aufwendige Arbeiten wie Syntax-Highlighting von Codeblöcken
    • Datenabruf
  • Client Components eignen sich für UIs, die auf Nutzereingaben reagieren oder deren Zustand sich im Zeitverlauf ändert
    • useState
    • Event-Listener
    • Client-seitige Interaktion
  • Wenn man die gesamte App als Client Components baut, verhält sie sich ähnlich wie ein bisheriges SSR-Framework
  • Man muss nicht die gesamte App auf einmal in Server Components umwandeln, sondern kann sie schrittweise dort einführen, wo der Nutzen am größten ist

Drei Schritte zur schrittweisen Einführung in einer echten Codebasis

  • Das von Mux verwendete Playbook besteht aus drei Schritten
    • Die Direktive "use client" an der App-Wurzel hinzufügen
    • Die Direktive im Render-Tree so weit wie möglich nach unten verschieben
    • Fortgeschrittene Patterns anwenden, wenn Performance-Probleme sichtbar werden
  • In Schritt 1 wird "use client" in der obersten page.tsx von Next.js 13 hinzugefügt, damit sich die App wie bisher verhält
  • Wenn serverseitiger Datenabruf nötig ist, fügt man eine Server Component als Parent einer Client Component hinzu
    • Die Server Component ruft die Daten ab
    • Die abgerufenen Daten werden als props an die Client Component übergeben
    • Das kann die bisherige Rolle von getServerSideProps ersetzen
  • In Schritt 2 wird "use client" von der obersten Komponente in Kindkomponenten verschoben
    • Bei <Title />, das keinen Client-Code benötigt, kann die Direktive entfernt und reines HTML ausgeliefert werden
    • Bei <Player />, das Client-Code benötigt, entstehen Fehler, daher bleibt "use client" erhalten
  • Dieser Ansatz sorgt dafür, dass bei neuen Komponenten und bestehenden Refactoring-Kandidaten Server Components berücksichtigt werden, und hilft dabei, die Bundle-Größe teilweise zu reduzieren

Patterns, die bei Performance-Problemen angewendet wurden

  • Die Mux-Dokumentationssite wird größtenteils statisch generiert, die Changelog-Sidebar stammt jedoch aus einem CMS
  • Wenn die Sidebar mit Suspense umschlossen wird, muss der Rest der App nicht warten, bis der CMS-Fetch abgeschlossen ist
  • Auch die loading.js-Konvention von Next.js 13 nutzt intern Suspense und Streaming
  • Um große Bibliotheken auf dem Server zu halten, müssen Client Components und Server Components passend platziert werden
    • Als Beispiel wurde die Syntax-Highlighting-Bibliothek Prism auf dem Server gehalten

Server Components in Client Components mischen

  • Komponenten, die eine Client Component importiert, werden zusammen mit ihr zu Client Components
  • Wenn man eine Server Component als Kind einer Client Component verwenden möchte, darf man sie nicht importieren, sondern muss sie über children oder props übergeben
    • Die Server Component wird auf dem Server gerendert
    • Das serialisierte Ergebnis wird an die Client Component übergeben
  • Der falsche Weg ist, eine Server Component direkt in einer Client-Component-Datei zu importieren
  • Der richtige Weg ist, zur nächstgelegenen übergeordneten Server Component hochzugehen und der Client Component die Server Component als Kind oder prop zu übergeben

Eine Datei lässt sich nicht halb Server, halb Client aufteilen

  • Es ist nicht möglich, die eine Hälfte einer Datei zur Server Component und die andere Hälfte zur Client Component zu machen
  • Mux verwendete häufig ein Pattern, bei dem die Funktionalität auf zwei Dateien aufgeteilt wurde
    • CodeBlock.server.js: importiert die große Syntax-Highlighting-Bibliothek und rendert auf dem Server
    • CodeBlock.client.js: verwendet useState und onClick, damit Nutzer zwischen Codebeispielen wechseln können
  • Die auf dem Server gerenderten Beispiele werden als props an die Client Component übergeben, sodass serverseitige Arbeit nicht ins Client-Bundle gelangt
  • Wenn CodeBlock.server.js in index.js erneut exportiert wird, müssen Nutzer nur CodeBlock importieren und sich nicht um die interne Server/Client-Trennung kümmern

Sicherstellen, dass Code nur auf dem Server ausgeführt wird

  • Anfangs wurde während der Entwicklung console.log hinzugefügt, um zu prüfen, ob die Logs vom Server oder aus dem Browser kamen
  • Um sicherzustellen, dass serverseitiger Code nicht ins Bundle aufgenommen wird, kann das server-only package importiert werden
  • server-only ist nützlich, um zu verhindern, dass große Bibliotheken oder geheime Schlüssel an die falsche Stelle verschoben werden
  • Next.js stellt Schutzmechanismen bereit, die verhindern, dass Umgebungsvariablen versehentlich im Browser-Bundle landen
  • server-only am Dateianfang hilft auch bei der Wartung
    • Zuständige sehen sofort, dass diese Datei auf dem Server ausgeführt wird

Kosten und Nutzen bei der Entscheidung für die Einführung

  • React Server Components sind keine Funktion, die man kostenlos bekommt
  • Zu den Kosten gehören neben Einschränkungen bei CSS-in-JS und React Context auch folgende Punkte
    • Verständnis der Ausführungsorte Server und Client
    • Verständnis von Hydration
    • Infrastrukturkosten
    • Code-Komplexität durch das Mischen von Client Components und Server Components
  • Komplexität vergrößert die Angriffsfläche für Bugs und kann die Wartbarkeit des Codes senken
  • Frameworks reduzieren Komplexität, beseitigen sie aber nicht
  • Zu den erwartbaren Vorteilen gehören
    • kleinere Bundle-Größen
    • schnellere Ausführung
    • Performance-Verbesserungen, die für SEO wichtig sind
    • fortgeschrittene Datenlade-Patterns für komplexe, datenreiche Sites
  • Wenn ein Team bereit ist, die zusätzliche kognitive Last zu tragen, und die Performance-Gewinne groß genug sind, kann RSC gut passen

1 Kommentare

 
GN⁺ 2023-09-03
Meinungen auf Hacker News
  • Bei serverseitigem Rendering bekommt der Client HTML, das sofort sichtbar ist.
    Das ist mir auch aufgefallen: Wenn man eine Plaintext-Datei auf den Server legt, wird sie ziemlich schnell an den Browser ausgeliefert.
    Legt man eine weitere Plaintext-Datei mit der Endung .css dazu, weiß der Browser, wie er sie verarbeiten muss, sodass sich die Elemente auf dem ersten Bildschirm bewegen und vielleicht sogar ziemlich gut aussehen.
    Ein netter Trick, aber immer noch zweitrangig gegenüber nützlichen Inhalten, die man auf dem ersten Bildschirm lesen kann.

    • Mein kleiner Bruder hat dieses Jahr angefangen, Webentwicklung zu lernen, und war völlig überrascht, als ich ihm sagte, dass man HTML über HTTP senden kann.
    • Browser haben ursprünglich als Hypertext-Clients begonnen, sind aber irgendwann zu einer Anwendungsplattform geworden, in der man sogar so etwas wie maßgeschneiderte Hypertext-Clients implementiert.
      Ich weiß nicht, wie aus „Lasst uns Funktionen hinzufügen, die Hypertext mächtiger machen“ irgendwann „Implementiert euch jetzt selbst brauchbare Anwendungen auf diesem großen, inkonsistenten Haufen von Features“ wurde.
    • Willst du als Nächstes sagen, dass man auch Textdateien ausliefern kann, die Code pro Seite ausführen?
    • Ich dachte, diese Technologie sei verloren gegangen.
  • Bevor man sich auf RSC einlässt, sollte man kurz innehalten.
    Was auch immer man bauen will, lässt sich mit einem echten Full-Stack-Framework oder einem klassischen Web-Framework viel einfacher, schneller und skalierbarer umsetzen.
    Rails/Django/Laravel/… mit Turbolinks/Htmx/… kombinieren oder einfach ein wenig clientseitiges JavaScript einstreuen, reicht oft schon.
    Wenn man Elixir/Phoenix kennt, kann man sogar mehrere Vorteile zugleich mitnehmen.
    Egal wie viele Leute darüber twittern: Man sollte nicht weiter in Richtung RSC gehen.
    Leute mit weniger als 10 Jahren Branchenerfahrung werden wieder über die grundlegenden Probleme stolpern, die man früher bei Vanilla-PHP-Sites hatte; ich habe sogar schon Inline-SQL-Hooks in React-Komponenten gesehen.
    Diesmal kommt noch viel mehr zufällige Komplexität obendrauf.
    Bleibt bei Verstand, bringt echte Produkte schnell heraus und verdient euch das Geld für den Lamborghini.

    • RSC erinnert mich an CORBA.
      CORBA mischt lokale und entfernte Komponenten, ist ausgereift und funktioniert in mehreren Sprachen.
      Warum nutzt es dann nicht jeder? Die meisten Entwickler von heute haben wahrscheinlich noch nie davon gehört.
      Wer eine weitere Architektur für verteilte Komponenten bauen will, sollte untersuchen, warum CORBA und seine Nachfolger sich nie breit durchgesetzt haben.
      Der Hinweis lautet: Versteckte Komponentengrenzen erzeugen versteckte Komplexität.
      Gleichzeitig funktionieren die Lager „servergerendertes HTML“ und „clientgerendertes HTML“ beide gut.
      Ich finde, wir können uns glücklich schätzen, dass man in jedem Webprojekt beide Optionen nutzen kann.
      Ich hoffe, die Arbeit an RSC verwässert nicht Reacts Unterstützung für rein clientgerenderte Apps.
      1. https://en.wikipedia.org/wiki/Common_Object_Request_Broker_A...
    • Wenn man Elixir/Phoenix kennt, stimmt das wirklich.
      Wenn man nicht zwingend eine vollständige progressive Rich-Frontend-App braucht, erledigt LiveView das meiste über serverseitige Komponenten mit minimalem JavaScript.
      Darüber hinaus bekommt jeder Nutzer einen serverseitigen Thread, sodass Änderungen aktiv an das Frontend des Nutzers gepusht werden können, ohne explizite JavaScript-Handler zu schreiben.
    • Genau das stimmt.
      Die Branche scheint unter Gedächtnisverlust im 10-Jahres-Zyklus zu leiden.
      Es gab sehr gute Gründe, warum man sich von servergerenderten UIs entfernt hat.
      Natürlich gibt es immer das Argument der Suchmaschinenoptimierung, aber wenn das eure Sorge ist, baut einfach eine traditionelle Server-Template-Site.
      Die überwiegende Mehrheit der Single-Page-Apps braucht SSR und dessen Komplexität überhaupt nicht.
    • Ich arbeite bei Mux, und als interessante Tatsache: Elixir war von Anfang an ein Kernbestandteil unserer Infrastruktur.
      Die ersten Dashboard-Oberflächen wurden komplett mit Phoenix gerendert, und nur auf Seiten, die wirklich anspruchsvolle clientseitige Interaktionen brauchten, wurde React gezielt eingebunden.
      Weil unser erstes Produkt ein Analytics-Dashboard war, wurde daraus schnell fast das gesamte Dashboard, und es war naheliegend, auf Basis der API, die wir unseren Kunden bereits bereitstellten, zu einer vollständigen Single-Page-App zu wechseln.
      Das war 2016, LiveView gab es also noch nicht, aber ich bin mir nicht sicher, ob wir heute eine andere Entscheidung treffen würden, wenn wir dieses Produkt neu bauen würden.
      Der Blogbeitrag handelt von der Anwendung, die unsere öffentliche Marketing-Site betreibt, und deren Anforderungen sind ziemlich anders; ich wollte aber erwähnen, dass auch wir Elixir/Phoenix verwenden und mögen.
  • Ich habe das Gefühl, alt zu werden
    Heutige Frameworks sind viel zu groß und komplex
    Selbst ein simples Web-„Hello world“ braucht eine riesige Build- und Compile-Pipeline, und jetzt kommen sogar noch serverseitige Komponenten dazu
    Ich frage mich wirklich, wie groß der Overhead ist
    Ich weiß nicht, durch wie viele Schichten Frontend- und Backend-Framework-Code ein Hello-World-Beispiel läuft
    Ich gehe zurück zu einem einfachen 10-KB-Komponenten-Framework, das neu baut, wenn ich nur F5 drücke

    • Solche Frameworks wurden nicht entwickelt, um simple Hello-World-Apps zu lösen
    • Bei vielen Websites habe ich frustrierenderweise das Gefühl, dass sie in jeder Hinsicht besser wären, wenn man sie einfach nur mit HTML und CSS gebaut hätte
      Man optimiert viel zu früh für schicke Features, die vielleicht irgendwann einmal kommen
      Das ist so, als würde man sagen, man müsse Ingenieure einstellen, um Kernproben zu nehmen und seismische Modellierung zu betreiben, bevor man einen Hühnerstall baut
    • Genau deshalb sieht man eine Bewegung weg von dieser Komplexität
      Junge Entwickler beginnen das jetzt zu erkennen
      So wie wir schreckliche Dinge wie SOAP und XML hinter uns gelassen haben und zu einfacheren, angenehmer nutzbaren Technologien gewechselt sind, lernt auch diese Generation wieder, dass Komplexität schädlich ist
      Vielleicht macht Softwareentwicklung für ein paar Jahre wieder Spaß, bevor die nächste Generation wieder alles vermasselt
    • Diese Art von Sichtweise ist wirklich nervig
      Eine Pipeline kann je nach Anwendungsfall so komplex oder so einfach sein wie nötig
      Man kann nur statische Dateien verwenden, ein kleines Makefile mit einem einzigen esbuild-Befehl nutzen oder eine riesige Webpack-Konfiguration mit 30 Plugins haben
      Man kann völlig frei nach den Anforderungen und der Komplexität dessen wählen, was man bauen will
      Außerdem ist es nur dann sinnvoll, Tools danach zu bewerten, wie leicht sich damit ein einfaches Hello world bauen lässt, wenn die Arbeit tatsächlich darin besteht, solche Apps zu bauen
    • Dieser Blogbeitrag behandelt SSR besser als die meisten Beiträge, die ich gesehen habe
      Wenn SSR oder Ableger davon ins Gespräch kommen, frage ich mich immer, ob das nicht unnötig alles komplexer macht
      React Server Rendering Components klingen, als seien sie zu weit gegangen, und sie widersprechen dem natürlichen Fluss der Developer Experience
      Wenn sich die Anwendungskomplexität verdoppelt, es mehr Coding-Fallen gibt und Entwickler langsamer und verwirrter werden, während man nur einen kleinen Performance-Gewinn erhält, frage ich mich, ob es das wert ist
      Frühe PHP-Sites und Rails-Apps ohne Single-Page-App haben auch lange gut funktioniert
  • Ich habe beim Erstellen einer neuen Anwendung mit Next.js und der neuen app-Verzeichnisstruktur einiges erlebt
    Erstens ist es schwer nachzuvollziehen, was auf dem Server passiert und was auf dem Client
    Um das zu wissen, muss man nachforschen, aber wenn man schnell Code schreibt, achtet man meistens nicht besonders darauf
    Eine kleine Änderung kann leicht dazu führen, dass große Teile einer Seite plötzlich vom Server auf den Client wandern wollen
    Ich weiß, dass ich vor dem finalen Release pro Seite eine vorsichtige und zeitaufwendige Prüfung machen muss, und das gefällt mir nicht
    Zweitens gehen viele bestehende React-Libraries davon aus, dass sie im Client ausgeführt werden, weil sie Hooks verwenden
    Dadurch kann Code auf den Client gezogen werden
    Ziel des Kampfes mit dem neuen Paradigma ist serverseitiges Rendering für schnelles Laden und Suchmaschinenoptimierung, aber wenn importierte Libraries nicht gut mitspielen, ist das komplette Verschwendung
    Drittens hat das neue Next.js-app-Verzeichnisparadigma Bugs
    Es ist noch neu und sehr komplex, sodass dynamische Routes, parallele Routes und deren Zusammenspiel vollständig kaputtgehen können
    Ich habe selbst ein Issue auf GitHub von Next.js eröffnet, und es gab viele Kommentare mit „bei mir auch“
    Einen der Ansätze, die ich verwendet hatte, hat ein Vercel-Entwickler kürzlich behoben, aber da hatte ich bereits einen anderen Ansatz gewählt, um das Problem zu umgehen
    Am nervigsten ist, dass die Entwicklungsumgebung Lazy Loading und Caching-Magie verwendet
    Sie scheint Seitenunterschiede zu berechnen und Teil-Updates über etwas wie WebSockets senden zu wollen, aber das kann komplett kaputtgehen und in einen nicht wiederherstellbaren Zustand geraten
    Manchmal löst ein Recompile irgendeine Kommunikation vom Server zum Client aus, und wenn ich zum Chrome-Tab zurückkehre, friert der Tab komplett ein, sodass ich den Prozess über den Chrome-Task-Manager beenden muss
    Insgesamt ist das alles noch sehr neu und hat viele raue Kanten

    • Bezieht sich die Aussage „viele bestehende React-Libraries gehen davon aus, dass sie im Client ausgeführt werden, weil sie Hooks verwenden“ nicht eher auf Context statt auf Hooks?
      Viele Hooks funktionieren auch serverseitig und tun tatsächlich nichts weiter, als Werte zu initialisieren
  • Interessant ist, dass PHP und JavaScript syntaktisch im Grunde ziemlich nah beieinander lagen.
    Der Unterschied beschränkte sich etwa auf das $-Zeichen oder das Keyword var, aber NodeJS sagte: „Wir wollen JS auf dem Server ausführen.“
    Und 15 Jahre später hat JavaScript schließlich aufgeholt und ist praktisch PHP ähnlich geworden – nur mit mehr Abkürzungen und einer steileren Lernkurve.
    Natürlich ist es cool, mit Suspense Daten vom Server zu Client-Komponenten zu streamen.
    Ich nutze NextJS 13, und mir gefällt, dass es SSR so einfach macht, wie es in PHP schon immer möglich war; ich kann es sehr empfehlen.

    • Fairerweise war PHP vor Version 7 je nach Zeitpunkt entweder eine Müllhalde oder etwas noch Gefährlicheres.
      Wenn Leute es als „Fraktal schlechten Designs“ bezeichneten, war das zu 100 % nachvollziehbar, und es war berechtigt, sich anderswo nach Lösungen umzusehen.
      Heute ist PHP eine deutlich bessere Sprache und einen erneuten Blick wert, aber man sollte nicht so tun, als sei es früher schon so gut gewesen wie heute.
      Und man sollte NodeJS nicht am React-Ökosystem messen.
      Die enorme Menge an APIs und Wrappern, die nötig ist, um React-basierte Systeme zu betreiben, geht auf das Konto der React-Community.
      Klassisches Stockholm-Syndrom.
    • PHP hat kein Client-Side Rendering, daher ist der Vergleich seltsam.
    • Oft wird ignoriert, dass sich auch die Browser selbst stark verbessert haben.
      Viele moderne Fortschritte wurden erst möglich, weil die Browser zuvor besser geworden sind.
      Es ist weniger ein vollständiger Kreis als vielmehr ein Gebilde, das aus sehr großer Entfernung wie ein Kreis aussieht.
    • Ich mochte NodeJS nie.
      Einerseits war es innovativ, weil man dank des Nebenläufigkeitsmodells schnellere Backends bauen konnte; andererseits fehlten viele Funktionen etablierter Backend-Sprachen wie Java oder PHP, sodass viele Patterns neu erfunden wurden.
      Auch die Sprache selbst brauchte Jahre, um das Niveau an „Sicherheit“ zu erreichen, das Java bereits hatte und auf das PHP zusteuerte.
      Bewährte und standardisierte Technologien wie XML und die vertraglichen Garantien, die es bieten konnte, wurden ebenfalls verworfen – mit Begründungen wie, es sei zu schwergewichtig, und JSON sei für Menschen leichter zu lesen und zu schreiben.
      Ich habe das Gefühl, dass mit dem Verzicht auf XML viel Zeit und Aufwand verloren ging.
      Die Dokumentation von REST/JSON-APIs ist immer noch schmerzhaft.
      Schon vor 20 bis 25 Jahren konnte man aus XML-Payloads Datenmodelle und Parser generieren.
      Ich weiß bis heute nicht, was an XML so problematisch gewesen sein soll.
      Auf der Leitung war es etwas schwerer als JSON, aber das ließ sich mit Kompression oder mit EXI (https://www.w3.org/TR/exi/) lösen, indem man daraus ein binäres Protokoll machte.
      Ich weiß nicht, ob sich EXI tatsächlich durchgesetzt hat, aber weil ich damals wusste, wie viel XML unterwegs war, hatte ich recht hohe Erwartungen daran.
    • Viele der ursprünglichen Gründe, aus denen NodeJS entstand, scheinen in Vergessenheit geraten zu sein.
      Damals sorgte nicht blockierende Ein-/Ausgabe für einen großen Performance-Schub.
      In den Köpfen moderner Entwickler scheint es jedoch zu einem dummen Tool degradiert worden zu sein, das JSON ausspuckt oder Toolchains hostet.
  • Man nutzt wohl, womit man vertraut ist, aber für eine Dokumentationsseite React statt eines fertigen statischen Site-Generators oder CMS mit Caching zu verwenden, wirkt wie Verschwendung.
    Aus Entwicklersicht kann React natürlich mehr Spaß machen.

    • Eine gute Dokumentationsseite hat viele kleine dynamische Teile.
      Stripe hat den Trend angestoßen, Code-Snippets mit dem API-Schlüssel des eigenen Kontos anzuzeigen, damit man sie direkt testen kann.
      Frontend-Dokumentationsseiten enthalten fast immer ausführbare Beispiele, die man direkt in der Dokumentation ausprobieren kann.
    • Ich höre dieses Argument oft, verstehe es aber nicht wirklich.
      Ein neues Projekt zu bootstrappen ist extrem einfach und schnell – im Grunde einfacher, als ein reines HTML-Projekt zu starten.
      Was übersehe ich?
      Außerdem interessiert mich die Sichtweise der Leute, die Downvotes geben, wirklich.
    • Stimme zu.
      Es ist statischer Inhalt; ich verstehe nicht, warum man ihn nicht als HTML generiert und nur ein wenig JavaScript für die Suche hinzufügt.
    • Es wird statisch generiert.
      Der Grund für React ist, im gesamten Frontend eine Sprache zu verwenden.
      So vermeidet man, dass die einen auf einer Site React verwenden und andere Gatsby/Hugo.
      Next.JS kann dasselbe wie Gatsby/Hugo, bietet aber mehr Funktionen und basiert auf React.
    • „Aus Entwicklersicht macht es mehr Spaß“ ist eigentlich ein Fluch – sowohl für Softwareentwickler als auch für Arbeitgeber.
  • Ich bin alt genug, um mich an die Zeiten zu erinnern, als der Server alles gerendert hat und CSS und JavaScript dazu da waren, die gerenderte Seite anzureichern.
    Das Web ist ein sehr düsterer und overengineerter Ort geworden.
    Fast unglaublich.
    Deshalb baue ich meine Apps so: zuerst Server-Rendering, später anreichern.

    • Im Großen und Ganzen stimme ich zu.
      Einklappbare Dropdowns oder Drag-and-drop mit jQuery sind nette Features, aber ich erinnere mich auch noch sehr deutlich an die State-Management-Hölle aus der JS/jQuery-Zeit und möchte dorthin nicht zurück.
    • Ihr benutzt JavaScript?
      Nur Spaß: Meine erste Geocities-Seite war HTML mit Dingen wie einem Besucherzähler oder marquee.
      Auch meine erste PHP-Anwendung/mein erstes PHP-Projekt in der Schule nutzte noch kein JS; für statische Menüs und Header verwendete ich Frames, und Daten gingen einfach per Formular-Submit ans Backend.
      Solche Zeiten gab es.
      In meinem ersten einjährigen Praktikum im Rahmen des Studiums verwendeten wir ein Java-Backend, JSX-Templates in der Darstellungsschicht und PrototypeJS für Dinge wie Dialoge oder animierte Akkordeons.
      Animation bedeutete damals: „die Höhe dieses Elements ein paar Mal pro Sekunde ändern“.
      In meinem ersten Job schrieb ich viel JS, das Seiten mit Dingen wie „In den Warenkorb legen“ oder Bildkarussells anreicherte; das war die jQuery-Ära.
      Im nächsten Job baute ich mit BackboneJS ziemlich miserabel eine UI, in der Support-Mitarbeiter in SAP-ähnliche Dinge schauen konnten.
      Danach ging es ebenfalls darum, ein Investmentbanking-Frontend für Kunden mit BackboneJS neu zu bauen.
      Das war ein Anwendungsfall, der sehr gut zu dem passte, was man damals Single-Page Application nannte.
      Suchmaschinenoptimierung war nicht nötig, reines Frontend-Rendering war schnell genug, es war API-zentriert, und damals begannen die Leute zu begreifen, dass man dieselbe API für Web und Mobile nutzen konnte.
    • Aus einer anderen Perspektive: Ich erinnere mich auch an die Zeit, als CSS und JavaScript erfunden wurden, und baue seitdem Websites.
      Meiner Meinung nach waren Webentwicklungswerkzeuge nie besser als heute, und auch die User Experience hat sich über die Jahre enorm verbessert.
      Was wir früher AJAX nannten, ist von einem netten Zusatz-Gimmick zu einem alltäglichen Grundbaustein in Form von Client Components und Single-Page Apps geworden.
      Server sind weiterhin leistungsfähig, wenn man das will, aber für interaktive Apps wie Dashboards, Karten, Spiele, Foren, Office-Apps oder Online-IDEs sind starke clientseitige Fähigkeiten gut.
      Dadurch konnten Alltags-Apps in großem Stil von maßgeschneiderten Desktop-Apps für jedes Betriebssystem auf eine universelle Plattform für alle Laptops und Desktops wandern.
      Natürlich erforderte diese Macht auch mehr Komplexität.
      Einen Blog oder eine Landingpage mit HTML/CSS zu schreiben, ist etwas ganz anderes, als eine vollständige Web-App zu schreiben.
      Angular und React entstanden, um die Entwicklung von Apps zu unterstützen, die um ein Vielfaches komplexer waren als zuvor – zu einer Zeit, als die JS-Runtime und die Sprache selbst im Vergleich zu serverseitigen Sprachen noch deutlich primitiver waren.
      In den späten 2010ern gab es eine wirklich schmerzhafte Phase, in der verschiedene JS-Frameworks jeweils nur sehr kleine Teile des Problems lösten.
      Heute ist das weniger der Fall.
      Next hat gewonnen und ist zum Default geworden, und das aus gutem Grund.
      Es bietet für Apps mittlerer Komplexität eine passende Abstraktionsebene und erlaubt es, serverseitiges Rendering und clientseitige Seiten gut zu mischen.
      React Server Components machen diese Unterscheidung zu einem saubereren First-Class-Konzept.
      Allerdings ergibt das erst ab einer gewissen Komplexität Sinn.
      Wenn man es nicht braucht, muss man es nicht verwenden.
      Für einen größtenteils statischen Blog oder eine Dokumentationsseite gibt es einfachere Architekturen.
      Man kann weiterhin HTML schreiben und nach Bedarf ein paar Zeilen JS einstreuen, und für die meisten kleinen Unternehmen sind auch WordPress oder Wix möglich.
      Wenn man aber komplexere Apps baut, ist React im Vergleich zu dem alten Ansatz wirklich ein Traum, bei jeder kleinen Interaktion zum Server zurückzugehen, die UI neu zu berechnen und jedes Mal die komplette HTML-Seite zu schicken.
      Dieser Ansatz führte dazu, dass Kontext, Position auf der Seite und halb ausgefüllte Formulare verloren gingen, er ermutigte dazu, Formulardaten als State zu benutzen, und oft verlor man Arbeit, wenn man versehentlich auf Zurück klickte oder – bevor einfache Cloud-Skalierung verfügbar war – Server häufig ausfielen.
      Meiner Ansicht nach ist es nur dann Overengineering, wenn es falsch eingesetzt wird.
      In den passenden Anwendungsfällen sind diese Werkzeuge wirklich nützlich und manchmal unverzichtbar.
      Der bedauerliche Teil ist vielleicht, dass sie zu oft gelehrt und ihr Einsatz auch in Situationen gefördert wird, in denen sie nicht nötig oder sogar schädlich sind.
      Am Ende sollte man das passende Werkzeug für die Aufgabe verwenden.
      Ich will React nicht gegenüber Vue, Svelte oder HTMX pushen; ich meine nur, dass clientseitige Komplexität ebenfalls ihren Nutzen hat.
    • Genau für diesen Ansatz, also Server Components, sind sie da.
  • Ich habe den Eindruck, dass React versucht, modernere, einfachere, schnellere und günstigere Alternativen einzuholen.
    Statt aber die grundlegenden Probleme – Re-Rendering, häufig nötige Memoization und leaky Abstractions – zu beheben, wird React immer komplexer.
    Wenn das Endergebnis großartig wäre, könnte ich den Aufwand verstehen, aber das ist es nicht.
    React ist in realen Umgebungen langsamer, als Benchmarks vermuten lassen, und Next ist noch schlimmer.
    In letzter Zeit habe ich viele sehr langsame Websites gesehen, die mit Next gebaut wurden.
    Ich verstehe es wirklich nicht.
    Wenn das React-Team React verbessern will, muss es den Kern reparieren.

    • Das können sie nicht reparieren.
      Inzwischen gibt es so viele Abhängigkeiten im Ökosystem, dass alles kaputtgehen würde.
      Target.com, Walmart.com, Microsoft Teams und unzählige andere Sites verwenden React.
      Dazu kommen ein riesiges Komponenten-Ökosystem und Unternehmen, die darauf aufgebaut sind.
      Die Kernkonzepte sind kaputt, aber sie zu reparieren würde bedeuten, potenziell alles andere kaputtzumachen.
      Wenn man ohnehin alles kaputtmacht, ist es besser, etwas anderes zu verwenden.
      Derzeit ist man durch die Masse der Abhängigkeiten an React gebunden und muss damit weiterrollen.
      React rendert standardmäßig neu und man muss sich herausoptieren, während Vue, Solid, Preact und Svelte alle nur dort einsteigen, wo es nötig ist.
      Das ist einer der Hauptgründe, warum es schwer korrekt zu verwenden und anfällig für bestimmte Arten von Bugs ist.
      Oberflächlich sieht es wie normales JavaScript aus, aber man muss ständig darauf achten, ob man sich herausoptieren muss; in anderen Frameworks sind solche Bugs selten oder kommen fast gar nicht vor.
    • Für Re-Rendering und die häufig nötige Memoization gibt es diese Arbeit:
      https://react.dev/blog/2023/03/22/react-labs-what-we-have-be...
  • Ich verstehe nicht, warum man jetzt wieder React im Backend verwendet, um HTML zu rendern
    Wollen wir etwa 10 Jahre zurück?

    • Dass es in „dieser Umgebung“ ein Template-System gibt, ist wirklich viel wert
      Ich wechsle heutzutage oft zwischen Svelte und Django-Templates, und allein dass Svelte das DOM kennt, macht die Erfahrung deutlich besser
      So etwas habe ich in einem Template-System, das nicht JS ist, noch nie gesehen
      PHP und jQuery usw. habe ich ebenfalls erlebt
    • Reacts Programmiermodell ist für viele attraktiv, und React passt gut zu Problemen mit vorhersagbarer Ausgabe wie HTML
      Außerdem ist es viel einfacher, die gesamte HTML-Erzeugung an einem Ort zu halten, wenn das Frontend React ist
    • 25-jährige „Senior“-Entwickler brauchten eine alte Technologie, auf die sie herabschauen konnten, um ihr Ego zu stützen, und PHP war dieses Ziel
    • Weil Vercel Ihr Backend hosten will und nach React greift
    • Es ist besser als die meisten anderen Template-Systeme, und wenn man Interaktivität hinzufügen möchte, kann man das mit einer Sprache und einem Paradigma erledigen
      Dazu kommt noch Unterstützung für statische Typisierung
  • Ich will RSC oder React nicht als die beste Lösung aller Zeiten verteidigen, aber einige der Gegenargumente hier sind unausgereift
    Die Vorteile von React/RSC sind technisch nicht dasselbe wie wenn ein Server HTML/CSS und etwas JavaScript zurückgibt
    Es bleibt eine einzige App, und im Vergleich zu SSR/Hydration ist es ein intelligenterer Umgang mit der Client/Server-Grenze
    Ich würde gerne fundiertere Einwände dazu lesen, ob React sich selbst in eine Sackgasse designt hat und welche Auswege es gibt, aber zu PHP zurückzukehren ist keine Antwort

    • HN ist heutzutage kein guter Ort, um eine fundierte Frontend-Perspektive zu bekommen
      React ist auch nicht so schwer zu lernen, und es gibt einen Grund, warum selbst Nicht-Entwickler nach ein paar Wochen Bootcamp die Grundlagen beherrschen
      JSX ist den Template-Systemen von Django, PHP und Rails objektiv überlegen
      Bei der Hälfte der hingeworfenen Gegenargumente habe ich den Eindruck, dass die Leute ihre eigenen Projekte nicht einmal mit etwas wie Lighthouse gebenchmarkt haben