前后端分离及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去做些折中的方案了。

整个迭代的过程大致分三个阶段:

  1. 基于React做前端渲染
  2. 引入Node环境
  3. 支持服务器端渲染

基于React重构前端

企业线的前端框架选型经历了一段时间的考虑,让人纠结的点在于,很多新兴的框架对低版本IE支持不好,比如AngularJs、VueJs、ReactJs,但是我们又不能放弃低版本IE,我个人比较倾向React,下面我列出几点:

  1. 更好的生态支持
  2. 更好的组件化开发方案
  3. 有虚拟DOM,更好的性能
  4. Redux状态管理
  5. 多端支持,Learn Once Write Anywhere
  6. 服务器端渲染支持

如果我们选择兼容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实现和官方的比较,差别很大,官方实现如下:

主要的差别如下:

  1. 官方的Action仅是一个指令,针对指令的处理是在Store中
  2. 官方有Dispatchor模块,其中注册了所有的Store,每个Action都会发送到每个Store,Store决定是否处理对应的Action,这样的设计隔离了Action和Store,不需要关心Action和Store对应关系,也就是对Action和Store做了解耦。
  3. 官方的业务逻辑在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支持前后端渲染,有些想法还没有落地,后续会逐步探索,希望本文对你有所帮助。

时间: 2024-08-24 10:29:32

前后端分离及React的一些研究的相关文章

一个简单粗暴的前后端分离方案

项目背景 刚刚参加完一个项目,背景:后端是用java,后端服务已经开发的差不多了,现在要通过web的方式对外提供服务,也就是B/S架构.后端专注做业务逻辑,不想在后端做页面渲染的事情,只向前端提供数据接口.于是协商后打算将前后端完全分离,页面上的所有数据都通过ajax向后端取,页面渲染的事情完全由前端来做.另外还有一个紧急的情况,项目要紧急上线,整个web站点的开发时间只有两周,两周啊!于是在这样的背景下,决定开始一次前后端完全分离的尝试. 之前开发都是同步渲染和异步渲染混搭的,有些东西可以有后

移动端开发者眼中的前端开发流程变迁与前后端分离

写在最开始 移动端与前端的区别 前端开发的混沌时代 后端 MVC MVC 方案实现 MVC 的缺点与改进 前端只写 Demo HTML 模板 后端 MVC 架构总结 AJAX 与前端 MVC 前后端分离的缺点 双端 MVC 不统一 SEO 性能不够 集中 Or 分离 Nodejs 前后端分离的哲学 Nodejs 分层 实战应用 风险控制 总结 参考资料 写在最开始 这是一篇面向移动端开发者的科普性文章,从前端开发的最初流程开始,结合示范代码,讨论开发流程的演变过程,希望能覆盖一部分前端开发技术栈

一个前后端分离方案[转载]

项目背景 背景:后端是用java,后端服务已经开发的差不多了,现在要通过web的方式对外提供服务,也就是B/S架构.后端专注做业务逻辑,不想在后端做页面渲染的事情,只向前端提供数据接口.于是协商后打算将前后端完全分离,页面上的所有数据都通过ajax向后端取,页面渲染的事情完全由前端来做.另外还有一个紧急的情况,项目要紧急上线,整个web站点的开发时间只有两周,两周啊!于是在这样的背景下,决定开始一次前后端完全分离的尝试. 之前开发都是同步渲染和异步渲染混搭的,有些东西可以有后端PHP帮你编译好,

简单粗暴的前后端分离方案

刚刚参加完一个项目,背景:后端是用java,后端服务已经开发的差不多了,现在要通过web的方式对外提供服务,也就是B/S架构.后端专注做业务逻辑,不想在后端做页面渲染的事情,只向前端提供数据接口.于是协商后打算将前后端完全分离,页面上的所有数据都通过ajax向后端取,页面渲染的事情完全由前端来做.另外还有一个紧急的情况,项目要紧急上线,整个web站点的开发时间只有两周,两周啊!于是在这样的背景下,决定开始一次前后端完全分离的尝试. 之前开发都是同步渲染和异步渲染混搭的,有些东西可以有后端PHP帮

一个简单粗暴的前后端分离方案(转)

项目背景 刚刚参加完一个项目,背景:后端是用java,后端服务已经开发的差不多了,现在要通过web的方式对外提供服务,也就是B/S架构.后端专注做业务逻辑,不想在后端做页面渲染的事情,只向前端提供数据接口.于是协商后打算将前后端完全分离,页面上的所有数据都通过ajax向后端取,页面渲染的事情完全由前端来做.另外还有一个紧急的情况,项目要紧急上线,整个web站点的开发时间只有两周,两周啊!于是在这样的背景下,决定开始一次前后端完全分离的尝试. 之前开发都是同步渲染和异步渲染混搭的,有些东西可以有后

浅谈前后端分离与实践(一)

一.起源 (故事纯属虚构,如有雷同,纯属巧合)传说在很久很久以前,我们有志之士有了个创业的想法,于是乎开始了自己的创业之梦,但是人手不足啊,于是乎所有角色老子一个人全包了: Roles: PM, DBA, RD, FED, Designer, ... Skills: Linux, MySQL, JAVA, JavaScript, HTML, CSS, ... Tools: phpmyadmin, photoshop, powerpoint, ... 我们用 express 应用生成器来模拟一下传

七个开源的 Spring Boot 前后端分离项目,一定要收藏!

前后端分离已经在慢慢走进各公司的技术栈,根据松哥了解到的消息,不少公司都已经切换到这个技术栈上面了.即使贵司目前没有切换到这个技术栈上面,松哥也非常建议大家学习一下前后端分离开发,以免在公司干了两三年,SSH 框架用的滚瓜烂熟,出来却发现自己依然没有任何优势! 其实前后端分离本身并不难,后段提供接口,前端做数据展示,关键是这种思想.很多人做惯了前后端不分的开发,在做前后端分离的时候,很容易带进来一些前后端不分时候的开发思路,结果做出来的产品不伦不类,因此松哥这里给大家整理了几个开源的前后端分离项

关于大型网站技术演进的思考(十四)--网站静态化处理—前后端分离—上(6)

前文讲到了CSI技术,这就说明网站静态化技术的讲述已经推进到了浏览器端了即真正到了web前端的范畴了,而时下web前端技术的前沿之一就是前后端分离技术了,那么在这里网站静态化技术和前后端分离技术产生了交集,所以今天我将讨论下前后端分离技术,前后端分离技术讨论完后,下一篇文章我将会以网站静态化技术的角度回过头来重新审视下前后端分离技术,希望通过这种审视来加深我们对两套技术的理解. 前后端分离技术我个人认为是web前端被专业化以后的必由之路,而nodejs的出现是前后端分离技术的一个强兴的催化剂,原

[转] 前后端分离开发模式的 mock 平台预研

引入 mock(模拟): 是在项目测试中,对项目外部或不容易获取的对象/接口,用一个虚拟的对象/接口来模拟,以便测试. 背景 前后端分离 前后端仅仅通过异步接口(AJAX/JSONP)来编程 前后端都各自有自己的开发流程,构建工具,测试集合 关注点分离,前后端变得相对独立并松耦合 开发流程 后台编写和维护接口文档,在 API 变化时更新接口文档 后台根据接口文档进行接口开发 前端根据接口文档进行开发 开发完成后联调和提交测试 面临问题 没有统一的文档编写规范,导致文档越来越乱,无法维护和阅读 开