REST JSON API Server und Client trennen? [geschlossen]


371

Ich bin dabei, eine Reihe von Web-Apps von Grund auf neu zu erstellen. ( Eine Übersicht finden Sie unter http://50pop.com/code .) Ich möchte, dass sie von vielen verschiedenen Clients aus aufgerufen werden können: Front-End-Websites, Smartphone-Apps, Backend-Webservices usw. Ich möchte also wirklich eine JSON REST API für jede.

Außerdem arbeite ich lieber am Back-End, daher träume ich davon, mich ausschließlich auf die API zu konzentrieren und jemanden einzustellen, der die Front-End-Benutzeroberfläche erstellt, egal ob es sich um eine Website, ein iPhone, Android oder eine andere App handelt.

Bitte helfen Sie mir bei der Entscheidung, welchen Ansatz ich wählen soll:

ZUSAMMEN IN SCHIENEN

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

Pro: Viele Präzedenzfälle. Tolle Standards und viele Beispiele dafür, wie man Dinge auf diese Weise macht.

Con: Die API muss nicht unbedingt mit der Web-App identisch sein. Ich mag es nicht, wenn / dann mit dem Switch-Ansatz antworten. Mischen von zwei sehr unterschiedlichen Dingen (UI + API).

REST SERVER + JAVASCRIPT-HEAVY CLIENT

Erstellen Sie einen Nur-JSON-REST-API-Server. 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, dies sei der richtige Weg. Theoretisch großartig. Scheint topaktuell und aufregend.

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

REST SERVER + SERVER-SIDE HTML CLIENT

Erstellen Sie einen Nur-JSON-REST-API-Server. 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. Das Bereitstellen von einfachem HTML5 ist jedoch kinderleicht und nicht clientintensiv.

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

Besonders auf der Suche nach Ratschlägen aus Erfahrung, nicht nur theoretisch.


50
Wir bevorzugen im Allgemeinen, dass spekulative, konzeptionelle Whiteboard-Fragen auf programmers.stackexchange.com gestellt werden, während Fragen hier auf Stack Overflow in 99% der Fälle den tatsächlichen Quellcode enthalten sollten . Aber es ist eine gut gestellte Frage, und ich liebe Ihre Arbeit, daher kann dies vorerst in die Grauzone fallen.
Jeff Atwood

2
Hat jemand einige Beispiele / Quellen (um ihre Gründe zu verstehen) für diejenigen, die sich von Option 2 entfernen?
Víctor López García

12
@frntk Der ursprüngliche Grund, warum viele Unternehmen (wie Twitter) Javascript-Clients machten, war, dass sie dachten, es wäre schneller. Jetzt erkennen sie, dass es tatsächlich langsamer ist. Siehe engineering.twitter.com/2012/05/… und openmymind.net/2012/5/30/Client-Side-vs-Server-Side-Rendering
Moshe Katz

1
Lesen Sie die Kommentare in den obigen Links. Viele der Annahmen des Artikels werden mit Logik und Erfahrung widerlegt.
Ricalsin

1
Heutzutage möchten Sie ein JSON-API-Backend gemäß den Spezifikationen von jsonapi.org erstellen ... :)
Askar

Antworten:


136

Bei Boundless haben wir Option 2 vertieft und sie Tausenden von Studenten zur Verfügung gestellt. Unser Server ist eine JSON-REST-API (Scala + MongoDB), und unser gesamter Client-Code wird direkt aus CloudFront heraus bereitgestellt (dh: www.boundless.com ist nur ein Alias ​​für CloudFront).

Vorteile:

  • Schneide / aufregend
  • Viel Geld für Ihr Geld: Die API bietet Ihnen die Grundlage für Ihren eigenen Webclient, mobile Clients, Zugriff von Drittanbietern usw.
  • außerordentlich schnelles Laden der Seite / Seitenübergänge

Nachteile:

  • Nicht SEO-freundlich / bereit ohne viel mehr Arbeit.
  • Erfordert erstklassige Web-Front-End-Leute, die bereit sind, mit der Realität einer Website-Erfahrung umzugehen, die zu 70% aus Javascript besteht, und was dies bedeutet.

Ich denke, dies ist die Zukunft aller Web-Apps.

Einige Gedanken für die Web-Front-End-Leute (hier wird all die Neuheit / Herausforderung dieser Architektur gegeben):

  • CoffeeScript. Viel einfacher, qualitativ hochwertigen Code zu erstellen.
  • Rückgrat. Tolle Möglichkeit, Ihre Logik und aktive Community zu organisieren.
  • HAMLC. Haml + CoffeeScript-Vorlagen => JS.
  • SASS

Wir haben ein Kabel für unsere Front-End-Entwicklung namens "Spar" (Single Page App Rocketship) entwickelt, das effektiv die Asset-Pipeline von Rails ist, die für die Entwicklung von Single-Page-Apps optimiert ist. Wir werden in den nächsten Wochen Open-Sourcing auf unserer Github- Seite sowie einen Blog-Beitrag veröffentlichen, in dem die Verwendung und die gesamte Architektur ausführlicher erläutert werden.

AKTUALISIEREN:

In Bezug auf die Bedenken der Menschen gegenüber Backbone denke ich, dass sie überbewertet sind. Backbone ist weit mehr ein Organisationsprinzip als ein tiefer Rahmen. Die Website von Twitter selbst ist ein riesiges Javascript-Biest, das jeden Eckfall von Millionen von Benutzern und älteren Browsern abdeckt, während Tweets in Echtzeit geladen, Müll gesammelt, viele Multimedia-Inhalte angezeigt usw. werden. Von allen "reinen" Js-Websites, die ich habe gesehen, Twitter ist die ungerade aus. Es wurden viele beeindruckend komplizierte Apps über JS bereitgestellt, die sehr gut abschneiden.

Und Ihre Wahl der Architektur hängt ganz von Ihren Zielen ab. Wenn Sie nach dem schnellsten Weg suchen, um mehrere Kunden zu unterstützen und Zugang zu guten Front-End-Talenten zu haben, ist die Investition in eine eigenständige API ein guter Weg.


1
Ein kleiner Punkt zum Hinzufügen: Obwohl ich nur Option 1 erstellt habe, kenne ich mehrere Entwickler mobiler Apps, die beginnen, parse.com als Backend zu verwenden, um einen schnellen Weg zu Nummer 2 zu ermöglichen.
Rhb123

Dinge wie Parse und Kinvey sind sehr interessant, ich kann nicht sagen, dass ich schon die Chance hatte, mit ihnen zu spielen. Hängt davon ab, ob Ihr Wert auf der Vorder- oder Rückseite des Stapels liegt
Aaron

Ich benutze den gleichen Ansatz mit Spinejs für das Frontend.
Nicolas Goy

Wie gehen Sie mit einer einzelnen Domain um, in der zwei separate Anwendungen ausgeführt werden? Z.B. Ich habe www.mysite.com und möchte eine öffentliche API verfügbar machen und ein Front-End für diese URL bereitstellen. Gemäß den REST-Prinzipien sollte mysite.com/product/24, auf das über einen Webbrowser zugegriffen wird, eine HTML-Seite zurückgeben, indem der HTTP Accept-Header betrachtet wird, und ein GET mit JSON im Accept-Header auf mysite.com/product/24 sollte JSON zurückgeben .
Erich

Wie würde AngularJS dafür abschneiden?
Ankan-Zerob

48

Sehr gut gefragt. +1. Dies ist sicherlich eine zukünftige nützliche Referenz für mich. Auch @Aaron und andere haben der Diskussion einen Mehrwert verliehen. Wie Ruby gilt diese Frage auch für andere Programmierumgebungen.

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

Option 1

Dieser ist ohne Zweifel der beliebteste. Aber ich finde die Implementierung sehr http-ish. Der ursprüngliche Code jeder API befasst sich mit dem Anforderungsobjekt. API-Code ist also mehr als reiner Ruby / Python / anderer Sprachcode.

Option 2

Ich habe das immer geliebt.

Diese Option impliziert auch, dass HTML nicht zur Laufzeit auf dem Server generiert wird. Auf diese Weise unterscheidet sich Option 2 von Option 3. Sie werden jedoch mithilfe eines Build-Skripts als statisches HTML erstellt. Beim Laden auf der Clientseite würde dieser HTML-Code den API-Server als JS-API-Client aufrufen.

  • Die Trennung von Bedenken ist ein großer Vorteil. Und sehr nach Ihren Wünschen (und meinen) implementieren Backend-Experten Backend-APIs. Testen Sie sie einfach wie den üblichen Sprachcode, ohne sich um den Framework- / http-Anforderungscode kümmern zu müssen.

  • Das ist wirklich nicht so schwierig, wie es auf der Frontend-Seite klingt. API-Aufrufe und daraus resultierende Daten (meistens json) stehen Ihrer clientseitigen Vorlage oder MVC zur Verfügung.

  • Weniger serverseitige Verarbeitung. Dies bedeutet, dass Sie sich möglicherweise für Standardhardware / weniger teure Server entscheiden.

  • Einfacher, Ebenen unabhängig zu testen und API-Dokumente einfacher zu generieren.

Es hat einige Nachteile.

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

  • i18n / l10n ist schwer. Da HTML im Wesentlichen statisch generiert wird, sind mehrere Builds pro unterstützter Sprache erforderlich (was nicht unbedingt eine schlechte Sache ist). Aber selbst damit haben Sie möglicherweise Eckfälle um 10n / i18n und müssen vorsichtig sein.

Option 3

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

Webseiten werden zur Laufzeit mithilfe von serverseitigen Vorlagen gerendert. Dies macht i18n / l10n mit etablierteren / akzeptierten Techniken viel einfacher. Möglicherweise ist ein http-Aufruf weniger für einen wesentlichen Kontext erforderlich, der für das Rendern von Seiten erforderlich ist, z. B. Benutzer, Sprache, Währung usw. Daher wird die serverseitige Verarbeitung durch das Rendern erhöht, möglicherweise jedoch durch weniger http-Aufrufe an den API-Server kompensiert.

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

Twitter Fall

Soweit ich weiß, führt Twitter möglicherweise das erste Rendern von Seiten auf dem Server durch, aber für Seitenaktualisierungen stehen noch einige API-Aufrufe und clientseitige Vorlagen zur Bearbeitung von DOM zur Verfügung. In diesem Fall müssen Sie also doppelte Vorlagen verwalten, was den Aufwand und die Komplexität erhöht. Im Gegensatz zu Twitter kann sich nicht jeder diese Option leisten.

Unser Projekt Stack

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

Mein Fazit und meine Empfehlung

Option 3!.

Alles in allem habe ich Option 2 erfolgreich verwendet, neige aber jetzt der Einfachheit halber zu Option 3. Das Generieren statischer HTML-Seiten mit einem Build-Skript und das Bereitstellen mit einem ultraschnellen Server, der sich auf das Bereitstellen statischer Seiten spezialisiert hat, ist sehr verlockend (Option 2).


Ich mag auch Option 2, aber Option 3 hat viele Vorteile, die wir nicht loswerden können. Ich versuche eine Hydrid-Lösung zu finden, die beide opt2 + opt3 kombiniert, aber es wird zu Kopfschmerzen wie Twitter führen.
Blue Smith

Ich liebe Option 3 und möchte sie für ein aktuelles Projekt verwenden. Gibt es ein Ego oder Git Repo, auf das Sie um Hilfe bitten können?
AmaChefe

@AmaChefe Ich wünschte. Für aktuelle Projekte, bei denen SEO von entscheidender Bedeutung ist, verwenden wir Option 3. Code ist jedoch kein Open Source. Wir verwenden flask + jinja2 und knockout / react.js.
Shekhar

28

Wir haben uns beim Bau von gaug.es für # 2 entschieden. Ich habe an der API (Ruby, Sinatra usw.) gearbeitet und mein Geschäftspartner Steve Smith hat am Frontend (Javascript-Client) gearbeitet.

Vorteile:

  1. Bewegen Sie sich schnell parallel. Wenn ich vor Steve arbeiten würde, könnte ich weiterhin APIs für neue Funktionen erstellen. Wenn er vor mir arbeiten würde, könnte er die API sehr leicht fälschen und die Benutzeroberfläche erstellen.

  2. API kostenlos. Der offene Zugriff auf die Daten in Ihrer App wird schnell zur Standardfunktion. Wenn Sie von Grund auf mit einer API beginnen, erhalten Sie diese kostenlos.

  3. Saubere Trennung. Es ist besser, sich Ihre App als API mit Clients vorzustellen. Sicher, der erste und wichtigste Client ist möglicherweise ein Web-Client, aber Sie können damit problemlos andere Clients (iPhone, Android) erstellen.

Nachteile:

  1. Abwärtskompatibilität. Dies hängt mehr mit einer API zusammen als mit Ihrer direkten Frage, aber sobald Ihre API verfügbar ist, können Sie sie nicht einfach brechen oder Sie brechen alle Ihre zwei Clients. Dies bedeutet nicht, dass Sie sich langsamer bewegen müssen, aber es bedeutet, dass Sie häufig zwei Dinge gleichzeitig zum Laufen bringen müssen. Das Hinzufügen zur API oder zu neuen Feldern ist in Ordnung, aber das Ändern / Entfernen sollte nicht ohne Versionierung erfolgen.

Ich kann mir momentan keine Nachteile mehr vorstellen.

Fazit: Der API + JS-Client ist der richtige Weg, wenn Sie eine API veröffentlichen möchten.

PS Ich würde auch empfehlen, Ihre API vollständig zu dokumentieren, bevor Sie sie veröffentlichen. Der Prozess der Dokumentation der Gaug.es-API hat uns wirklich geholfen, imp

http://get.gaug.es/documentation/api/


13
Darf ich fragen, wie Sie das Web-Frontend mit der REST-API authentifizieren? Ich habe gesehen, dass Sie einen API-Schlüssel benötigen, um mit der API zu kommunizieren, die Sie erhalten, indem Sie sich bei Ihrem Benutzerprofil anmelden. Aber wie bekommt der Webclient seinen API-Schlüssel, wenn Sie wissen, was ich meine?
Sebastian Wramba

@SebastianWramba Das ist spät, aber da Ihr Kommentar 12 positive Stimmen erhalten hat ... würde ich mir so etwas wie die Passwortautorisierung von OAuth2 ansehen . Wenn Sie der Ersteller der App sind, die die API aufruft, ist dies wahrscheinlich der gewünschte Ansatz, da der API-Schlüssel nicht direkt verwendet wird. Wenn es sich um eine Drittanbieter-App handelt, muss sich der Benutzer auf Ihrer Website anmelden, um den API-Schlüssel zu erhalten. Anschließend verwendet der Benutzer diesen Schlüssel (und alle anderen erforderlichen Anmeldeinformationen), um über seine App, Website usw. auf die API zuzugreifen.
GreeKatrina

10

Ich gehe lieber den Weg von # 2 und # 3. Hauptsächlich, weil # 1 die Trennung von Bedenken verletzt und alle möglichen Dinge miteinander vermischt. Schließlich müssen Sie einen API-Endpunkt haben, der keine passende HTML-Seite / etc hat, und Sie befinden sich in einem Bach mit vermischten HTML- und JSON-Endpunkten in derselben Codebasis. Es wird zu einem verdammten Chaos, selbst wenn es MVP ist, müssen Sie es irgendwann neu schreiben, weil es so chaotisch ist, dass es sich nicht einmal lohnt, es zu retten.

Wenn Sie sich für # 2 oder # 3 entscheiden, können Sie eine API haben, die (größtenteils) unabhängig davon gleich funktioniert. Dies bietet große Flexibilität. Ich bin noch nicht zu 100% auf Backbone / Ember / Whatever / etc.js verkauft. Ich finde es großartig, aber wie wir bei Twitter sehen, ist dies nicht optimal. ABER ... Twitter ist auch ein riesiges Biest eines Unternehmens und hat Hunderte Millionen Nutzer. Daher kann jede Verbesserung einen enormen Einfluss auf das Endergebnis in verschiedenen Bereichen verschiedener Geschäftsbereiche haben. Ich denke, die Entscheidung beinhaltet mehr als nur Geschwindigkeit, und sie lassen uns nicht darauf ein. Aber das ist nur meine Meinung. Allerdings rabattiere ich Backbone und seine Konkurrenten nicht. Diese Apps sind großartig zu bedienen, sehr sauber und reagieren (größtenteils) sehr schnell.

Die dritte Option hat ebenfalls einen gültigen Reiz. Hier würde ich dem Pareto-Prinzip (80/20-Regel) folgen und 20% Ihres Haupt-Markups (oder umgekehrt) auf dem Server rendern lassen und dann einen netten JS-Client (Backbone / etc) den Rest ausführen lassen . Möglicherweise kommunizieren Sie nicht zu 100% mit der REST-API über den JS-Client, aber Sie werden bei Bedarf einige Arbeiten ausführen, um die suer-Erfahrung zu verbessern.

Ich denke, dies ist eines dieser Probleme, bei denen es darauf ankommt, und die Antwort lautet: Es hängt davon ab, was Sie tun, wem Sie dienen und welche Art von Erfahrung Sie von ihnen erwarten. Angesichts dessen denke ich, dass Sie zwischen 2 oder 3 oder einem Hybrid von ihnen entscheiden können.


+1 zu Hybrid von 2 und 3
Ujjwal Ojha

7

Ich arbeite derzeit an der Konvertierung eines riesigen CMS von Option 1 nach Option 3, und es läuft gut. Wir haben uns entschieden, das Markup serverseitig zu rendern, da SEO für uns eine große Sache ist und wir möchten, dass die Websites auf Mobiltelefonen eine gute Leistung erbringen.

Ich verwende node.js für das Back-End des Clients und eine Handvoll Module, um mir zu helfen. Ich bin etwas früh im Prozess, aber das Fundament ist gelegt und es geht darum, die Daten zu überprüfen, um sicherzustellen, dass alles richtig ist. Folgendes verwende ich:

  • Express für die Grundlage der App.
    (https://github.com/visionmedia/express)
  • Anforderung zum Abrufen der Daten.
    (https://github.com/mikeal/request)
  • Unterstreichen Sie Vorlagen, die serverseitig gerendert werden. Ich verwende diese auf dem Client wieder.
    (https://github.com/documentcloud/underscore)
  • UTML umschließt die Vorlagen des Unterstrichs, damit sie mit Express funktionieren.
    (https://github.com/mikefrey/utml)
  • Upfront sammelt Vorlagen und lässt Sie auswählen, welche an den Client gesendet werden sollen.
    (https://github.com/mrDarcyMurphy/upfront)
  • Express Expose übergibt die abgerufenen Daten, einige Module und Vorlagen an das Front-End.
    (https://github.com/visionmedia/express-expose)
  • Backbone erstellt Modelle und Ansichten im Front-End, nachdem die weitergegebenen Daten verschluckt wurden.
    (https://github.com/documentcloud/backbone)

Das ist der Kern des Stapels. Einige andere Module, die ich hilfreich fand:

  • fleck (https // github.com / trek / fleck)
  • Moment (https // github.com / timrwood / moment)
  • Stift (https // github.com / LearnBoost / Stift)
  • smoosh (https // github.com / fat / smoosh)
    ... obwohl ich mich mit Grunzen beschäftige (https // github.com / cowboy / grunt)
  • Konsolenspur (//github.com/LearnBoost/console-trace).

Nein, ich benutze kein Kaffeeskript.

Diese Option funktioniert sehr gut für mich. Die Modelle im Back-End sind nicht vorhanden, da die Daten, die wir von der API erhalten, gut strukturiert sind und ich sie wörtlich an das Front-End weitergebe. Die einzige Ausnahme ist unser Layoutmodell, bei dem ich ein einzelnes Attribut hinzufüge, das das Rendern intelligenter und leichter macht. Ich habe dafür keine ausgefallene Modellbibliothek verwendet, sondern nur eine Funktion, die das hinzufügt, was ich bei der Initialisierung benötige, und sich selbst zurückgibt.

(Entschuldigung für die seltsamen Links, ich bin zu sehr ein n00b für einen Stapelüberlauf, um so viele zu posten)


1
Sie rendern also markupseitig, geben dem Client jedoch weiterhin Vorlagen und verwenden Backbone?
Shannon

7

Wir verwenden die folgende Variante von # 3: Erstellen Sie einen Nur-JSON-REST-API-Server. 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 Funktionen bereitstellt, die die beiden Server benötigen.

Wir kennen keinen Präzedenzfall, also ist es eine Art Experiment. Bisher (kurz vor dem Eintritt in die Beta) hat es ziemlich gut geklappt.


Ich denke über diese Option nach, um einige Probleme im Zusammenhang mit einem ordnungsgemäßen API-Client zu vermeiden, z. B. die Authentifizierung. Ich würde gerne mehr darüber erfahren, wie Sie das Ganze strukturiert haben und wie Sie die Trennung und Kommunikation zwischen den drei verschiedenen Teilen verwalten. Kann ich etwas lesen? Vielen Dank!
MartinodF

2
@MartinodF Wir hosten auf Google App Engine, die sich auf Java oder Python beschränkt. Wollte Python verwenden, wurde aber gezwungen, Java zu verwenden, weil wir Zahlen knacken (Py kann mit C / C ++ auf GAE nicht erweitert werden). Wir haben Streifen (Streifen, nicht Streben, nicht Frühling) als Präsentationsrahmen ausgewählt. Sehr zufrieden damit. Das Ganze ist eine Java-App auf GAE. Die Kernfunktionalität ist in einer Reihe von Java-Paketen implementiert und in einer internen API verfügbar gemacht. Es gibt ein Servlet, das den JSON-REST-Dienst bereitstellt, und ein anderes, das als Stripes-Webanwendung konfiguriert ist. Da es sich nur um eine GAE Java-App handelt, ist die Kommunikation trivial.
Thomas Becker

Vielen Dank für den Einblick, es ist sehr nützlich!
MartinodF

7

Normalerweise gehe ich zur zweiten Option und verwende Rails zum Erstellen der API und das Backbone für das JS-Zeug. Mit ActiveAdmin können Sie sogar kostenlos ein Admin-Panel erhalten . Ich habe Dutzende von mobilen Apps mit dieser Art von Backend ausgeliefert. Es hängt jedoch stark davon ab, ob Ihre App interaktiv ist oder nicht.

Ich habe diesen Ansatz am letzten RubyDay.it vorgestellt : http://www.slideshare.net/matteocollina/enter-the-app-era-with-ruby-on-rails-rubyday

Bei der dritten Option sollten Sie pajax wie bei Github ausprobieren, um die Reaktionsfähigkeit der zweiten Option zu erhalten .


6

Ich bin ungefähr 2 Monate in einem 3-Monats-Projekt, das den zweiten Ansatz verfolgt, den Sie hier skizziert haben. Wir verwenden eine RESTful API-Serverseite mit backbone.js auf der Vorderseite. Handlebars.js verwaltet die Vorlagen und jQuery übernimmt die AJAX- und DOM-Manipulation. Bei älteren Browsern und Suchspinnen haben wir auf das serverseitige Rendern zurückgegriffen, verwenden jedoch dieselben HTML-Vorlagen wie das Handlebars-Frontend mit Mozilla Rhino.

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

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

Bei der Auswahl dieser Infrastruktur war es von entscheidender Bedeutung, dass diese beiden Teile des Projekts völlig unabhängig voneinander agierten. Wenn Sie nach einer Architektur suchen, mit der Sie verschiedene unabhängige Ressourcen ohne Abhängigkeiten mischen können, ist dieser Ansatz einen Blick wert.

Ich fürchte, ich bin kein Ruby-Typ, daher kann ich die anderen Ansätze nicht kommentieren. Manchmal ist es in Ordnung, ein Risiko einzugehen. In anderen Fällen ist es besser, auf Nummer sicher zu gehen. Sie werden sich je nach Art des Projekts selbst kennen.

Viel Glück bei Ihrer Wahl hier. Ich bin gespannt, was andere auch teilen.


1
Sie erkennen also, ob die Anforderung von einem Suchbot stammt, und stellen vorgerenderten HTML-Code bereit, falls dies der Fall ist, und JS + -Vorlagen, wenn dies nicht der Fall ist.
Shannon

4

Ich mag # 3, wenn meine Website keine 100% CRUD-Implementierung meiner Daten sein wird. Welches ist noch zu passieren.

Ich bevorzuge Sinatra und werde die App einfach in ein paar verschiedene Rack-Apps mit unterschiedlichen Zwecken aufteilen. Ich werde eine API-spezifische Rack-App erstellen, die alles abdeckt, was ich für die API benötige. Dann vielleicht eine User-Rack-App, die meine Webseite präsentiert. Manchmal fragt diese Version die API bei Bedarf ab, aber normalerweise geht es nur um die HTML-Site.

Ich mache mir darüber keine Sorgen und führe nur eine Abfrage der Persistenzschicht von der Benutzerseite aus, wenn ich sie brauche. Ich bin nicht übermäßig besorgt, eine vollständige Trennung zu schaffen, da sie normalerweise unterschiedlichen Zwecken dienen.

Hier ist ein sehr einfaches Beispiel für die Verwendung mehrerer Rack-Apps. Ich habe dort ein kurzes Abfragebeispiel hinzugefügt, damit Sie sehen können, wie es auf die API-App trifft. Sie können sehen, wie einfach es mit Sinatra und dem Mounten mehrerer Rack-Apps für verschiedene Zwecke sein kann.

https://github.com/dusty/multi-rack-app-app


1

Einige großartige 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, Last- und Verkehrsmuster auf einer API vorherzusagen, und Kunden, die die API unabhängig voneinander bedienen, haben eine einfachere Bereitstellung und Skalierung. Wenn Sie dies mit menschlichen Webzugriffsmustern tun müssen, ist dies weniger einfach. Außerdem wird Ihre API-Nutzung möglicherweise viel schneller skaliert als Ihr Webclient, und dann können Sie sehen, wohin Sie Ihre Bemühungen lenken müssen.

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


1

Für atyourservice.com.cy verwenden wir serverseitig gerenderte Vorlagen für Seiten, insbesondere um diesen Teil abzudecken. Und Verwenden der API für Interaktionen nach dem Laden der Seite. Da unser Framework MVC ist, werden alle Controller-Funktionen in die JSON-Ausgabe und die HTML-Ausgabe dupliziert. Vorlagen sind sauber und erhalten nur ein Objekt. Dies kann in Sekundenschnelle in js-Vorlagen umgewandelt werden. Wir pflegen immer die serverseitigen Vorlagen und konvertieren sie auf Anfrage einfach in js zurück.


1

Isomorphes Rendering und progressive Verbesserung. Welches ist, was ich denke, dass Sie in Option drei geleitet wurden.

Isomorphes Rendern bedeutet, dass dieselbe Vorlage verwendet wird, um serverseitiges Markup zu generieren, das Sie im clientseitigen Code verwenden. Wählen Sie eine Vorlagensprache mit guten serverseitigen und clientseitigen Implementierungen. Erstellen Sie vollständig gebackenes HTML für Ihre Benutzer und senden Sie es über den Draht. Verwenden Sie auch Caching.

Progressive Verbesserung bedeutet, dass Sie mit der clientseitigen Ausführung, dem Rendern und dem Abhören von Ereignissen beginnen, sobald Sie alle Ressourcen heruntergeladen haben und die Funktionen eines Clients bestimmen können. Wo immer möglich auf funktionale Funktionen ohne Client-Skript zurückgreifen, um Barrierefreiheit und Abwärtskompatibilität zu gewährleisten.

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 gut funktionieren.


1

REST-Server + JavaScript-lastiger Client war das Prinzip, dem ich in meiner letzten Arbeit gefolgt bin.

Der REST-Server wurde in node.js + Express + MongoDB (sehr gute Schreibleistung) + Mongoose ODM (ideal zum Modellieren von Daten, einschließlich Validierungen) + CoffeeScript implementiert ideal (ich würde jetzt stattdessen ES2015 verwenden) implementiert, was für mich gut funktionierte. Node.js mag im Vergleich zu anderen möglichen serverseitigen Technologien relativ jung sein, aber es hat mir ermöglicht, eine solide API mit integrierten Zahlungen zu schreiben.

Ich habe Ember.js als JavaScript-Framework verwendet und der größte Teil der Anwendungslogik wurde im Browser ausgeführt. Ich habe SASS benutzt (speziell SCSS) für die CSS-Vorverarbeitung verwendet.

Ember ist ein ausgereiftes Framework, das von einer starken Community unterstützt wird. Es ist ein sehr leistungsfähiges Framework, bei dem in letzter Zeit viel Arbeit geleistet wurde, die sich auf die Leistung konzentriert, wie die brandneue Glimmer-Rendering-Engine (inspiriert von React).

Das Ember Core Team befindet sich in der Entwicklung derzeit FastBoot , mit dem Sie Ihre JavaScript-Ember-Logik serverseitig ausführen können (insbesondere node.js) und vorgerenderten HTML-Code Ihrer Anwendung (der normalerweise im Browser ausgeführt wird) an den Benutzer senden können. Es ist großartig für SEO und User Experience, da er nicht so lange auf die Anzeige der Seite wartet.

Ember CLI ist ein großartiges Tool, mit dem Sie Ihren Code organisieren können, und es hat sich gut mit der wachsenden Codebasis skalieren lassen. Ember hat auch ein eigenes Addon-Ökosystem und Sie können aus einer Vielzahl von Ember-Addons wählen . Sie können Bootstrap (in meinem Fall) oder Foundation ganz einfach herunterladen und Ihrer App hinzufügen.

Um nicht alles über Express zu bedienen, habe ich mich entschieden, nginx für die Bereitstellung von Bildern und JavaScript-lastigen Clients zu verwenden. Die Verwendung von Nginx Proxy war in meinem Fall hilfreich:

upstream app_appName.com {
  # replace 0.0.0.0 with your IP address and 1000 with your port of node HTTP server
  server 0.0.0.0:1000;
  keepalive 8;
}

server {
  listen 80 default_server;
  listen [::]:80 default_server ipv6only=on;

  client_max_body_size 32M;

  access_log  /var/log/nginx/appName.access.log;
  error_log  /var/log/nginx/appName.error.log;

  server_name appName.com appName;

  location / {
     # frontend assets path
     root /var/www/html;
     index index.html;

     # to handle Ember routing
     try_files $uri $uri/ /index.html?/$request_uri;
  }

  location /i/ {
    alias /var/i/img/;
  }

  location /api/v1/ {
    proxy_pass  http://app_appName.com;

    proxy_next_upstream error timeout invalid_header http_500 http_502
http_503 http_504;
    proxy_redirect off;
    proxy_buffering off;
    proxy_set_header        Host            $host;
    proxy_set_header        X-Real-IP       $remote_addr;
    proxy_set_header        X-Forwarded-For $proxy_add_x_forwarded_for;
  }
}

Pro: Ich liebe die Trennung von API und Client. Kluge Leute sagen, dies sei der richtige Weg. Theoretisch großartig. Scheint topaktuell und aufregend.

Ich kann sagen, dass es auch in der Praxis großartig ist. Ein weiterer Vorteil der Trennung der REST-API besteht darin, dass Sie sie später für andere Anwendungen wiederverwenden können. In einer perfekten Welt sollten Sie in der Lage sein, dieselbe REST-API nicht nur für Webseiten, sondern auch für mobile Anwendungen zu verwenden, wenn Sie eine schreiben möchten.

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

Die Dinge sehen jetzt anders aus. Es gibt viele Beispiele für die Ausführung der REST-API + viele Clients, die diese verwenden.


1

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

Dies hat den Vorteil, dass die API-Server unabhängig von den Webservern skaliert werden können. Wenn Sie mehrere Clients haben, müssen die Websites nicht im gleichen Umfang skaliert werden wie die Webserver, da einige Clients auf Telefon / Tablet oder Desktop basieren.

Dieser Ansatz bietet Ihnen auch eine gute Grundlage für die Öffnung Ihrer API für Ihre Benutzer, insbesondere wenn Sie Ihre eigene API verwenden, um alle Funktionen für Ihre Website bereitzustellen.


1

Eine sehr schöne Frage, und ich bin überrascht, da ich dachte, dass dies heutzutage eine sehr häufige Aufgabe ist, so dass ich viele Ressourcen für dieses Problem haben werde, was sich jedoch als nicht wahr herausstellte.

Meine Gedanken lauten wie folgt: - Erstellen Sie ein Modul, das die gemeinsame Logik zwischen den API-Controllern und den HTML-Controllern aufweist, ohne json zurückzugeben oder HTML zu rendern, und fügen Sie dieses Modul sowohl in den HTML-Controller als auch in den API-Controller ein. Tun Sie dann beispielsweise, was Sie möchten ::

module WebAndAPICommon
    module Products

        def index
            @products = # do some logic here that will set @products variable
        end

    end
end


class ProductsController < ApplicationController
    # default products controlelr, for rendering HMTL pages 
    include WebAndAPICommon

    def index
        super
    end

end



module API
    class ProductsController
        include WebAndAPICommon

        def index
            super
            render json: @products
        end

    end
end

0

Ich habe mich für einen hybriden Ansatz entschieden, bei dem wir Sinatra als Basis, ActiveRecord / Postgress usw. verwenden, um Seitenrouten (schlanke Vorlagen) bereitzustellen, die eine REST-API verfügbar machen, die die Web-App verwenden kann. In der frühen Entwicklung erfolgt das Auffüllen ausgewählter Optionen über das Rendern von Hilfsprogrammen in die schlanke Vorlage. Wenn wir uns jedoch der Produktion nähern, wird dies gegen einen AJAX-Aufruf einer REST-API ausgetauscht, da wir uns mehr um die Geschwindigkeit beim Laden von Seiten usw. kümmern.

Dinge, die in Slim einfach zu rendern sind, werden auf diese Weise behandelt, und Dinge (das Ausfüllen von Formularen, das Empfangen von Formular-POST-Daten von jQuery.Validation submitHandlerusw. usw. sind allesamt offensichtlich AJAX)

Testen ist ein Problem. Im Moment bin ich ratlos beim Versuch, JSON-Daten an einen Rack :: Test POST-Test zu übergeben .


0

Ich persönlich bevorzuge Option (3) als Lösung. Es wird an fast allen Standorten verwendet, die ein ehemaliger Arbeitgeber (bekannter Name) von mir hat. Dies bedeutet, dass Sie einige Front-End-Entwickler finden können, die alles über Javascript, Browser-Macken und so weiter wissen, um Ihr Front-End zu codieren. Sie müssen nur "curl xyz und du bekommst etwas json" kennen und los geht's.

In der Zwischenzeit können Ihre schweren Back-End-Leute die Json-Anbieter codieren. Diese Leute müssen überhaupt nicht über Präsentation nachdenken und sorgen sich stattdessen um flockige Backends, Zeitüberschreitungen, ordnungsgemäße Fehlerbehandlung, Datenbankverbindungspools, Threading und Skalierung usw.

Option 3 bietet Ihnen eine gute, solide dreistufige Architektur. Dies bedeutet, dass das, was Sie aus dem Front-End ausspucken, SEO-freundlich ist, für die Arbeit mit alten oder neuen Browsern (und solchen mit deaktiviertem JS) verwendet werden kann und auf Wunsch auch als clientseitiges Javascript-Template verwendet werden kann (Sie könnten es also) Machen Sie Dinge wie den Umgang mit alten Browsern / Googlebot mit statischem HTML, aber senden Sie JS-erstellte dynamische Erlebnisse an Benutzer mit dem neuesten Chrome-Browser oder was auch immer.

In allen Fällen, in denen ich Option 3 gesehen habe, handelt es sich um eine benutzerdefinierte Implementierung von PHP, die nicht besonders zwischen Projekten übertragbar ist, geschweige denn in Open Source-Land. Ich denke, in jüngerer Zeit wurde PHP möglicherweise durch Ruby / Rails ersetzt, aber das Gleiche gilt immer noch.

FWIW, $ current_employer könnte Option 3 an einigen wichtigen Stellen nutzen. Ich suche ein gutes Ruby-Framework, in dem ich etwas bauen kann. Ich bin mir sicher, dass ich eine Menge Edelsteine ​​zusammenkleben kann, aber ich würde ein einzelnes Produkt bevorzugen, das im Großen und Ganzen eine Template-, Curling-, optionale Authentifizierungs- und optionale Memcache / Nosql-verbundene Caching-Lösung bietet. Dort finde ich nichts Kohärentes :-(


Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.