时间:2021-08-27 09:59:23 | 栏目:vue | 点击:次
由于之前的数据库防火墙产品与数据库审计产品使用的是同一套代码,随着两个产品功能的差异越来越大,代码的冗余度和偶合度越来越高,为了便于后期维护以及添加新功能,所以基于原来的项目代码,进行了代码结构拆分。
注意:本次拆分只拆分了可以拆分的部分,有的模块例如:规则、关于我们,是没有进行拆分的,一是有的模块很简单,没必要拆分;二是有的模块原先写得代码偶合太严重,无法拆分,如果要拆分,需要花费大量精力去梳理代码,同时还要后端配合拆分。
将此次代码拆分方案记录下来,便于后来的开发人员快速熟悉项目结构。
项目拆分前,区分数审和防火墙功能的流程如上图所示。
访问系统时,先加载入口文件 main.js,然后加载登录页 login.vue,加载登录页的同时获取产品模式并保存到 session.storage.platformType 中,接着用户登录系统进入具体页面,该页面同时包含了数审和防火墙的功能,根据 session.storage.platformType 保存的值来判断,具体显示哪个功能。
项目拆分前的目录结构如上图所示。
该目录结构是初始化一个 Vue 项目时的基本目录,根据目录结构,基本上看不出该项目包含了两个不同的产品,也不知道不同产品模式下会加载哪一部分文件,结构不清晰。
通过分析,可以发现当前的系统流程和目录结构是存在很多问题的,大概总结下:
项目拆分后,区分数审和防火墙功能的流程如上图所示。
访问系统时,先加载入口文件 main.js,该文件中写了路由拦截相关的逻辑,在路由拦截时,如果没有产品模式,则要先获取产品模式,否则会被拦截,进不去系统。获取产品模式后,根据当前产品模式,会注册对应的登录页、路由配置、接口请求等。当注册完毕后,每次访问具体的页面,都应该是独立的模块了。
项目拆分后的目录结构如上两个图所示。
该目录结构经过拆分,已经可以清晰地看到不同产品之间分离出来的文件了,从入口文件开始,经过路由拦截后,会加载指定的登录页,然后把对应产品需要的文件合并到公共文件中。比如:http 请求、路由配置等。最终结果,程序只会把需要的文件加载进去。
经过重新设计,解决了当前项目存在的一些问题:
/** * @Name: main.js * @Author: cqfeng * @Description: 项目入口 js 文件 * @MainFunction: 引入和注册一些全局资源 **/ //...省略的代码... // 路由拦截,使用全局导航守卫beforeEach router.beforeEach(async (to, from, next) => { // 如果没有产品模式,先获取产品模式 if (!store.state.productMode.productMode) { await store.dispatch('productMode/SET_PRODUCT_MODE'); } //...省略的代码...
/** * @Name: product-mode.js * @Author: cqfeng * @Description: 产品模式相关逻辑处理文件 * @MainFunction: 保存当前产品模式,根据不同产品模式配置 产品登录页、http 请求 等资源 **/ import Vue from 'vue'; import portService from '@/assets/js/service/http/http'; // axios请求 import router from '@/router/index'; // 默认路由配置,动态路由配置 import httpAAS from '@/assets/js/service/http/http-aas'; // 数审独有的 http 请求 import httpFW from '@/assets/js/service/http/http-fw'; // 防火墙独有的 http 请求 import globalConstant from '@/assets/js/const/global-constant'; // 项目全局常量 export default { namespaced: true, state: { productMode: '', // 产品模式,进入系统或刷新页面时获取 }, mutations: { // 修改产品模式 changeProductMode: function (state, value) { state.productMode = value; }, }, actions: { async SET_PRODUCT_MODE({ commit, state }) { let res = await portService.getProductMode(); if (res.data.code === 0) { commit('changeProductMode', res.data.data.productMode); } // 如果是数审产品 if (state.productMode === globalConstant.COMMON.AAS) { // 设置产品登录页 router.addRoutes([ { path: '/login', name: 'login', component: resolve => { require(['@/views/login.vue'], resolve); }, } ]); // 合并 http 请求,挂载到 Vue 原型上 Vue.prototype.portService = Object.assign(portService, httpAAS); } // 如果是防火墙产品 else if (state.productMode === globalConstant.COMMON.DBSG) { // 设置产品登录页 router.addRoutes([ { path: '/login', name: 'login', component: resolve => { require(['@/views/views-fw/login.vue'], resolve); }, } ]); // 合并 http 请求,挂载到 Vue 原型上 Vue.prototype.portService = Object.assign(portService, httpFW); } } } };
经过拆分,数审和防火墙的代码目录已经算是基本分开了,这个过程花费的力气也很大,也引发了我的一些思考,一套代码多个项目的这种方案是否算好的方案,还有没有其他更好的方案。如果项目一开始,就按照一套代码多个项目的设计来开发,会不会后期的维护成本会低一些?这些问题我也没有答案,希望后来者能够继承历史经验,更好地开发出优秀的项目。
起初设计拆分方案的时候,有两种方案,一种是通过获取产品模式动态改变当前产品功能,一种是在打包时通过打包参数打包指定产品包。最终的方案是选择第一种。但是,在这个过程中也参考了一些网上的实现方案,这里列出来方便以后需要用到进行参考。