前后端分离及React的一些研究
前言
在对英才网企业线前端不断的完善过程中,我们尝试进行了前后端分离,引入Node环境、以及在使用React的过程中,自行开发DOM渲染框架,解决React兼容低版本IE的问题,在这个过程中,我们有了一些经验和体会,希望本文对您有所帮助。
为什么前后端分离
原有架构下,后端系统基于Java语言实现,通过Velocity模板实现服务器端渲染,前端同学维护静态资源,在维护页面状态时,还需要模板和脚本互传参数,模板中还会有很多UI逻辑,等等,前后端耦合很深,这种模式下开发效率非常低,联调成本非常高,同时Velocity的模板和前端代码如果是分开管理和维护,针对前端静态资源的的构建流程不方便对Velocity模板进行静态资源的引用替换,影响了自动化发布流程,也限制了前端的发展空间。
如何前后端分离
前后端分离包括前后端开发分离,以及前后端物理分离,前后端的开发分离还是基于原有的架构,通过提供相关的平台工具,比如Jello,Mock等,弥合前后端耦合的点,使前后端开发工作可以独立开展,后期通过平台无缝集成。
前后端的物理分离是完全的系统级别的分离,比如Web服务器采用PHP或者Node,或者前端同学去学Java语言,完全接管了Web服务器这一层的开发,不过对前端同学的要求太高了,不是每个人都是全栈工程师,相比PHP和Java,Node对前端同学来说,学习成本低了一些,不过仅仅是语言层面,从浏览器运行时环境切换到服务器运行环境还是需要更多的实践经验,比如我遇到很多前端开发同学想学习Node,但是无从下手,如果不切换到后端思维,还是没法深入Node的。
开发分离相比较物理分离更难一些,因为对平台工具要求比较高,引入了新的工具,也引入了新的维护工作、流程和规范,如果前端同学没有按规范编写模板,虽然在开发环境下完美运行,但是后面发布到运行环境,还是有一定的风险的,毕竟在开发模式下,模板的运行环境是不一致的,对前端新手来说,学习规范也需要不少成本。
物理分离相对更容易一些,前端接管Web服务器,开发和运行环境是一致的,不过对前端同学的要求更高了,还需要了解Web服务器相关的知识,Node对前端来说,入门成本还是比较低的,引入Node以后,针对Node的监控也是一个问题,Node是单进程单线程,如果不能很好的处理异常,进程会挂掉,虽然可以用pm2等进程管理器可以保证进程稳定性,但是异常就是不可预测的错误。
还有关于纯浏览器端渲染,也就是SPA,也是一种分离,纯浏览器端渲染的情况下,前后端耦合进一步降低,只是数据接口的耦合,通过Mock服务约定一直的API,前后端并行开发。
关于前后端分离的更多内容可以看看玉伯的这篇文章[:Web 研发模式演变](https://github.com/lifesinger/lifesinger.github.com/issues/184)
我们前后端分离计划
原有的项目目前还是基于后端的MVC架构,后续随着改版逐步迁移到浏览器端渲染,Node环境准备好以后,提供基于Node的服务器端渲染能力。
上文提到,企业线是不需要做SEO的,可以做纯浏览器端的渲染,不过为了更好的优化加载体验,以及未来在其他业务线的改版做技术储备,可以在企业线尝试去做。
要实现的目标就是,一套组件代码,同时支持前端渲染和后端渲染,这样就不需要为SEO去做些折中的方案了。
整个迭代的过程大致分三个阶段:
- 基于React做前端渲染
- 引入Node环境
- 支持服务器端渲染
基于React重构前端
企业线的前端框架选型经历了一段时间的考虑,让人纠结的点在于,很多新兴的框架对低版本IE支持不好,比如AngularJs、VueJs、ReactJs,但是我们又不能放弃低版本IE,我个人比较倾向React,下面我列出几点:
- 更好的生态支持
- 更好的组件化开发方案
- 有虚拟DOM,更好的性能
- Redux状态管理
- 多端支持,Learn Once Write Anywhere
- 服务器端渲染支持
如果我们选择兼容IE的框架,目前只有Avalon,Backbone等,这样的框架要么过时,要么生态欠佳,未来UI的扩展会受限制。
最终,我们还是选择了React生态,而且,自行实现了针对低版本IE的DOM渲染,达到了兼容低版本IE的目的。
为了实现兼容低版本IE,我们针对React进一步深入了解,比如关于Jsx的编译,虚拟DOM的渲染,diff算法,flux架构等
关于Jsx转换和DOM渲染
React引入了Jsx语法,实现在JavaScript中内联的方式书写HTML,相比之前的字符串模板引擎,开发体验上了一个台阶,我们非常希望能使用Jsx开发我们的组件,Jsx最终是如何被渲染成真是的DOM的呢,在github上,有不少针对jsx的转换器,比如:
l nativejsx:JSX to native DOM API transpilation.
l jsx-transform :This module aims to be a standard and configurable implementation of JSX decoupled from React for use with Mercury or other modules.
l jsx-runtime:Runtime for rendering JSX-IR. Runtime does not renders JSX-IR, otherwise it provides common interfaces for Renderer to be implemented.
上面三个项目都实现了对Jsx的解析,比如nativejsx,将Jsx编译成真实的DOM创建代码,jsx-transform将Jsx独立出来,可以使用在 其他的vdom技术,jsx-runtime提供了更灵活基础库,借助这个库,可以方便的将jsx转换其他的想要的格式,具体如何转换,可以自己控制,比如Jsx转换成DOM创建代码,转换成React需要的的格式,或者转换成字符串等。
具体到React中,转换过程是这样的:
为了兼容低版本IE,我们尝试自己做了DOM的渲染,和React比较,去除了虚拟DOM,过程如下:
渲染过程兼容了React的API,比如:React.createClass,React.createElement,这样以后可以平滑切换到React,并且可以和React进行性能的对比。
关于去除虚拟DOM,有利也有弊。
有利的是首次渲染的性能得到提升,React原有的方式是先构建虚拟DOM树,然后用虚拟DOM树去构建真实的DOM树,这个过程肯定是有性能损耗。
弊端是增量更新无法做diff,React的高性能体现在通过diff算法实现对DOM的增量更新,如果系统增量更新不多,虚拟DOM就不必要了。
其实最佳的方式是首次渲染就是服务器端渲染,增量更新采用React的模式,如果可以控制页面那些组件服务器端渲染,哪些做前端渲染,就更好了。
这里做个数据对比,
库文件大小:
渲染时间对比:
去除虚拟DOM后,虽然带来性能的提升,但是没有虚拟DOM的React,不能称之为React,React更多给我们带来的是对UI架构的重新思考,加入一个抽象中间层,多端能够共用一套状态数据,和状态变迁逻辑,而UI的渲染可以针对多端去实现,这样为未来带来了很好的扩展能力。
Flux框架的轻量级实现
在状态管理方面,我们目前没有引入流行Redux或者alt等Flux框架,官网提供的Flux的实现又很复杂,Redux框架又不是很了解,所以暂时先实现了一个轻量级的Flux框架,不过,实现非常简单,每个组件一个Store,UI组件监听Store的change事件,Action负责Store数据的维护。
后端API的调用放在Action中,Store存在的作用在于方便多个View共享数据,比如一个View可以监听多个Store的change事件。
这个Flux实现和官方的比较,差别很大,官方实现如下:
主要的差别如下:
- 官方的Action仅是一个指令,针对指令的处理是在Store中
- 官方有Dispatchor模块,其中注册了所有的Store,每个Action都会发送到每个Store,Store决定是否处理对应的Action,这样的设计隔离了Action和Store,不需要关心Action和Store对应关系,也就是对Action和Store做了解耦。
- 官方的业务逻辑在Store中,在Store中可以获取当前的state,处理完业务以后,更新state,触发change事件。
相比之下,我们的的设计只能是刚刚够用,缺点是Action和View的关系,Action和Store的关系,都是强耦合的,相比较之后才了解了官方设计的精髓。
还有另一个问题,页面是用多个Store,还是使用使用一个Store,这个经典的Flux实现和Redux实现的差别,当我们想实现服务器端的渲染时发现,单一的Store是最好的,而多个Store,数据准备非常不方便。所以未来,我们会引入Redux。
引入Node环境
Node环境最近才准备好,Node的优点是很简单,缺点就是太简单了,以至于在复杂的业务线上,不敢投入使用,比如遇到异常容易崩溃的单线程,比如多层的回调代码,过于自由JavaScript语言带来的不可预测性,类似Java、.Net这样的语言,有些错误可以在编译期暴露,而JavaScript执行期才知道是否有Bug,过于自由,代码混乱,可读性差,以至于有时候改别人的代码不如自己再实现一套。
为了解决JavaScript本身的问题,出现一些及技术,增强JavaScript语言的健壮性,比如Facebook的Flow,微软的TypeScript,还有CoffeeScript,都可以弥补JavaScript的类型过弱的问题。
随着对ES6的支持越来越好,对异步和面向对象方面方面JavaScript的支持也越来越好,使JavaScript具备构建大型应用的能力。
关于Node的进程监控,初期在运营线搭建了套监控系统,用到如下的系统:
l StatsD:基于Node,用于向graphite的收集器发送数据
l Carbon : 后台服务,监听端口数据(TCP/UDP)
l Whisper :数据库,存储时间序列的数据
l Graphite:基于时间序列数据库的图形展示系统
l Grafana:强大的图形自定义功能,从Graphite抽取数据
基于这个系统的监控截图:
不过系统按最低的标准配置,没有集群,只是在单一业务里尝试用,大面积用恐怕支撑不了,最近,我们将Node的监控接入集团运营部的open-falcon,架构部的WMonitor,Node的监控问题也终于解决。
引入Node对前后端分离非常有利,前端静态资源的构建、发布单独走流程,不需要对其他系统的依赖,还有Node对服务器端渲染的支持,越来越多的公司在做同构直出,借助Node解决SEO的问题。
支持服务器渲染
在支持服务器端渲染方面,React有很好的支持,可以将React组件渲染成HTML,或者借助前文提到的Jsx转换工具,直接可以将Jsx转换成HTML,方法还是很多的,前端渲染和后端渲染的过程大致如下:
需要注意的两个地方:
1.Store数据准备:
前端渲染和服务器端渲染不同的地方是,前端将渲染分阶段进行,比如,一般会分三步:
1) UI框架展现,不加载数据
2) 发起加载数据的异步请求,UI处于Loading状态
3) 数据加载结束,重新渲染UI
后端渲染需要前后端配合:
1) 后端数据准备,渲染出HTML
2) 前端做事件绑定,完成后续操作
2.导航
前端导航通过URL的hash实现导航,页面不刷新,后端导航,需要请求回发到服务器端,重新实现一次渲染。导航组件包括:站点导航、分页导航,Tab导航等。
前面提到Redux的状态管理,整个页面组件用一个Store,非常利于页面的服务器端渲染,只需要将Store数据准备好,整个组件就可以实现渲染,如何渲染,完全取决于Store的数据,比如,对需要服务器端渲染的组件,提供数据,不需要渲染的,不提供,后续在浏览器端判断,做异步的加载,如果能实现这样一套的组件架构,会提升开发效率,较少工作量,会有更好的加载体验。
结束语
本文讨论了前后端分离的一些想法,特别是针对Node实现大前端,自定义Jsx的渲染,基于React+Redux支持前后端渲染,有些想法还没有落地,后续会逐步探索,希望本文对你有所帮助。
前后端分离及React的一些研究的更多相关文章
- python drf+xadmin+react+dva+react-native+sentry+nginx 搭建前后端分离的博客完整平台
前言: 经过差不多半年的开发,搭建从前端到服务器,实现了前后端分离的一个集PC端.移动端的多端应用,实属不易,今天得空,好好写篇文章,记录这些天的成果.同时也做个分享. 演示网站地址: http:// ...
- 前后端分离Web项目中,RBAC实现的研究
在前后端分离Web项目中,RBAC实现的研究 最近手头公司的网站项目终于渐渐走出混沌,走上正轨,任务也轻松了一些,终于有时间整理和总结一下之前做的东西. 以往的项目一般使用模板引擎(如ejs)渲染 ...
- k.tt 研究下生成的逻辑代码:从壹开始前后端分离 [.netCore 填坑 ] 三十二║ 四种方法快速实现项目的半自动化搭建
更新 1.更新小伙伴 @大龄Giser 提出好点子:试试VS的插件扩展:VSIX.ItemProject等,将T4模板给制作插件,这里先记下,有懂的小伙伴可以自己先试试,我会在以后更新. 2.感谢小伙 ...
- 前后端分离框架前端react,后端springboot跨域问题分析
前后端分离框架前端react,后端springboot跨域问题分析 为啥跨域了 前端react的设置 springboot后端设置 为啥跨域了 由于前后端不在一个端口上,也是属于跨域问题的一种,所以必 ...
- React:快速上手(8)——前后端分离的跨域访问与会话保持
React:快速上手(8)——前后端分离的跨域访问与会话保持 跨域访问 跨域是指从一个域名的网页去请求另一个域名的资源.比如从http://www.baidu.com/ 页面去请求http://www ...
- GraphQL + React Apollo + React Hook + Express + Mongodb 大型前后端分离项目实战之后端(19 个视频)
GraphQL + React Apollo + React Hook + Express + Mongodb 大型前后端分离项目实战之后端(19 个视频) GraphQL + React Apoll ...
- 在前后端分离Web项目中,RBAC实现的研究
最近手头公司的网站项目终于渐渐走出混沌,走上正轨,任务也轻松了一些,终于有时间整理和总结一下之前做的东西. 以往的项目一般使用模板引擎(如ejs)渲染出完整页面,再发送到浏览器展现.但这次项目的处理方 ...
- java前后端分离是否会成为趋势
现在项目当中使用的是springboot+springcloud,这套框架也用了半年了,springboot是spring4.0的升级版,简化了springmvc的xml配置,是spring家族中目前 ...
- 七个开源的 Spring Boot 前后端分离项目,一定要收藏!
前后端分离已经在慢慢走进各公司的技术栈,根据松哥了解到的消息,不少公司都已经切换到这个技术栈上面了.即使贵司目前没有切换到这个技术栈上面,松哥也非常建议大家学习一下前后端分离开发,以免在公司干了两三年 ...
随机推荐
- Angular5 错误: ngModel cannot be used to register form controls with a parent formGroup directive
在创建一个表单时,出现了这样的错误: 原因是,在最外层的form中使用了 formGroup 指令,但在下面的某个input 元素中,使用了ngModel 指令,但没有加入formControl 指令 ...
- oracle--高级使用(merge)(递归START WITH)分析函数over
1.俩种表复制语句 SELECT INTO和INSERT INTO SELECT两种表复制语句 CT: create table <new table> as select * from ...
- Java web 加载过程
1.Web容器初始化过程 2.SpringMVC中web.xml配置 3.认识ServletContextListener 4.认识ContextLoaderListener 5.Dispatcher ...
- VSL基础
VSL是Virtools提供的一个非常有创意的脚本语言,它以输写代码的方式(区别于Virtools现有的图形化编程界面)进行编程开发,提高了程序的可读性和工作效率. 下图的功能是:将一个3D物体拷贝出 ...
- Sql Server主副本和辅助副本间账号同步以及权限同步
问题描述 SqlServer如果配置了AlwaysOn,其数据库账号信息同步会出现问题. 我遇到的情况是在主副本添加了账号信息,且给某个数据库添加了权限,这个账号会同步至辅助副本,但是数据库角色信息没 ...
- linux安装mysql(tar.gz)
1. 查看卸载自带的mysql # rpm -qa|grep MySQLMySQL-X.X.X#rpm -e MySQL-X.X.X # rpm -qa|grep mariadb #有些版本还得查看卸 ...
- 微信JS-SDK选择图片遇到的坑
微信JS-SDK选择图片遇到的坑 有个需求要在微信企业号里面做开发,有个功能是选择图片,使用input标签肯定是不管用了,Android手机上不能多选,所以使用了微信的JS-SDK提供的相关API,这 ...
- keep-alive 被 beforeRouteEnter 骗了
大家中秋假期快乐,假期分享一些实战文章给大家,原创不易,欢迎转发,一起学习 现在大家基本都在单页应用里面使用了 keep-alive 来缓存不活动的组件实例,而不是销毁它们. 如果你还没有使用,可以看 ...
- 加秘钥的SSH
import paramiko private_key = paramiko.RSAKey.from_private_key_file('id_rsa31.txt') # 创建SSH对象 ssh = ...
- 初入vue.js(1)
本文章属于个人在学习vue的随笔,留作与大家分享,技术交流之用,如果有错误,请大家多多指正.谢谢 首先说一下vue的使用方式: vue的使用方式一共有两种,第一种是直接在官网上下载vue.js的文件, ...