[TOC]
# 什么是前后端分离
## 传统开发模式
相信很多做过Web开发童鞋应该都会经历这样一种开发模式,利用后端语言提供的模版引擎编写HTML/XML页面,比如:
* PHP 开发有 Smarty模板引擎
* Java web工程有jsp页面
* Python 各个Web框架都有各自的模板引擎
* NodeJS 的express你懂得
都有一个共同的特点,服务器端后台语言生成解析后的HTML/XML格式返回给客户端,例如浏览器端访问直接返回解析好的HTML,浏览器直接就解释执行。
在传统的像ASP,JSP和PHP等开发模式中,前端是处在一个混沌的状态中,可以说是没有独立的“人格”可言。
前端负责切图和编写静态页面模板,后端将数据渲染到前端提供的页面模板中,最后将页面渲染到浏览器展示。
这个过程中,前端只提供页面模板或者写一些JavaScript脚本,有的甚至JS脚本都是后端来写,前端的作用只局限于切图和样式模板文件,这种角色就是传说中的“切图仔”。
前后端分离,不只是简单的代码的分离。
首先是要**架构上分离解耦**,逐渐摆脱前后端在架构上的依赖,前后端各司其职,分开部署在不同的服务器上,通过RESTful接口传递数据。减轻后端服务器的压力,后端服务器不再负责页面渲染,只负责输入数据,吞吐量提升了好几倍。
其次是逻辑分离,不分离的时候,对于业务代码的界限很不明确,业务逻辑基本都放在后端,分离之后,前端也承担了一部分不该后端来写的业务逻辑,数据处理更加清晰。
最后是系统分离,同一个后端系统,可以将同样的接口数据提供给PC端、Mobile端和Native端等不同的前端终端,不需要为每一种终端提供一套接口。同样,对于前端应用来说,可以更方便的调用多个后端服务器的接口,处理和展示多个系统间的数据。
# 为什么要前后端分离
前后端分离,让软件开发的流程更加清晰,解决了开发阶段的痛点。
从前,前端不止要学习后端的模板渲染语法,还要配置后端的开发环境,并不断同步后端的代码,这对于前端来说是非常痛苦的。
而现在,前端有自己的服务器,不需要再依靠后端服务器来支持项目运行,如果在开发阶段,还可以使用mock数据(要先和后端确定接口数据结构),摆脱对后端接口的依赖,这样极大的提高了开发效率,系统分工也更加明确。
# 前后端分离后,需要考虑哪些事情
分离后的前端,不再是一个简单的HTML文件,已经是一个独立的应用系统。除了要考虑页面的数据渲染展示,还要用工程化的思想来考虑前端的架构,前后端的交互和数据安全等事情。
## 架构
**前端应用部署在 Nodejs、Nginx 或者 Nodejs Nginx 组合的服务器上,通过反向代理转发页面请求到后端服务器,相当于在传统的流程中加了 Nodejs 这一层**。
当然,也可以用Nodejs服务器来承担一部分负载均衡的工作,业务逻辑也可以放在Nodejs这一层来处理,例如:通过判断请求是来自 PC 还是 APP ,将请求发到不同的后端服务器。
Nodejs的架构中,分层如下:
![](https://box.kancloud.cn/40545917fb37e224ba3b5ab0cadfe170_590x611.png)
让我们来回想一下软件开发流程中的几个关键环节:
(1)产品经理提需求,画原型;
(2)UI设计师根据原型出设计图;
(3)测试团队根据产品原型编写测试用例,制定测试计划;
(4)架构师根据原型编写API文档;
(5)前后端工程师基于API文档完成业务开发;
(6)测试、改BUG、发布。
API文档环节直接关系到了前端和后端两个开发团队,也是整个软件开发流程中耗时最大的环节。
![](https://box.kancloud.cn/0b9af4bc13447e620053eae878321880_613x355.png)
## RESTful接口交互
前后端分离之后,更多的是采用 RESTful 风格的接口与后端进行数据交互。(如果你们的项目还在使用静态的API文档,比如word文档,那你们必定经历着巨大的痛苦)
REST是“呈现状态转移(REpresentational State Transfer)”的缩写,一种API的架构风格,在客户端和服务端之间通过呈现状态的转移来驱动应用状态的演进。
在 REST 样式的 Web 服务中,每个资源都有一个地址。资源本身都是方法调用的目标,方法列表对所有资源都是一样的。这些方法都是标准方法,包括 HTTP GET、POST、PUT、DELETE,还可能包括 HEADER 和 OPTIONS。
RESTful的API设计,使得后端通过接口向前端传递数据,数据的格式通常是JSON这种通用的格式。对前端来说,只要后端返回过来的是RESTful的数据就行,不管后端是用Java写,还是用python或PHP,拜托对后端的依赖,做到前端系统的独立。
REST服务的调试:[Postman](http://www.getpostman.com/) 和 [Insomnia](https://insomnia.rest/)
## 使用模板引擎
前后端分离之后,前端工程师需要将通过API获取的数据呈现到页面上,虽然也可以通过jQuery对页面一个一个赋值,但是这种效率太低了,或者也可通过在JavaScript中拼接HTML,但是这种方式太难维护HTML代码了,也很难阅读。因此最好的方式就是使用模板引擎。
前端的模板引擎跟后端模板引擎很相似,比如JSP或cshtml(razor),他们的语法都非常相似,他们所实现的功能也几乎一样:将数据绑定到HTML模板。VueJs和react都可以充当这样的模板引擎。我们最终没有选用react而是选用了VueJs的原因只有一个,那就是VueJs是真正的响应式,而react改变model之后需要手工调用setState才会更新UI,这是完全无法忍受的。
因为这个原因,我们只能选择VueJS作为模板引擎。
## 工程化构建
Nodejs不止可以用来做前端服务器,在开发阶段,它也能发挥很大的作用。
前端生态的发展,是围绕着Nodejs进行的。用npm来管理项目依赖,可以很好的维护和运行在Nodejs环境上。
打包工具grunt、gulp、webpack和rollup等,都是运行在nodejs上,再结合语法编译、打包部署等插件,将应用输入成一个完整的应用。
如果你使用了Angular、React或Vue框架,或者你使用浏览器暂时还不兼容的ES6语法,还需要在应用打包前用babel将语法编译成浏览器可识别的ES5的语法。
## SPA
SPA是单页Web应用(single page web application,SPA)的简写,就是只有一张Web页面的应用,是加载单个HTML 页面并在用户与应用程序交互时动态更新该页面的Web应用程序。
像Angular、React或Vue就是为了SPA而设计的,结合前端路由库(react-router、vue-router)和状态热存储(redux、vuex)等,可以开发出一个媲美Native APP的Web APP,用户体验得到了很大的提升。
当然,SPA也不是完美的,也不是适合所有的web应用,需要结合项目和场景来选择。
SPA有如下缺点:
* 初次加载耗时增加。可以通过代码拆分、懒加载来提升性能,减少初次加载耗时。
* SEO不友好,现在可以通过 **Prerender** 或 **Server render** 来解决一部分。
* 页面的前进和后端需要开发者自己写,不过现在一些路由库已经帮助我们基本解决了。
* 对开发者要求高,由于做SPA需要了解一整套技术栈,所以,要考虑后期是否有合适的人选进行维护。
## mock(模拟数据)
前后端分离框架中的API mock思路
想要实现真正的前后端分离,那就必须得用好API mock(模拟数据)。使用mock数据的好处有两个:
1. 前端开发人员可以基于API文档生成mock数据,在后端开发人员将API发布出来之前就可以完成整个业务流程的开发;
2. 使用mock数据能够更低成本、更快速地,通过直接修改mock数据的方式,调试页面样式、调试页面功能。
### 全局的mock开关
为什么要设置这样一个全局的mock开关呢?主要基于以下两点考虑:
1. 设置全局的mock开关之后就不再需要针对每一个页面设置mock开关,更容易维护,避免项目中有多个mock开关而难以统一开关状态;
2. 如果发布时忘记将mock开关给关掉,那么发布之后一运行发布者就会发现mock开关忘了关,然后可以快速修复之后再重新发布,从而避免不小心将正式服更新为mock数据源。
正是由于以上两点考虑,我们的全局mock开关可以帮助程序开发者和发布者更不容易犯错。
# 解决请求问题
前后端分离后,我们只需要Server端告诉我们Api URL即可,那么这会产生一个问题:Ajax跨域。这里就不能使用一般的跨域解决方法去解决,比如jsonp,iframe信使等等,因为我们还有POST请求。
于是Http Proxy类工具就有用了,比如我就会在BrowserSync加入中间件判断每一个请求,如果是/api前缀就会代理到API Server端,API Server端收到数据后再返回给BrowserSync,BrowserSync再返回给浏览器端。这样就解决跨域请求的问题
生产环境有两种部署,一种是放到后台项目里,这就没啥说的,另外一种就是前后端分开部署,那就在前端WebServer处理端写点转发规则就好,如Nginx,Apache都支持。
# 静态资源路径问题
如果你的项目有上传资源功能,那自然就会产生用户资源,那前后端分离后,如何来处理这个问题呢?得先看模式。
资源与后台项目放一起,后台处理完后需要返回前台一个相对路径,如果资源时一台单独的服务器,那就需要返回资源的绝对URL即可。
# 会话
Web项目最头疼的就是无状态导致会话问题,传统的Web项目都使用Session/Cookie,但在前后端分离,集群部署模式下这Session明显缺陷太多。token方式已经是当前Web端解决会话的主流,并且有很多开源好用的token生成管理程序,基本上拿来就能用。
# 参考
[WebAPI 实现前后端分离的示例](https://www.jb51.net/article/133131.htm)
# 其他
https://segmentfault.com/a/1190000003969465
[解析前端开发中的缓存优化](http://blog.sina.com.cn/s/blog_14eda87f50102wsmo.html)
在前端性能优化中应用HTTP缓存的三部曲
[前端开发中,对图片的优化技巧有哪些?](https://www.zhihu.com/question/21815101)
[HTML5缓存机制浅析:移动端Web加载性能优化](http://www.csdn.net/article/1970-01-01/2826489)
[web项目发布 客户端 js css文件缓存的解决办法有哪些,如何做更合理呢?](https://www.zhihu.com/question/30771729)
[前端工程精粹(一):静态资源版本更新与缓存](http://www.infoq.com/cn/articles/front-end-engineering-and-performance-optimization-part1/)
http://www.infoq.com/cn/profile/%E5%BC%A0%E4%BA%91%E9%BE%99
http://www.cnblogs.com/dojo-lzz/p/5515839.html
http://www.cnblogs.com/justTheOne-bin/category/554127.html
http://blog.fens.me/series-nodejs/
https://segmentfault.com/a/1190000006741200
# 调试和部署
监听文件变动,自动刷新浏览器 (LiveReload)
文件指纹,hash 值生成
FTP 发布部署
ZIP 项目打包
- 讲解 Markdown
- 示例
- SVN
- Git笔记
- github 相关
- DESIGNER'S GUIDE TO DPI
- JS 模块化
- CommonJS、AMD、CMD、UMD、ES6
- AMD
- RequrieJS
- r.js
- 模块化打包
- 学习Chrome DevTools
- chrome://inspect
- Chrome DevTools 之 Elements
- Chrome DevTools 之 Console
- Chrome DevTools 之 Sources
- Chrome DevTools 之 Network
- Chrome DevTools 之 Memory
- Chrome DevTools 之 Performance
- Chrome DevTools 之 Resources
- Chrome DevTools 之 Security
- Chrome DevTools 之 Audits
- 技巧
- Node.js
- 基础知识
- package.json 详解
- corepack
- npm
- yarn
- pnpm
- yalc
- 库处理
- Babel
- 相关库
- 转译基础
- 插件
- AST
- Rollup
- 基础
- 插件
- Webpack
- 详解配置
- 实现 loader
- webpack 进阶
- plugin 用法
- 辅助工具
- 解答疑惑
- 开发工具集合
- 花样百出的打包工具
- 纷杂的构建系统
- monorepo
- 前端工作流
- 爬虫
- 测试篇
- 综合
- Jest
- playwright
- Puppeteer
- cypress
- webdriverIO
- TestCafe
- 其他
- 工程开发
- gulp篇
- Building With Gulp
- Sass篇
- PostCSS篇
- combo服务
- 编码规范检查
- 前端优化
- 优化策略
- 高性能HTML5
- 浏览器端性能
- 前后端分离篇
- 分离部署
- API 文档框架
- 项目开发环境
- 基于 JWT 的 Token 认证
- 扯皮时间
- 持续集成及后续服务
- 静态服务器搭建
- mock与调试
- browserslist
- Project Starter
- Docker
- 文档网站生成
- ddd