单独REST JSON API服务器和客户端?
我即将创build一堆web应用程序。 (请参阅http://50pop.com/code的概述。)我希望他们能够从许多不同的客户端访问:前端网站,智能手机应用程序,后端Web服务等,所以我真的想要一个每个JSON REST API。
另外,我更喜欢在后端工作,所以我把自己的注意力全部集中在API上,并雇用其他人来制作前端UI,无论是网站,iPhone,Android还是其他应用程序。
请帮我决定我应该采取的方法:
在铁路上
制作一个非常标准的Railsnetworking应用程序。 在控制器中,执行respond_with开关,以提供JSON或HTML。 JSON响应是我的API。
临:很多先例。 伟大的标准和许多这样做的事例。
Con:不一定希望API与Web应用程序相同。 不喜欢,如果/然后respond_with切换方法。 混合两个非常不同的东西(UI + API)。
REST SERVER + JAVASCRIPT-HEAVY客户端
制作一个仅限JSON的REST API服务器。 使用Backbone或Ember.js作为客户端JavaScript直接访问API,在浏览器中显示模板。
Pro:我喜欢API和客户端的分离。 聪明的人说这是要走的路。 理论上很好。 似乎前沿和激动人心。
Con:先例不多。 这样做的例子并不多。 公共示例(twitter.com)感觉迟钝,甚至不采用这种方法。
REST SERVER + SERVER-SIDE HTML客户端
制作一个仅限JSON的REST API服务器。 制作一个基本的HTML网站客户端,只访问REST API。 较less的客户端JavaScript。
Pro:我喜欢API和客户端的分离。 但是,提供纯HTML5是相当简单的,而不是客户密集型的。
Con:先例不多。 这样做的例子并不多。 框架也不支持这个。 不知道如何处理它。
特别是从经验中寻找build议,而不仅仅是理论上的。
在Boundless ,我们select了第二个选项,并将其推广给数千名学生。 我们的服务器是一个JSON REST API(Scala + MongoDB),我们所有的客户端代码都是从CloudFront直接提供的(例如:www.boundless.com只是CloudFront的别名)。
优点:
- 新锐/激动人心
- 为您的压力感到震惊:API为您自己的Web客户端,移动客户端,第三方访问等提供基础。
- 非常快速的网站加载/页面转换
缺点:
- 不是SEO友好/准备好没有更多的工作。
- 需要一stream的networking前端人员已经准备好应付现场经验的70%的JavaScript和这意味着什么。
我认为这是所有networking应用程序的未来。
networking前端人员的一些想法(这是所有的新/挑战都给了这个架构):
- CoffeeScript的。 生成高质量代码更容易。
- 骨干。 伟大的方式来组织你的逻辑和积极的社区。
- HAMLC。 Haml + CoffeeScript模板=> JS。
- 上海社会科学院
我们已经为我们的前端开发构build了一个名为“Spar”(单页面应用程序Rocketship)的线索,它实际上是Rails针对单页面应用程序开发所调整的资产pipe道。 我们将在接下来的几周内在我们的github页面上开放采购,并附上博客文章,更详细地解释如何使用它和整体架构。
更新:
关于人们对Backbone的关注,我认为它们被高估了。 骨干远不止是一个深层框架,而是一个组织原则。 Twitter的网站本身就是一个Javascript的巨兽,覆盖了数百万用户和传统浏览器的每一个angular落,同时实时加载推文,垃圾收集,显示大量多媒体等等。在所有'纯粹'的js站点中,看到,Twitter是奇怪的一个出来。 有很多令人印象深刻的复杂的应用程序通过JS交付,非常好。
你的build筑select完全取决于你的目标。 如果您正在寻找支持多个客户的最快捷方式,并获得良好的前端人才,那么投资独立API是一个好方法。
很好问。 +1。 当然,这对我来说是未来有用的参考。 @Aaron和其他人也为讨论增加了价值。 像Ruby一样,这个问题同样适用于其他编程环境。
我已经使用了前两个选项。 第一个为许多应用程序,第二个为我的开源项目Cowoop
选项1
这个无疑是最受欢迎的一个。 但我觉得实现非常多http-ish。 每个API的初始代码都在处理请求对象。 所以API代码比纯ruby / python /其他语言代码更多。
选项2
我一直喜欢这个。
这个选项也意味着HTML不是在服务器上运行时生成的。 这是选项2与选项3的不同之处。但是使用构build脚本构build为静态html。 在客户端加载时,这些HTML会以JS API客户端的forms调用API服务器。
分离的关注是很大的优势。 非常喜欢(和我的)后端专家实现后端API,像普通的语言代码一样轻松地testing它们,而不用担心框架/ http请求代码。
这确实不像前端那样困难。 API调用和结果数据(主要是json)可用于您的客户端模板或MVC。
较less的服务器端处理。 这意味着你可以去商品硬件/较便宜的服务器。
更容易独立地testing图层,更容易生成API文档。
它确实有一些缺点。
许多开发人员发现这个过于devise,很难理解。 所以有可能机构会受到批评。
i18n / l10n很难。 由于HTML本质上是生成的,所以构build时间是静态的,每个支持的语言需要多个构build(这不一定是坏事)。 但即使如此,你也可能在十月十八日左右有个案,需要小心。
选项3
这种情况下的后端编码必须与第二个选项相同。 选项2的大部分要点也适用于此。
网页使用服务器端模板呈现运行时。 这使得i18n / l10n比较成熟/可接受的技术更容易。 对于像用户,语言,货币等页面渲染所需的一些重要上下文可能less一个http调用。因此,服务器端处理随着渲染而增加,但可能通过对API服务器的较lessHTTP调用来补偿。
现在,服务器上的服务器呈现页面,前端现在更多地与编程环境绑定。 这可能不是许多应用程序的考虑因素。
Twitter案例
据我所知,Twitter可能会做他们在服务器上的初始页面呈现,但对于页面更新,它仍然有一些API调用和客户端模板来操纵DOM。 所以在这种情况下,你有两个模板来维护,这增加了一些开销和复杂性。 与Twitter不同,并不是每个人都可以承受这个select
我们的项目堆栈
我碰巧使用Python。 我使用JsonRPC 2.0而不是REST。 我build议REST,尽pipe我喜欢JsonRPC的各种理由的想法。 我使用下面的库。 有人考虑选项2/3可能会发现它有用。
- API服务器:Python一个快速的Web微框架 – Flask
- 前端服务器:Nginx
- 客户端MVC: Knockout.js
- 其他相关工具/库:
- jQuery的
- Accounting.js货币的货币
- Webshim :跨浏览器填充
- 导演 :客户端路由
- sphc :HTML代
我的结论和build议
选项3!
所有说,我已经成功地使用了选项2,但现在倾向于选项3一些简单。 使用构build脚本生成静态HTML页面,并使用专门提供静态页面的超高速服务器为其提供服务是非常诱人的(选项2)。
build设gaug.es时,我们select了#2。 我从事API(ruby,sinatra等)和我的业务合作伙伴史蒂夫·史密斯(Steve Smith)在前端(JavaScript客户端)工作。
优点:
-
平行移动。 如果我在Steve之前工作,我可以继续为新function创buildAPI。 如果他在我之前工作,他可以非常容易地伪造API,并构buildUI。
-
API免费。 开放访问您的应用程序中的数据正在迅速成为一个标准function。 如果你从头开始使用API,你可以免费获得这个API。
-
清洁分离。 最好将您的应用程序视为客户端的API。 当然,第一个也是最重要的客户端可能是networking客户端,但它可以让您轻松创build其他客户端(iPhone,Android)。
缺点:
- 向后兼容性。 这与API直接相关的问题比你的直接问题更重要,但是一旦你的API出现在那里,你就不能破坏它,或者你把所有的客户都打破了。 这并不意味着你必须慢一点,但是这意味着你必须经常做两件事情。 添加到API或新的领域是好的,但更改/删除不应该没有版本。
我现在再也想不起来了。
结论:如果您打算发布一个API,API + JS客户端就是要走的路。
PS我也build议在发布之前完整logging你的API。 loggingGaug.es API的过程确实帮助了我们
我更喜欢去#2和#3的路线。 主要是因为#1违反了关注的分离和各种东西的混杂。 最终你会发现需要有一个没有匹配的HTML页面的API端点,你将会在同一个代码库中混合使用HTML和JSON端点。 它变成了一个混乱的混乱,即使它的MVP,你最终必须重新写它,因为它太杂乱,甚至不值得打捞。
使用#2或#3可以让你完全拥有一个相同的API(绝大多数情况下)。 这提供了很大的灵活性 我还没有100%在Backbone / ember / whatever / etc.js上销售。 我认为它很棒,但是正如我们在twitter上看到的那样,这不是最佳的。 但是,Twitter也是一家公司的巨兽,拥有数以亿计的用户。 所以任何改进都会对各业务部门的各个领域的底线产生巨大的影响。 我觉得这个决定比速度还要多,他们也不会让我们这样做。 但那只是我的个人意见。 不过,我不打折骨干及其竞争对手。 这些应用程序是伟大的使用,非常干净,非常敏感(大部分)。
第三个选项也有一些有效的吸引力。 这是我遵循帕雷托原则(80/20规则),并有20%的主要标记(或反之亦然)呈现在服务器上,然后有一个不错的JS客户端(主干/等)运行其余的。 您可能无法通过JS客户端与REST API进行100%的通信,但是如果有必要,您将进行一些工作,以使更好的体验。
我认为这是其中的一个“取决于”的问题,答案是“取决于”你正在做什么,你所服务的对象以及你希望他们接受什么样的经验。 鉴于我认为你可以决定2或3或混合他们。
我目前正在将一个巨大的CMS从选项1转换到选项3,并且进展顺利。 我们select渲染标记服务器端,因为SEO对我们来说是一个大问题,我们希望这些网站在手机上performance良好。
我使用node.js作为客户端的后端和一些模块来帮助我。 我在这个过程中有些早,但是基础已经确定了,而且这是一个重新审视数据的问题,确保它们都能正确显示。 以下是我正在使用的:
- 快递为应用程序的基础。
(https://github.com/visionmedia/express); - 请求获取数据。
(https://github.com/mikeal/request); - 得到渲染服务器端的下划线模板。 我在客户端重用这些。
(https://github.com/documentcloud/underscore); - UTML包装下划线的模板,使它们能够与Express一起工作。
(https://github.com/mikefrey/utml); - 预先收集模板,让我们select发送给客户端。
(https://github.com/mrDarcyMurphy/upfront); - Express Expose将获取的数据,一些模块和模板传递到前端。
(https://github.com/visionmedia/express-expose); - 主干在吞咽传递的数据之后,在前端创build模型和视图。
(https://github.com/documentcloud/backbone);
这是堆栈的核心。 我发现一些其他模块有帮助:
- 斑点(https // github.com / trek /斑点)
- 瞬间(https // github.com / timrwood /时刻)
- 手写笔(https // github.com / LearnBoost /手写笔)
- smoosh(https // github.com / fat / smoosh)
…虽然我正在调查grunt(https // github.com / cowboy / grunt) - 控制台跟踪(//github.com/LearnBoost/console-trace)。
不,我不使用咖啡标记。
这个选项对我来说真的很好。 后端模型是不存在的,因为我们从API获得的数据结构良好,我逐字地传递给前端。 唯一的例外是我们的布局模型,我添加了一个单一的属性,使渲染更智能和更轻。 我没有使用任何花哨的模型库,只是一个函数,增加了我需要的初始化和返回自己。
(对于怪异的链接抱歉,我太多的堆栈溢出n00b让我张贴这么多)
我们使用#3的以下变体:制作仅JSON的REST API服务器。 制作一个HTML网站服务器。 HTML Web服务器不像在您的变体中那样是REST API服务器的客户端。 相反,这两个人是同龄人。 在表面之下,有一个内部API提供了两个服务器所需要的function。
我们不知道有任何先例,所以这是一种实验。 到目前为止(即将进入testing版),它已经相当不错了。
我通常会select第二个选项,使用Rails来构buildAPI,以及JS的主干。 您甚至可以使用ActiveAdmin免费获得pipe理面板。 我已经用这种后端发送了数十个移动应用程序。 但是,这很大程度上取决于您的应用是否是交互式的。
我在最后一个RubyDay.it上做了一个关于这个方法的介绍: http : //www.slideshare.net/matteocollina/enter-the-app-era-with-ruby-on-rails-rubyday
对于第三个选项,为了获得第二个选项的响应能力,你可以像Github一样尝试pajax 。
我大概需要2个月的时间来完成一个3个月的项目,这需要你在这里列出的第二个方法。 我们在前面使用一个RESTful API服务器端和backbone.js。 Handlebars.jspipe理模板,jQuery处理AJAX和DOM操作。 对于旧版浏览器和search蜘蛛,我们已经退到了服务器端渲染,但是我们使用的是与使用Mozilla Rhino的Handlebars前端相同的HTML模板。
我们之所以select这个方法有很多不同的原因,但是非常清楚这个方法还没有被大规模的certificate,所以它有点冒险。 所有的一切,一切都很顺利到目前为止。
到目前为止,我们刚刚在使用一个API,但在项目的下一个阶段,我们将使用第二个API。 第一个是大量的数据,第二个更像是一个CMS通过API。
让这两个项目完全相互独立,是select这个基础设施的关键考虑因素。 如果您正在寻找一种架构来混合不同的独立资源而没有任何依赖关系,那么这就是值得一看的方法。
恐怕我不是一个ruby的人,所以我不能评论其他方法。 有时冒险是可以的。 其他时候最好保证安全。 您将根据项目的types自行决定。
祝你在这里好运。 很想看看别人分享什么。
我喜欢#3,当我的网站不会是我的数据的100%CRUD实现。 哪些还没有发生。
我更喜欢sinatra,并将应用程序分成几个不同的目的不同的机架应用程序。 我将制作一个API特定的机架应用程序,将涵盖我需要的API。 然后,也许是一个用户机架应用程序,将呈现我的网页。 有时候,如果需要的话,这个版本会查询API,但是通常它只是关心自己的html网站。
我不担心它,只需要从用户端执行持久层查询。 我并不是过分关心创build一个完整的分离,因为他们通常会服务于不同的目的。
这是使用多个机架应用程序的一个非常简单的例子。 我在那里添加了一个快速的jQuery示例,让您看到它打到API应用程序。 你可以看到sinatra和安装具有不同用途的多机架应用程序是多么的简单。
这里已经有了一些很好的答案 – 我肯定会推荐#2或#3 – 分离在概念上是好的,但在实践中也是如此。
在API上预测诸如负载和stream量模式之类的事情可能很难,我们看到谁独立服务于API的客户可以更容易地进行configuration和缩放。 如果你不得不这样做与人类networking访问模式,这是不容易的。 此外,您的API使用可能会比您的Web客户端更快地扩展,然后您可以看到在哪里指导您的工作。
在#2#3之间真的取决于你的目标 – 我同意#2可能是webapps的未来 – 但也许你想要更直接的东西,如果这个频道只是一个很多!
对于atyourservice.com.cy我们正在使用服务器端渲染模板的页面,特别是覆盖部分。 并在页面加载后使用API进行交互。 由于我们的框架是MVC所有的控制器function被复制到JSON输出和HTML输出。 模板是干净的,只接收一个对象。 这可以在几秒钟内转换成js模板。 我们始终维护服务器端模板,并根据请求重新转换为js。
同构渲染和渐进式增强。 第三种select,我认为你是这样做的。
同构呈现意味着使用相同的模板来生成标记服务器端,就像在客户端代码中使用一样。 select良好的服务器端和客户端实现的模板语言。 为您的用户创build完全烘焙的HTML并将其发送。 也使用caching。
渐进增强意味着一旦获得了所有下载的资源,就可以开始执行客户端执行和渲染以及事件监听,并且可以确定客户端的function。 尽可能回到function性的无客户端脚本function,以实现可访问性和向后兼容性。
是的,当然,为这个应用程序function编写一个独立的json API。 但是,不要走得太远,你写一个JSON API的东西,作为静态的HTML文件工作正常。
REST服务器+ JavaScript重用客户端是我在最近的工作中遵循的原则。
REST服务器是在node.js + Express + MongoDB (非常好的写入性能)+ Mongoose ODM (非常适用于build模数据,包括validation)+ CoffeeScript (我现在去ES2015)中实现的,这对我来说非常合适。 与其他可能的服务器端技术相比,Node.js可能相对年轻,但是这使得我可以使用集成的支付编写可靠的API。
我已经使用Ember.js作为JavaScript框架,并且大部分应用程序逻辑都是在浏览器中执行的。 我已经使用SASS (SCSS专门)进行CSS预处理。
Ember是由强大社区支持的成熟框架。 这是一个非常强大的框架,最近有很多工作都集中在性能上,比如全新的Glimmer渲染引擎 (受React的启发)。
Ember Core Team正在开发FastBoot ,让你可以在服务器端执行你的JavaScript Ember逻辑(特别是node.js),并将你的应用程序的预渲染HTML(通常在浏览器中运行)发送给用户。 对于search引擎优化和用户体验来说,这是非常好的,因为他不会等待页面显示。
Ember CLI是一个很棒的工具,可以帮助你组织你的代码,它可以很好的扩展代码库。 Ember也有自己的插件生态系统,你可以select各种Ember插件 。 您可以轻松获取Bootstrap(在我的情况下)或Foundation,并将其添加到您的应用程序。
不要通过Express服务所有的东西,我select使用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; } }
Pro:我喜欢API和客户端的分离。 聪明的人说这是要走的路。 理论上很好。 似乎前沿和激动人心。
我可以说这在实践中也很棒。 分离REST API的另一个好处是可以在以后为其他应用程序重新使用它。 在完美的世界中,如果你决定编写一个,你应该能够使用相同的REST API不仅用于网页,而且也用于移动应用程序。
Con:先例不多。 这样做的例子并不多。 公共示例(twitter.com)感觉迟缓,甚至不采用这种方法。
事情看起来不一样了。 有很多REST API +很多客户端在使用它的例子。
我决定采用Infiniforms的Option#2 架构 ,因为它提供了一个将UI与业务逻辑分开的好方法。
这样做的好处是API服务器可以独立于Web服务器进行扩展。 如果您有多个客户端,那么这些网站将不需要像Web服务器那样扩展,因为某些客户端可能是基于手机/平板电脑或桌面的。
这种方法也为您的用户开放API提供了很好的基础,特别是如果您使用自己的API为您的网站提供所有function。
一个非常好的问题,我很惊讶,因为我认为现在这是一个非常普遍的任务,这样我将有足够的资源来解决这个问题,然而事实并非如此。
我的想法如下: – 创build一些在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
我已经去了一个混合的方法,我们用Sinatra作为基础,ActiveRecord / Postgress等提供页面path(苗条模板)公开REST API的Web应用程序可以使用。 在早期的开发中,像填充select的选项是通过helper渲染到slim模板中完成的,但是当我们接近生产时,当我们开始更关心页面加载速度等等时,这个被replace为一个AJAX对REST API的调用。
在Slim中很容易渲染的东西就是这样处理的,东西(填充表单,从jQuery.Validation的submitHandler
等接收表单POST数据,都是AJAX)
testing是一个问题。 现在我很难将JSON数据传递给Rack :: Test POSTtesting 。
我个人更喜欢选项(3)作为解决scheme。 它几乎用在我所有的前雇主(家喻户晓)的所有网站上。 这意味着你可以得到一些前端的开发人员,他们知道所有的Javascript,浏览器的怪癖和不知道你的前端代码。 他们只需要知道“curlxyz,你会得到一些json”,他们走了。
同时,你的重量级后端可以编写Json提供程序。 这些人根本不需要考虑performance,而是担心后端,超时,优雅的error handling,数据库连接池,线程和缩放等问题。
选项3为您提供了一个良好的,坚实的三层架构。 这意味着你从前端吐出的东西是SEO友好的,可以使用旧的或新的浏览器(和那些与JSclosures),并可以仍然是JavaScript客户端模板,如果你想(所以你可以像使用静态HTML处理旧浏览器/谷歌机器人,但发送JSbuild立dynamic的经验,使用最新的Chrome浏览器或任何人)。
在所有的情况下,我已经看到选项3,这是一个PHP的自定义实现,不能在项目之间转移,更不用说在开源的土地。 我想最近PHP可能已被replace为Ruby / Rails,但同样的事情仍然如此。
FWIW,$ current_employer可以在几个重要的地方使用选项3。 我正在寻找一个良好的Ruby框架,在其中build立一些东西。 我敢肯定,我可以把一大堆gem粘合在一起,但我更喜欢单一的产品,广泛提供模板,“curl”,可选authentication,可选的memcache / nosql连接caching解决scheme。 在那里,我没有find任何一致的:-(
在Rails中构build一个JSON API是第一类,JSONAPI :: Resources gem为http://jsonapi.org spec'd API做了繁重的工作。
- Angular.js vs Knockout.js vs Backbone.js
- Backbone.jserror handling – 你怎么做?
- Backbone.js视图中$ el和el有什么区别?
- 基于backbone.js的许多框架的现实优势和弱点是什么?
- 如何触发model.save()上的成功callback?
- 需要从Underscore.js中解释_.bindAll()函数
- 在Backbone.js集合上调用fetch()时会触发什么事件?
- JavaScript console.log导致错误:“主线程上的同步XMLHttpRequest已被弃用…”
- 将parameter passing到主干视图的Backbone事件对象