为什么选微前端?
公司有 5 个前端项目,都是不同时期、不同团队做的,技术栈也不一样。有 React、有 Vue、还有老项目用 jQuery。
老板想整合成一个系统,让用户在一个页面里就能访问所有功能。如果重写,成本太高。如果用 iframe,体验太差。最后选了微前端,用 qiankun 做框架。
第一个坑:样式隔离
qiankun 的样式隔离有两种:Shadow DOM 和 Scoped CSS。我们一开始用 Shadow DOM,发现很多第三方库的样式不生效。
比如 Ant Design,它的样式是全局的,在 Shadow DOM 里就显示不正常。后来改成 Scoped CSS,给每个子应用的样式加前缀,才解决了问题。
但 Scoped CSS 也有问题,就是样式前缀会影响性能。每个样式规则都要处理,子应用多了,性能就下来了。
第二个坑:路由冲突
主应用和子应用都用 React Router,路由就冲突了。主应用的路由是 /,子应用的路由也是 /,访问子应用的时候,主应用的路由也会匹配。
我们用了 activeRule 来区分,但有时候还是会有问题。特别是子应用内部跳转的时候,主应用的路由也会响应。
后来统一了路由规范,主应用用 /main/*,子应用用 /app1/*、/app2/* 这样的格式,才避免了冲突。
第三个坑:状态共享
主应用和子应用之间要共享状态,比如用户信息、主题设置。qiankun 提供了 initGlobalState,但用起来很麻烦。
每个子应用都要监听状态变化,还要处理状态同步。如果子应用很多,状态管理就乱套了。
我们最后用了 EventBus,主应用发事件,子应用监听。虽然简单粗暴,但至少能工作。
第四个坑:资源加载
子应用的资源加载是个大问题。qiankun 要求子应用把资源路径改成相对路径,但很多项目用的是绝对路径。
我们用了 __webpack_public_path__ 动态设置,但有些第三方库不支持,还是会有问题。
更麻烦的是,子应用的资源如果很大,加载就很慢。我们做了代码分割和懒加载,但还是不够。
第五个坑:开发体验
微前端的开发体验很差。本地开发要启动主应用和所有子应用,启动一次要等好几分钟。
调试也很麻烦,子应用的错误堆栈不完整,很难定位问题。热更新也不稳定,经常要手动刷新。
我们做了个开发工具,一键启动所有应用,但还是不够方便。
第六个坑:版本管理
主应用和子应用是独立部署的,版本管理就复杂了。主应用更新了,子应用可能还没更新,就会有兼容性问题。
我们定了版本规范,主应用和子应用要同步更新。但实际操作中,还是经常出问题。
我们是怎么解决的?
样式隔离
统一用 Scoped CSS,给每个子应用分配唯一的前缀。虽然性能有影响,但至少能工作。
路由管理
统一路由规范,主应用和子应用用不同的路径前缀。路由跳转都用主应用的路由,子应用内部跳转也要通知主应用。
状态共享
用 EventBus + 全局状态管理。主应用维护全局状态,子应用通过事件订阅和发布来同步状态。
资源加载
统一资源路径规范,所有资源都用相对路径。做了 CDN 加速和资源预加载,提升加载速度。
如果重新开始
如果重新做一个微前端项目,我会:
- 先评估是否真的需要微前端,能不用就不用
- 如果要用,统一技术栈,至少框架要一样
- 做好路由规划和状态管理方案
- 建立完善的开发工具和部署流程
什么时候该用微前端?
微前端适合这些场景:
- 多个独立团队维护不同的前端项目
- 项目技术栈不同,无法统一
- 需要渐进式迁移老项目
- 项目规模很大,需要拆分
但如果:
- 团队很小,项目也不大
- 技术栈可以统一
- 没有老项目要迁移
那还是用单体应用更省心。
总结
微前端不是银弹,它解决了一些问题,但也带来了新的问题。样式隔离、路由管理、状态共享、资源加载,这些都是要提前考虑的。
如果你们项目也在考虑微前端,建议先评估一下是否真的需要。如果要用,也要做好心理准备,这玩意儿比想象中复杂。
我们的项目用了一年多,虽然问题很多,但至少能工作。如果重新选择,我可能会考虑其他方案,比如模块联邦(Module Federation),或者干脆重写。
评论区