¿Servidor y cliente API REST JSON separados? [cerrado]


371

Estoy a punto de crear un montón de aplicaciones web desde cero. (Consulte http://50pop.com/code para obtener una descripción general). Me gustaría poder acceder a ellos desde muchos clientes diferentes: sitios web front-end, aplicaciones para teléfonos inteligentes, servicios web de back-end, etc. Así que realmente quiero un API JSON REST para cada uno.

Además, prefiero trabajar en el back-end, así que sueño con mantener mi enfoque exclusivamente en la API y contratar a alguien más para que haga la interfaz de usuario frontal, ya sea un sitio web, iPhone, Android u otra aplicación.

Por favor, ayúdame a decidir qué enfoque debo tomar:

JUNTOS EN CARRILES

Haga una aplicación web Rails muy estándar. En el controlador, realice el conmutador respond_with, para servir JSON o HTML. La respuesta JSON es entonces mi API.

Pro: muchos precedentes. Excelentes estándares y muchos ejemplos de hacer las cosas de esta manera.

Con: No necesariamente quiero que la API sea la misma que la aplicación web. No me gusta si / luego responde_con enfoque de cambio. Mezclando dos cosas muy diferentes (UI + API).

REST SERVER + JAVASCRIPT-PESADO CLIENTE

Cree un servidor API REST solo para JSON. Use Backbone o Ember.js para JavaScript del lado del cliente para acceder a la API directamente, mostrando plantillas en el navegador.

Pro: Me encanta la separación de API y cliente. Las personas inteligentes dicen que este es el camino a seguir. Genial en teoría. Parece vanguardista y emocionante.

Con: No hay mucho precedente. No hay muchos ejemplos de esto bien hecho. Los ejemplos públicos (twitter.com) se sienten lentos e incluso se están alejando de este enfoque.

REST SERVER + SERVER-SIDE CLIENT HTML

Cree un servidor API REST solo para JSON. Cree un cliente de sitio web HTML básico, que solo acceda a la API REST. Menos JavaScript del lado del cliente.

Pro: Me encanta la separación de API y cliente. Pero servir HTML5 simple es bastante infalible y no requiere mucho cliente.

Con: No hay mucho precedente. No hay muchos ejemplos de esto bien hecho. Los marcos no admiten esto también. No estoy seguro de cómo abordarlo.

Especialmente buscando consejos de la experiencia, no solo en teoría.


50
En general, preferimos que las preguntas especulativas y conceptuales de la pizarra vayan a programmers.stackexchange.com, mientras que las preguntas aquí en Stack Overflow deben contener el código fuente real el 99% del tiempo. Pero, es una pregunta bien hecha y me encanta su trabajo, por lo que esto puede caer en el área gris por ahora.
Jeff Atwood

2
¿Alguien tiene algunos ejemplos / fuentes (para comprender sus razones) para aquellos que se están alejando de la opción 2?
Víctor López García

12
@frntk La razón original por la que muchas empresas (como Twitter) estaban haciendo clientes Javascript era porque pensaban que sería más rápido. Ahora, se están dando cuenta de que en realidad es más lento. Ver engineering.twitter.com/2012/05/… y openmymind.net/2012/5/30/Client-Side-vs-Server-Side-Rendering
Moshe Katz

1
Lea los comentarios en los enlaces de arriba. Muchos de los supuestos del artículo son refutados con lógica y experiencia.
Ricalsin

1
En estos días, querrías hacer un back-end API JSON siguiendo las especificaciones de jsonapi.org ... :)
Askar

Respuestas:


136

En Boundless , hemos profundizado con la opción # 2 y la hemos implementado para miles de estudiantes. Nuestro servidor es una API JSON REST (Scala + MongoDB), y todo nuestro código de cliente se sirve directamente desde CloudFront (es decir: www.boundless.com es solo un alias para CloudFront).

Pros:

  • Vanguardista / emocionante
  • Mucho dinero por su dinero: API le brinda la base para su propio cliente web, clientes móviles, acceso de terceros, etc.
  • Transiciones de página / carga de sitio extremadamente rápidas

Contras:

  • No es compatible con SEO / listo sin mucho más trabajo.
  • Requiere gente de front-end web de primer nivel que esté lista para hacer frente a la realidad de una experiencia de sitio que es 70% javascript y lo que eso significa.

Creo que este es el futuro de todas las aplicaciones web.

Algunas reflexiones para la gente del front-end web (que es donde se da toda esta novedad / desafío a esta arquitectura):

  • CoffeeScript. Mucho más fácil de producir código de alta calidad.
  • Columna vertebral. Gran manera de organizar su lógica y comunidad activa.
  • HAMLC. Plantillas Haml + CoffeeScript => JS.
  • HABLAR CON DESCARO A

Hemos creado un arnés para nuestro desarrollo front-end llamado 'Spar' (Single Page App Rocketship) que es efectivamente la cartera de activos de Rails ajustada para el desarrollo de aplicaciones de una sola página. Dentro de las próximas semanas, estaremos en código abierto en nuestra página de github , junto con una publicación de blog que explica cómo usarlo y la arquitectura general con mayor detalle.

ACTUALIZAR:

Con respecto a las preocupaciones de las personas con Backbone, creo que están sobrevaloradas. La columna vertebral es mucho más un principio organizativo que un marco profundo. El sitio de Twitter en sí es una bestia gigante de Javascript que cubre todos los rincones de millones de usuarios y navegadores heredados, mientras carga tweets en tiempo real, recolecta basura, muestra gran cantidad de multimedia, etc. De todos los sitios js 'puros' que he visto, Twitter es el extraño. Ha habido muchas aplicaciones impresionantemente complicadas entregadas a través de JS que funcionan muy bien.

Y su elección de arquitectura depende completamente de sus objetivos. Si está buscando la forma más rápida de brindar soporte a múltiples clientes y tener acceso a un buen talento inicial, invertir en una API independiente es una excelente manera de hacerlo.


1
Un punto menor para agregar: si bien solo he creado la opción n. ° 1, conozco a varios desarrolladores de aplicaciones móviles que están comenzando a usar parse.com como back-end para permitir una ruta rápida al n. ° 2.
Rhb123

Cosas como Parse y Kinvey son muy interesantes, no puedo decir que haya tenido la oportunidad de jugar con ellos todavía. Depende de si su valor está en la parte delantera o trasera de la pila, supongo
Aaron

Yo uso el mismo enfoque con spinejs para la interfaz.
Nicolas Goy

¿Cómo maneja un solo dominio que ejecuta dos aplicaciones separadas? P.ej. Tengo www.mysite.com y quiero exponer una API pública y publicar un front-end en esa URL. Fiel a los principios REST, mysite.com/product/24 al que se accede desde un navegador web debería devolver una página HTML mirando el encabezado HTTP Accept, y un GET con JSON en el encabezado Accept en mysite.com/product/24 debería devolver JSON .
Erich

¿Cómo AngularJS se las arreglaría para esto?
Ankan-Zerob

48

Muy bien preguntado. +1. Por supuesto, esta es una referencia útil futura para mí. También @Aaron y otros agregaron valor a la discusión. Al igual que Ruby, esta pregunta es igualmente aplicable a otros entornos de programación.

He usado las dos primeras opciones. El primero para numerosas aplicaciones y el segundo para mi proyecto de código abierto Cowoop

Opción 1

Este es sin duda el más popular. Pero creo que la implementación es muy http-ish. El código inicial de cada API se aplica al objeto de solicitud. Entonces, el código API es más que puro código ruby ​​/ python / other language.

opcion 2

Siempre me ha encantado esto.

Esta opción también implica que HTML no es tiempo de ejecución generado en el servidor. Así es como la opción 2 es diferente de la opción 3. Pero se compilan como html estático utilizando un script de compilación. Cuando se carga en el lado del cliente, este HTML llamará al servidor API como cliente API JS.

  • La separación de las preocupaciones es una gran ventaja. Y para su gusto (y el mío), los expertos de backend implementan API de backend, pruébelos fácilmente como el código de idioma habitual sin preocuparse por el código de solicitud de marco / http.

  • Esto realmente no es tan difícil como parece en el lado frontend. Las llamadas API y los datos resultantes (principalmente json) están disponibles para su plantilla del lado del cliente o MVC.

  • Menos procesamiento del lado del servidor. Significa que puede optar por hardware básico / servidor menos costoso.

  • Más fácil de probar capas de forma independiente, más fácil de generar documentos API.

Tiene algunos inconvenientes.

  • Muchos desarrolladores encuentran esto sobredimensionado y difícil de entender. Entonces, es probable que la arquitectura sea criticada.

  • i18n / l10n es difícil. Dado que HTML se genera esencialmente, el tiempo de compilación es estático, uno necesita múltiples compilaciones por idioma compatible (lo cual no es necesariamente algo malo). Pero incluso con eso, puede tener casos de esquina alrededor de l10n / i18n y debe tener cuidado.

Opción 3

La codificación del backend en este caso debe ser la misma que la segunda opción. La mayoría de los puntos para la opción 2 también son aplicables aquí.

Las páginas web se ejecutan en tiempo de ejecución utilizando plantillas del lado del servidor. Esto hace que i18n / l10n sea mucho más fácil con técnicas más establecidas / aceptadas. Puede ser una llamada http menos para algún contexto esencial necesario para la representación de la página, como el usuario, el idioma, la moneda, etc. Por lo tanto, el procesamiento del lado del servidor aumenta con la representación, pero posiblemente se compensa con menos llamadas http al servidor API.

Ahora que las páginas están representadas en el servidor, el frontend ahora está más vinculado con el entorno de programación. Esto podría no ser incluso una consideración para muchas aplicaciones.

Caso de Twitter

Según tengo entendido, Twitter puede hacer su representación inicial de la página en el servidor, pero para las actualizaciones de la página todavía tiene algunas llamadas API y plantillas del lado del cliente para manipular DOM. Entonces, en tal caso, tiene que mantener plantillas dobles, lo que agrega algo de sobrecarga y complejidad. No todos pueden permitirse esta opción, a diferencia de Twitter.

Nuestro proyecto Stack

Yo uso Python. Yo uso JsonRPC 2.0 en lugar de REST. Sugiero REST, aunque me gusta la idea de JsonRPC por varias razones. Yo uso las bibliotecas a continuación. Alguien que considere la opción 2/3 podría encontrarlo útil.

  • Servidor API: Python Un micro framework web rápido - Frasco
  • Servidor frontend: Nginx
  • MVC del lado del cliente: Knockout.js
  • Otras herramientas / libs relevantes:

Mi conclusión y recomendación

Opción 3 !.

Dicho todo esto, he usado la opción 2 con éxito, pero ahora me inclino hacia la opción 3 por simplicidad. Generar páginas HTML estáticas con un script de compilación y servirlas con uno de los servidores ultrarrápidos que se especializan en servir páginas estáticas es muy tentador (Opción 2).


También me gusta la opción 2, pero la opción 3 tiene muchas ventajas de las que no podemos deshacernos. Estoy tratando de encontrar alguna solución hidrid que combine ambos opt2 + opt3, pero provocará dolores de cabeza como Twitter.
Blue Smith

Me encanta la opción 3, y mi objetivo es usarla para un proyecto actual. ¿Algún repositorio de eg o git al que pueda pedir ayuda?
AmaChefe

@AmaChefe, deseo. Para el proyecto actual donde el SEO es crucial, usamos la opción 3. Pero el código no es de código abierto. Usamos frasco + jinja2 y knockout / react.js.
Shekhar

28

Optamos por el # 2 al construir gaug.es. Trabajé en la API (ruby, sinatra, etc.) y mi socio comercial, Steve Smith, trabajó en el front-end (cliente javascript).

Pros:

  1. Muévete rápidamente en paralelo. Si trabajara antes que Steve, podría seguir creando API para nuevas funciones. Si trabajaba por delante de mí, podría falsificar la API muy fácilmente y construir la interfaz de usuario.

  2. API de forma gratuita. Tener acceso abierto a los datos en su aplicación se está convirtiendo rápidamente en una característica estándar. Si comienzas con una API desde cero, obtienes esto gratis.

  3. Separación limpia Es mejor pensar en su aplicación como una API con clientes. Claro, el primer y más importante cliente puede ser uno web, pero lo configura para crear fácilmente otros clientes (iPhone, Android).

Contras:

  1. Compatibilidad al revés. Esto está más relacionado con una API que con su pregunta directa, pero una vez que su API está disponible, no puede simplemente romperla o romper todas sus clientes dos. Esto no significa que tenga que moverse más despacio, pero sí significa que a menudo debe hacer que dos cosas funcionen a la vez. Agregar a la API o nuevos campos está bien, pero cambiar / eliminar no debe hacerse sin versionar.

No puedo pensar en más contras en este momento.

Conclusión: el cliente API + JS es el camino a seguir si planea lanzar una API.

PD: También recomendaría documentar completamente su API antes de lanzarla. El proceso de documentación de la API de Gaug.es realmente nos ayudó a mejorar

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


13
¿Puedo preguntar cómo autentica la interfaz web con la API REST? Vi que necesita una clave API para comunicarse con la API que se obtiene iniciando sesión en su perfil de usuario. Pero, ¿cómo obtiene el cliente web su clave API, si sabes a qué me refiero?
Sebastian Wramba

@SebastianWramba Esto es tarde, pero como tu comentario recibió 12 votos a favor ... miraría algo como la autorización de contraseña de OAuth2 . Si usted es el creador de la aplicación que llama a la API, este es el enfoque que probablemente desee, ya que no utiliza la clave API directamente. Si se trata de una aplicación de terceros, tiene el inicio de sesión del usuario en su sitio web para obtener su clave API, y luego el usuario usa esa clave (y cualquier otra credencial necesaria) para acceder a la API a través de su aplicación, sitio web, etc.
GreeKatrina

10

Prefiero ir por la ruta del # 2 y # 3. Principalmente porque # 1 viola la separación de preocupaciones y entremezcla todo tipo de cosas. Eventualmente, encontrará la necesidad de tener un punto final de API que no tenga una página HTML / etc coincidente y se encontrará en un arroyo con puntos finales HTML y JSON entremezclados en la misma base de código. Se convierte en un desastre, incluso si es MVP, tendrás que volver a escribirlo eventualmente porque es tan desordenado que ni siquiera vale la pena salvarlo.

Ir con # 2 o # 3 le permite tener completamente una API que actúa igual (en su mayor parte) independientemente. Esto proporciona una gran flexibilidad. Todavía no estoy 100% vendido en Backbone / ember / whatever / etc.js. Creo que es genial, pero como estamos viendo con Twitter, esto no es óptimo. PERO ... Twitter también es una gran bestia de compañía y tiene cientos de millones de usuarios. Por lo tanto, cualquier mejora puede tener un gran impacto en el resultado final en varias áreas de varias unidades de negocios. Creo que hay más en la decisión que la velocidad sola y no nos dejan entrar en eso. Pero esa es solo mi opinión. Sin embargo, no descarto el backbone y sus competidores. Estas aplicaciones son excelentes para usar y son muy limpias y muy receptivas (en su mayor parte).

La tercera opción también tiene un atractivo válido. Aquí es donde seguiría el principio de Pareto (regla 80/20) y tendría el 20% de su marcado principal (o viceversa) representado en el servidor y luego tendría un buen cliente JS (backbone / etc) ejecutar el resto . Es posible que no se esté comunicando al 100% con la API REST a través del cliente JS, pero hará algún trabajo si es necesario para mejorar la experiencia del suer.

Creo que este es uno de esos tipos de problemas "depende" y la respuesta es "depende" de lo que estás haciendo, a quién estás sirviendo y qué tipo de experiencia quieres que reciban. Dado que creo que puedes decidir entre 2 o 3 o un híbrido de ellos.


+1 al híbrido de 2 y 3
Ujjwal Ojha

7

Actualmente estoy trabajando para convertir un gran CMS de la opción 1 a la opción 3, y me está yendo bien. Elegimos representar el lado del servidor de marcado porque el SEO es un gran problema para nosotros, y queremos que los sitios funcionen bien en teléfonos móviles.

Estoy usando node.js para el back-end del cliente y un puñado de módulos para ayudarme. Estoy un poco temprano en el proceso, pero la base está establecida y es una cuestión de revisar los datos para garantizar que todo funcione correctamente. Esto es lo que estoy usando:

  • Expresar para la base de la aplicación.
    (https://github.com/visionmedia/express)
  • Solicitud para obtener los datos.
    (https://github.com/mikeal/request)
  • Subrayar plantillas que se representan en el lado del servidor. Reutilizo estos en el cliente.
    (https://github.com/documentcloud/underscore)
  • UTML ajusta las plantillas de subrayado para que funcionen con Express.
    (https://github.com/mikefrey/utml)
  • Upfront recopila plantillas y le permite elegir cuáles se envían al cliente.
    (https://github.com/mrDarcyMurphy/upfront)
  • Express Expose pasa los datos recuperados, algunos módulos y plantillas al front-end.
    (https://github.com/visionmedia/express-expose)
  • Backbone crea modelos y vistas en el front-end después de tragar los datos que se transmitieron.
    (https://github.com/documentcloud/backbone)

Ese es el núcleo de la pila. Algunos otros módulos que he encontrado útiles:

  • fleck (https // github.com / trek / fleck)
  • momento (https // github.com / timrwood / moment)
  • stylus (https // github.com / LearnBoost / stylus)
  • smoosh (https // github.com / fat / smoosh)
    ... aunque estoy investigando el gruñido (https // github.com / cowboy / grunt)
  • seguimiento de consola (//github.com/LearnBoost/console-trace).

No, no estoy usando coffeescript.

Esta opción me está funcionando muy bien. Los modelos en el back-end no existen porque los datos que obtenemos de la API están bien estructurados y los paso literalmente al front-end. La única excepción es nuestro modelo de diseño donde agrego un solo atributo que hace que el renderizado sea más inteligente y ligero. No utilicé ninguna biblioteca de modelos sofisticada para eso, solo una función que agrega lo que necesito en la inicialización y me devuelve.

(Perdón por los enlaces extraños, soy demasiado n00b para que el desbordamiento de la pila me permita publicar tantos)


1
Entonces, ¿está procesando el marcado del lado del servidor pero todavía está dando plantillas al cliente y está utilizando Backbone?
Shannon

7

Utilizamos la siguiente variante del n. ° 3: Crear un servidor API REST solo para JSON. Hacer un servidor de sitio web HTML. El servidor web HTML no es, como en su variante, un cliente para el servidor REST API. En cambio, los dos son compañeros. No muy lejos de la superficie, hay una API interna que proporciona la funcionalidad que necesitan los dos servidores.

No conocemos ningún precedente, por lo que es algo experimental. Hasta ahora (a punto de entrar en beta), ha funcionado bastante bien.


Estoy pensando en esta opción para evitar algunos problemas relacionados con ser un cliente API adecuado, como la autenticación. Me gustaría saber más sobre cómo estructuró todo y cómo maneja la separación y la comunicación entre las tres partes diferentes. ¿Hay algo que pueda leer? ¡Gracias!
MartinodF

2
@MartinodF Hospedamos en Google App Engine, que se limita a Java o Python. Quería usar Python, pero me forzaron a Java porque redujimos los números (no podemos extender Py con C / C ++ en GAE). Elegimos Stripes (Stripes, no Struts, not Spring) para el marco de presentación. Muy contento con eso. Todo es una aplicación Java en GAE. La funcionalidad principal se implementa en un montón de paquetes Java y se expone en una API interna. Hay un servlet que proporciona el servicio JSON REST y otro que está configurado como una aplicación web Stripes. Como se trata de una aplicación GAE Java, la comunicación es trivial.
Thomas Becker

Gracias por la información, es muy útil!
MartinodF

7

Por lo general, voy por la segunda opción, usando Rails para construir la API, y la columna vertebral para las cosas de JS. Incluso puede obtener un panel de administración de forma gratuita con ActiveAdmin . He enviado decenas de aplicaciones móviles con este tipo de backend. Sin embargo, depende en gran medida si su aplicación es interactiva o no.

Hice una presentación sobre este enfoque en el último RubyDay.it : http://www.slideshare.net/matteocollina/enter-the-app-era-with-ruby-on-rails-rubyday

Para la tercera opción, para obtener capacidad de respuesta de la segunda, es posible que desee probar el pijama como lo hace Github.


6

Estoy cerca de 2 meses en un proyecto de 3 meses que toma el segundo enfoque que describiste aquí. Usamos un servidor RESTful API con backbone.js en el frente. Handlebars.js administra las plantillas y jQuery maneja la manipulación de AJAX y DOM. Para los navegadores más antiguos y las arañas de búsqueda, hemos recurrido a la representación del lado del servidor, pero estamos utilizando las mismas plantillas HTML que la interfaz de Manillar con Mozilla Rhino.

Elegimos este enfoque por muchas razones diferentes, pero somos muy conscientes de que es un poco arriesgado dado que aún no se ha demostrado a gran escala. De todos modos, todo va bastante bien hasta ahora.

Hasta ahora hemos estado trabajando con una API, pero en la siguiente fase del proyecto trabajaremos con una segunda API. El primero es para grandes cantidades de datos, y el segundo actúa más como un CMS a través de una API.

Tener estas dos partes del proyecto actuando completamente independientes entre sí fue una consideración clave en la selección de esta infraestructura. Si está buscando una arquitectura para combinar diferentes recursos independientes sin dependencias, vale la pena echarle un vistazo a este enfoque.

Me temo que no soy un chico Ruby, así que no puedo comentar sobre los otros enfoques. A veces está bien arriesgarse. Otras veces es mejor ir a lo seguro. Te reconocerás dependiendo del tipo de proyecto.

Mucha suerte con tu elección aquí. Deseoso de ver lo que otros comparten también.


1
¿Entonces detecta si la solicitud proviene de un robot de búsqueda y sirve HTML pre-renderizado si es así, y Plantillas JS + si no lo es?
Shannon

4

Me gusta # 3 cuando mi sitio web no va a ser una implementación 100% CRUD de mis datos. Lo que aún está por suceder.

Prefiero sinatra y simplemente dividiré la aplicación en algunas aplicaciones de rack diferentes con diferentes propósitos. Haré una aplicación de rack específica de API que cubrirá lo que necesito para la API. Entonces, tal vez, una aplicación de rack de usuario que presente mi página web. A veces, esa versión consultará la API si es necesario, pero generalmente solo se ocupa del sitio html.

No me preocupo por eso y solo hago una consulta de capa de persistencia desde el lado del usuario si lo necesito. No estoy demasiado preocupado por crear una separación completa, ya que generalmente terminan sirviendo para diferentes propósitos.

Aquí hay un ejemplo muy simple del uso de múltiples aplicaciones de rack. Agregué un ejemplo de jquery rápido allí para que lo veas golpear la aplicación API. Puedes ver lo simple que puede ser con sinatra y montar múltiples aplicaciones de rack con diferentes propósitos.

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


1

Algunas respuestas geniales aquí ya - definitivamente recomendaría # 2 o # 3 - la separación es buena conceptualmente pero también en la práctica.

Puede ser difícil predecir cosas como los patrones de carga y tráfico en una API y los clientes que vemos que atienden la API de forma independiente tienen un tiempo más fácil de aprovisionamiento y escalado. Si tiene que hacer eso con los patrones de acceso web humanos, es menos fácil. Además, su uso de API podría terminar aumentando mucho más rápido que su cliente web y luego puede ver hacia dónde dirigir sus esfuerzos.

Entre el n. ° 2 y el n. ° 3, realmente depende de tus objetivos. Estoy de acuerdo en que el n. ° 2 es probablemente el futuro de las aplicaciones web, pero tal vez quieras algo más directo si ese canal solo va a ser uno de muchos.


1

Para atyourservice.com.cy estamos utilizando plantillas renderizadas del lado del servidor para páginas especialmente para cubrir la parte se. Y usando la API para interacciones después de cargar la página. Dado que nuestro marco es MVC, todas las funciones del controlador se duplican en salida json y salida html. Las plantillas son limpias y reciben solo un objeto. Esto se puede transformar en plantillas js en segundos. Siempre mantenemos las plantillas del lado del servidor y simplemente reconvertimos a js a pedido.


1

Representación isomórfica y mejora progresiva. Que es a lo que creo que te dirigías en la opción tres.

representación isomorfa significa usar la misma plantilla para generar el marcado del lado del servidor que usa en el código del lado del cliente. Elija un lenguaje de plantillas con buenas implementaciones del lado del servidor y del lado del cliente. Cree html completamente horneado para sus usuarios y envíelo por cable. Utilice el almacenamiento en caché también.

la mejora progresiva significa comenzar a ejecutar y ejecutar el lado del cliente y escuchar eventos una vez que haya descargado todos los recursos y pueda determinar las capacidades de un cliente. Recurrir a la funcionalidad funcional sin cliente-script siempre que sea posible para accesibilidad y compatibilidad con versiones anteriores.

Sí, por supuesto, escriba una API JSON independiente para la funcionalidad de esta aplicación. Pero no vaya tan lejos como para escribir una API json para cosas que funcionan bien como documentos html estáticos.


1

El servidor REST + cliente pesado en JavaScript fue el principio que he seguido en mi trabajo reciente.

El servidor REST se implementó en node.js + Express + MongoDB (muy buen rendimiento de escritura) + Mongoose ODM (excelente para modelar datos, validaciones incluidas) + CoffeeScript (ahora iría a ES2015) que funcionó bien para mí. Node.js podría ser relativamente joven en comparación con otras posibles tecnologías del lado del servidor, pero me permitió escribir API sólida con pagos integrados.

He usado Ember.js como marco de JavaScript y la mayor parte de la lógica de la aplicación se ejecutó en el navegador. He usado SASS (SCSS específicamente) para el preprocesamiento de CSS.

Ember es un marco maduro respaldado por una comunidad fuerte. Es un marco muy poderoso con mucho trabajo que se está haciendo recientemente centrado en el rendimiento, como el nuevo motor de renderizado Glimmer (inspirado en React).

Ember Core Team está en proceso de desarrollar FastBoot , que le permite ejecutar su lógica Ember de JavaScript en el lado del servidor (específicamente node.js) y enviar HTML pre-renderizado de su aplicación (que normalmente se ejecutaría en el navegador) al usuario. Es excelente para SEO y la experiencia del usuario, ya que no espera tanto tiempo para que se muestre la página.

Ember CLI es una gran herramienta que lo ayuda a organizar su código y funcionó bien para escalar con una creciente base de código. Ember también tiene su propio ecosistema de complementos y puede elegir entre una variedad de complementos de Ember . Puede tomar fácilmente Bootstrap (en mi caso) o Foundation y agregarlo a su aplicación.

Para no servir todo a través de Express, he elegido usar nginx para servir imágenes y clientes con JavaScript. Usar el proxy nginx fue útil en mi caso:

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: Me encanta la separación de API y cliente. Las personas inteligentes dicen que este es el camino a seguir. Genial en teoría. Parece vanguardista y emocionante.

Puedo decir que también es genial en la práctica. Otra ventaja de separar la API REST es que puede reutilizarla más tarde para otras aplicaciones. En un mundo perfecto, debería poder usar la misma API REST no solo para la página web, sino también para las aplicaciones móviles si decide escribir una.

Con: No hay mucho precedente. No hay muchos ejemplos de esto bien hecho. Los ejemplos públicos (twitter.com) se sienten lentos e incluso se están alejando de este enfoque.

Las cosas se ven diferentes ahora. Hay muchos ejemplos de hacer API REST + muchos clientes lo consumen.


1

Decidí optar por la arquitectura de la Opción # 2 para Infiniforms , ya que proporcionaba una excelente manera de separar la IU de la lógica empresarial.

Una ventaja de esto es que los Servidores API pueden escalar independientemente de los servidores web. Si tiene varios clientes, entonces los sitios web no necesitarán escalar en la misma medida que los servidores web, ya que algunos clientes estarán basados ​​en teléfono / tableta o computadora de escritorio.

Este enfoque también le brinda una buena base para abrir su API a sus usuarios, especialmente si utiliza su propia API para proporcionar todas las funcionalidades de su sitio web.


1

Una pregunta muy agradable y me sorprende, ya que pensé que esta es una tarea muy común hoy en día, de modo que tendré muchos recursos para este problema, sin embargo, resultó no ser cierto.

Mis pensamientos son los siguientes: - Cree un módulo que tenga la lógica común entre los controladores API y los controladores HTML sin devolver json o renderizar html, e incluya este módulo tanto en el controlador HTML como en el controlador API, luego haga lo que quiera, por ejemplo :

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

He optado por un enfoque híbrido donde usamos Sinatra como base, ActiveRecord / Postgress, etc. para servir rutas de página (plantillas delgadas) exponen una API REST que la aplicación web puede usar. En el desarrollo inicial, cosas como completar las opciones de selección se realizan a través de ayudantes que se procesan en la plantilla delgada, pero a medida que nos acercamos a la producción, esto se cambia por una llamada AJAX a una API REST a medida que comenzamos a preocuparnos más por las velocidades de carga de la página, etc.

Las cosas que son fáciles de procesar en Slim se manejan de esa manera, y cosas (llenar formularios, recibir datos POST de jQuery. Validaciones, submitHandleretc., es obviamente AJAX)

La prueba es un problema. En este momento estoy perplejo tratando de pasar datos JSON a una prueba POST Rack :: Test .


0

Personalmente prefiero la opción (3) como solución. Se usa en casi todos los sitios que tiene un antiguo empleador (de nombre familiar). Significa que puede obtener algunos desarrolladores front-end que saben todo sobre Javascript, peculiaridades del navegador y otras cosas para codificar su front-end. Solo necesitan saber "curl xyz y obtendrás algo de json" y listo.

Mientras tanto, sus chicos de back-end pesados ​​pueden codificar a los proveedores de Json. Estos chicos no necesitan pensar en la presentación en absoluto, y en su lugar se preocupan por los backends inestables, los tiempos de espera, el manejo elegante de errores, los grupos de conexiones de bases de datos, los subprocesos y el escalado, etc.

La opción 3 le brinda una buena y sólida arquitectura de tres niveles. Significa que las cosas que escupe desde el front-end son amigables con el SEO, se pueden hacer funcionar con navegadores antiguos o nuevos (y aquellos con JS desactivado), y aún podrían ser plantillas de JavaScript del lado del cliente si lo desea (para que pueda hacer cosas como manejar navegadores antiguos / googlebot con HTML estático, pero enviar experiencias dinámicas creadas por JS a personas que usan el navegador Chrome más reciente o lo que sea).

En todos los casos que he visto la Opción 3, ha sido una implementación personalizada de algunos PHP que no es especialmente transferible entre proyectos, y mucho menos en tierra de código abierto. Supongo que más recientemente PHP pudo haber sido reemplazado por Ruby / Rails, pero el mismo tipo de cosas sigue siendo cierto.

FWIW, $ current_employer podría hacer con la Opción 3 en un par de lugares importantes. Estoy buscando un buen marco de Ruby en el que construir algo. Estoy seguro de que puedo unir una carga de gemas, pero preferiría un solo producto que, en términos generales, proporcione una solución de almacenamiento en caché conectada con plantilla, 'curling', autenticación opcional, memcache / nosql opcional. Ahí no encuentro nada coherente :-(


Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.