前后端分离,顾名思义,就是前端与后端分开。分开什么?分开开发,分开部署。
这里以java web开发作为例子:我们学web开发的时候会接触到spring mvc框架,spring mvc开发时前端一般都用jsp作为展示页面,后端用servlet处理请求。再到springboot框架,前端使用thymeleaf或者freemarker作为模板引擎展示,后端用controller处理请求。
其中jsp和thymeleaf,freemarker都有一个共同点:页面都是可以内嵌java代码的。页面里面嵌入了java(后端程序设计语言)代码,就导致页面和后端服务的耦合度特别高——前后端开发的时候粘在一起了。
而如果我们要部署spring mvc/springboot的项目的话,前后端代码也都是打包在一个war包/jar包里的,部署的时候也是一起部署的,就导致前端要修改/后端要修改的话项目都要重新打包部署——前后端部署也粘在一起了。
怎样才算分开开发呢?那当然就是前端页面只用写html + js + css,后端不用写jsp,不用使用thymeleaf等模板引擎来做html的渲染了。
怎样才算分开部署呢?将前端项目和后端项目分开成两部分分别部署到服务器里。
所以,前端项目和后端项目分开开发,分开部署的都算是前后端分离。
我们为什么要前后端分离
- 项目变大后难以更新维护
我们也都知道,一个项目开发出来之后,都会一直更新维护。
那每次项目更新升级都会添加新功能,代码量也会增加,项目也会越来越大。如果采取前后端不分离的开发方式,前后端的更新迭代对于前端工程师和后端工程师或是全栈工程师而言也是巨大的压力:当一个页面需要前端工程师和后端工程师一起才能做好的时候,对他们而言,沟通可能是比代码更令人头疼的问题;当一个项目开发团队都是全栈工程师,如果项目变大,首先令人头疼的问题应该是:怎样才能招到合格的全栈工程师——毕竟全栈工程师对程序员的要求更高。而且当前端页面或后端接口出现问题时,我们不得不重新打包编译整个项目以进行项目的更新与维护,而项目越大,打包与编译所耗费的时间就越长。
- 项目耦合太严重难以复用
上文也有提到,如果使用模板引擎或是jsp这种特殊的页面,都会出现在页面上写java代码的情况。那么如果想要进行代码复用,难度肯定是特别高的:每次复用后端接口都需要重新修改前端页面,并在上面添加java代码。
- 项目加载更加耗费资源和时间
如果要加载一个使用了thymeleaf的页面,首先我们需要调用thymeleaf引擎来解析页面上的java代码,然后再对页面进行渲染,而一般的静态页面只需要直接渲染就可以。如果我们项目需要承载更多的并发的时候,我们也只能将前后端结合的部署包进行多包部署以扩充系统性能,但这样也浪费了一部分资源。
前后端分离有什么好处
- 提升前端与后端开发效率
前端与后端可以分开干了,各干各的,各自都只需要负责各自擅长的东西:前端只需要管html,css和js,后端只需要管java。只要商量确定好接口文档,甚至连开发进度都可以不统一:前端用js来mock数据进行测试,后端用postman等接口测试工具来做接口测试。
- 项目更新维护变简单
当我们需要更新维护前端页面时,只需要对前端项目的bug进行修缮,然后对前端项目进行打包部署就行,后端也是一样。而当团队需要扩招的时候,擅长单一职责(前端/后端)的人也更好找。
- 提高接口复用率
如果我们需要开发一个相似的项目,或者复用之前项目的后端模块,只需要将模块拿出来后进行小改动就行。而不是像以前一样大费周折,还要将接口对应的旧页面上的相应java代码移植到新的页面上(甚至还会出现不兼容的情况)。
- 让页面加载变得更快
我们将前端页面打包成静态页面进行部署,用户只需要访问静态页面就行,比起需要多一步解析交互代码的thymeleaf等模板引擎,普通的html页面肯定会快上一些,而有的时候这就不只是快上那么一点了。甚至我们可以引入nodejs作为中间岛,将前端页面的渲染放在nodejs上进行处理,直接将结果呈现反馈给浏览器。
- 提升服务器资源利用率
如果我们需要扩充系统并发量,只需要把前端页面在不超过后端接口QPS的情况下进行分包部署,做好负载均衡就行。而不需要将整个项目分包部署,尤其是多部署后端服务——这特别占用服务器资源。而如果超过了后端接口的QPS,后端当然也要分包部署了。
前后端分离带来的问题
- 跨域问题(CORS)
跨域问题应该是最常见的问题了。当我们用到Ajax进行数据请求的时候,跨域问题就会出现。这个问题的解决方法也是特别简单的,后端在返回的请求header中添加Access-Control-Allow-Origin就可以解决了。不同应用场景有不同设置方法,而这个问题百度来答案比什么都快。
- 单点登录问题
这个问题也是最近我在做项目对接的时候遇到的,具体是在对接cas的单点认证时,请求服务的单点登录接口是直接接入门户网站的,而这个接口对接的是后端而不是前端。当我们从门户访问接入应用的单点登录链接时,请求是直接发送到后端的。由于前端没接入nodejs,所以并没有办法将请求直接发送到前端进行登录验证。而整个认证流程都在后端进行的话,前端页面就无法正常获取登录后的jwt了。所以要在第一步请求的时候,将生成的token和jsessionid写入前端的认证处理页面来做页面跳转和登录认证的进一步进行。