写点什么

大型前端应用如何做系统融合?

  • 2024-05-28
    北京
  • 本文字数:4425 字

    阅读完需:约 15 分钟

大型前端应用如何做系统融合?

1. 背景介绍

1.1. 业务介绍

A 平台与 B 平台同属于同一系统链路上,前者主要致力于为用户提供注册入驻服务,后者则专注于提供具体业务操作服务。两者皆为运营人员所依赖的在线管理工具。

1.2. 现状分析

目前这两个平台服务于同一业务方,且 B 应用的页面已经 100%嵌入到了 A 应用的平台上,除此以外目前存在系统上及体验上的痛点如下:




所以当时我们考虑既然服务于同一业务方是否能在代码层面上将两个平台进行融合,通过系统的融合来达到优化用户体验以及降本增效的效果呢?

2. 成果展示

平台融合后,主要的优化点体现在以下四方面:

优化前(跳转单个页面白屏时间达 2998ms 左右):


优化后(跳转单个页面白屏时间 800ms 左右):


3. 具体措施

3.1. 方案调研

3.1.1. 部署方式

•部署优化:A 应用前后端合部署,现计划分离前端独立部署;

•资源节约:经行云部署平台调研,拟采用混合部署策略,将 A 应用与 B 应用前端静态资源集中部署于一组容器,以优化资源利用;


3.1.2. 代码仓库整合

•A 应用的三个项目与后端共享一个代码仓库,采用统一的编码标准;而 B 应用则使用独立的代码仓库,需从中分离出前端代码,并确保分离过程不影响现有配置;

3.1.3. 项目框架

•4 个项目的技术选型框架都为 vue2,依赖项略有不同;

3.1.3. 系统权限

•A 应用和 B 应用为 erp 登录;

3.2. 架构设计

为了让用户融合无体验差别,两个平台的用户继续使用各自的域名进行访问,融合后的项目可以自动识别当前环境,加载对应的内容;保证融合前后用户查看的内容是一致的;


3.3. 具体方案

3.3.1. 目录结构设计

针对融合,我们首先考虑的是融合后如何防止文件冲突,减少融合的复杂度,降低出问题的概率。保证两个系统能正常运行;拆分逻辑分以下三个方面:

1.文件拆分与分类

两个系统涉及到几十个文件,经过分析,我们将其拆分成以下几部分内容:【页面文件、公共组件文件、mock 文件、AxPI 接口文件、基础请求封装文件、路由组件文件、Store 文件、公共样式文件、公共方法组件、mainjs 文件、index.html 文件】

2. 结构整合与差异化处理

由于两个项目的结构相似,我们可以针对各个部分进行整合。整体的思路是,对于差异比较大的文件,建立两个独立的文件夹,分别包含系统 A 和系统 B 的内容;然后通过一个 index 文件,识别到当前的运行环境是系统 A 还是系统 B,再分别加载对应的内容;

3. 内容融合与冲突解决

针对差异比较小或者无差异的文件,我们将文件内容进行融合。对于冲突的内容,我们进行了手动修改,并对全局引用部分进行同步修改;

├── root│   ├── mocks│   ├── public│   ├── src│   │   ├── api│   │   │   ├── apiA      // 存储 A 业务请求接口│   │   │   ├── apiB       // 存储 B 业务请求接口│   │   │   ├── apiC         // 存储 C 业务请求接口│   │   │   ├── baseHttp.js   // 封装基础请求│   │   │   ├── ARequest.js   // A业务的公共处理,请求header和响应code码等处理│   │   │   ├── BRequest.js  //  B业务的公共处理,请求header和响应code码等处理│   │   │   ├── CRequest.js   // C业务的公共处理,请求header和响应code码等处理│   │   │   ├── DRequest.js  //  D业务的公共处理,请求header和响应code码等处理│   │   ├── assets│   │   │   ├── icons     // icon内容│   │   ├── common│   │   │   ├── config│   │   │   ├── styles      // 一些公共的样式│   │   ├── components      // 公共组件│   │   ├── directive       // 自定义指令│   │   ├── layout        //公共布局│   │   ├── router│   │   │   ├── a.js   // 对应a应用│   │   │   ├── b.js   // 对应b应用│   │   │   ├── c.js   // 对应c应用│   │   │   ├── index.js│   │   ├── store│   │   │   ├── modules│   │   │   ├── getters.js│   │   │   ├── index.js│   │   ├── utils   │   │   ├── views│   │   │   ├── a    // a 业务文件│   │   │   ├── b    // b 业务文件│   │   │   ├── c    // c 业务文件│   │   ├── main.js│   │   └── App.vue│   ├── env│   ├── package.json
复制代码


3.3.2. 应用类型判断

应用类型判断是我们重要的一环,是我们识别环境的基础,当用户通过不同的域名访问到应用的时候,前端维护一个映射表,不同的域名代表不同的应用;在 main.js 文件中会在第一时间执行判断识别;

let APPLICATION_TYPE = 'a'let host = window.location.host;
// 维护域名列表,包含测试和线上环境const A_HOST = ['a.com','a_pre.com']const B_HOST = [] const C_HOST = []const D_HOST = []
if(A_HOST.includes(host)){ APPLICATION_TYPE = 'a'}else if(B_HOST.includes(host)){ APPLICATION_TYPE = 'b'}else if(C_HOST.includes(host)){ APPLICATION_TYPE = 'c'}else if(D_HOST.includes(host)){ APPLICATION_TYPE = 'd'}// 挂载全局window._APPLICATION_TYPE = APPLICATION_TYPE
复制代码


3.3.3. 路由设计

根据不同的域名获取路由配置,根据路由配置生成路由;系统 A 和系统 B 各自维护一个路由列表;当从后端请求回来路由结构之后,根据不同的应用映射不同的文件内容;其中路由 path 保持不变,compoent 增加前缀(应用类别)找到对应的应用下的组件;

•第一步:前端获取当前域名,确认当前应用

根据全局的 APPLICATION_TYPE 字段识别
复制代码


•第二步:前端维护一个路由列表

let router=[{    path: '/home',    component: Layout,    meta: {  title: '首页', icon: 'el-icon-s-grid', alwaysShow: true },    redirect: '/home',    children: [      {        path: '/home',        component: () => import('@/views/home/index'),        name: 'home',        meta: { title: '首页', icon: ''}      }    ]  }]
复制代码

•第三步:根据当前应用请求后端接口,获取路由配置信息(component 的路径前拼接各个应用的文件名)

let RouterApi={'a':'/api1','b':'/api2','c':'api3'}api.get(RouterApi[APPLICATION_TYPE])component='各个应用文件名'+接口返回路径
复制代码

•第四步:针对在路由信息放置在前端的应用,前端维护一个路由的配置信息表

import dRouter from './d.json'if(APPLICATION_TYPE==='d'){   router=dRouter}
复制代码

•第五步:根据路由配置信息,生成路由结构

•第六步:实例化 Vue 对象

3.3.4. 环境变量设计

环境主要分为以下几种:mock 环境、本地开发环境、测试环境、线上环境

不同的环境对应不同的变量文件,在变量文件中设置每个端需要用到的参数,结合 APPLICATION_TYPE 和变量文件的配置,获取到对应的参数

示例:

# .env.pruduction
# a 业务VUE_APP_A_BASEURL = '' # b 业务VUE_APP_B_BASEURL = ''# c 业务VUE_APP_C_BASEURL = ''# d业务VUE_APP_D_BASEURL = ''
复制代码


3.3.5. 请求设计

1.公共请求的封装

封装基础的公共请求 createHttp.js,各业务基于公共的请求和各自的 code 码,请求参数等信息进行再次封装,然后可以按照业务需求调用;

•基础请求:createHttp.js

•业务公共封装:

a. ARequest.js(A 业务公共参数和 code 码处理)

b. BRequest.js (B 业务公共参数和 code 码处理)

c. CRequest.js(C 业务公共参数和 code 码处理)

d. DRequest.js(D 业务公共参数和 code 码处理)

•业务层调用:

a. api/apiA A 业务接口

b. api/apiB B 业务接口

c. api/apiC C 业务接口

// 公共请求封装  baseHttp.jsexport const createHttp = (baseUrl, successFun = () => {}, errorFun = () => {}, requestInterceptor = () => {}) => {  const http = axios.create({    baseURL: baseUrl,    timeout: 5 * 60 * 1000,    withCredentials: true  })  // http request 拦截器  http.interceptors.request.use(    async config => {      await requestInterceptor(config)      return config    },    err => {      return Promise.reject(err)    }  )  // http response 拦截器  http.interceptors.response.use(successFun, errorFun)  return http}
复制代码


2. 直接调用后端服务请求封装

//A业务基础请求 function requestInterceptor(){    // A系统公共请求参数处理... }function successFn(){    // A系统公共响应结果处理 统一新增}function errorFn(){    // A共异常处理 包括code码等情况}export default createHttp(baseUrl,successFn,errorFn,requestinterceptor)
复制代码


3. 业务接口使用,根据不同的业务划分不同的目录分支

// A业务请求调用ARequest.get(url,{params:data})
复制代码


//B业务请求调用BRequest.post(url,{params:data})
复制代码


3.3.6. 权限和登录

根据应用类型字段 APPLICATION_TYPE,识别不同的环境,请求不同的服务端接口;不同的服务端代表了不同的应用;

针对不同的应用的未登录情况,前端维护多套登录处理逻辑,根据应用类型进行不同的处理逻辑;

3.3.7. 公共函数设计

创建一个公共的 utils 文件夹,针对两个项目中的公共函数进行合并,针对有冲突的函数,进行命名修改,全局引入的部分进行路径和函数的同步修改;

3.3.8. 脚手架配置设计

梳理了两个项目的脚手架配置差异项及各个配置的作用,对配置作了部分的修改和优化,在满足原有的功能情况下不影响正常的项目运行;

3.3.9. Vuex store 设计

store 的整体结构保持不变,在项目引用的地址也保持不变,由于项目中使用 store 的地方较多,保持结构不变能保证改动成本最小,针对两个项目中模块名重复的情况,手动把模块里的内容进行合并;


针对现有的名称重复内容不一样的函数,根据应用类型字段 APPLICATION_TYPE 把两个函数进行融合进行分别处理;

3.3.10. 页面引用设计

•引用方式变更

由于业务需求,应用 A 中嵌套了应用 B 的页面,之前通过 iframe 引用。融合后,页面文件和组件不再隔离,可以直接引入应用 B 的文件和组件;

•后端数据打通

应用 A 的后端服务器上有一些功能,如下载列表,应用 B 项目需要使用时因数据不通难以直接引用。前端融合后,可以在应用 B 中直接引用应用 A 的页面组件,实现业务的顺畅使用。效果如下:

4. 总结

在经历了为期两个月的紧张工作后,我们成功地将两个大型项目进行了深度整合,取得了显著的阶段性成果。通过这一融合过程,我们不仅统一了项目的代码规范和架构,还显著提升了组件的复用率。尽管在这个过程中我们遇到了诸多挑战和曲折,但最终的成果——用户体验的显著提升——使一切努力都显得弥足珍贵。

我们深知,每一个成功的项目背后都有无数次的尝试和优化。在这个过程中,我们不断学习、适应和完善,最终实现了项目的无缝融合。我们相信,这段经历和我们所取得的成果,不仅为我们团队带来了宝贵的经验和教训,也可能为那些正在经历类似挑战的同学提供了一些启示和帮助。


作者:前端研发 高雅薇

来源:京东零售技术 转载请注明来源

发布于: 4 小时前阅读数: 11
用户头像

还未添加个人签名 2024-01-12 加入

京东零售那些事,有品、有调又有料的研发资讯,带你深入了解程序猿的生活和工作。

评论

发布
暂无评论
大型前端应用如何做系统融合?_JavaScript_京东零售技术_InfoQ写作社区