将REST JSON API服务器和客户端分离?

372

我即将从零开始创建一堆Web应用程序。 (请参阅http://50pop.com/code进行概述。)我希望它们可以从许多不同的客户端访问:前端网站、智能手机应用程序、后端Web服务等。因此,我确实想要每个应用程序都有JSON REST API。

此外,我更喜欢在后端工作,所以我幻想着自己专注于API,然后聘请其他人制作前端UI,无论是网站、iPhone、Android还是其他应用程序。

请帮助我决定应采取哪种方法:

在Rails中一起构建

创建一个非常标准的Rails Web应用程序。在控制器中,使用respond_with开关,提供JSON或HTML服务。然后,JSON响应成为我的API。

优点:有很多先例。伟大的标准和许多这样做的示例。

缺点:不一定希望API与Web应用程序相同。不喜欢if/then respond_with开关方法。混合了两个非常不同的东西(UI + API)。

REST服务器+JavaScript密集客户端

创建一个仅JSON的REST API服务器。使用Backbone或Ember.js进行客户端JavaScript,直接访问API,在浏览器中显示模板。

优点:我喜欢API和客户端的分离。聪明人说这是正确的方式。理论上很棒。看起来很前沿和令人兴奋。

缺点:先例不多。没有做好这个的很多示例。公共示例(twitter.com)感觉迟缓,甚至正在切换到其他方法。

REST服务器+服务器端HTML客户端

创建一个仅JSON的REST API服务器。制作一个基本的HTML网站客户端,只访问REST API。客户端JavaScript较少。

优点: 我喜欢API和客户端的分离。但提供普通的HTML5相当简单,不需要客户端的大量计算。

缺点: 缺乏先例。没有很多成功的实例可供借鉴。框架对此支持不够好。不确定如何着手处理。

尤其是希望从经验上获得建议,而不仅仅是理论方面的。


52
通常情况下,我们更喜欢把那些探讨概念和想法的白板问题放到http://programmers.stackexchange.com上,而在Stack Overflow上发问时,99%的情况下应该包含实际源代码。但这是一个很好的问题,我很喜欢你的工作,所以现在可以算是灰色地带。 - Jeff Atwood
12
很多公司(例如Twitter)最初采用JavaScript客户端的原因是他们认为它会更快。但现在,他们意识到这样做其实更慢了。请参见以下链接:http://engineering.twitter.com/2012/05/improving-performance-on-twittercom.html 和 http://openmymind.net/2012/5/30/Client-Side-vs-Server-Side-Rendering/ - Moshe Katz
18个回答

1

等同渲染和渐进增强。这是我认为你在第三个选项中要去的方向。

等同渲染意味着使用与客户端代码相同的模板来生成服务器端标记。选择具有良好服务器端和客户端实现的模板语言。为您的用户创建完全烤制的html并将其发送到线路上。也使用缓存。

渐进增强意味着一旦您下载了所有资源并确定了客户端功能,就开始执行和呈现客户端并监听事件。尽可能回退到无客户端脚本的功能以提高可访问性和向后兼容性。

是的,当然要为此应用程序功能编写一个独立的json api。但不要过分追求为正常的静态html文档编写json api。


1
我们在atyourservice.com.cy网站上使用服务器端渲染模板来覆盖搜索引擎优化的部分,并在页面加载后使用API进行交互。由于我们的框架是MVC,所有控制器函数都会被复制到json输出和html输出中。模板干净简洁,只接收一个对象,可以在几秒钟内转换为js模板。我们始终保持服务器端模板,并在请求时重新转换为js。

1
我决定选择Option #2的架构来实现Infiniforms,因为它提供了一种很好的方法来将UI与业务逻辑分离。
这样做的一个优点是API服务器可以独立于Web服务器进行扩展。如果您有多个客户端,那么网站不需要像Web服务器那样扩展到同样的程度,因为一些客户端将基于手机/平板电脑或桌面。
这种方法还为向用户开放API提供了良好的基础,特别是如果您使用自己的API为您的网站提供所有功能。

1

这里已经有一些很好的答案了 - 我肯定会推荐#2或#3 - 在概念上和实践中分离是很好的。

预测API的负载和流量模式可能很困难,我们看到那些独立提供API服务的客户更容易进行配置和扩展。如果您必须将其与人类Web访问模式混合在一起,那么就不太容易了。此外,您的API使用可能会比Web客户端更快地扩展,然后您可以看到应该将自己的精力放在哪里。

在#2 #3之间,它真的取决于您的目标 - 我同意#2可能是Web应用程序的未来 - 但是如果该渠道只是众多渠道之一,也许您想要更简单的东西!


1

在我最近的工作中,我遵循了 REST 服务器 + JavaScript 重客户端的原则。

REST 服务器使用 node.js + Express + MongoDB(非常好的写作性能)+ Mongoose ODM(适用于建模数据,包括验证)+ CoffeeScript(现在我会选择 ES2015),对我来说效果很好。相对于其他可能的服务器端技术,Node.js 可能还比较年轻,但它使我能够编写集成付款的稳定 API。

我使用 Ember.js 作为 JavaScript 框架,大部分应用程序逻辑在浏览器中执行。我使用 SASS(具体而言是 SCSS)进行 CSS 预处理。

Ember是一个成熟的框架,由强大的社区支持。它是一个非常强大的框架,最近着重于性能方面的工作,比如 全新的Glimmer渲染引擎(受到React的启发)。
Ember核心团队正在开发 FastBoot,它可以让您在服务器端(具体来说是node.js)执行JavaScript Ember逻辑,并将应用程序的预渲染HTML(通常在浏览器中运行)发送给用户。这非常有利于SEO和用户体验,因为用户不需要等待太长时间才能显示页面。 Ember CLI 是一个很棒的工具,可以帮助您组织代码,并且随着代码库的增长而良好地扩展。Ember也拥有自己的插件生态系统,您可以从多种 Ember插件 中进行选择。您可以轻松地获取Bootstrap(在我的情况下)或Foundation,并将其添加到您的应用程序中。
为了不通过Express服务所有内容,我选择使用nginx来提供图片和JavaScript-heavy客户端。在我的情况下,使用nginx代理非常有帮助:
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;
  }
}

优点:我喜欢API和客户端的分离。聪明人说这是正确的方法。在理论上非常好。看起来很前沿和令人兴奋。
我可以说,在实践中也非常好。将REST API分离的另一个优点是,您以后可以将其重用于其他应用程序。在完美的世界中,您应该能够不仅为网页使用相同的REST API,而且如果您决定编写移动应用程序,还应该能够使用它。
缺点:先例不多。没有多少成功的例子。公共示例(twitter.com)感觉迟钝,甚至正在转向其他方法。
现在情况看起来不同了。有许多示例使用REST API + 许多客户端来消费它。

0
在Rails中构建JSON API是一流的,JSONAPI::Resources gem为符合http://jsonapi.org规范的API提供了重要的支持。

0

我采用了混合方法,使用Sinatra作为基础,ActiveRecord / Postgress等来提供页面路由(slim模板),公开REST API以供Web应用程序使用。在早期开发中,像填充选择选项这样的东西是通过帮助程序呈现到slim模板中完成的,但随着我们接近生产,这将被替换为对REST API的AJAX调用,因为我们开始更关心页面加载速度等方面。

易于在Slim中呈现的内容会以这种方式处理,而内容(如填充表单,从jQuery.Validation的submitHandler接收表单POST数据等)则显然是AJAX。

测试是一个问题。现在我遇到了困难尝试将JSON数据传递给Rack :: Test POST测试


0

我个人更喜欢选项(3)作为解决方案。在我的前雇主(家喻户晓的公司)的几乎所有网站上都使用了这种方法。这意味着你可以找到一些前端开发人员,他们对JavaScript、浏览器怪癖等方面非常了解,让他们编写前端代码。他们只需要知道“curl xyz并获取一些json”,然后就能开始工作了。

与此同时,你的重量级后端开发人员可以编写Json提供程序。这些人完全不需要考虑演示,并且反而要担心不稳定的后台、超时、优雅的错误处理、数据库连接池、线程和扩展等问题。

选项3给你提供了一个良好、坚实的三层架构。这意味着你从前端发布的内容是有利于SEO的,可以适应新旧浏览器(包括禁用JS的浏览器),如果你想的话,仍然可以是JavaScript客户端模板(这样你就可以通过静态HTML处理旧版浏览器/Googlebot,但是向使用最新Chrome浏览器或其他浏览器的用户发送JS生成的动态体验)。

在我看到的所有情况下,选项3都是一些PHP的自定义实现,这些实现在项目之间甚至不能很好的转移,更不用说在开源领域了。我猜最近可能已经用Ruby/Rails替换了PHP,但是同样的事情仍然成立。

顺便说一下,$current_employer在几个重要的地方可以使用选项3。我正在寻找一个好的Ruby框架来构建某些东西。我相信我可以将一堆宝石粘在一起,但我更喜欢一个单一的产品,它广泛提供模板、'curling'、可选身份验证、可选的memcache/nosql连接缓存解决方案。但是我找不到任何连贯的东西 :-(


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接