寰宇网

对前后端分离的思考

结合在学校做易班轻应用时候的一些思考,记录下我为什么要做前后端分离的历史/原因/意义/效果。

历史背景

一开始说要给易班做轻应用的时候是懵逼的,什么叫轻应用。于是分三个阶段循序渐进地来做这个事。

静态网页

首先,琢磨了一下发现,所谓轻应用,好像其实就是个网页嘛。OK,最简单的就是静态网页。

做了一些诸如大物实验数据辅助处理系统,就是拿js算一些加减乘除、生活查询,就是根据客户端时间判断水房是否开门等等。

找个服务器配置下LNMP(linux + nginx + mysql + php 是个服务器环境配置一键脚本),静态页面和资源丢上去,完工。

动态网页

接下来难度升级,做个带后端服务的真正的应用了。因为是给易班做,目标是吸引用户到易班上,这些轻应用我基本没有考虑过自己做用户表,就是用户信息都是直接从易班开放平台获取。

这个地方涉及到Oauth2.0协议拿数据,易班开放平台做的这一个呢有一些让我觉得不舒服的限制,比如回调地址和应用地址必须是同一个,精确到完整的url,还有必须是点对点调用,就是不能回调到多个位置。(注意这是一个问题)

之后技术选型,选的是springboot框架,一个神奇Java的框架,特点是开发速度特别快,让人觉得,这还是Java web框架么?它为很多东西提供缺省配置,省去编写复杂的xml文件的时间。

部署上也极其方便,内嵌了tomcat,最后build出来的是一个jar包。在一台安装了jdk的电脑上输入java -jar xxxx.jar即可运行,不需要考虑tomcat的配置。(就是这一点让我放弃了PHP的laravel)

拿springboot写了3、4个应用吧。比如抽奖、查询、签到等,都是这个框架,配上模板引擎thymeleaf做的。

在完成了3、4个应用后,我发现了这种模式的一些问题,为了解决这些问题:

前后端分离

这个阶段里,我希望前端和后端独立部署,后端砍掉View层,把Controller层暴露出来,以API形式提供服务。

前端是一种类似于Client的模式,向后端发起请求。后端吐json格式的数据。前端拿到数据后自己去渲染数据到页面上。(前端渲染,参考 写了个前端渲染的教程

截至到离开组织,该架构初步实现,完成了一个demo级别的应用。其中后端以springboot作为框架,运行在服务器的8086还是多少端口来着有点记不清了。

原因

前端方面

为什么后端的View层要被砍掉?因为后端不会专业的前端技能。

前端上我希望向工程化、组件化、模块化看齐(好像并没有做到QAQ),要求前端工程要使用一些脚手架/脚本/node工具,进行诸如资源压缩合并混淆的工作,也就是前端其实是单独的工程。需要单独打包。

那么这样的前端生成的结果如果作为V层放到后端,后端同学需要在一堆乱码中找到需要替换的变量用模板语法改写。当然我们也可以让前端同学学习下thymeleaf直接以模板语法来写。

但是问题还是存在的。

这将导致,应用的升级无比麻烦。仅仅只是前端样式上的一个小变化,就需要前端先修改,再打包,给后端,后端打包,再部署。必须要求前后端在一起工作,频繁交流,才可以。但这对学生开发团队太难了,都有课的人。

后端方面

除了前后端必须联调导致修改不便之外,还有一旦部署,再想修改很难这个问题。因为用户信息没有存自己的表,必须走易班授权,上线的产品修改地址要审核,要本地测试得把回调地址指回本地,改好后又要指回去,又要审核一次。我怎么给用户解释应用不见了这个问题……?卒……

还有一个问题是,我前面说为什么选springboot框架时说过,是因为这个框架简单,开发简单,上手简单,部署简单。部署简单是有代价的!

没在服务器上配置tomcat,打包又是jar包,相当于每个应用,都是独立的,跑在独立的tomcat容器里,运行3个应用就等于开了三个tomcat,5个应用就是5个tomcat,tomcat本来就比较重,再这么开下去,服务器很快就受不了。(虽然按微服务架构的思路来说就应该把应用划分得足够细粒度,但是确实穷,又不想优化它的部署方式,以一个简单的方式部署有利于后面做持续集成、持续部署,而且我没有充足的服务器资源)

结果

前后端分离,把所有的应用都写在一起,整合应用,只用一个tomcat装。前端请求不同的接口获得数据。还有把一些config信息从代码里转移到了yml文件里。因为生产环境和开发环境的配置文件不同,再也不用像以前那样手工反复修改代码了。

具体做法

springboot的controller用@RestController注解,提供json格式的输出,方便快捷变成一个RESTful微服务后端。

前端项目直接部署到nginx服务器,阅读后端文档,自己请求API拿数据,展示。前端可以自由选择框架,angular1/2,react,vue,ember等等,反正接口在那。

遇到的问题就是跨域,用CORS解决了。这里还有个坑,就是CORS这种跨域资源共享一般是结合ajax请求来使用,ajax是默认不带cookie的,通过查资料修改CORS的配置解决掉了。暂时没别的问题了。

后面看时间如果有空可能拿出一个例子讲一下。