微前端是什么?

微前端是一种前端开发的架构风格,它将一个完整的前端应用拆分成多个小型的、独立的功能模块,这些模块被称为微前端。每个微前端都可以有自己的代码库、依赖包、自动化测试套件以及Devops流程。它们中的每一个极有可能由一个单独的前端团队负责,并且与其他功能模块相互独立地进行开发、测试和部署,从而提高了开发流程的效率。微前端在平台产品中应用尤为广泛。例如云计算平台中的各个服务可以通过微前端的方式嵌入到云平台前端控制台中。

微前端的优缺点

优点:

  • 独立开发和部署:每个微前端可以由不同的团队负责,团队可以自主决定开发进度和发布时间,无需与其他团队过度协调。比如一个专门负责用户个人中心微前端的团队,可以独立进行功能迭代和发布。
  • 技术栈灵活:不同的微前端可以根据自身需求选择不同的技术栈。例如,一个微前端可以使用 React 框架,另一个可以使用 Vue 框架,这样可以充分利用各种技术的优势。
  • 可扩展性强:能够根据业务需求,方便地添加、删除或更新微前端模块。当业务需要增加新功能时,只需要开发新的微前端并集成到系统中即可。

缺点:

  • 微前端架构本身比单体架构复杂得多。需要设计合理的集成策略来确保各个微前端能够协同工作。
  • 各个团队可能会过度关注自己负责的微前端,而忽视了整体的用户体验和业务流程。
  • 每个微前端都有自己的资源,在初始加载时可能会导致页面加载时间变长。不同微前端之间的交互可能会带来一定的性能损耗。

综合微前端的优缺点可以看出,如果是平台性质的UI或者涉及多个团队合作开发的UI,微前端是比较适合的架构。而对于小型应用与小型团队,单页应用程序可能更加适合。

微前端的实现方式

  • 路由加载独立应用:应用基于路由分离,每条路由加载独立应用(微前端),每个微前端通过API获取外壳页面并渲染到自己的模板中去,从而可以共享外壳所提供的通用功能,如认证、页头、导航栏等。
  • 基于iframe的微前端:将每个微前端嵌入自己的iframe中,由单页应用(SPA)充当容器,SPA协调iframe间的通信。这是一种较老的方法,虽然分离程度较好,但存在安全、数据共享等诸多问题需要解决。
  • Web组件:把每个微前端构建为可独立部署的独立组件(.js文件形式),应用在布局中的占位符处加载和渲染它们,由Web组件告知浏览器何时何地创建组件。不过这种方式下组件体积大,需要捆绑框架版本,要注意性能跟踪。
  • 模块联邦(Module Federation):主要基于一种 “集成契约” 的概念。在构建阶段,各个微前端模块和主应用之间定义好交互的接口和规则,这些就像是它们之间的 “契约”。例如,规定了模块提供哪些公共的函数、变量或者组件,以及主应用如何调用这些内容。这个契约不需要复杂的构建时依赖,只是简单地明确了交互的方式。在运行时,主应用可以根据用户的操作或者业务逻辑,动态地加载不同的微前端模块。
  • NPM包方法:每个微前端作为单独的 NPM 包发布,外壳应用列出并整合这些包。其优点是设置简单,缺点是需要单一依赖版本,且微前端发布依赖外壳发布,可能产生跨团队依赖,阻碍更新。

以下实现的耦合度如下图所示:

开源微前端框架对比

Single-SPA

Github: https://github.com/single-spa/single-spa

Single-SPA是一个比较早期的微前端框架,它的核心思想是将多个单页应用组合成一个整体的应用。它提供了一种在浏览器中加载和卸载不同单页应用的机制,使得每个单页应用可以独立开发和部署。

优点:

  • 技术栈灵活:允许不同的微前端使用不同的JavaScript框架(如React、Vue、Angular等),每个微前端可以根据自己的需求选择最适合的技术栈。例如,一个微前端可以用 React 实现复杂的用户交互界面,另一个可以用 Vue 构建简单的展示型页面。
  • 轻量级集成:相对来说比较轻量级,主要通过JavaScript的生命周期钩子(如mount、unmount等)来控制微前端的加载和卸载。这使得它在一些对性能要求较高、资源有限的场景下也能有较好的表现。

缺点:

  • 学习曲线较陡:由于它的实现原理涉及到多个单页应用的协调,开发者需要深入理解单页应用的生命周期以及如何在Single-SPA的架构下进行集成。例如,需要处理好不同微前端之间的样式隔离、全局状态共享等复杂问题。
  • 缺少内置的复杂功能:对于一些高级功能,如动态模块加载的优化、跨微前端的高效通信等,Single-SPA没有提供很完善的内置解决方案,需要开发者自己实现或者借助其他第三方库。

Module Federation(Webpack 5)

Github: https://github.com/webpack/webpack
文档:https://webpack.js.org/concepts/module-federation/

随着 Webpack 5 推出的模块联邦是一种更现代化的微前端解决方案。它基于 Webpack 的模块加载机制,允许在运行时动态加载微前端模块,并且可以在不同的构建之间共享模块。

优点:

  • 高效的模块共享:能够在多个微前端之间共享代码和模块,避免了重复加载相同的代码,提高了应用的整体性能。例如,多个微前端都使用了相同的UI库,通过模块联邦可以只加载一次。
  • 动态加载优势:支持在运行时根据用户的操作或者业务逻辑灵活地加载微前端模块,这对于实现个性化的用户体验或者根据不同的场景加载不同的功能非常有用。比如,在一个电商应用中,可以根据用户是否登录动态加载不同的购物车微前端。

缺点:

  • 对 Webpack 依赖较强:因为它是基于 Webpack 5 构建的,所以对 Webpack 的依赖比较高。如果项目没有使用 Webpack 或者想要切换到其他构建工具,可能会遇到困难。
  • 配置相对复杂:为了正确地设置模块联邦,需要对 Webpack 的配置有比较深入的了解,包括如何定义模块的暴露和引入,如何处理不同模块之间的版本兼容性等问题。

Open Components

Github: https://opencomponents.github.io/

Open Components 是一个专注于组件化微前端的开源框架。它强调将微前端作为可复用的组件进行开发和管理,使得这些组件可以在不同的应用场景中轻松集成。

优点:

  • 组件化思维:以组件为核心,便于开发人员将功能拆分为独立的组件,并且这些组件可以独立更新和维护。例如,可以将一个复杂的表单组件作为一个微前端,它可以在多个不同的业务流程中使用,并且每个使用场景可以独立地对其进行优化。
  • 易于共享和复用:组件的设计使得它们在不同的项目或者应用之间的共享和复用变得更加容易。可以通过一个简单的组件仓库来管理和发布这些微前端组件,其他应用可以方便地从仓库中获取并使用。

缺点:

  • 应用范围有限:由于它过于强调组件化,对于一些大型的、复杂的应用架构可能不太适用。在这些应用中,可能需要更全面的微前端集成方案,而不仅仅是组件的复用。
  • 集成深度较浅:在处理一些深层次的微前端集成问题,如跨组件的复杂业务逻辑、不同组件之间的深度交互等方面,Open Components 可能没有提供足够强大的解决方案。

qiankun(乾坤)

Github: https://github.com/umijs/qiankun

优点:

  • 完善的生态:由蚂蚁金服开源,拥有较为完善的生态和文档支持,对于开发者来说,上手相对容易,遇到问题能够比较方便地从社区或文档中找到解决方案。
  • 功能丰富:提供了微应用的加载、通信、状态管理等一整套解决方案。它可以很好地管理多个微前端应用的生命周期,确保子应用的正确加载、卸载和切换,使得微前端的实现更加便捷。
  • 兼容性较好:对于不同技术栈的兼容性较好,可以支持多种前端框架,如 React、Vue 等,这对于企业中存在多种技术选型的项目来说非常实用,可以降低技术整合的难度。

缺点:

  • 体积稍大:相对于一些轻量级的微前端框架,qiankun 的体积可能会稍大一些,这可能会在一定程度上影响应用的加载性能,特别是对于网络环境较差或对性能要求较高的场景,需要额外关注。
  • 定制化程度:由于它提供了较为完整的解决方案,对于一些有特殊需求的项目,可能需要进行一定的定制化开发,以满足项目的特定要求,这可能会增加开发的工作量和复杂度。

wujie(无界)

Github: https://github.com/Tencent/wujie

优点:

  • 原生隔离性好:是一款基于 Web Components + iframe 微前端框架,Web Components 可以有效隔离元素之间的样式,iframe 可以给子应用提供一个原生隔离的运行环境,相比自行构造的沙箱,能更好地和外部解耦,在隔离性方面表现出色。
  • 功能强大:支持子应用保活、子应用嵌套、多应用激活、应用共享、去中心化通信、生命周期钩子、插件系统等功能,能够满足复杂业务场景下的需求。
  • 支持多种框架:对于不同的前端框架也有较好的支持,开发者可以根据项目需求选择合适的技术栈进行开发。

缺点:

  • 学习成本较高:由于其实现原理涉及到 Web Components 和 iframe 等技术的结合,对于开发者来说,需要对这些技术有一定的了解和掌握,学习成本相对较高。
  • 性能优化难度大:虽然在隔离性方面有优势,但 iframe 的使用可能会在一定程度上影响性能,需要开发者进行针对性的性能优化,这对于开发者的技术水平要求较高。