- Das Hardcover-Team migrierte wegen nachlassender Performance der Next.js-basierten Architektur, hoher Kosten und sinkender Entwicklungsgeschwindigkeit zu Ruby on Rails + Inertia.js
- Für die Anforderungen SSR mit SEO, direkte DB-Anbindung und Beibehaltung von React fiel die Wahl auf Inertia.js
- Ausschlaggebend für den Wechsel waren unerwartet explodierende Kosten bei Vercel und Cloud Run sowie die Unklarheiten beim Caching in Next.js
- Inertia.js erwies sich als ideale Möglichkeit, ein Rails-Backend mit einem React-Frontend zu verbinden, wodurch SSR und Cache-Management einfacher wurden
- Nach der Umstellung verbesserten sich Google Pagespeed und SEO-Werte, und Verweildauer sowie Sichtbarkeit in der Suche nahmen zu
Hintergrund der Umstellung
- Zu Beginn entschied man sich für Next.js mit SEO- und SSR-Unterstützung und baute eine Architektur auf Basis einer GraphQL-API
- Die meisten Daten wurden im Browser clientseitig angefragt, statische Daten dagegen auf dem Server gecacht
- Mit der Zeit führten fehlendes Caching zu mehr API-Anfragen, nachlassende Performance und eine langsamere Entwicklungsumgebung zu Problemen
Probleme mit Next.js
- Auch nach dem Wechsel zum App Router blieb der Geschwindigkeitsgewinn gering; Apollo-POST-Anfragen wurden nicht gecacht, sodass der erwartete Effekt ausblieb
- Durch Änderungen am Preismodell von Vercel stiegen die monatlichen Kosten von 30 auf 354 US-Dollar
- Auch Cloud Run war anfangs günstig, stieg aber auf bis zu 524 US-Dollar
- Die Caching-Struktur von Next.js war schwer zu durchschauen, effizientes Management dadurch kaum möglich
- Das Entwicklungstempo sank deutlich, was das Onboarding neuer Teammitglieder erschwerte
Warum Rails + Inertia.js
- SSR sollte erhalten bleiben, gleichzeitig wollte man Daten direkt aus der Datenbank abrufen
- React sollte weiter genutzt werden; Remix, react-rails und react_on_rails wurden ebenfalls geprüft, letztlich fiel die Entscheidung aber auf inertia-rails
- Mit Inertia.js lässt sich Rails-Routing ohne Frontend-Routing nutzen, und auch SSR ist unkompliziert umsetzbar
- Im Controller erfolgt das Rendering mit
inertia: '페이지명', das Caching wird über Rails.cache.fetch umgesetzt
- React-Komponenten empfangen Props über
usePage()
SSR- und Build-Struktur
- Für SSR wird in
application.tsx zwischen hydrateRoot und createRoot verzweigt
- Vite läuft als eigenständiger Server und unterstützt Hot Reload während der Entwicklung
- Automatisierte Deployments von Rails + Vite erfolgen über Docker und Kamal, getrennt nach Staging und Production
- Beim Deployment wird der Befehl
make deploy ausgeführt; der Asset Host nutzt CloudFlare zur Cache-Optimierung
Auswirkungen der Umstellung
- Nach dem Migrations-Deployment am 18. März 2025 stiegen die Sichtbarkeit in der Google-Suche und die Seitengeschwindigkeit
- Die Total Blocking Time verbesserte sich deutlich, ebenso der Pagespeed-Score
- Die durchschnittliche Verweildauer der Besucher stieg von 3 auf 6 Minuten
- Der Traffic blieb stabil, während die Zahl der Registrierungen konstant blieb
Künftige Aufgaben und Verbesserungen
- Gemeinsame Layouts lassen sich nur schwer wiederverwenden, zudem wird jede Seite vollständig neu gerendert
- SSR-Debugging ist schwierig, und das Setup ist komplex
- Für die Kombination aus Inertia.js und Rails gibt es wenig Dokumentation; vieles wurde über die Discord-Community gelöst
- Statt Suspense muss man sich an den Inertia-Ansatz gewöhnen
- Derzeit wird Hasura weiterhin genutzt; einige Inertia-Funktionen wie Form und Flash werden noch nicht eingesetzt
Fazit und Ausblick
- Die Struktur integriert React und Rails auf natürliche Weise und verbessert dadurch Entwicklungsproduktivität und Wartbarkeit
- Mit der Entscheidung für Inertia.js wurden Geschwindigkeit, SSR und Typsicherheit gleichzeitig gesichert
- Geplant sind als Nächstes eine Open-Source-Veröffentlichung und der Aufbau einer Contributor-Community
2 Kommentare
Beim Einsatz von
Linkin Next.js gibt es derzeit Diskussionen darüber, dass für die Verwendung von React Server Components in der URL Parameter wie?_rsc=1ip3ierzeugt und verarbeitet werden. Man hört auch, dass die CDN-Kosten dadurch stark gestiegen seien. Das Next.js-Entwicklungsteam soll sich des Problems bewusst sein, aber auf welche Weise und wann es gelöst wird, ist noch unklar.Hacker-News-Kommentare
Server-Side Rendering (SSR) ist nie verschwunden, und das Web erinnert sich erst jetzt wieder daran, warum das einmal der Standard war. Das erste Rendering und SEO sind immer noch besser, wenn das Markup vom Server kommt. Verschiedene Frameworks wie Rails + Turbo, HTMX, Phoenix LiveView und React Server Components setzen standardmäßig auf SSR. Die meisten Dashboards und CRUD-Apps brauchen keinen Client-Router, keinen globalen State und kein 200-kB-Hydration-Bundle, sondern nur teilweise HTML-Ersetzungen
Der eigentliche Treiber sind die Kosten der Komplexität. Jede Zeile Client-JS bringt Build-Tools, npm-Audit-Lärm und Supply-Chain-Risiken mit sich. Wenn man diese Payload reduziert, verbessern sich Performance und Sicherheit gleichzeitig. Natürlich profitieren Apps wie Figma oder Gmail weiterhin von schwerer Client-Logik. Deshalb entsteht das Muster „standardmäßig HTML, JS nur dort, wo es gebraucht wird“. Man sollte in Inseln denken, nicht in einer vollständigen SPA
Es gibt also eine Rückkehr zum Server, aber das ist keine Nostalgie nach PHP von 2004. Es geht darum, JavaScript richtig einzuhegen und HTML wieder 90 % der langweiligen Arbeit machen zu lassen, die es schon immer gut konnte
Wir haben NextJS in einigen Projekten verwendet, stellen es aber bereits schrittweise ein. Es gibt mehrere Gründe dafür, aber einige Hauptfaktoren sind folgende
Die Story rund um Authentifizierung ist schwierig. next-auth hatte einige Einschränkungen, weshalb wir am Ende iron-session verwendet haben. Zum Beispiel konnten wir keine dynamischen ID-Provider-Domains verwenden und mussten deshalb den gesamten openid-Flow selbst übernehmen. Das war machbar, aber für ein ausgereiftes Framework ein unerwarteter Zeitfresser
Da der NextJS-Server nicht unser primäres API-Gateway war, mussten wir alle Requests per Proxy weiterleiten. Die Dokumentation war nicht klar und brachte zusätzliche zufällige Probleme mit sich, etwa Request-Timeouts oder maximale Header-Größen
Das Framework drängt sehr aggressiv in Richtung Cloud, was mit unseren Zielen kollidierte
Die Maintainer waren nicht besonders hilfreich. Andere Tools/Frameworks nutzen wir trotz ihrer Mängel, weil ihre Maintainer sehr gut erreichbar und hilfsbereit sind (Danke an Chillicream/HotChocolate)
Ich erinnere mich, letztes Jahr einen Blogpost darüber gelesen zu haben, dass sich SEO verbessert habe, nachdem man in Next.js vom Page Router auf den App Router gewechselt war. Diesmal wechseln wir wegen steigender Vercel-Kosten von Next zu React+Inertia.js. Würde man dieselbe App statt bei einem Cloud-Anbieter auf einem eigenen VPS deployen, wäre das Problem gelöst. Ich verstehe jedoch nicht, warum man diese Komplexität überhaupt will. Braucht eine App zur Buchverfolgung wirklich GraphQL, ein separates Frontend-Framework und einen komplexen Build-Prozess, oder hätte man das nicht von Anfang an lösen können, indem man eine einzelne RoR-App mit HTML-Templates auf einem VPS deployed?
Jedes Mal, wenn ich Artikel und Diskussionen über das Web und den Stack sehe, stelle ich die Frage: „Welches Problem wird hier eigentlich gelöst?“ Die Antwort lautet immer: „Text auf dem Bildschirm anzeigen“
Ich frage mich, was Leute tun, wenn sie einen JS-Full-Stack wollen, besonders wenn eine DB dabei ist. Die ORM-Situation ist ziemlich zersplittert, oder man muss reines SQL schreiben. Und dann muss man sich immer noch für ein Backend entscheiden. Nimmt man express? Next.js ist bekannt, verfolgt aber eine fragwürdige Agenda. Remix, Astro, TanStack usw. Es ist verwirrend, weil man ständig neu abwägen und neu bewerten muss, was man verwenden soll
Bei privaten Projekten lande ich oft wieder bei Ruby on Rails. Es ist immer ein Vergnügen. Andererseits gibt es zu wenige verfügbare Rails-Entwickler (relativ zu JS), sodass es für professionelle Projekte nicht geeignet ist. JS und oft auch Java als Backend zu wählen, ist unverantwortlich
Ich frage mich, ob noch jemand ähnlich empfindet
Frontend- und Backend-Entwickler haben lange Zeit nicht gut miteinander gesprochen
Historisch gesehen habe ich als Backend-Entwickler Html/JS/CSS gehasst. Es ist ein bedeutend anderes Paradigma als Swing/Awt, WinForms, Android UX usw. Allein das hat mich frustriert und beim Backend gehalten. Um Frontend zu lernen, musste man diese drei Dinge lernen. Erst jetzt gewöhne ich mich daran
Frontend-Entwickler mussten dagegen „noch eine andere Sprache“ lernen. Viele Sprachen haben im Vergleich zu nvm andere/nervigere Build-Systeme. Und wie jeder weiß, der schon einmal die Sprache gewechselt hat, muss man neue Frameworks, Paradigmen usw. lernen
Stattdessen haben einige erkannt, dass man JavaScript ins Backend drücken kann. Das hatte viele Nachteile, aber für Leute, die „Dinge einfach fertigbekommen“, vor allem in einer Welt von „füg einfach mehr Server hinzu“ und „VC-Geld ist umsonst! Verbrenn es für Infrastruktur!“, waren diese Nachteile nichts, worüber man sich Sorgen machte
Aber Frontend-Entwickler, jetzt „Full-Stack-Entwickler“, in Wirklichkeit aber eher „alles-in-JavaScript“-Entwickler, produzieren weiter in auffälliger Weise. Das spiegelt sich nun in LinkedIn-Stellenanzeigen wider, die nach Next.JS/Node.JS/sonstigen Rollen verlangen. Eine Sprache, die alles beherrscht
Nur ein paar Gedanken, aber ich denke, das hängt stark damit zusammen, warum sich Leute für Next.JS entscheiden
Ich kann zu den technischen Aspekten nichts sagen (ich kenne nur Next.js und nicht Rails, daher ist unklar, ob dieser Beitrag den Komfort des Autors mit Rails widerspiegelt oder eine technisch geeignetere Architektur). Aber ich finde es seltsam, wenn ein Unternehmen mit mehreren Software-Ingenieuren sich über Infrastrukturkosten von unter 1.000 Dollar im Monat Sorgen macht. Sich über Hosting-Kosten Gedanken zu machen, ist nicht klug
Wenn Rails sich auf echte erstklassige Unterstützung für Interoperabilität mit Frontend-Frameworks konzentriert hätte, wäre es inzwischen viel größer. In Hotwire ist viel Aufwand geflossen, aber ich möchte React verwenden, und andere wollen wahrscheinlich ebenfalls das nutzen, womit sie vertraut sind
Ich frage mich, warum es überhaupt eine Debatte Next.js vs. SSR gibt. Next.js ist hybrid und macht das ziemlich gut. Im Gegensatz zu anderen SPA-Frameworks erzeugt Next.js vorgerendertes HTML für schnelles Initial Loading und bietet Konfigurationsschalter für effiziente JS-Chunks, für das Preloading beim Hover über Links oder nach dem Rendern der Seite für alle n+1-Links sowie für effizientes Image-(Vor-)Loading abhängig von Breakpoints (im Vergleich zu reinen SSR-Lösungen oft die Achillesferse)
Ich habe ein wenig Rails geschrieben, aber ich verstehe nicht ganz, warum Leute so begeistert davon sind. Es war völlig in Ordnung, aber ich habe nichts Besonderes daran gefunden