[Ruby-On-Rails-3] Separate REST JSON API Server und Client?


Answers

Sehr gut gefragt. +1. Das ist sicher eine nützliche Referenz für mich. Auch @Aaron und andere haben zur Diskussion beigetragen. Wie Ruby ist diese Frage auch auf andere Programmierumgebungen anwendbar.

Ich habe die ersten beiden Optionen verwendet. Erstens für zahlreiche Anwendungen und zweitens für mein Open-Source-Projekt Cowoop

Option 1

Dieser ist zweifellos der populärste. Aber ich finde Implementierung sehr http-ish. Der ursprüngliche Code jeder API wird für den Umgang mit dem Anfrageobjekt verwendet. API-Code ist also mehr als reiner Ruby / Python / anderer Sprachcode.

Option 2

Ich habe das immer geliebt.

Diese Option bedeutet auch, dass HTML nicht auf dem Server generiert wird. So unterscheidet sich Option 2 von Option 3. Sie werden jedoch als statisches HTML mit einem Build-Skript erstellt. Wenn dieser HTML-Code auf der Clientseite geladen wird, würde er den API-Server als JS-API-Client aufrufen.

  • Trennung von Bedenken ist ein großer Vorteil. Und sehr nach Ihren Wünschen implementieren Backend-Experten Backend-APIs, testen sie einfach wie gewöhnlicher Sprachcode, ohne sich Gedanken über den Framework / http-Anforderungscode machen zu müssen.

  • Das ist wirklich nicht so schwierig wie es auf der Frontend-Seite klingt. Sind API-Aufrufe und resultierende Daten (meist json) für Ihre clientseitige Vorlage oder MVC verfügbar?

  • Weniger serverseitige Verarbeitung Es bedeutet, dass Sie sich für Standard-Hardware / weniger teure Server entscheiden.

  • Es ist einfacher, Layer unabhängig voneinander zu testen und API-Dokumente einfacher zu erstellen.

Es hat einige Nachteile.

  • Viele Entwickler finden dies überentwickelt und schwer zu verstehen. Es besteht also die Chance, dass Architektur kritisiert wird.

  • i18n / l10n ist schwer. Da HTML im Wesentlichen generierte Build-Zeit ist statisch, braucht man mehrere Builds pro unterstützte Sprache (was nicht unbedingt eine schlechte Sache ist). Aber selbst damit haben Sie Ecken um l10n / i18n und müssen vorsichtig sein.

Option 3

Die Backend-Codierung muss in diesem Fall der zweiten Option entsprechen. Die meisten Punkte für Option 2 gelten auch hier.

Webseiten werden mit serverseitigen Vorlagen zur Laufzeit gerendert. Dies macht i18n / l10n mit etablierten / akzeptierten Techniken viel einfacher. Es kann ein weniger HTTP-Aufruf für einen wesentlichen Kontext sein, der für das Seitenrendering benötigt wird, wie Benutzer, Sprache, Währung usw. Die serverseitige Verarbeitung wird mit dem Rendern erhöht, aber möglicherweise durch weniger HTTP-Aufrufe an den API-Server kompensiert.

Jetzt, da die Seiten auf dem Server gerendert werden, ist das Frontend jetzt stärker an die Programmierumgebung gebunden. Dies ist möglicherweise für viele Anwendungen nicht einmal eine Überlegung.

Twitter-Fall

Wie ich es verstehe, macht Twitter sein erstes Seitenrendering auf dem Server, aber für Seitenaktualisierungen hat es immer noch einige API-Aufrufe und Client-seitige Vorlagen, um DOM zu manipulieren. In einem solchen Fall müssen Sie also doppelte Vorlagen verwalten, was zu Mehraufwand und Komplexität führt. Nicht jeder kann sich diese Option leisten, im Gegensatz zu Twitter.

Unser Projekt Stapel

Ich benutze Python. Ich benutze JsonRPC 2.0 anstelle von REST. Ich schlage REST vor, obwohl ich die Idee von JsonRPC aus verschiedenen Gründen mag. Ich benutze unten Bibliotheken. Jemand, der Option 2/3 in Betracht zieht, könnte es nützlich finden.

  • API Server: Python Ein schnelles Web-Mikro-Framework - Flask
  • Frontend-Server: Nginx
  • Clientseite MVC: Knockout.js
  • Andere relevante Werkzeuge / Bibliotheken:

Mein Fazit und Empfehlung

Option 3 !.

Alle sagten, ich habe Option 2 erfolgreich verwendet, aber jetzt für etwas Einfachheit in Richtung Option 3 gelehnt. Es ist sehr verlockend, statische HTML-Seiten mit Build-Skript zu erstellen und sie mit einem der ultraschnellen Server zu versehen, die auf die Bereitstellung statischer Seiten spezialisiert sind (Option 2).

Question

Ich bin dabei, eine Reihe von Web-Apps von Grund auf neu zu erstellen. (Siehe http://50pop.com/code für einen Überblick.) Ich möchte, dass sie von vielen verschiedenen Clients aus zugänglich sind: Front-End-Websites, Smartphone-Apps, Back-End-Webservices usw. Ich möchte also wirklich ein JSON-REST-API für jeden.

Außerdem arbeite ich lieber am Backend, also träume ich davon, dass ich mich ausschließlich auf die API konzentriere und jemand anderes für die Front-End-Benutzeroberfläche einstelle, egal ob Website, iPhone, Android oder eine andere App.

Bitte helfen Sie mir zu entscheiden, welchen Ansatz ich wählen sollte:

GEMEINSAM IN SCHIENEN

Erstellen Sie eine sehr standardmäßige Rails Web-App. Führen Sie im Controller den Befehl respond_with aus, um entweder JSON oder HTML zu verwenden. Die JSON-Antwort ist dann meine API.

Pro: Viele Präzedenzfälle. Große Standards und viele Beispiele, wie man die Dinge so macht.

Con: Die API muss nicht unbedingt dieselbe sein wie die Web-App. Ich mag es nicht, wenn / dann mit Switch-Ansatz antworten. Zwei sehr unterschiedliche Dinge mischen (UI + API).

REST-SERVER + JAVASCRIPT-SCHWERER KUNDE

Richten Sie einen JSON-REST-API-Server ein. Verwenden Sie Backbone oder Ember.js für clientseitiges JavaScript, um direkt auf die API zuzugreifen und Vorlagen im Browser anzuzeigen.

Pro: Ich liebe die Trennung von API und Client. Kluge Leute sagen, dass dies der richtige Weg ist. Großartig in der Theorie. Scheint modern und aufregend.

Con: Nicht viel Präzedenzfall. Nicht viele Beispiele dafür sind gut gelungen. Öffentliche Beispiele (twitter.com) fühlen sich träge und schalten sogar von diesem Ansatz ab.

REST-SERVER + SERVER-SEITEN-HTML-CLIENT

Richten Sie einen JSON-REST-API-Server ein. Erstellen Sie einen einfachen HTML-Website-Client, der nur auf die REST-API zugreift. Weniger clientseitiges JavaScript

Pro: Ich liebe die Trennung von API und Client. Aber einfaches HTML5 zu bedienen ist ziemlich sicher und nicht kundenintensiv.

Con: Nicht viel Präzedenzfall. Nicht viele Beispiele dafür sind gut gelungen. Frameworks unterstützen dies ebenfalls nicht. Ich bin mir nicht sicher, wie ich es angehen soll.

Vor allem nach Rat aus Erfahrung suchen, nicht nur in der Theorie.




Isomorphes Rendering und progressive Verbesserung. Welches ist meiner Meinung nach in Option drei?

Isomorphes Rendering bedeutet, dass dieselbe Vorlage verwendet wird, um Markup serverseitig zu generieren, wie Sie es im clientseitigen Code verwenden. Wählen Sie eine Template-Sprache mit guten serverseitigen und clientseitigen Implementierungen. Erstellen Sie vollständig gebackenes HTML für Ihre Benutzer und senden Sie es auf den Draht. Verwenden Sie auch Caching.

Progressive Enhancement bedeutet, dass Sie die clientseitige Ausführung und das Rendern und das Abhören von Ereignissen starten, sobald Sie alle Ressourcen heruntergeladen haben und Sie eine Client-Funktion ermitteln können. Rückgriff auf funktionale client-script-lose Funktionalität, wo immer möglich, für Zugänglichkeit und Abwärtskompatibilität.

Ja, natürlich schreiben Sie eine eigenständige JSON API für diese App-Funktionalität. Aber gehen Sie nicht so weit, dass Sie eine JSON-API für Dinge schreiben, die als statische HTML-Dokumente funktionieren.




Ich bevorzuge den Weg von # 2 und # 3. Vor allem, weil # 1 die Trennung von Belangen verletzt und alle möglichen Dinge vermischt. Irgendwann werden Sie feststellen, dass Sie einen API-Endpunkt benötigen, der keine passende HTML-Seite / etc. Aufweist, und Sie werden mit eingebetteten HTML- und JSON-Endpunkten in der gleichen Codebasis einen Creek haben. Es wird zu einem verdammten Durcheinander, selbst wenn es sein MVP ist, wirst du es irgendwann neu schreiben müssen, weil es so unordentlich ist, dass es nicht einmal die Rettung wert ist.

Wenn Sie mit # 2 oder # 3 fortfahren, können Sie eine API verwenden, die unabhängig davon (größtenteils) gleich funktioniert. Dies bietet eine große Flexibilität. Ich bin noch nicht 100% auf Backbone / ember / was auch immer / etc.js verkauft. Ich finde es großartig, aber wie wir es bei Twitter sehen, ist das nicht optimal. ABER ... Twitter ist auch ein großes Unternehmen und hat Hunderte von Millionen Nutzern. Jede Verbesserung kann sich auf die verschiedenen Bereiche der verschiedenen Geschäftsbereiche auswirken. Ich denke, es gibt mehr als nur Geschwindigkeit, und das lässt uns nicht im Stich. Aber das ist nur meine Meinung. Ich verzichte jedoch auf das Backbone und seine Konkurrenten. Diese Apps sind großartig zu verwenden und sind sehr sauber und reagieren sehr (größtenteils).

Die dritte Option hat auch einige gültige Reiz. Dies ist, wo ich das Pareto-Prinzip (80/20 Regel) folgen und 20% Ihrer Hauptmarkierung (oder umgekehrt) auf dem Server gerendert hätte und dann einen netten JS-Client (Backbone / etc) den Rest davon ausführen lassen würde . Sie kommunizieren vielleicht nicht zu 100% mit der REST-API über den JS-Client, aber Sie werden bei Bedarf etwas Arbeit verrichten, um die Suter-Erfahrung zu verbessern.

Ich denke, das ist eine dieser "es kommt auf" Arten von Problemen und die Antwort ist "es hängt davon ab, was Sie tun, wem Sie dienen und welche Art von Erfahrung Sie wollen, dass sie erhalten. Da ich denke, dass Sie zwischen 2 oder 3 oder eine Mischung aus ihnen entscheiden können.




Das Erstellen einer JSON-API in Rails ist die erste Klasse. Das JSONAPI :: Resources-Juwel übernimmt die Schwerarbeit für eine http://jsonapi.org spec'd-API.




Wir verwenden die folgende Variante von # 3: Richten Sie einen JSON-REST-API-Server ein. Erstellen Sie einen HTML-Website-Server. Der HTML-Webserver ist nicht wie in Ihrer Variante ein Client für den REST-API-Server. Stattdessen sind die beiden Peers. Nicht weit unter der Oberfläche befindet sich eine interne API, die die Funktionalität bereitstellt, die die beiden Server benötigen.

Uns ist kein Präzedenzfall bekannt, also ist es experimentell. Bis jetzt (vor der Beta), hat es ziemlich gut geklappt.




Ich entschied mich für die Architektur von Option # 2 für Infiniforms , da sie eine großartige Möglichkeit bot, die Benutzeroberfläche von der Geschäftslogik zu trennen.

Ein Vorteil davon ist, dass die API Server unabhängig von den Webservern skalieren können. Wenn Sie mehrere Clients haben, müssen die Websites nicht im selben Umfang skaliert werden wie die Webserver, da einige Clients auf Telefon-, Tablet- oder Desktop-Basis laufen.

Dieser Ansatz bietet Ihnen auch eine gute Grundlage, um Ihre API für Ihre Benutzer zu öffnen, insbesondere wenn Sie Ihre eigene API verwenden, um alle Funktionen für Ihre Website bereitzustellen.




Ich habe mich für einen hybriden Ansatz entschieden, bei dem wir Sinatra als Basis verwenden, ActiveRecord / Postgress usw., um Seitenrouten (schlanke Templates) bereitzustellen, um eine REST-API verfügbar zu machen, die die Web-App verwenden kann. In der frühen Entwicklung wird das Ausfüllen von Auswahloptionen über Helfer gemacht, die in die schlanke Vorlage rendern, aber wenn wir uns der Produktion nähern, wird dies für einen AJAX-Aufruf an eine REST-API ausgelagert, da wir uns mehr um Seitenladegeschwindigkeiten und so weiter kümmern.

Dinge, die in Slim leicht zu rendern sind, werden auf diese Weise gehandhabt, und Sachen (Formulare submitHandler , POST-Daten von jQuery.Validations submitHandler usw. erhalten, sind alle AJAX)

Testen ist ein Problem. Gerade jetzt bin ich ratlos , wenn ich versuche, JSON-Daten an einen Rack-Test-POST-Test zu übergeben .




Einige gute Antworten hier bereits - ich würde definitiv # 2 oder # 3 empfehlen - die Trennung ist konzeptionell gut, aber auch in der Praxis.

Es kann schwierig sein, Dinge wie Lade- und Verkehrsmuster auf einer API vorherzusagen, und Kunden, die sehen, wer die API unabhängig bedient, haben eine einfachere Zeit für die Bereitstellung und Skalierung. Wenn Sie das mit menschlichen Web-Zugriffsmustern tun müssen, ist es weniger einfach. Auch Ihre API-Nutzung wird möglicherweise schneller skaliert als Ihr Web-Client und Sie können sehen, wohin Sie Ihre Bemühungen lenken müssen.

Zwischen # 2 # 3 hängt es wirklich von deinen Zielen ab - ich würde zustimmen, dass # 2 wahrscheinlich die Zukunft von Webapps ist - aber vielleicht möchtest du etwas einfacher haben, wenn dieser Kanal nur einer von vielen sein wird!




Ich bin etwa 2 Monate in einem 3-Monats-Projekt, das den zweiten Ansatz, den Sie hier skizziert haben, nimmt. Wir verwenden eine RESTful-API-Server-Seite mit backbone.js auf der Vorderseite. Handlebars.js verwaltet die Vorlagen und jQuery behandelt die AJAX- und DOM-Manipulation. Bei älteren Browsern und Such-Spidern haben wir wieder auf serverseitiges Rendering zurückgegriffen, aber wir verwenden dieselben HTML-Templates wie das Frontend-Frontend mit Mozilla Rhino.

Wir haben diesen Ansatz aus vielen verschiedenen Gründen gewählt, sind uns aber bewusst, dass dies ein wenig riskant ist, da es bisher noch nicht in großem Umfang bewiesen wurde. Alles gleich, alles läuft bisher ziemlich reibungslos.

Bis jetzt haben wir nur mit einer API gearbeitet, aber in der nächsten Phase des Projekts werden wir mit einer zweiten API arbeiten. Der erste ist für große Datenmengen und der zweite verhält sich eher wie ein CMS über eine API.

Die Tatsache, dass diese beiden Teile des Projekts völlig unabhängig voneinander agieren, war ein wichtiger Aspekt bei der Auswahl dieser Infrastruktur. Wenn Sie nach einer Architektur suchen, die verschiedene unabhängige Ressourcen ohne Abhängigkeiten masht, dann ist dieser Ansatz einen Blick wert.

Ich fürchte, ich bin kein Ruby-Typ, also kann ich die anderen Ansätze nicht kommentieren. Manchmal ist es in Ordnung, ein Risiko einzugehen. Andere Male ist es besser, auf Nummer sicher zu gehen. Sie werden sich abhängig von der Art des Projekts entscheiden.

Viel Glück mit Ihrer Wahl hier. Ich bin gespannt, was andere ebenfalls teilen.




Links