浅谈前后端分离
之所以想聊聊前后端分离这个话题,是因为发现自己及身边很多人对围绕 前后端分离的h5、单页应用和服务端渲染等概念理解不准确,对我来说,都不好意思说自己是web开发者,所以专门去了解和整理了相关的知识,以此分享给大家:
何为前后端分离?
随着近几年移动互联网的兴起,特别是前端领域的html5,CSS3,ECMAScript5和6(也就是javaScript语言的规范)的制定并被业界支持,前后端 分离这种技术架构越来越流行,笔者近3年 参与的实际项目,基本上都是 采用前后端分离的开发模式。
那么,什么是前后端分离呢?去网上一搜,答案挺多的,都没有绝对的对错,只是站在不同的角度去定义而已。我比较认可的定义如下:在技术架构上,前后端只通过Restful风格(最佳实践)的API以JSON 数据格式(使用最多)进行交互,而不是组织或岗位的分离。
其实,要想讲清前后端 分离这个概念,得回顾一下整个web开发的历史,特别是js的历史,在分工上,其实之前 也可以算是前后端分离,老一代的前端开发都不叫软件工程师,大家爱称切图仔或妹,但在技术架构上,前后端的代码基本上是在一个工程里,后端开发语言通过各种前端模板引擎(如淘宝的kissy template,腾讯的artTemplate,百度的baiduTemplate等) 来渲染前端页面,或者是类似以Java语言为基础的动态生成web页面的jsp技术等,前后端在架构上紧密关联的。
这就是大家常听到的耦合,体现在 改一下前端页面的展示,特别是涉及交互逻辑的,整个工程(前后端代码)往往都要一起重新发布上线一次,存在耗时长、不灵活、前后端沟通过多等不足,所以就慢慢有了 前后端 分离这种技术架构来 解耦,即前后端的代码在不同的项目工程,各自发布上线,降低相互间的联系。
举个在搜狐真实项目的例子,我们客户端有android, ios和h5三个平台,业务为个人小额信用贷款,类似腾讯微信里的微粒贷,后端基于Java开发,只提供restful 风格的API服务,android, ios和h5在一个项目工程(为快速验证业务和降低成本,我们基于rective native 统一了客户端,多数客户端架构都是各端一个项目工程,技术栈也不一样,比如目前我们做的系统Android基于java, ios基于oc, h5基于vue,pc 端基于自研的ecui),前后端通过json进行交互,当时为了让系统更灵活和降低 前后端的复杂度,我们还加入了node中间层进行合并请求和格式化数据等。
为何需要前后端分离?
通过前一节,我们应该知道本节探讨的,准确来讲,应该是web开发 为什么 会出现 前后端 分离 这种技术架构?显然,技术 基本都是源于 业务发展的客观需要,扯大了讲 就是 马克思谈的 经济学了。
作为技术,还是不吹了。。。移动互联网时代,最明显的改变就是智能手机了,手机上的原生APP,以及在手机浏览器访问的web app(圈内简称h5, 因为HTML5规范引入了很多移动端相关特性),各端 的交互不一样,而且越来越复杂,传统的MVC技术架构(如Java系统的 控制层 负责接收参数,调用相关 业务层,封装 数据 以及通过路由 渲染 到jsp页面)实现起来越来越吃力,甚至不可能了。
举例来说,以前基于jsp的javaWeb项目没有那么苛刻的性能要求,但在大数据时代,对于web系统的性能要求越来越高,前后端耦合在一起的架构模式已经不能满足大型web系统的需要,所以需要找一种解耦的方式,来大幅度提升系统的性能和灵活度。
而且,之前的UI出图后,前端只负责将设计图切成html,然后再由java工程师来将html套成jsp页面的协作模式,出错率较高;动态资源和静态资源全部耦合在一起,服务器压力也大;还有jsp技术本身的性能,前端开发需要使用Java IDE并配置环境等,让前后端都很痛苦。
其他基于PHP,甚至是基于node的MVC web系统,只要是前后端耦合的,在开发复杂web 应用时,都会存在类似的问题,所以最近几年 前后端分离 的技术架构成了 很多架构师 设计系统时的首选,当然我们自己开发个博客或者是小系统,使用传统的前后端耦合的模式可能会成本更低、效率更高。
总之,即使现在前后端 分离的技术架构 很流行,但我们也不能瞎跟风,为了分离而分离,一切都要从业务需要和团队技能情况出发。
如何实现 前后端技术 分离?
相信细心的读者已经发现,我们本节 谈 的是前后端 技术的分离如何去实现,因为近几年还有一个 高大上的职位名称在 互联网圈很流行,那就是 全栈工程师,比如Facebook喊出了,他们只招 full stack 工程师的招聘口号,同时开源了 react这个划时代的前端技术栈,并且他们在项目中也大量使用 node作为 后端开发语言。
关于 全栈 的概念,网上其实也吵得比较厉害,这里不多说,其实我觉得 关键就是正确认识自己,能力强的就多学点、多干点,自然而然就成了全栈工程师了,而对于多数像我这样普通的开发者,还是老老实实干好自己 领域内的事情,从个人成长和职业规划上更有力。
回到本节主题,我们要实现的不是 前后端 分工 的分离,而是技术架构的分离:让前端专注于视图层、交互逻辑和前端控制层(可选,如Nodejs);让后端专注于控制层(Restful API)& 服务层 & 数据访问层。
前后端各自分工,API完成之前,前端人员一般使用mock server获取假数据实现UI设计及交互,后端人员自己进行API单元测试,不用互相等待;API完成之后,后端部署到非线上服务器,通过nginx 做反向代理各种资源和服务的请求,前后端再对接联调;最后发布上线的时候,各端发布各端的工程,一般多数后端使用jekkins,多数前端工程通过CI进行自动的构建和打包发布上线系统新需求。
对于小白,看完前面的回答,多数估计还不理解如何去实现前后端分离,我再补充一下我们真实项目的例子,但不会细化到代码层面哈。这里以我们部门所有人都参与的淘车拍 车商管理和二手车源拍卖 系统为例,简单分享一下哈。
业务场景:为二手车商提供一个管理公司车辆、交易订单、客户和员工的日常管理,以及评估、整备和牌证等管理,参与二手车源竞拍等功能的Saas平台,车商员工需要通过原生APP进行日常办公,管理层或录入大量表单时需要通过PC端进行操作,而某些功能 如 车源竞拍还需要可以分享车源到微信进行导流及开辟小程序里快速参与车源拍卖,后端还需要调用 大量兄弟部门和合作方的服务等,最后还会涉及金融,进行相关的风控审核等。
前后端 技术分离方案:客户端包含Android(基于Java)、IOS(基于OC), h5(基于vue技术栈,通过webpack启动本地node服务器代理后端接口请求),pc 端web页面(基于自研的ecui技术栈,通过启动和配置本地的ngnix服务器代理请求),小程序(基于官方开发工具和文档),原生app会嵌入h5的页面,客户端的各端都有各自的工程,都是独立开发和上线部署,然后通过Restful 风格的API以JSON的数据格式和后端进行交互,前后端完全分离,在服务器上通过Ngnix分发前端静态资源和java后端的接口服务的请求,举例来说,车源拍卖的某些接口,如所有正在拍卖的车源,ECUI开发pc后台、h5页面和小程序 请求的都是同一接口,返回都是同样的json数据。
前后端 技术分离的方案有很多,比如API 接口设计可以使用以资源为核心Restful,还可以使用以操作为核心REST-RPC接口风格;数据也未必一定是JSON格式的,也有XML,特定的二进制等等;前后端的技术栈 更是数不胜数;而且也不一定非要用ngnix做代理分发服务器,所以具体如何实现,需要大家结合实际去做技术选型。
一些易混淆的概念
前后端分离 VS 单页应用
前后端分离:页面全部通过ajax获取数据并进行处理;初级分离--页面和后端代码都部署在一起,但是代码虽然在一个项目中但是是分开的,页面只处理渲染和跳转,不处理数据,后端代码只处理数据,不管渲染和跳转;高级分离--前端代码和后端代码分开部署,开发团队分成前端和后端两个团队,只由API接口这个纽带连接。
单页应用:一个应用的所有内容在一个页面中,一次性进行加载,用户操作时显示页面的不同内容,这要求单页面应用需是数据由API接口获取的,也即是前后端分离的;多页面应用,则是资源分布在多个页面中,用户操作时,在多个页面中跳转。
前后端分离加上SPA的情况下,后端除了关键路径带认证那种的请求给你重定向之外,一般的路由逻辑都是前后端共享的,部分处理逻辑也是前后端共享,并且后端提供数据接口,与接口相关的数据处理逻辑就是后端独有
前端分离 VS 后端渲染
后端渲染:后端的程序在把html页面吐给前端之前,先把html页面上的特定区域,特定符号,给用数据填充过,再扔给前端,这就是后端渲染。
前端渲染:后端的html页面作为静态文件存在,前端请求时后端不对该文件做任何内容上的修改,直接以资源的方式返回给前端,前端拿到页面后,根据写在html页面上的js代码,对该html的内容进行修改。
传统后端渲染 VS ssr服务端渲染
以前的服务器渲染,是以“文档”为核心思想。服务器端的逻辑是把HTML, CSS, Javascript当作一个静态文件,对“文档”而言不存在“指令”和“数据”的区别,一切都是数据。所以我们可以看到之前服务器渲染,诸多服务端框架最基础的组件之一就是文档模版,比如JSP之类,核心设计理念就是HTML文件里放占位符然后由服务端逻辑替换成实际数据后一股脑返回。
Web 2.0时代最大的思想革命本质不是前后端分离,而是把网页当作独立的应用程序(app)。前后端分离只是实现这一新架构的必然结果。对程序而言指令和数据是分离的。HTTP GET拿到的不是渲染后的网页,而是一个由html和Javascript组成的app, 这个app以浏览器为虚拟机。装载和显示数据是app启动之后的运行逻辑。
现在的服务器渲染的目的只是为了加速和搜索引擎优化(准确的说是非Google引擎优化,因为Google可以解析Javascript动态网页)。而实现也很简单:拿个浏览器核心跑一下app然后把生成的html存起来给搜索爬虫就行了。与其说是渲染,不如说是“快照”,就像给app截图一样。