架构所需对部分项目进行重构,理想状态是项目可以拆分、独立开发测试和部署。微前端独立开发部署且于技术栈无关的特点是理想的解决方案。
一,什么是微前端
微前端就是将前端应用拆分为更小、更易于管理的多个应用,通过一个主应用来加载这些子应用。举个例子,某个功能庞大的系统(某团),某团外卖、某团优选、某团骑行等模块若全都处于一个项目中,项目代码量逐渐庞大,项目可维护性难免会降低;微前端可将这些模块单独拆成独立子应用,通过统一入口分别跳转,子应用发布、报错、测试流程仅限于子应用,不会受别的业务影响,同时也不影响别的业务,实现业务解耦。
二,为什么使用微前端
1,微前端优点
1,独立开发部署:不同的微前端应用可以独立开发和部署,不限制技术栈和框架
2,独立运行:每个微应用之间状态隔离,运行时状态不共享
3,易于维护:应用拆分,实现业务解耦
4,技术兼容性:被基座应用加载前,所有子应用已经编译成原生代码输出,所以基座应用可以加载各类技术栈编写的应用;由于拆分后应用体积明显变小,并且每个应用只实现一个业务模块,因此其内聚性更强;另外子应用本身也是完整的应用,所以它可以独立编译、测试和部署;
5,耦合性:由于各个子应用只负责各自的业务模块,所以耦合性很低,非常便于独立开发;
6,扩展性:由于拆分出的应用都是完整的应用,因此专门升级某个功能模块就成为了可能,并且当需要增加模块时,只需要创建一个新应用,并修改基座应用的路由规则即可。
当然,微前端方案也会存在一些缺点:
2,微前端缺点
1,子应用间的资源共享能力较差(某些静态资源需要单独拷贝一份)
2,需要对现有代码进行改造,改造存在成本
子应用之间保持独立,一些公共资源(iconfont等)不共享,子应用间工具函数、通用业务组件等不易共享,可能使得项目整体体积反而变大
三,微前端框架选型
1,微前端实现方案对比
技术方案 | 描述 | 技术栈 | 优点 | 缺点 | 单独构建 / 部署 | 构建速度 | SPA 体验 | 项目侵入性 | 学习成本 | 通信难度 |
iframe | 每个微应用独立开发部署,通过 iframe的方式将这些应用嵌入到父应用系统中 | 无限制 | 1. 技术栈无关,子应用独立构建部署 | 体验差、路由无法记忆、页面适配困难、无法监控、依赖无法复用,兼容性等都具有局限性,资源开销巨大,通信困难 | 支持 | 正常 | 不支持 | 高 | 低 | 高 |
Nginx 路由转发 | 通过Nginx配置实现不同路径映射到不同应用 | 无限制 | 简单、快速、易配置 | 在切换应用时触发发页面刷新,通信不易 | 支持 | 正常 | 不支持 | 正常 | 低 | 高 |
Npm 集成 | 将微应用抽离成包的方式,发布Npm中,由父应用依赖的方式使用,构建时候集成进项目中 | 无限制 | 1. 编译阶段的应用,在项目运行阶段无需加载,体验流畅 | 1. 影响主应用编译速度和打包后的体积 | 不支持 | 慢 | 支持 | 高 | 高 | 正常 |
通用中心路由基座式 | 微应用可以使用不同技术栈;微应用之间完全独立,互不依赖。统一由基座工程进行管理,按照DOM节点的注册、挂载、卸载来完成。 | 无限制 | 子应用独立构建,用户体验好,可控性强,适应快速迭代 | 学习与实现的成本比较高,需要额外处理依赖复用 | 支持 | 正常 | 支持 | 高 | 高 | 正常 |
特定中心路由基座式 | 微应用业务线之间使用相同技术栈;基座工程和微应用可以单独开发单独部署;微应用有能力复用基座工程的公共基建。 | 统一技术栈 | 子应用独立构建,用户体验好,可控性强,适应快速迭代 | 学习与实现的成本比较高,需要额外处理依赖复用 | 支持 | 正常 | 支持 | 高 | 高 | 正常 |
webpack5 模块联邦 | webpack5 模块联邦 去中心模式、脱离基座模式。每个应用是单独部署在各自的服务器,每个应用都可以引用其他应用,也能被其他应用所引用 | 统一技术栈 | 基于webpack5,无需引入新框架,学习成本低,像引入第三方库一样方便,各个应用的资源都可以相互共享应用间松耦合,各应用平行的关系 | 需要升级Webpack5技术栈必须保持一致改造旧项目难度大 | 支持 | 正常 | 支持 | 低 | 低 | 正常 |
常见实现框架:
(1)qiankun乾坤: 蚂蚁金服开发维护,基于 Single-SPA, 提供了更加开箱即用的 API ( single-spa + sandbox + import-html-entry ) 做到了,技术栈无关、并且接入简单
(2)MicroApp:京东出品,一款基于WebComponent的思想,轻量、高效、功能强大的微前端框架
(3)single-spa:微服务化的 JavaScript 前端解决方案 (本身没有处理样式隔离, js 执行隔离) 实现了路由劫持和应用加载
(4)无界:腾讯开发维护,实现预加载,应用保活(类似keep-alive),配置成本低;但是2022年推出,时间太短,缺乏社区打磨
除此持外还有piral,mosaic等框架,综合对比考虑后,选择使用更成熟的蚂蚁qiankun接入项目,原因如下:
(注:截止2023,qiankun官方不支持vite,目前使用qiankun集成vite构建的vue项目需要依赖插件)
· 保证技术栈统一 Vue、微应用之间完全独立,互不影响。
· 友好的“微前端方案“,与技术栈无关接入简单、像iframe一样简单
· 改造成本低,对现有工程侵入度、业务线迁移成本也较低。
· 和原有开发模式基本没有不同,开发人员学习成本较低。
· qiankun 的微前端有4年使用场景以及 Issue 问题解决积累,社区也比较活跃,在踩坑的路上更容易自救~
2,应用搭建
此处搭建按照官网步骤逐步搭建,不赘述,举例几个需要注意的点:
(1)静态资源需要支持跨域,nginx部分配置允许跨域
(2)子应用间互相通信不易过于频繁,若是交互过于频繁,考虑合并为一个子应用
(3)样式隔离,开启沙箱隔离可能会存在样式影响
(4)应用间的icon图标会出现重名情况
(5)子应用打开速度若是过慢,考虑项目进行优化,优先去除多余依赖包,组件按需加载,页面等待loading,其次再考虑打包体积优化、nginx压缩、cdn加速等。(微前端的作用在于拆分,而不是速度)
3,vue中qiankun踩坑
以下是在项目中遇到过的坑点(血泪教训):
(1)微应用入口文件需要导入对应的生命周期bootstrap、mount、unmount
(2)子应用中某个icon图标不显示或者图标出现问题,检查入口文件中是否对图标做过相应配置,在对应改动
(3)此bug困扰了近一周,项目打开就报错
仔细检查配置__POWERED_BY_QIANKUN__ 对应 Render()
入口文件main.js中需要引入public-path.js; 出现此类bug可按照官方文档步骤,仔细检查相关配置
(4)页面报错跨域,检查代理配置,需要添加对应跨域配置
(5)子应用与主应用element样式影响,导致子应用弹框定位至document顶部,如下:
子应用中弹框定位丢失,在子应用实例render生成阶段重新定位弹框到子应用内,解决方法参考 http://t.csdnimg.cn/5XlGh
(6)主子应用间传值,传值数据结构不复杂情况 可以考虑此种方法: 主应用props中定义actions 在子应用中接收并挂载到根节点就可以通过this.$root.parentActions访问此方法并在主应用的全局状态监听onGlobalStateChange即可
如果传值参数较为复杂频繁,主应用初始化加载子应用时将setGlobalState等传递过去,子应用组件中考虑重新封装方法
四,总结与思考
微前端是一种多个团队通过独立发布功能的方式来共同构建现代化 web 应用的技术手段及方法策略。系统可独立拆分为多个独立灵活的小应用,每个应用可以独立开发、独立部署、独立运行,最终在将这些小应用联合到主应用上成为一个完整的应用,而整个过程对用户来说是无感的!
当然,需要明确的点是,微前端并不是万能的,qiankun也不是一个绝对完整的微前端解决方案。在实际运用中,需要注意的点还有很多,改造过程主要目的应该是【改造】,原本的页面交互逻辑应是无需过多更改的。