我即将从头开始创建一堆网络应用。 (有关概述,请参阅http://50pop.com/code。)我希望能够从许多不同的客户端访问它们:前端网站,智能手机应用程序,后端Web服务等。所以我真的想要一个JSON REST API for a每一个。
另外,我更喜欢在后端工作,所以我梦想着我将我的注意力完全放在API上,并聘请其他人来制作前端用户界面,无论是网站,iPhone,Android还是其他应用
请帮我决定采取哪种方法:
一起在铁路上
制作一个非常标准的Rails网络应用程序。在控制器中,执行respond_with开关,以提供JSON或HTML。 JSON响应就是我的API。
亲:很多先例。伟大的标准和许多以这种方式做事的例子。
Con:不一定要API与网络应用相同。不喜欢if / then respond_with切换方法。混合两个非常不同的东西(UI + API)。
REST SERVER + JAVASCRIPT-HEAVY CLIENT
制作仅限JSON的REST API服务器。使用Backbone或Ember.js直接访问客户端JavaScript,在浏览器中显示模板。
专业:我喜欢API&分离客户。聪明的人说这是要走的路。理论上很棒。似乎前沿和令人兴奋。
Con:没有多少先例。这方面的例子并不多。公共示例(twitter.com)感觉迟钝&甚至改变了这种做法。
REST服务器+服务器端HTML客户端
制作仅限JSON的REST API服务器。创建一个基本的HTML网站客户端,仅访问REST API。减少客户端JavaScript。
专业:我喜欢API&分离客户。但是提供简单的HTML5是相当万无一失的。不是客户密集型的。
Con:没有多少先例。这方面的例子并不多。框架也不支持这一点。不确定如何接近它。
特别是从经验中寻求建议,而不仅仅是在理论上。
答案 0 :(得分:133)
在Boundless,我们已经深入了解选项#2并将其推广到数千名学生。我们的服务器是JSON REST API(Scala + MongoDB),我们所有的客户端代码都是直接从CloudFront提供的(即:www.boundless.com只是CloudFront的别名)。
优点:
缺点:
我认为这是所有网络应用的未来。
对网络前端人员的一些想法(这是所有新的/挑战给予这种架构的地方):
我们为前端开发构建了一个称为“Spar”(单页应用程序Rocketship)的工具,它实际上是Rails为单页面应用程序开发而调整的资产管道。我们将在接下来的几周内通过我们的github页面进行开源,以及一篇博客文章,详细解释如何使用它和整体架构。
更新:
关于人们对Backbone的关注,我认为他们被高估了。 Backbone更像是一个组织原则,而不是一个深层框架。 Twitter的网站本身就是一个巨大的Javascript野兽,覆盖了数百万用户的每个角落。传统浏览器,实时加载推文,垃圾收集,显示大量多媒体等。在我看过的所有'纯'js网站中,Twitter是奇怪的。通过JS提供的许多令人印象深刻的复杂应用程序非常好。
您选择的架构完全取决于您的目标。如果您正在寻找支持多个客户的最快方式并且能够获得优秀的前端人才,那么投资独立的API是一个很好的方式。
答案 1 :(得分:48)
很好问。 +1。当然,这对我来说是未来有用的参考。 @Aaron和其他人也为讨论增添了价值。 像Ruby一样,这个问题同样适用于其他编程环境。
我使用了前两个选项。第一个用于众多应用程序,第二个用于我的开源项目Cowoop
选项1
这个无疑是最受欢迎的一个。但我发现实施非常多的http-ish。每个API的初始代码都处理请求对象。所以API代码不仅仅是纯ruby / python /其他语言代码。
选项2
我一直很喜欢这个。
此选项还表示HTML不是在服务器上生成的运行时。这是选项2与选项3的不同之处。但是使用构建脚本构建为静态html。在客户端加载时,这些HTML会将API服务器称为JS API客户端。
关注点分离是一个很大的优势。非常喜欢(和我的)后端专家实现后端API,像通常的语言代码一样轻松测试它们,而不用担心框架/ http请求代码。
这真的不像前端那样难听。 API调用和结果数据(主要是json)可用于客户端模板或MVC。
减少服务器端处理。这意味着您可以购买商品硬件/更便宜的服务器。
更容易独立测试图层,更容易生成API文档。
确实有一些缺点。
许多开发人员发现这个过于设计且难以理解。所以建筑可能会受到批评。
i18n / l10n很难。由于HTML本质上是生成的,因此构建时间是静态的,每个支持的语言需要多个构建(这不一定是坏事)。但即便如此,你可能会在l10n / i18n附近遇到拐角情况,需要小心。
选项3
在这种情况下,后端编码必须与第二个选项相同。选项2的大多数要点也适用于此。
使用服务器端模板呈现网页运行时。这使得i18n / l10n更容易使用更成熟/可接受的技术。对于用户,语言,货币等页面呈现所需的一些基本上下文,可能只需少一次http调用。因此,服务器端处理会随着呈现而增加,但可能会因对API服务器的较少http调用而得到补偿。
现在页面是服务器上呈现的服务器,现在前端与编程环境更紧密相关。这可能不是许多应用程序的考虑因素。
据我所知,Twitter可能会在服务器上进行初始页面渲染,但对于页面更新,它仍然有一些API调用和客户端模板来操作DOM。因此,在这种情况下,您需要维护双模板,这会增加一些开销和复杂性。与Twitter不同,并非所有人都能买得起这个选项。
我碰巧使用Python。我使用JsonRPC 2.0而不是REST。我建议REST,虽然我喜欢JsonRPC的想法有各种原因。我使用下面的库。考虑选项2/3的人可能会发现它很有用。
选项3!
所有人都说,我已成功使用选项2但现在倾向于选项3以简化。使用构建脚本生成静态HTML页面并使用专门提供静态页面的超快速服务器提供服务非常诱人(选项2)。
答案 2 :(得分:28)
我们在建造gaug.es时选择了#2。我参与了API(ruby,sinatra等),我的业务合作伙伴Steve Smith在前端(javascript客户端)工作。
优点:
快速并行移动。如果我领先于史蒂夫,我可以继续为新功能创建API。如果他在我之前工作,他可以非常轻松地伪造API并构建UI。
API免费。对应用程序中的数据进行开放式访问很快就会成为标准功能。如果您从头开始使用API,则可以免费获得。
清洁分离。最好将您的应用视为客户端的API。当然,第一个也是最重要的客户端可能是网络客户端,但它可以帮助您轻松创建其他客户端(iPhone,Android)。
缺点:
我现在不能再想到了。
结论:如果您计划发布API,API + JS客户端就是您的选择。
P.S。我还建议在发布之前完整记录您的API。记录Gaug.es API的过程确实帮助了我们
答案 3 :(得分:10)
我更喜欢走#2和#3的路线。主要是因为#1违反了关注点的分离并混合了各种各样的东西。最终你会发现需要一个没有匹配的HTML页面/等的API端点,你将在同一个代码库中使用混合的HTML和JSON端点。它变成了一个疯狂的混乱,即使它的MVP,你将不得不重新写它最终因为它太混乱,甚至不值得打捞。
使用#2或#3可以让你完全拥有一个相同(大部分)相同的API。这提供了很大的灵活性我还没有100%在Backbone / ember / what / etc.js上销售。我认为它很棒,但正如我们在twitter上看到的那样,这不是最佳选择。但是...... Twitter也是一家公司的巨大野兽,拥有数亿用户。因此,任何改进都会对各个业务部门的各个领域的底线产生巨大影响。我认为除了速度之外,还有更多的决定,而且他们不会让我们参与其中。但那只是我的个人意见。但是,我不打折骨干及其竞争对手。这些应用程序很好用,非常干净,响应速度很快(大部分)。
第三种选择也有一些有效的诱惑力。这是我遵循帕累托原则(80/20规则)并在服务器上呈现20%的主标记(反之亦然),然后有一个漂亮的JS客户端(骨干/等)运行其余部分。您可能无法通过JS客户端与REST API进行100%通信,但如果有必要,您将做一些工作以使更好的体验。
我认为这是“依赖于”那些问题之一,答案是“它取决于”你正在做什么,你所服务的人以及你希望他们接受什么样的经历。鉴于我认为你可以决定2或3或他们的混合。
答案 4 :(得分:7)
我通常会选择第二个选项,使用Rails构建API,以及JS内容的主干。您甚至可以使用ActiveAdmin免费获得管理面板。 我用这种后端运送了数十个移动应用程序。 但是,这在很大程度上取决于您的应用是否具有互动性
我在上一篇RubyDay.it http://www.slideshare.net/matteocollina/enter-the-app-era-with-ruby-on-rails-rubyday
上介绍了这种方法对于第三个选项,为了获得第二个选项的响应性,您可能想要像Github那样尝试pajax。
答案 5 :(得分:7)
我目前正在努力将巨大的CMS从选项1转换为选项3,并且它进展顺利。我们选择渲染标记服务器端,因为SEO对我们来说是一个大问题,我们希望这些网站在手机上表现良好。
我使用node.js作为客户端的后端和一些模块来帮助我。我在这个过程的某个早期阶段,但基础已经确定,这是一个重复数据的问题,确保一切正确。以下是我正在使用的内容:
这是堆栈的核心。我发现其他一些有用的模块:
不,我没有使用coffeescript。
此选项对我来说非常有用。后端的模型是不存在的,因为我们从API获得的数据结构良好,并且我将其逐字传递给前端。唯一的例外是我们的布局模型,其中我添加了一个使渲染更智能和更轻的属性。我没有使用任何花哨的模型库,只是一个在初始化时添加我需要的函数并自行返回。
(对不起奇怪的链接,我对堆栈溢出的n00b太多了,让我发布那么多)
答案 6 :(得分:7)
我们使用以下#3的变体: 制作仅限JSON的REST API服务器。制作HTML网站服务器。与您的变体一样,HTML Web服务器不是REST API服务器的客户端。相反,这两个是同行。在表面不远处,有一个内部API,提供两个服务器所需的功能。
我们不知道任何先例,所以它是一种实验性的。到目前为止(即将进入测试阶段),它已经很好地完成了。
答案 7 :(得分:6)
我进入为期3个月的项目大约需要2个月,这是你在这里概述的第二种方法。我们在前面使用带有backbone.js的RESTful API服务器端。 Handlebars.js管理模板,jQuery处理AJAX和DOM操作。对于较旧的浏览器和搜索蜘蛛,我们已经回到服务器端渲染,但我们使用与使用Mozilla Rhino的Handlebars前端相同的HTML模板。
我们之所以选择这种方法有很多不同的原因,但我们非常清楚它有一点风险,因为它还没有得到大规模的证明。一切都相同,到目前为止一切都很顺利。
到目前为止,我们刚刚使用了一个API,但在项目的下一阶段,我们将使用第二个API。第一种是大量数据,第二种是通过API更像CMS。
让这两个项目完全相互独立是选择这个基础设施的关键考虑因素。如果您正在寻找一种架构来混搭不同的独立资源而没有任何依赖性,那么这种方法值得一看。
我担心我不是Ruby人,所以我不能对其他方法发表评论。有时可以承担风险。其他时候最好安全地玩。你会根据项目的类型自己做。
祝你好运。热衷于了解其他人分享的内容。
答案 8 :(得分:4)
当我的网站不是我的数据的100%CRUD实现时,我喜欢#3。这还没有发生。
我更喜欢sinatra,只是将应用程序分成几个不同用途的机架应用程序。我将制作一个API特定的机架应用程序,它将涵盖我对API的需求。然后可能是一个用户机架应用程序,它将显示我的网页。有时,如果需要,该版本将查询API,但通常只关注html网站。
我不担心它,如果需要,只需从用户端进行持久层查询。我并不过分关注创建完全分离,因为它们通常最终会用于不同的目的。
以下是使用多个机架应用的非常简单示例。我在那里添加了一个快速的jquery示例,以便您看到它在API应用程序中。你可以看到sinatra有多么简单,并且可以安装多个不同用途的机架应用程序。
答案 9 :(得分:1)
这里有一些很好的答案 - 我绝对建议#2或#3 - 分离在概念上也很好,但在实践中也是如此。
很难预测API上的负载和流量模式等内容,而我们看到谁独立提供API的客户可以更轻松地进行配置和扩展。如果你必须使用人类网络访问模式进行操作,那就不那么容易了。此外,您的API使用最终可能比您的Web客户端更快地扩展,然后您可以看到在哪里指导您的工作。
在#2#3之间它确实取决于你的目标 - 我同意#2可能是webapps的未来 - 但是如果那个频道只是其中之一,你可能想要更直接的东西!
答案 10 :(得分:1)
对于atyourservice.com.cy,我们使用服务器端呈现的页面模板,尤其是覆盖se部分。并在页面加载后使用API进行交互。 由于我们的框架是MVC,所有控制器函数都复制到json输出和html输出。模板很干净,只接收一个对象。这可以在几秒钟内转换为js模板。我们始终维护服务器端模板,并根据请求重新转换为js。
答案 11 :(得分:1)
同构渲染和渐进增强。这是我认为你在第三选项中的目标。
同构渲染表示使用相同的模板生成标记服务器端,就像在客户端代码中使用一样。选择具有良好服务器端和客户端实现的模板语言。为您的用户创建完全烘焙的html并将其发送到网上。也使用缓存。
渐进增强意味着,一旦您下载了所有资源并开始进行客户端执行,呈现和事件监听,您就可以确定客户端功能。尽可能降低功能性客户端脚本功能,以实现可访问性和向后兼容性。
是的,当然是为这个应用程序功能编写一个独立的json api。但是,到目前为止,你还没有写过一个json api来处理那些作为静态html文档工作正常的东西。
答案 12 :(得分:1)
REST服务器+ JavaScript重度客户端是我在最近的工作中遵循的原则。
REST服务器在node.js + Express + MongoDB(非常好的写作性能)+ Mongoose ODM中实现(非常适合建模数据,包括验证)+ {{3 (我现在改为ES2015)这对我很有用。与其他可能的服务器端技术相比,Node.js可能相对年轻,但它使我可以编写带有集成支付的可靠API。
我已将CoffeeScript用作JavaScript框架,并且大部分应用程序逻辑都在浏览器中执行。我已经使用Ember.js(特别是SCSS)进行CSS预处理。
Ember是一个由强大社区支持的成熟框架。它是一个非常强大的框架,最近完成了大量关于性能的工作,例如SASS(受React启发)。
Ember核心团队正在开发brand new Glimmer rendering engine,让您在服务器端执行JavaScript Ember逻辑(具体是node.js)并发送应用程序的预渲染HTML(这通常会在浏览器中运行给用户。它非常适合搜索引擎优化和用户体验,因为他没有等待很长时间才能显示页面。
FastBoot是一款很棒的工具,可以帮助您整理代码,并且可以随着代码库的增长而扩展。 Ember还拥有自己的插件生态系统,您可以从Ember CLI种类中进行选择。您可以轻松地抓取Bootstrap(在我的情况下)或Foundation并将其添加到您的应用程序。
不是通过Express提供所有服务,我选择使用nginx来提供图像和JavaScript重度客户端。在我的情况下使用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& amp;的分离客户。聪明人说这是 要走的路。理论上很棒。似乎前沿和令人兴奋。
我可以说它在实践中也很棒。分离REST API的另一个优点是,您可以稍后将其重新用于其他应用程序。在完美世界中,您应该能够使用相同的REST API,不仅适用于网页,还适用于移动应用程序,如果您决定编写一个。
Con:没有多少先例。这方面的例子并不多。上市 例子(twitter.com)感觉迟钝&甚至正在切断 这种方法。
现在看起来不一样了。有很多做REST API的例子+很多客户都在使用它。
答案 13 :(得分:1)
我决定为Infiniforms寻找选项#2的架构,因为它提供了一种将UI与业务逻辑分开的好方法。
这样做的一个优点是API服务器可以独立于Web服务器进行扩展。如果您有多个客户端,那么网站将不需要扩展到与Web服务器相同的程度,因为某些客户端可以是手机/平板电脑或基于桌面的。
此方法还为您向用户开放API提供了良好的基础,尤其是当您使用自己的API为您的网站提供所有功能时。
答案 14 :(得分:1)
一个非常好的问题,我很惊讶,因为我认为现在这是一项非常常见的任务,因此我将有足够的资源来解决这个问题,但结果并非如此。
我的想法如下: - 创建一些在API控制器和HTML控制器之间具有通用逻辑的模块,不用返回json或渲染html,并将此模块包含在HTML控制器和API控制器中,然后执行任何操作,以便例如:
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
答案 15 :(得分:0)
我选择了混合方法,我们将Sinatra用作基础,ActiveRecord / Postgress等用于提供页面路由(超薄模板),以展示Web应用程序可以使用的REST API。在早期开发中,诸如填充选择选项之类的东西是通过帮助程序渲染到slim模板中完成的,但是当我们接近生产时,随着我们开始关注页面加载速度等等,这将被换出以进行对REST API的AJAX调用。
在Slim中易于渲染的东西会以这种方式处理,填充(填充表单,从jQuery.Validation的submitHandler
接收表单POST数据等等,都是明显的AJAX)
测试是一个问题。现在我很难过trying to pass JSON data to a Rack::Test POST test。
答案 16 :(得分:0)
我个人更喜欢选项(3)作为解决方案。它几乎用于我所有的雇主(家喻户晓)雇主的所有网站。这意味着你可以得到一些前端开发人员,他们了解Javascript,浏览器怪癖以及编写前端的所有内容。他们只需要知道“卷曲xyz,你就会得到一些json”而且他们会离开。
与此同时,您的重量级后端人员可以编写Json提供商的代码。这些人根本不需要考虑演示,而是担心后端,超时,优雅的错误处理,数据库连接池,线程和扩展等。
选项3为您提供了良好,可靠的三层架构。这意味着你从前端吐出的东西是SEO友好的,可以使用旧的或新的浏览器(以及关闭JS的那些),如果你想的话,仍然可以是Javascript客户端模板(所以你可以做一些事情,比如使用静态HTML处理旧浏览器/ googlebot,但是向使用最新Chrome浏览器或其他人的人发送JS构建的动态体验。
在我见过选项3的所有情况下,它都是一些PHP的自定义实现,在项目之间不能特别转移,更不用说进入开源领域了。我想最近PHP可能已被Ruby / Rails取代,但同样的事情仍然存在。
FWIW,$ current_employer可以在几个重要的地方使用选项3。我正在寻找一个很好的Ruby框架来构建一些东西。我敢肯定我可以将大量的宝石粘在一起,但我更喜欢一个广泛提供模板,'卷曲',可选身份验证,可选的memcache / nosql连接缓存解决方案的产品。在那里,我没有找到任何连贯的东西: - (
答案 17 :(得分:0)
在Rails中构建JSON API是第一类,JSONAPI :: Resources gem为http://jsonapi.org spec'd API做了大量工作。