一、背景
效率工程
随着业务的发展,组织规模的扩大,越来越多的企业开始意识到协作效率对于企业团队的重要性,甚至是决定其在某个行业竞争中突围的关键,是企业长久生存的根本。
得物效率工程运用产品、技术、数据等手段,全面提升公司的效率。在管理效率、协同效率、跨团队沟通效率、产研协作效率、办公效率等各方面持续探索,高效驱动公司发展。
效率工程的业务场景
上面提到,效率工程为提升企业协作效率而生,因此会面临大量中后台应用场景。
这些中后台应用体现为「PC 站点、H5 站点、飞书应用、特定机器环境」等,面向所有内部员工和部分外部用户。
在面向多类型用户和使用场景等条件下,效率工程技术产品在稳定性、体验、扩展性等方面面临的挑战非常多。
效率工程面临的问题
效率工程主要的业务形态是「PC 站点的大型中后台应用」,此类应用的布局大多数是这样的:
图片
针对这类场景,有此类产品研发经验的同学,对其面对的问题也会比较熟悉:
- 依赖管理方面。非 monorepo 类仓库下,对于只有一个 package.json 对依赖管理,底层依赖如 antd 等版本升级困难,因为回归成本很高。
a.个别底层依赖的升级是难以避免的,尤其是涉及稳定性、可维护性、用户体验方面,在某个节点会爆发问题影响线上
- 代码耦合度方面。微前端下,如果没有做好抽象,基座和子应用的代码耦合度容易偏高。
- 基座通常包括:Layout、权限控制等通用模块难免的,在基座中可能包括对特定页面的处理逻辑,这里不再举例
- 业务投放成本方面。有些业务的内容区非常适合投放到多个平台,但通常情况下中后台应用代码的布局和内容部分是强耦合的。单独将内容区域投放到外部平台,要一个个处理,成本很高。
- 比如某个重报表类平台,其报表展示能力能否应用在更多平台上,其投放能力是最重要的影响因素
经过调研后,我们引入微应用来解决目前遇到的问题:
微应用
一个基于“monorepo & 微前端 & 基座与业务分离”的、包括“文档 & 工具”的一套体系化降低研发成本和提升用户体验的技术产品。
这是面向得物效率工程业务场景下,我们对微应用的定义。
系统案例:得物学习平台
得物效率工程的学习平台,是面向得物员工、劳务人员、鉴别师、客服等人群的大型中后台应用,产品形态是 PC / H5 / 飞书应用等。是非常典型的适用于「微应用」推进的项目。
图片
依赖管理方面
学习平台原来是非 monorepo 结构,只用一个 package.json 做依赖管理,底层依赖 antd 等的版本极难更新,很难享受到最新版本的快乐。
代码耦合度方面
学习平台 Layout 和各个页面内容部分代码是强耦合的,Layout 中也有部分页面的业务逻辑。
业务投放成本方面
学习平台的多个页面对外投放是整体性投放,需要对 Layout 做特殊处理、权限特殊处理等方式处理后,才能开始投放,投放成本高,而且投放方案不通用。
二、问题分析
Why:为什么做?为什么这样做?
- 中后台应用越来越臃肿已成为共识
- 中后台需要在功能越来越多的情况下,轻量化地迭代
- monorepo 配合微前端,是中后台应用轻量化迭代的有效方案
Who: 用户是谁?
- 业务前端:能够快速理解迁移方案、低成本使用配套工具完成迁移、有充分的 Q/A 文档介绍
- Leader:能够通过看板等产品、结合指标,快速判断迁移后的工程质量,在长期维护状态下保证工程质量不快速下降
What:做什么?
- 最佳实践文档:面向业务前端,要求通俗易懂,业务前端可以在 0.5D 内快速理解整个方案
- 迁移工具:提供一个工具,帮助开发者快速完成迁移
- 巡检看板:查看各类指标,如依赖版本是否过期、公共模块位置是否合理等
When:什么时候做?
- 一个中后台项目子应用超过 X 个,感官越来越臃肿的情况下,可以考虑做微应用化了
- 想在中后台项目前期打好基础,便于后续迭代提效,可以考虑使用微应用了
Where:在哪里做?
- 解释:很显然这不是在说物理位置,在研发流程中,这个工具该处于什么位置
- 迁移中:在业务开发者本机执行迁移动作、飞书文档完成背景介绍
- 迁移后:有在线的巡检平台可以:执行巡检、查看巡检报告
How:如何做?
- 要同时进行 monorepo 化和微前端化,工作量大、操作复杂、稳定性保障难度大
- 第 1 步:以 1 个项目试点,跑通流程、输出“最佳实践(初版)”、输出“迁移工具(初版)”
- 第 2 步:以 1 个项目验证全套方案,输出“最佳实践(修正版)”、输出“迁移工具(修正版)”
- 第 3 步:以 1 个项目完成全套方案,输出“最佳实践(完整版)”、输出“迁移工具(完整版)”
- 第 4 步:更多项目接入
三、明确目标
根据 SMART 原则,我们制定了如下目标(时间限制在 3 个月内):
1. 降低微应用化迁移成本,中大型应用的微应用化迁移耗时降低 30%
耗时降低计算公式:1 - (有 SOP 时微应用化迁移估时 / 无 SOP 时微应用化迁移估时)
2. 降低学习平台维护成本,管理端和学员端公共依赖升级时的测试耗时降低 50%
耗时降低计算公式:1 - (微应用化后的测试估时 / 微应用化前的测试估时)
四、推进方案
经过以上分析,我们的推进方案在「输出、里程碑、技术架构、测试方案、效果预估」等方面进行了确认。
输出
1. 面向业务开发者
a.《效率前端微应用最佳实践》文档:帮助业务开发者可以在 0.5D 理解迁移所需的各类背景
b.「微应用迁移技术产品 monopower」:帮助业务开发者完成应用 monorepo 化过程 90% 的工作量
2. 面向 Leader
a.「在线巡检能力和报告」:帮助 Leader 查看项目完成微应用迁移后,工程质量是如何的,这里包括了一系列的指标
里程碑
图片
如上图,里程碑整体分为 2 个阶段:
第一阶段,通过业务的少量落地完成方案验证,侧重在验证
第 1 步:以 1 个项目试点,跑通流程、输出“最佳实践(初版)”、输出“迁移工具(初版)”,落地 1 ~ 2 个页面
第 2 步:以 1 个项目验证全套方案,输出“最佳实践(修正版)”、输出“迁移工具(修正版)”,落地 3 ~ 10 个页面
第二阶段,业务全量迁移,侧重在业务落地
以 1 个项目完成全套方案,输出“最佳实践(完整版)”、输出“迁移工具(完整版)”,落地该应用全部页面
技术架构
1. 迪米特法则
即最小知识原则,在 SOLID 设计原则中符合 「Single,单一职责;Open-Close:开闭原则」的思想。
我们在考虑微应用技术架构所具备的特征时,更注重简单、可靠、闭环,也就是迪米特法则。
简单:输出的技术产品和文档,需要面向真正用户,易于理解,使用门槛低
可靠性:业内微前端产品(qiankun / wujie / micro-app / ...)对比,各自的优缺点,是否满足业务需求
闭环:当项目进行微应用化后,定时巡检和告警会触发运行,定期扫描工程质量并通知到相关方
2. 整体架构
图中绿色区域是需要开发的产品或文档。
图片
整体架构包括以下核心模块:
a.新增微应用仓库
不在老仓库进行微应用化改造,保证稳定性。
b.monopower cli/server
i.一键改造非 monorepo 项目为 monorepo 项目
图片
ii.扫描项目质量,并输出报告和告警
图片
c.微应用迁移最佳实践文档
3. 一键 monorepo 化
转换过程
- 对原工程做「基于 AST 或正则」的依赖分析
- 调整目录结构为 monorepo
- 对新工程中代码做「基于 AST 或正则」的引用路径修正
比如,原工程中有 import utils from '@/utils',新工程可能需要变为 import utils from '@monorepo/utils'
图片
技术实现
a.对原工程做依赖解析后,会生成包含依赖树的 json 文件存储在本地
b.基于 json 文件 和 monorepo 结构规范,生成新的 monorepo 化的工程结构
c.基于 json 文件和 monorepo 结构规范,对新的 monorepo 化的工程中的引用路径做修正
图片
多次 monorepo 化
由于学习平台的微应用化持续近 3 个月,期间会经历多次迭代。
比如 A/B/C 3 个页面是待微应用化的页面,用 3 个迭代分别对 A/B/C 3 个页面进行微应用化。
那么,A 页面上线后,假如第二个迭代,原仓库依然需要对 A 页面修改,就意味着,第二个迭代要同时上线 A/B 页面。
为了减少回归测试成本,我们用 monopower transfer 做了一个转换后的 diff 展示,如果 A 页面在两次迭代被进行了两次 transfer,且 diff 没有变化,就不需要回归测试。
测试方案
1. 两个方案
a. 以单个路由为粒度,每次全量切换该路由的流量到微应用版本 b. 以整个工程为粒度,按照人群/流量分布为维度,定向灰度到微应用版本
2. 选定方案
最终我们用第一个测试方案。原因如下:
a. 学习平台是微应用推进的第一个验证型项目,短时间内全量完成改造的难度太大
b. 以单个路由为粒度,能够逐步修复问题,验证整体方案的可行性
3. 应用效果
使用第一个方案,在整个微应用落地过程中是比较顺利的,平稳地将近 40 个页面逐批次切换到微应用模式。
这里也频繁用到了「推进方案 -- 技术架构 -- 一键 monorepo 化」中提到的“多次 monorepo 化”,利用 monopower transfer 的 diff 结果,来减少回归测试成本。
效果评估
1. 学习平台改造前后的工程结构对比
改造前:
图片
改造后:
图片
2. 迁移前
系统自检:
图片
3. 迁移中
迁移步骤:
i.安装命令行 monopower
ii.在当前项目执行 monopower transfer,执行 monorepo 化
iii.逐个页面测试
图片
正向依赖分析:
比如入口文件 index.tsx,可以基于该入口文件做依赖树的可视化分析
图片
反向依赖分析:
用于分析某个文件被哪些文件引用,用于分析该文件的重要性等
图片
4. 迁移后
定期巡检,输出巡检报告,包括且不限于「工程化配置、代码质量、公共依赖引用、依赖收敛、稳定性、性能、用户体验」等分析结果。
巡检工具内部,可以结合静态文件扫描和运行时模拟,对当前项目做全方位扫描,当然侧重在微应用方面的健康度。
五、目标达成情况
上文中提到了「微应用」推进的目标,这里分开演示效果。
目标 1:降低微应用化迁移成本,中大型的微应用化迁移耗时降低 30%
耗时降低计算公式:1 - (有 SOP 时微应用化迁移估时 / 无 SOP 时微应用化迁移估时)
改造前
图片
用 monopower transfer 对学习平台进行 monorepo 化改造:
图片
图片
改造后
图片
目标 2:降低学习平台维护成本,管理端和学员端公共依赖升级时的测试耗时降低 50%
耗时降低计算公式:1 - (微应用化后的测试估时 / 微应用化前的测试估时)
很显然,这是利用了 monorepo 类工程的天然优势:依赖隔离。
图片
学习平台可以针对管理端和学员端做依赖隔离,从而可以单独升级学员端、管理端业务的底层依赖。
六、推进的经验教训
变与不变
上述推进方案确认后,剩下的就是根据各个里程碑完成对应进度即可,因此在推进过程中,没有遇到「进度」方面的问题。
当然在推进途中,随时会面临实际的技术问题、人员调整、业务压力等,除了保持足够的心理准备外,在“技术调研”阶段,为关键链路做好多个方案对比和意外状况的预案尤为重要。
比如,在微前端选型中,社区中有诸多方案可选(iframe / qiankun / wujie / micro-app 等),在初期拟定某个微前端方案后,如果中途遇到难以解决的问题,就需要及时复盘、调整到备选方案。
备选方案也要做足功课,这是我们在推进微应用落地过程中的重要经验
Babel在实际应用中的劣势
在上文介绍「推进方案 - 技术架构- 一键 monorepo 化」时,我们提到了: 在对原工程做 monorepo 化时,需要对原工程进行“依赖解析”和“代码引用路径修正”。其中专门强调了「基于 AST 或正则」。
图片
图片
最开始,我们是基于 Babel 的 AST 解析能力,对工程做「依赖解析和代码转换」的。
但实践过程中发现了 2 个问题:
速度慢
对于效率工程的大型中后台应用,代码规模是庞大的,基于 Babel 做一次 AST 解析,尤其是再配合外部封装的 DFS 类算法框架,进行一次全量解析的耗时有时会持续 10min 以上,这和我们原来的期待(30s 以内)是不相符的。
最初,我们只是对外部封装的 DFS 类算法框架做了时间复杂度上的优化(如加缓存、转为 BFS 可中断的方式等),效果并不明显,根源还是 Babel 的 AST 解析性能瓶颈。
不正确的新代码
对源码做 AST 插件中的节点修改后,生成的新代码,会修改额外的代码,比如 ts 类型声明
比如,源码中的:
const stringList: string[] = []
const stringList:any[] = []
原因也基本明确,Babel 的插件配置不够合理,但调整成本还是很高的,我们对各类配置进行过尝试,不是很理想。
最终,我们选择了看起来最笨拙,却是性能最好的办法--“正则匹配字符串”来帮助进行依赖解析。
这是部分代码截图(正则是用 GPT 生成的,很棒,辅以人工检查即可)。
图片
团队锻炼
这部分其实是团队管理和项目管理部分了,如果推进人是比较资深的同学是能很快地完成中大型项目的核心难点工作的,但也有不少同学有成长的意愿以及完成挑战的能力。
那负责推进的同学,就要学会拆解、放手,让有意愿有潜力的同学多多承担重要工作,同时把控风险,保证项目的顺利推进。
很荣幸,这个项目在推进的 3 个月内,涌现了多位成长明显的同学,在整个项目高质量完成的结果上,贡献了自己的力量,而且很多问题的发现、解决、通用化方案输出是这些同学主动推动的。
推进能力模型
值得思考的是,以效率前端微应用推进为例,成功推进一个中大型项目,需要具备怎样的能力和工作方式?
下图能力模型是我比较喜欢参考的:
图片
基于这个能力模型,衍生出的比如:主动性、技术储备、任务分解等各类能力都是可以纳入这个模型参考的。
以下是上述能力模型在具体事务上的工作技巧实践:
- 闭环式推进
- 工作四象限
七、技术之外
本文介绍的技术方案,是效率前端微应用推进的初期设计的,推进 3 个月以来,中途经历了各种各样的困难,也有额外的技术小项被纳入微应用推进方案,但整体的方向没有大的变化。
除了技术方面,我有个心得:“推进的同学,需要有良好的心理素质,并能为自己寻找资源”。
良好的心理素质
「Everything is under control」,我想这是设计技术方案的同学需要慢慢具备的心理素质。
在推进过程中,你对遇到的困难是否有心理准备?比如技术方案被挑战、研发体验变化带来的反弹、回滚难度是否都考虑过。“出现各类问题是很正常的”,是我在推进任何项目都有的心理准备。
为自己寻找资源
在各方对推进项目价值没有太大异议的前提下,推进的同学需要假设任何人包括 Leader 对你需要的帮助是完全不了解的,此时,你需要作为需求方向各个具备资源或者能够调动资源的人寻求合理的帮助。
八、后续:深水区之前端微服务化
本文从背景出发,详细介绍了效率前端微应用推进初期设定的技术方案。在推进的 3 个月中,除了完成上述工作外,有多个很重要的技术小项、人员陆续加入。
在下一阶段,得物效率前端微应用的推进将重点关注业务微服务化能力的建设。
微服务化在后端领域已经讲了很久,在前端领域通常大家提到的是微前端,但本文中提到的「前端微服务化」更侧重业务的多端投放能力。
比如,某个中后台应用的报表能力很强,在其他平台上,想接入这些报表的话,有几个方式可以做:
- 该中后台应用做对外投放能力改造,成本与该应用本身复杂度相关,投放后,方案不具备通用性
- 该中后台应用采用微服务化能力提升,提升成本极低(比如引入一个微服务化增强脚本即可),子页面中的报表即可独立投放到其他平台
后续要推进的即是第二个方案类似的方向,这是部分实现思路:
图片
在业务场景中,如果能够做到「布局 与 内容」的松耦合,对于业务本身的多场景接入大有益处,这也是「微应用」推进面临的一个深水区,值得重度投入,后续有不错进展的话,我们会及时分享。