后台管理系统的技术迭代之路

1,274 阅读10分钟

17年的时候接手了一个用户后台管理系统,这个项目一直是由Java后端同学维护,可能是因为不同组都会进行修改的关系,很多页面几乎不可维护,甚至出现一个页面加载多个jQuery库相互覆盖的情况。而且也因为每个组都会去改动,加上原始的需求文档缺失,哪些功能可用,哪些功能已经不需要,更是处于不可知的状态。另外页面的UI设计看上去的陈旧感和年代感太过上头,仿佛回到了那个56k上网的年代。

1.0时代:JSP+SPA

全站推倒重做势在必行,而产品也正有此意,于是一拍即合,愉快(并没有)的讨论确定方案,但由于时间紧迫,做了比较多技术上的妥协。

  • 由于原来的系统兼容IE6,产品不希望改动太过激进,只允许提高到兼容IE8
  • 由于页面存在公共部分,所以要做前端路由减少相同内容的加载,提高页面跳转的速度
  • 页面也由原来的JSP直出,改成JSP+SPA

前端技术栈:JQuery + Requirejs + ArtTemplate

后端:JSP直出

页面内容布局比较接近圣杯布局(如下图所示)

IMG_5613.JPG

  • 公共页头(全站点通用)
  • 左侧导航(本系统使用)
  • 业务内容部分
  • 公共页脚(全站点通用)

JSP直出的页面也包含了上面的这些部分,因为页头、导航和页脚是每个页面都共有的,于是把前端路由限制在业务内容部分。当点击左侧导航或者右边业务内容部分触发路由跳转时,将会走前端路由,只请求业务内容的html(无需加载页头和页脚)。

页面路由逻辑如下: image.png

反思

  • 虽然我们通过引入前端路由,解决了页面公共内容重复加载问题,但是由于需要兼容IE8,我们没办法使用业界的MVVM框架Vue或React,导致需要重复造轮子。
  • 开发过程中发现有较多的页面,其内容和布局都是比较接近,可以抽象出一套业务UI组件使用,但是现有基于JQuery + Requirejs + ArtTemplate的技术栈,实现起来的可用性和可维护性较差。
  • 没有业务UI库,导致每一个功能和需求都需要设计资源,前端也需要每次都重新切图,特别消耗人力。

2.0时代:SPA & UI库

Vue 2

时间来到18年,经过一年的迭代,上面提到的反思问题越发制约项目的发展,加上这一年的用户数据,使用IE8、9、10的用户已经越来越少了,果断说服产品不再支持这些浏览器,终于可以用上Vuejs了。

基于Vue 2的UI库

接下来,前端与设计、产品一起反复讨论,一起定下来一套统一的UI设计规范,同时基于这套规范之上的,结合业务场景,抽象出一套业务UI库。

为什么没有使用市面上已有的UI库(例如element-UI,iView等),主要基于几点考量:

  1. 我们有自己的设计规范,照搬现成的UI库不合适,还需要进行定制化,这里面研究现有UI库的学习成本并不比做一套新的少多少,而且后期扩展可能还需要更进一步的魔改,可能会受到一些限制,包括版本升级、潜在的bug(还记得antd的hohoho么)等等。
  2. 我们需要不仅限于基础的UI模块,例如button、spinner等,还需要业务场景的UI模块,例如searchbar、dialog、avatar等。
  3. 希望通过开发业务UI库,提高同学们的技术能力和水平,毕竟使用和开发是两回事,更何况是自己既是开发者,又是使用者,能对此有更深刻的理解。

最终,用了60人天,开发出包含24个UI组件的第一版业务UI库;并同样花了60人天把原来的页面使用Vue 2 + 业务UI库进行重构。

image.png

虽然在这次升级重构的过程中耗费巨大的人力,但是对于一个持续不断的新增需求和版本迭代的项目来说,其实长远来说是节约了非常多的人力。

  • 由于有现成的UI组件,很多需求都不再需要设计资源,使得项目周期更紧凑。
  • 出现新的场景需要新的UI组件,在第一次开发出来之后,后续可以加入到UI库中,持续打磨和扩大UI组件库。
  • 前端有了UI组件之后,可以直接套现成的组件,根据观察,开发效率至少提高50%。
  • 设计规范和用户体验得到了统一,减少用户使用的学习成本。

3.0时代:TypeScript

很快又过了一年(19年),随着时间的推移,项目的功能慢慢积累递增,业务流程越发复杂,加上开发人员的流动,很多功能的逻辑已经不是三言两语就能说清楚。新接手或者临时帮忙的同事都会遇到一个很头痛的问题,这段代码、这些变量和对象要怎样修改,需要深入查询上下文,才能比较清楚的了解到整体的面貌,但这个过程需要耗费很多的时间。于是,找到了TypeScript,提高代码的可读性和可维护性。

TypeScript

个人觉得TypeScript的好处有:

  • 静态类型标记,配合工作流/IDE进行类型检测
  • IDE进行语法提示
  • 方便重构和拓展

当然,天下没有免费的午餐,要获得这些好处,就要付出其他成本:

  • TypeScript的学习成本
  • 新功能的首次开发时间增加,额外的时间主要在声明各种接口、类型等
  • 开发过程中的心智成本,毕竟TypeScript不是真正的静态类型语言,有时要仔细区分哪些代码是标记,哪些是真正被编译出来成为JavaScript
  • JavaScript本身一些比较灵活的用法无法使用或者需要做更多的声明标记才能使用(具体场景可以看看这里TypeScript小状况之遍历对象属性
  • 一些本身没有对TypeScript支持的外部库,引入进来要么anyscript(但有违初衷),要么还要给这个库写d.ts(当然在现在2021年这种情况好转不少,但是当年可以分分钟让人裂开)

但是,很快就发现,事情并没有那么简单。

当我们在Vue 2上面尝试使用TypeScript的时候,并没有那么顺利,因为Vue 2开发的时候,并没有考虑到TypeScript,所以开发者需要使用很迂回的方式,这使得开发效率大幅降低到一个很难接受的水平,我们尝试了2个功能,平均增加25-50%的工作量。

React

这时,我们把目光投向了React。

相对于Vue 2,React在使用TypeScript上支持得更好,开发起来更加顺畅。与此同时也带来了新问题,同一个项目使用了Vue 2的情况下,怎样可以同时使用另一个框架React呢?

当时我们考虑到时间比较紧迫,使用了一个比较直接的方式————iframe。整体项目以及大部分的功能都是使用Vue 2,新功能则在新的单独项目中使用React,并开发了一套基于postMessage的bridge,供主页面和iframe进行通信(iframe路由变化、页面加载、滚动等事件)。

基于React的UI库

同时,我们需要把之前基于Vue 2的UI库,开发一个支持TypeScript的React版。得益于之前的UI库开发经验,这次开发React版的过程更顺利,虽然一开始团队内很多同学对React都不是很熟悉,但是一边开发业务,一边补全UI库组件的过程中,也很快上手。

4.0时代:微前端

不知不觉,我们的后台管理系统在2020年已经到了接手后的第4个年头,这个系统已经成为了一个拥有25个功能模块、72个子功能模块大型项目。

痛点

随着项目的持续,渐渐的我们遇到了一些痛点:

  • 项目包含的功能复杂繁多,修改某个功能都需要整体打包构建,以及测试回归,牵一发动全身。
  • 多人同时开发的时候,经常需要进行代码合并。
  • 代码体积越来越大,构建和发布耗时变长,影响开发效率。
  • 项目经过长期维护和迭代,当年选择的技术栈优势不再,反而成为了历史包袱,新功能却因此不能选择更适合业务场景的技术,只能沿用原有的;而整个项目使用新技术栈则需要整体重构,代价高昂。
  • 某些较常用的功能,外部系统需要使用时,只能把代码复制粘贴一份,并且后续维护两份代码。

解决方案

偶然之间,遇到了微前端框架,仔细研究发现,这正好能解决我们的痛点。

价值

  • 技术栈无关(父子应用之间、子应用之间都可以采用不同的技术栈)
  • 应用独立性(各应用之间可以是相互独立的运行时,独立的代码仓库,独立的构建/发布流程,使得开发和部署互不干扰,同时也可以使得应用可以更好的复用)
  • 渐进式升级(各应用可以单独进行技术升级迭代,升级过程更加平滑可控)

项目结构

image.png

实施规划

  • 完成基础设施的前置工作
    • 封装贴合业务的微前端框架(包括路由支持、应用通讯模块)
    • UI库支持自定义前缀(不同应用可能使用不同版本的UI库)
    • 工作流改造支持微前端项目
  • 项目父应用接入微前端
  • 子应用接入微前端
    • 新功能直接开发为微前端子应用
    • 老功能在新需求涉及时果断进行改造
    • 在资源/时间允许下,适时对老功能进行改造

由于业务需求紧迫,没有一整段时间去进行改造,所以采用分阶段的形式进行,最终在五个阶段,历时2个季度完成微前端改造。

现实收益

  • 无论是项目构建,还是多人开发的代码合并,都让开发效率得到提高。
  • 降低了因为疏忽导致项目之间相互影响和依赖的情况,质量获得提升,测试回归的耗时也减少了。
  • 原来使用React的功能和Vue的父应用,需要用iframe方案解决的,可以直接上微前端,页面加载性能获得优化。
  • 升级新版本的技术栈或者其他技术栈的障碍没了,各功能模块也可以完全根据业务需要或者技术趋势去选择,不用绑在一棵树上吊死,技术迭代升级更加平滑
  • 子应用可以单独访问,也可以同时被不同的父应用所引入。

无巧不成书,正好不久我们要把这个后台管理系统,按用户角色拆分成2个项目,里面共用的一些基础功能,在改造成微前端子应用之后,能顺利的被两个项目所使用。

未来规划

考虑到后台管理系统本身逻辑和页面UI的相似性,后面会往低代码的方向去走,节约业务开发的工作量,多做其他更有价值和意义的事情。