一、前言
毕业的第一份工作一直在做tob系统,具体做的业务是营销这块,tob系统通常都业务复杂,工程庞大,作为一名前端开发,在前端业务开发中自热也遇到了不少问题??
二、背景
简单说下背景,大家可以思考下,自己做的业务里面有没有遇到如下类似问题?:
一条业务线或者一条产品线下往往包括多个工程,举个?:
比如营销业务线,会包括运营页面搭建系统、运营策略搭建系统、资源管理系统(CMS)、用户标签画像系统等等…
工程之间不仅在业务上,在代码层面也紧密相关。工程之前多少存在一些公用模块,比如营销业务线中每个系统都在切换子系统菜单、人群标签、跳转设置等; 一处业务修改,就需要在多个工程的相同组件做相同改造,维护成本高;此外改造完都需要走一遍部署,特别是在交付场景下,重新上线部署的成本更高?
简单示意图如下?
三、现状分析
四、需求
一次开发、一次部署、多处应用?
(注:widget:把一个公共模块称之为一个widget)
五、常见解决方案
大家这时候通常会想到iframe、npm等如下方案?:(以上几种方式适用于不同的使用场景,也可以组合一起使用)
- iframe
- 实现
- 把公共模块抽离为独立的页面,用iframe形式嵌入
- 缺点
- 这里就不说了
- 实现
- npm包
- 实现
- 把公共模块抽离为独立的工程,打包为npm包,各工程下载依赖npm包,实现代码复用
- 缺点
- 在公共仓库改造完后,需要更新npm包,走npm包发布流程
- npm包更新之后,需要在各业务工程升级npm包,部署上线
- 调试时,npm包代码已压缩,定位问题困难,且需要到公共模块修改才行
- 实现
- git subtree/git submodule
- 实现
- 可以实现一个仓库作为其他仓库的子仓库,把公共模块抽离为子仓库,各工程引入,实现代码复用
- 缺点
- 在公共仓库改造完后,需要在各业务工程拉取最新代码,部署上线
- 实现
总结如下:
iframe交互不友好,其他两者停留在代码复用层面,无法满足需求?
六、实践方案
结合 git subtree 和微前端思想,探索出了一个 utils on subtree;business on widget 实践总结?
什么意思❓
把基本不会变化的工具放到 subtree,利用 subtree 上面的工具去动态加载会变业务组件(如下图),这样一来就解决了多工程公共模块的痛点。再将 subtree 抽象为 sdk,以更友好的方式管理多工程公共模块
具体实现?
将公共模块抽离到公共工程,每个模块打包成一个umd bundle,再用sdk在具体业务工程承接公共模块,如下图?
sdk提供的能力?
渲染组件,承接组件的事件、props、slot等,我们的技术栈都是vue,所以只支持vue,使用如下:
<template>
<widget-render src="widget地址" :name="name" @logout-click="handleLogoutClick" >
<template slot="xxx">
<div>xxx</div>
</template>
</widget-render>
</template>
<script>
import { WidgetRender, EventCenter } from "widget-sdk"
export default {
components: {
WidgetRender
},
data() {
return {
name: 'widget-sdk'
}
},
methods: {
handleLogoutClick() {
console.log('触发退出登录按钮')
},
},
mounted() {
const bus = new EventCenter('namescope')
bus.emit('event-name')
}
}
</script>
复制代码
sdk具体实现见?
github:github.com/zxyue25/wid…
npm:www.npmjs.com/package/wid…
七、可发展方向
- 本篇文章讨论的解决方案可抽离为通用解决方案,如下?
这时候可以提供一个公共服务脚手架,提供快速搭建公共工程的能力
- 与webpack的联邦模块有类似的地方,可结合探索
- 公共模块可从业务公共模块拓展为通用公共模块,比如一个团队/BU下 tob系统每个工程的表格势必都会封装一层,提供一个封装好的table供团队/BU使用,可做到UI&交互统一,贴一张我们把各个系统的通用模块都规范为统一UI&交互的图,布局、表格上的搜索表单、表格、面包屑、菜单、错误页等,各个系统都是统一的,且UI/交互升级时,修改通用公共模块即可?