前后端分离及react的一些研究

coder_zyz coder_zyz     2022-08-28     171

关键词:

前言

在对英才网企业线前端不断的完善过程中,我们尝试进行了前后端分离,引入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支持前后端渲染,有些想法还没有落地,后续会逐步探索,希望本文对你有所帮助。

关于前后端分离与不分离

...要负责程序设计架构思想,管理数据库等。   前后端分离和微服务一样,渐渐地影响了新的大型系统的架构。微服务和前后端分离要解决是类似的问题,解耦——可以解耦复杂的业务逻辑,解耦架构。可要是说相像吧... 查看详情

前后端分离及不分离

前后端不分离  在前后端不分离的应用模式中,前端页面看到的效果是由后端控制,由后端渲染页面或重定向,后端需要控制前端的展示,前端与后端的耦合度很,这种应用模式比较适合纯网页应用,但是当后端对接APP时,APP... 查看详情

vue.js---实现前后端分离架构中前端页面搭建

【Vue.js实现前后端分离架构中前端页面搭建】一、前后端分离1.简介前后端分离属于软件架构的一种。其核心思想是把前端项目(Node.js实现的)和后端项目独立部署到不同的服务器上,前端项目在通过Ajax请求服务器... 查看详情

前后端分离框架

...ps://www.cnblogs.com/shanrengo/p/6397734.html前言:分离模式  对前后端分离研究了一段时间,恰逢公司有一个大项目决定尝试使用前后端分离模式进行,便参与其中。该项目从2016年初立项至今,平平稳稳得度过,但也涌现出越来越多... 查看详情

论前后端分离的好处

前后端分离最大的意义在于前后端可以并行开发。现在搞BS架构程序,前后端分离应该是主流了。前后端分离有什么好处呢?我认为最大的好处是,使得前后端可以并行开发。其次是前后端分离成2个不同的工种,... 查看详情

springboot+react前后端分离多模块项目框架搭建流程(代码片段)

...是基于SpringBoot【后端】+Vue或React【前端】,说是前后端分离,实际还是全栈,只是静态资源搭上了前端的框架而已。那么就面临一个问题,既然不是纯粹的前后端分离,怎么调试前端呢?怎么搭建项目... 查看详情

《springboot入门及前后端分离项目实践》系列介绍

...绍,第三个部分是SpringBoot项目实践开发。SpringBoot介绍、前后端分离、API规范等内容旨在让读者更加熟悉SpringBoot及企业开发中需要注意的事项并具有使用SpringBoot技术进行基本功能开发的能力;这最后的项目实战为课程的主要部... 查看详情

前后端分离实践

前后端分离并不是什么新鲜事,到处都是前后端分离的实践。然而一些历史项目在从一体化Web设计转向前后端分离的架构时,仍然不可避免的会遇到各种各样的问题。由于层出不穷的问题,甚至会有团队质疑,一体化好好的,为... 查看详情

八个开源的springboot前后端分离项目,一定要收藏!

八个开源的SpringBoot前后端分离项目最近前后端分离已经在慢慢走进各公司的技术栈,不少公司都已经切换到这个技术栈上面了。即使贵司目前没有切换到这个技术栈上面,我们也非常建议大家学习一下前后端分离开发,以免在... 查看详情

八个开源的springboot前后端分离项目,一定要收藏!

八个开源的SpringBoot前后端分离项目最近前后端分离已经在慢慢走进各公司的技术栈,不少公司都已经切换到这个技术栈上面了。即使贵司目前没有切换到这个技术栈上面,我们也非常建议大家学习一下前后端分离开发,以免在... 查看详情

前后端分离微服务架构如何设计

...道最多的。比如:一般前端工作包括六个部分:后端如果前后端职责划分很清楚的话,后端更多开发工作在于业务接口设计、业务逻辑处理以及数据的持久化存储,并提供详细的接口设计文档给前端开发人员使用。一般后端工作... 查看详情

微信小程序前后端分离怎么实现

微信小程序前后端分离的主要实现方式是将前端和后端的代码逻辑分开,前端负责展示和交互,后端负责数据处理和逻辑控制。下面简单介绍一下微信小程序前后端分离实现的一些关键步骤:1.前端代码开发:使用微信小程序开... 查看详情

前后端分离的一些尝试

背景        目前使用SpringMVC框架进行开发,用户访问controller的url,controller收到页面数据后分发给serverice做处理,处理完后在controller中根据页面所需要的数据进行整合,最后将打包好的信息发给指定... 查看详情

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

前后端分离已经在慢慢走进各公司的技术栈,根据松哥了解到的消息,不少公司都已经切换到这个技术栈上面了。即使贵司目前没有切换到这个技术栈上面,松哥也非常建议大家学习一下前后端分离开发,以免在公司干了两三年... 查看详情

前后端分离的springboot+vue项目打包教程

...务器上去,我也去网上找了一些关于springboot+vue的前后端分离的项目的打包及发布教程,但是网上的一些教程都是各种方法都有,所以在 查看详情

理解什么是前后端分离

 HTML、CSS、JS。AJAX或Fetch。学习一个前端的框架,React或者Vue或者Angularjs2都可以。学会一个前端的路由框架,如React-Router或者Vue-Router。在学会3的基础上你肯定已经搭建好前端的开发环境了,所有和后端的交互走AJAX或者Fetch。S... 查看详情

docker环境下的前后端分离项目部署与运维项目简介及环境要求

项目简介本教程将从零开始部署一个前后端分离的开源项目,利用docker虚拟机的容器技术,采用分布式集群部署,将项目转换成为高性能、高负载、高可用的部署方案。包括了MySQL集群、Redis集群、负载均衡、双机热备等等。部... 查看详情

前后端分离之接口文档管理及数据模拟工具docdoc与dochelper

前后端分离的常见开发方式是:后端:接收http请求->根据请求url及params处理对应业务逻辑->将处理结果序列化为json返回前端:发起http请求并传递相关参数->获取返回结果处理相关逻辑分离的主要目的是让前后端可以并行的... 查看详情