一种相互独立的前端应用程序组成一个更大的应用程序的架构风格。
如何让这些独立的前端应用程序组成一个整体?
大概有5种方式来做集成:
根据请求的路由不同,在服务端组合模版、返回html资源到客户端。
此时把各子应用程序作为一个包。主应用把它们作为依赖。打包主应用后,便能得到完整的应用程序。
其实这种方式可以算作是微前端的前身,iframe天然具有样式隔离、运行时隔离的特性。但iframe方式在交互、路由管理方面是有劣势的。
这种方式,把子应用的js入口文件引入到主应用,并暴露一系列声明周期函数让主应用去控制。这也是目前主流的集成方式。single-spa和基于single-spa的qiankun都是这种方式。
            
<html>
  <head>
    <title>Feed me!</title>
  </head>
  <body>
    <h1>Welcome to Feed me!</h1>
    <!-- 暴露生命周期函数 -->
    <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">
      // 路由和入口函数的映射
      const microFrontendsByRoute = {
        '/': window.renderBrowseRestaurants,
        '/order-food': window.renderOrderFood,
        '/user-profile': window.renderUserProfile,
      };
      const renderFunction = microFrontendsByRoute[window.location.pathname];
      // 适时渲染特定的子应用到容器
      renderFunction('micro-frontend-root');
    </script>
  </body>
</html>
            
        
        这种方式把微应用作为一个自定义元素,需要把自定义元素的js定义引入。无需暴露生命周期函数,把微应用元素作为普通元素去操作。 MicroApp 是基于这种方式。
            
<html>
  <head>
    <title>Feed me!</title>
  </head>
  <body>
    <h1>Welcome to Feed me!</h1>
    <!-- 每个js文件和自定义元素关联 -->
    <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">
      // 路由和自定元素的映射
      const webComponentsByRoute = {
        '/': 'micro-frontend-browse-restaurants',
        '/order-food': 'micro-frontend-order-food',
        '/user-profile': 'micro-frontend-user-profile',
      };
      const webComponentType = webComponentsByRoute[window.location.pathname];
      //适时将自定义元素渲染到容器
      const root = document.getElementById('micro-frontend-root');
      const webComponent = document.createElement(webComponentType);
      root.appendChild(webComponent);
    </script>
  </body>
</html>
            
        
        css天生就是全局的,行内样式又会让页面结构和表现混合。为了解决样式隔离的问题,社区想出了各种方式。这些方式都适用于微前端架构。
除了这些通用的解决方案,微前端架构还可以通过在主应用改写所有子应用的样式。比如子应用的所有类名加个属性选择器来做区分。qiankun就是这样做的。
            
div[data-qiankun="0000000000000000000"]{
    color: red;
}