前言
项目从8月份至今以历时4个月的开发直至落地,算是对我入行一年半的整体总结,如有不足可以指出😄
项目开始前
公司针对实际业务存在多套自研系统,并且每套系统都有独自的登录鉴权逻辑,存在系统间相互调用的情况,本项目需要解决这一个问题并且逐步废弃/迁移/替换老系统的对应功能,简单说就是老系统的功能后续是要复刻进来的.
- 针对以上需求衍生出来的一些问题
- 实际业务模块之间更新发布不能出现,更新业务A会发布业务B的代码的情况
- 各个业务模块之间切换需要是无感的,交互表现需要是一致的
- 解决方案
- 项目采用传统多页面访问逻辑,实际业务模块为 单页面SPA 单独业务占用独立的访问路径。
- 所有项目在实际访问中都存在于同域下所以他们之间的本地数据可以共通(公用token),这样就不需要单点登录
- 项目直接使用 pan神 的 element-admin-template 进行一些修改创建模版代码仓库,直接进入业务开发阶段,新的业务开新的仓库发布到新的路径即可,表现上初期能保持绝对一致
graph TD
登录页-xx.xx.com/login.html --> 工作台-xx.xx.com/nav.html
工作台-xx.xx.com/nav.html --> 业务A模块-xx.xx.com/A
工作台-xx.xx.com/nav.html --> 业务B模块-xx.xx.com/B
工作台-xx.xx.com/nav.html --> 业务C模块-xx.xx.com/C
工作台-xx.xx.com/nav.html --> 业务C模块-xx.xx.com/admin
业务开发中
实际开发中总会遇到一些冗余逻辑(需要偷懒)/项目槽点优化(兼容/访问速度/交互)
基础数据下拉
先对下拉的冗余代码进行分析
- el-option为数组循环结果需要绑定 label 和 value
- 使用下拉时需要 el-select 套 el-option
- 下拉数据需要写请求代码(不管是一次性加载下拉数据或者打开页面再加载下拉数据对于服务器来说都是多余的负担) 以上是现有项目的最终分析如下为现阶段最终解决方案
- 对select组件进行二次封装代码如下(主要实现代码)
- 对于数据处理方案为 懒加载,协调后端的就不讲了,最终实现为前端保留后端提供的key 维护成 store,
- store 暴露对应的 getter,getter方法内置了请求数据的api
- 初始化时store为一堆的空数组
- 实际页面使用计算属性去读取对应的 getter, 第一次读取时会触发 getter的请求api 同时立即返回现有的数据
- 因为缓存机制后续读取对应字段自动返回之前的结果
- 发起的请求返回数据后立即更新state,计算属性会同步更新数据,自此项目运行期间不会再向服务器请求该下拉的数据
一些实现的伪代码
更新的逻辑
stateDiagram-v2
store --> 暴露对应的getter
暴露对应的getter --> 计算属性第一次读取触发更新逻辑
暴露对应的getter --> 计算属性第一次读取返回空数据
暴露对应的getter --> 计算属性非第一次读取vue机制直接取上次缓存数据/不再触发更新逻辑
计算属性第一次读取触发更新逻辑 --> store
在实际项目中使用中的情况显得干净/代码量少
表格的简单封装
这里使用了一定程度的jsx能力,代码已经剔除了公司业务需要的功能保留简单的基础能力,
如上图代码组件中el-table的属性会通过$attrs进行二次转发,这样保持了el-table的基础能力配置,el-table-column 通过循环遍历进行递归渲染,渲染逻辑分为三种情况.情况一存在自定义render方法那么传入render函数交出自定义渲染的能力,情况二不存在子级列直接绑定属性渲染,第三种情况存在子级列绑定属性渲染的同时进入递归渲染子级。
实际业务页面只需要维护对应的列数组信息就能完成所有表格的配置简化大量冗余代码的配置,并且对应的cols参数可以在任意业务直接复用,以下截图为项目中对于表格的优化使用情况对比
cols数据配置化
通用业务布局组件
其实通用的后台项目列表页是高度同质化的页面
- 条件搜索区
- 数据表格展现区
- 分页/合计汇总区 很通用的上中下结构,数据展示对于来说业务需要表格尽可能的占据页面空白的位置并且需要高效的自适应能力,对于开发人员来说页面过多的时候这样就会出现很多冗余代码,所以如下的用业务布局组件就诞生了(伪代码)
如上图暴露了3个具名插槽在实际的列表页只需要写入对应的插槽就能实现简单的布局能力,这里css单独给.zhong实用了flex会自动根据剩余空间占满.box的空间这样就能达到表格高度自适应的效果
如上相同的业务布局组件有多个就不一一赘述了
业务逻辑mixin
公司业务相关的就不多说了依旧用列表页进行举例
以上为列表页常用的代码此时只需要进行职责拆分,进行组合mixin到实际业务代码中就能减少很多冗余代码的编写,一些通用的逻辑方法甚至可以直接进行全局混入
第三方组件包cdn处理
目前针对第三方包进行cdn强缓存处理,专门在公司两地服务器配置了cdn服务器,第三方包资源直接就近取并强缓存,这样我们实际打包出来的代码均为业务代码nginx改为协商缓存有效解决发布新版本的缓存问题,并且相对来说体积小加载快
相同代码如何跨模块共享
开发中遇到 业务A开发的代码逻辑能在业务B中直接复用,如果是单纯的代码拷贝这样跟新维护就很麻烦,当接入老系统功能的时候可能出现好几个项目相互拷贝的问题,至此就诞生了本项目的第一个npm包 专门负责提供公用的业务布局组件的npm包,只需要使用明令行进行批量更新包即可解决代码拷贝的痛点,以此为基础分别总共新增了
- 通用的工具方法包
- 通用的mixin混入包
- 通用组件包(业务逻辑/业务布局/特殊交互组件)
- cdn包(打包时使用,通过包名直接提取cdn地址,方便同步)
自此剩余内容均为业务代码开发,以上线三个系统(主要还是管理系统都是重复的列表页查询/详情页提交表单操作开发很简单,以上内容封装结束基本上午出原型下午就开始等接口) 两个移动端应用
项目产品化
随着项目的上线使用,稳定的功能出产速度,领导对于我们项目组提出了新的要求,就现有后台系统架构的模式需要实现一套sass 或者 可单独业务拆分部署的功能,简单来讲就是有同行想要我们部分后台业务系统,我们要让系统可以拆开卖,卖的模式就是 sass平台或者 提供部署支持
根据以上要求对现有项目代码的npm包进行了调整封装 前端整体开发架构如下图
base包
base包提供项目基础能力分别为
- 通用页面(layout,404,login,layout,home...)
- 通用请求模块(axios拦截器进行基础封装,同时直接内置 用户登录/获取菜单等基础接口)
- 内置状态管理(如页面缓存,菜单收藏,菜单信息,按钮权限数据)
- 内置路由模块(暴露异步加载路由方法实际项目传入对应的组件实例进行动态生成路由)
- 内置鉴权(菜单权限/按钮权限)
- 产品化组件(现今存货的工业用后台系统功能尽量都抄过来,比如表格需要提供高度自动填充屏幕/列允许个性化设置/列设置根据账号记忆/支持快捷键操作等等,表格筛选列管理后端配置实际效果类似于直接配sql(领导总是想法很多😊),其他的还在激烈讨论中后续更新base包统一发布) 综上所述对于 base包 的定义差不多就是,新的业务模块引入 base包调用引导方法能直接运行项目,直接进行全新业务的开发不需要关注基础是如何运作的.
使用base包能有效的解决几个场景
- 公司业务系统拓展能快速进入业务开发不需要使用cli 搭建项目框架
- 在整体业务组件更新时使用npm包更新版本能很好并且快速的进行迭代,一条批量更新包版本的代码就能完成所有业务模块的更新和发布
- 在后续的不管是sass平台化还是提供独立部署均能利用base包更新来给客户提供增量更新,设置可以提供插件包进行定制更新,并且不会影响到其他项目或业务模块
其他的包
- components包主要提供vue组件因为他并不会影响项目运行所以不被整合到base包中
- common包提供重复的逻辑代码mixin 和 通用的工具方法
- cdn包需要将第三方包进行cdn优化减小体积专门提供给打包时使用 可以看到除去base包以外的几个npm包均为不影响项目基础运行代码,只是提供给开发人员简化使用,后续这块的开发构想为,代码偷懒的内容足够多了=> 抽离核心逻辑 => 进入base包成为产品化组件的一部分 => 正式从非核心模块包中移除
总结
以上为我负责的后台系统中非业务内容的整体总结
- 现在对项目做了哪些?
- 第三方包cdn处理使用强缓存
- 业务代码发布在nginx中使用协商缓存解决项目更新后部分机器缓存导致未更新的情况
- 两地工厂服务器,内网拦截,外网就近转发
- 传统多页面 + 业务单页面spa模式 允许业务系统独立发布
- 对于业务代码进行了封装转化为npm包实现了 业务系统之间共享基础逻辑代码(更多时间偷懒摸鱼)
- 对于项目基础代码进行封装转化为npm包 为后续公司卖给同行用作准备(不过好像现在就有公司想要当小白鼠😊)
- 其他的暂时憋不出来字了,感觉后台系统贴合业务的功能就那么些东西没太大难度
- 还有暂时没做的
- 移动端兼容问题解决(开发的移动端app,部分产线员工老手机无法兼容需要想办法搞定的)
- 移动端首屏优化(工厂网络环境比较极端,需要尽可能保证最快加载页面)
- 大领导和产品在做的ui规范(目前还没定稿就先不写样式相关内容了)
- 把vue2改成vue3整体技术栈升级(😊没错就是这么莽)