【解决方案】微前端实现方案

2023/07/21 14:33:30

单一项目随着时间推移,规模会越来越大,以至于难以维护。

微前端的思路就是将大应用拆分为若干个小应用,每个小应用都独立开发、部署。

实现思路

MPA

将系统分为多个仓库维护,在首页聚合所有平台的入口或提供统一的导航组件,采用 MPA(Multi-page Application)多页应用模式。

存在以下缺点:

  • 只能以页面维度拆分,无法拆分至区块部分。
  • 用户在使用时体验感不如 SPA 应用。
  • 不同系统间无法直接通信。
  • 公共部分更新时,所有子项目都要跟着更新。

iframe 嵌套子项目

iframe 可以保证样式和全局变量的良好隔离,但他的最大问题也在于他的隔离性无法被突破,导致应用间上下文无法被共享,随之带来的开发体验、产品体验的问题。

存在以下缺点:

Why Not Iframeopen in new window

  • URL 不同步。浏览器刷新 iframe url 状态丢失、后退前进按钮无法使用。

  • UI 不同步,DOM 结构不共享。如无法显示整页弹窗。

  • 全局上下文完全隔离,内存变量不共享。iframe 内外系统的通信、数据同步等需求,主应用的 cookie 要透传到根域名都不同的子应用中实现免登效果。

  • 加载慢,每次子应用进入都是一次浏览器上下文重建、资源重新加载的过程。

js 加载子应用

将子应用打包成 js 文件,通过 script 标签引入,每个子应用按约定暴露出相应的生命周期钩子,并且在加载后将其绑定到 window 对象下给主应用访问。然后主应用程序确定渲染哪个子应用,调用相关渲染函数传入渲染节点。

<html>
  <head>
    <title>Feed me!</title>
  </head>
  <body>
    <h1>Welcome to Feed me!</h1>
    <!-- These scripts don't render anything immediately -->

    <!-- Instead they attach entry-point functions to window' -->
    <script src="https://browse.example.com/bundle.js"></script>
    <script src="https://order.example.com/bundle.js"></script>
    <script src="https://profile.example.com/bundle.js"></script>
    <div id="micro-frontend-root"></div>
    <script type="text/javascript">
      // These global functions are attached to window by the above scripts
      const microFrontendsByRoute = {
        "/": window.renderBrowseRestaurants,
        "/order-food": window.renderOrderFood,
        "/user-profile": window.renderUserProfile,
      };
      const renderFunction = microFrontendsByRoute[window.location.pathname];
      // Having determined the entry-point function, we now call it,// giving it the ID of the element where it should render itself
      renderFunction("micro-frontend-root");
    </script>
  </body>
</html>

存在以下缺点:

  • 对现有项目来说改造成本高,需要将子项目打包成 js 文件。
  • 丧失了按需加载、首屏资源加载优化、css 独立打包等优化措施。

webpack5 提供了模块联邦open in new window功能,通过模块联邦可以在多个应用中任意导入/导出模块,从而实现模块的共享。使用模块联邦可以一定程度上减少项目改造的成本。

微前端框架

micro-appopen in new window

qiankunopen in new window

single-spaopen in new window

参考

微前端的前世今生open in new window