首页技术专题博客目录我的收藏关于与联系

微前端的教训:qiankun 项目踩坑实录

公司要整合多个前端项目,选了 qiankun 做微前端。用了一年多,踩了不少坑。这篇文章记录一下遇到的问题和解决方案,给想用微前端的同学提个醒。

为什么选微前端?

公司有 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),或者干脆重写。

评论区