做者:戴嘉华前端
转载请注明出处,保留原文连接和做者信息程序员
开发一个Web应用的时候咱们通常都会简单地分为前端工程师和后端工程师(注:在一些比较复杂的系统中,前端能够细分为外观和逻辑,后端能够分为CGI和Server)。前端工程师负责浏览器端用户交互界面和逻辑等,后端负责数据的处理和存储等。先后端的关系能够浅显地归纳为:后端提供数据,前端负责显示数据。ajax
在这种先后端的分工下,会常常有一些疑惑:既然前端数据是由后端提供,那么后端数据接口尚未完成,前端是否就没法进行编码?怎么样才能作到先后端独立开发?后端
考虑这么一个场景:Alex和Bob是一对好基友,他们有个能够颠覆世界的idea,准备把它实现出来,可是他们不须要程序员,由于他们就是程序员。说干就干,两个就干上了。Alex写前端,Bob写后端。跨域
Alex和Bob都通过良好的训练,循序渐进地把产品的主要功能设计,交互原型,视觉设计作好了,而后他们根据产品功能和交互制定了一堆叼炸天的先后端交互的API,这套API就相似于一套先后端开发的“协议”,Alex和Bob开发的时候都须要遵照。例如其中一个发表评论的功能:浏览器
// API: Create New Comment v2 // Ajax, JSON, RESTful url: /comments type: POST request: {content: "comment content.", userId: 123456} response: - status: 200 data: {result: "SUCCESS", msg: "The comment has been created."} - status: 404 data: {result: "failed", msg: "User is not found."}
Alex的前端须要向/comments
这个url以POST
的方式发送相似于{content: "comment content.", userId: 123456}
这样的JSON请求数据;Bob的服务端识别后之后,操做成功则返回200状态和上面的JSON的数据,不一样的操做状态有不一样的响应数据(为了简单起见只列出了两种,200和404)。服务器
API制定完之后,Alex和Bob就开始编码了。Alex把评论都外观和交互写完了,可是写到发表评论功能就纳闷了:Alex如今须要发Ajax过去,可是只能把Ajax代码写好,由于是本地服务器,却没法获取到数据:前端工程师
// jQuery Ajax $.ajax({ // 这个ajax直接报错,由于这个是Alex的前端服务器,请求没法获取数据; url: "/comments", type: "POST", data: {content: content, userId: userId}, success: funtion(data) { // 这里不会被执行 } })
相比起来Bob就没有这个烦恼,由于后端是基于测试驱动开发,且后端能够轻易地模拟前端发送请求,能够对前端没有依赖地进行开发和测试。app
Alex把这种状况和Bob说了,Bob就说,要不咱们把代码弄到你本地先后端链接一下,这不就能够测试了吗。Alex以为Bob简直是天才。前后端分离
他们把先后端代码代码都部署到Alex的本地服务器之后,通过一系列的测试,调试,终于把这个API链接成功了。可是他们发现这个方法简直不科学:难道每写一个API都要把先后端连接测试一遍吗?并且,Alex的若是须要测试某个API,而Bob的这个API还没写好,Alex这个功能模块的进度就“阻塞”了。
后面还有168个API须要写,不能这么作。Alex和Bob就开始思考这个问题的解决方案。
在这个场景下,先后端是有比较强的数据依赖的关系,后端依赖前端的请求,前端依赖后端的响应。然后端能够轻松模拟前端请求(基本上能写后端的语言均可以直接发送HTTP请求),前端没有一个比较明显的方案来能够作到模拟响应,因此这里的须要解决的点就是:如何给前端模拟的响应数据。
先来一句很是形而上的话:若是两个对象具备强耦合的关系,咱们通常只要引入第三个对象就能够打破这种强耦合的关系。
+---------+ +---------+ | | | | | Object1 | <--------> | Object2 | | | | | +---------+ +---------+ Before +---------+ +---------+ | | | | | Object1 | <-- ✕ ---> | Object2 | | | | | +---+-----+ +-----+---+ | | | | | | | | | | | +---------+ | | | | | +-----> | Object3 | <------+ | | +---------+ After
在咱们上述开发的过程当中,先后端的耦合性太强了,咱们须要借助额外的东西来打破它们的耦合性。因此,在先后端接口定下来之后,咱们根据接口构建另一个Server,这个Server会一一响应前端的请求,而且根据接口返回数据。固然这些数据都是假数据。咱们把这个Server叫作Mock Server,而Bob真正在开发的Server叫作Real Server。
+-------------------+ +-------------------+ | | +-------- ✕ ------> | | | Browser | | Real Server | | | <---+ | | +--------------+----+ | +-------------------+ | | | | | | | | Request Response | | | | | | | +----+--------------+ +---> | | | Mock Server | | | +-------------------+
Mock Server是根据API实现的,可是是没有数据逻辑的,只是很是简单地返回数据。例如上面Alex和Bob的发表评论的接口在Mock Server上是这样的:
// Mock Server // Create New Comment API route.post("/comments", function(req, res) { res.send(200, {result: "Success"}); })
Alex在开发的时候向Mock Server发出请求,而不是向Bob的服务器发出请求:
// Sending Request to Mock Server // jQuery Ajax $.ajax({ url: config.HOST + "/comments", type: "POST", data: {content: content, userId: userId}, success: funtion(data) { // OK } })
注意上面的config.HOST
,咱们把服务器配置放在一个全局共用的模块当中:
// Front-end Configuration Module var config = modules.exports; config.HOST = "http://192.169.10.20" // Mock Server IP
那么上面咱们实际上是向IP为http://192.169.10.20
的Mock Server发出请求http://192.169.10.20/comments
发出POST的请求。
当Alex和Bob都代码写好了之后,须要链接调试了,Alex只要简单地改一下配置文件便可把全部的请求都转向Bob所开发的Real Server:
// Front-end Configuration Module var config = module.exports; // config.HOST = "http://192.169.10.20" // Mock Server IP config.HOST = "http://changing-world-app.com" // Real Server Domain
而后Alex和Bob就能够愉快地分离独立开发,而最后只须要联合调试就能够了。
总结一下基本上先后端分离开发包括下面几个步骤:
固然要注意,若是接口修改了,Mock Server要同步修改。
Mock Server具体应该如何构建?应该存放在哪里?应该怎么维护?
先后端是不一样的两个工程,它们各自占用一个仓库。Mock Server应该和它们分离出来,独立进行开发和维护,也就是说会有三个仓库,Mock Server是一个单独的工程。
Mock Server能够部署在本地,也能够部署到远程服务器,二者之间各有优劣。
作法:把Mock Server工程部署到一个远程的always on的远程服务器上,前端开发的时候向该服务器发请求。
优势:
缺点:
(在写这篇博客的时候,逛Hacker News,恰好看到有人作了一个开发辅助工具(http://reqr.es/),能够用于开发时响应前端请求,其实也就是这里所说的远程Mock Server。真是不能再巧更多。)
作法:前端把Mock Server克隆到本地,开发的时候,开启前端工程服务器和Mock Server,全部的请求都发向本地服务器,获取到Mock数据。
优势:
缺点:
Mock Server工程通常能够由后端开发人员来维护。由于在开发的过程当中,后端由于各类缘由可能须要修改API,后端人员是最熟悉请求的响应数据和格式的人,能够同步维护Mock Server和Real Server,更好保证数据的一致。Mock Server维护起来并不复杂,对于比较大多工程来讲,这样的前期准备和过程的维护是很是值得的。
因此要点就是:根据API构建能够模拟服务器响应的Mock Server,用于前端请求模拟数据进行测试。
再重复总结一下先后端分离开发包括下面几个步骤:
当开发只有我一我的的时候,我更喜欢后端独立开发,开发前端的时候开个Real Server来作响应。又爽又快。其实若是团队的人是full-stack的话,彻底能够按照功能模块来划分任务,而不是分为前端工程师和后端工程师。
但通常来讲仍是会选择先后端职能划分,对于这种状况下的多人开发的工程来讲,先后端分离开发的方式确实须要考虑和构建的,能够更好帮助咱们构建一个高效,规范化,流程化的开发流程。
仍是那句话,没有银弹,全部的东西都须要根据实际状况来构建独特的流程。
无
(全文完)